VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/UsbNet.cpp

Last change on this file was 108375, checked in by vboxsync, 2 months ago

UsbNet: Removed trailing blanks bugref:10779

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 89.8 KB
Line 
1/* $Id: UsbNet.cpp 108375 2025-02-25 14:49:37Z vboxsync $ */
2/** @file
3 * UsbNet - USB NCM Ethernet Device Emulation.
4 */
5
6/*
7 * Copyright (C) 2007-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_USB_NET
33#include <VBox/vmm/pdmusb.h>
34#include <VBox/vmm/pdmnetifs.h>
35#include <VBox/vmm/pdmnetinline.h>
36#include <VBox/log.h>
37#include <VBox/err.h>
38#include <VBox/scsi.h>
39#include <iprt/assert.h>
40#include <iprt/critsect.h>
41#include <iprt/mem.h>
42#include <iprt/semaphore.h>
43#include <iprt/string.h>
44#include <iprt/uuid.h>
45#include "VBoxDD.h"
46
47
48/*********************************************************************************************************************************
49* Defined Constants And Macros *
50*********************************************************************************************************************************/
51/** @name USB Ethernet string IDs
52 * @{ */
53#define USBNET_STR_ID_MANUFACTURER 1
54#define USBNET_STR_ID_PRODUCT 2
55#define USBNET_STR_ID_MAC_ADDRESS 3
56/** @} */
57
58/** @name USB Ethernet vendor and product IDs
59 * @{ */
60#define VBOX_USB_VENDOR 0x80EE
61#define USBNET_PID 0x0040
62/** @} */
63
64
65/*********************************************************************************************************************************
66* Structures and Typedefs *
67*********************************************************************************************************************************/
68
69#pragma pack(1)
70typedef struct USBCDCNOTIFICICATION
71{
72 uint8_t bmRequestType;
73 uint8_t bNotificationCode;
74 uint16_t wValue;
75 uint16_t wIndex;
76 uint16_t wLength;
77} USBCDCNOTIFICICATION;
78#pragma pack()
79AssertCompileSize(USBCDCNOTIFICICATION, 8);
80
81#define USB_CDC_NOTIFICATION_CODE_NETWORK_CONNECTION 0x00
82#define USB_CDC_NOTIFICATION_CODE_CONNECTION_SPEED_CHANGE 0x2a
83
84
85#pragma pack(1)
86typedef struct USBCDCNOTIFICICATIONSPEEDCHG
87{
88 USBCDCNOTIFICICATION Hdr;
89 uint32_t DLBitRate;
90 uint32_t ULBitRate;
91} USBCDCNOTIFICICATIONSPEEDCHG;
92#pragma pack()
93AssertCompileSize(USBCDCNOTIFICICATIONSPEEDCHG, 8 + 2 * 4);
94
95
96#pragma pack(1)
97typedef struct USBCDCFUNCDESCHDR
98{
99 uint8_t bFunctionLength;
100 uint8_t bDescriptorType;
101 uint8_t bDescriptorSubtype;
102} USBCDCFUNCDESCHDR;
103#pragma pack()
104AssertCompileSize(USBCDCFUNCDESCHDR, 3);
105
106#define USB_CDC_DESCRIPTOR_TYPE_INTERFACE 0x24
107#define USB_CDC_DESCRIPTOR_TYPE_ENDPOINT 0x25
108
109
110#define USB_CDC_DESCRIPTOR_SUB_TYPE_HEADER 0x00
111#define USB_CDC_DESCRIPTOR_SUB_TYPE_CALL_MGMT 0x01
112#define USB_CDC_DESCRIPTOR_SUB_TYPE_ACM 0x02
113#define USB_CDC_DESCRIPTOR_SUB_TYPE_DLM 0x03
114#define USB_CDC_DESCRIPTOR_SUB_TYPE_PHONE_RINGER 0x04
115#define USB_CDC_DESCRIPTOR_SUB_TYPE_PHONE_STATE_REPORTING 0x05
116#define USB_CDC_DESCRIPTOR_SUB_TYPE_UNION 0x06
117#define USB_CDC_DESCRIPTOR_SUB_TYPE_COUNTRY_SELECTION 0x07
118#define USB_CDC_DESCRIPTOR_SUB_TYPE_PHONE_OPERATING_MODES 0x08
119#define USB_CDC_DESCRIPTOR_SUB_TYPE_USB_TERMINAL 0x09
120#define USB_CDC_DESCRIPTOR_SUB_TYPE_NETWORK_CHANNEL_TERMINAL 0x0a
121#define USB_CDC_DESCRIPTOR_SUB_TYPE_PROTOCOL_UNIT 0x0b
122#define USB_CDC_DESCRIPTOR_SUB_TYPE_EXTENSION_UNIT 0x0c
123#define USB_CDC_DESCRIPTOR_SUB_TYPE_MULTI_CHANNEL_MGMT 0x0d
124#define USB_CDC_DESCRIPTOR_SUB_TYPE_CAPI_CONTROL_MGMT 0x0e
125#define USB_CDC_DESCRIPTOR_SUB_TYPE_ETHERNET_NETWORKING 0x0f
126#define USB_CDC_DESCRIPTOR_SUB_TYPE_ATM_NETEORKING 0x10
127#define USB_CDC_DESCRIPTOR_SUB_TYPE_WIRELESS_HANDSET_CONTROL 0x11
128#define USB_CDC_DESCRIPTOR_SUB_TYPE_MOBILE_DIRECT_LINE_MODEL 0x12
129#define USB_CDC_DESCRIPTOR_SUB_TYPE_MDLM_DETAIL 0x13
130#define USB_CDC_DESCRIPTOR_SUB_TYPE_DEVICE_MGMT_MODEL 0x14
131#define USB_CDC_DESCRIPTOR_SUB_TYPE_OBEX 0x15
132#define USB_CDC_DESCRIPTOR_SUB_TYPE_COMMAND_SET 0x16
133#define USB_CDC_DESCRIPTOR_SUB_TYPE_COMMAND_SET_DETAIL 0x17
134#define USB_CDC_DESCRIPTOR_SUB_TYPE_PHONE_CONTROL_MODEL 0x18
135#define USB_CDC_DESCRIPTOR_SUB_TYPE_OBEX_SERVICE_IDENTIFIER 0x19
136#define USB_CDC_DESCRIPTOR_SUB_TYPE_NCM 0x1a
137
138
139#pragma pack(1)
140typedef struct USBCDCHDRFUNCDESC
141{
142 USBCDCFUNCDESCHDR Hdr;
143 uint16_t bcdCDC;
144} USBCDCHDRFUNCDESC;
145#pragma pack()
146AssertCompileSize(USBCDCHDRFUNCDESC, 5);
147
148
149#pragma pack(1)
150typedef struct USBCDCUNIONFUNCDESC
151{
152 USBCDCFUNCDESCHDR Hdr;
153 uint8_t bControlInterface;
154 uint8_t bSubordinateInterface0;
155} USBCDCUNIONFUNCDESC;
156#pragma pack()
157AssertCompileSize(USBCDCUNIONFUNCDESC, 5);
158
159
160#pragma pack(1)
161typedef struct USBCDCECMFUNCDESC
162{
163 USBCDCFUNCDESCHDR Hdr;
164 uint8_t iMACAddress;
165 uint32_t bmEthernetStatistics;
166 uint16_t wMaxSegmentSize;
167 uint16_t wMaxNumberMCFilters;
168 uint8_t bNumberPowerFilters;
169} USBCDCECMFUNCDESC;
170#pragma pack()
171AssertCompileSize(USBCDCECMFUNCDESC, 13);
172
173
174#pragma pack(1)
175typedef struct USBCDCNCMFUNCDESC
176{
177 USBCDCFUNCDESCHDR Hdr;
178 uint16_t bcdNcmVersion;
179 uint8_t bmNetworkCapabilities;
180} USBCDCNCMFUNCDESC;
181#pragma pack()
182AssertCompileSize(USBCDCNCMFUNCDESC, 6);
183
184
185#define USB_CDC_NCM_FUNC_DESC_CAP_F_PACKET_FILTER RT_BIT(0)
186#define USB_CDC_NCM_FUNC_DESC_CAP_F_NET_ADDR RT_BIT(1)
187#define USB_CDC_NCM_FUNC_DESC_CAP_F_ENCAPSULATED_CMD RT_BIT(2)
188#define USB_CDC_NCM_FUNC_DESC_CAP_F_MAX_DATAGRAM RT_BIT(3)
189#define USB_CDC_NCM_FUNC_DESC_CAP_F_CRC_MODE RT_BIT(4)
190#define USB_CDC_NCM_FUNC_DESC_CAP_F_NTB_INPUT_SIZE_8BYTE RT_BIT(5)
191
192
193/**
194 * Our NCM interface class descriptor.
195 */
196#pragma pack(1)
197typedef struct USBNCMFUNCDESC
198{
199 USBCDCHDRFUNCDESC FuncHdr;
200 USBCDCUNIONFUNCDESC Union;
201 USBCDCECMFUNCDESC Ecm;
202 USBCDCNCMFUNCDESC Ncm;
203} USBNCMFUNCDESC;
204#pragma pack()
205AssertCompileSize(USBNCMFUNCDESC, sizeof(USBCDCHDRFUNCDESC) + sizeof(USBCDCUNIONFUNCDESC) + sizeof(USBCDCNCMFUNCDESC) + sizeof(USBCDCECMFUNCDESC));
206
207#pragma pack(1)
208typedef struct USBNCMNTBPARAMS
209{
210 uint16_t wLength;
211 uint16_t bmNtbFormatsSupported;
212 uint32_t dwNtbInMaxSize;
213 uint16_t wNdpInDivisor;
214 uint16_t wNdpInPayloadRemainder;
215 uint16_t wNdpInAlignment;
216 uint16_t u16Rsvd0;
217 uint32_t dwNtbOutMaxSize;
218 uint16_t wNdpOutDivisor;
219 uint16_t wNdpOutPayloadRemainder;
220 uint16_t wNdpOutAlignment;
221 uint16_t wNtpOutMaxDatagrams;
222} USBNCMNTBPARAMS;
223#pragma pack()
224AssertCompileSize(USBNCMNTBPARAMS, 28);
225
226#define VUSB_REQ_GET_NTB_PARAMETERS 0x80
227
228
229#pragma pack(1)
230typedef struct USBNCMNTH16
231{
232 uint32_t dwSignature;
233 uint16_t wHeaderLength;
234 uint16_t wSequence;
235 uint16_t wBlockLength;
236 uint16_t wNdpIndex;
237} USBNCMNTH16;
238#pragma pack()
239AssertCompileSize(USBNCMNTH16, 12);
240typedef USBNCMNTH16 *PUSBNCMNTH16;
241typedef const USBNCMNTH16 *PCUSBNCMNTH16;
242
243#define USBNCMNTH16_SIGNATURE UINT32_C(0x484d434e)
244
245
246typedef struct USBNCMNDP16DGRAM
247{
248 uint16_t wDatagramIndex;
249 uint16_t wDatagramLength;
250} USBNCMNDP16DGRAM;
251AssertCompileSize(USBNCMNDP16DGRAM, 4);
252typedef USBNCMNDP16DGRAM *PUSBNCMNDP16DGRAM;
253typedef const USBNCMNDP16DGRAM *PCUSBNCMNDP16DGRAM;
254
255#pragma pack(1)
256typedef struct USBNCMNDP16
257{
258 uint32_t dwSignature;
259 uint16_t wLength;
260 uint16_t wNextNdpIndex;
261 USBNCMNDP16DGRAM DataGram0;
262 USBNCMNDP16DGRAM DataGram1;
263 /* More pairs of wDatagramIndex/wDatagramLength can follow. */
264} USBNCMNDP16;
265#pragma pack()
266AssertCompileSize(USBNCMNDP16, 16);
267typedef USBNCMNDP16 *PUSBNCMNDP16;
268typedef const USBNCMNDP16 *PCUSBNCMNDP16;
269
270#define USBNCMNDP16_SIGNATURE_NCM0 UINT32_C(0x304d434e)
271#define USBNCMNDP16_SIGNATURE_NCM1 UINT32_C(0x314d434e)
272
273
274#pragma pack(1)
275typedef struct USBNCMNTH32
276{
277 uint32_t dwSignature;
278 uint16_t wHeaderLength;
279 uint16_t wSequence;
280 uint32_t dwBlockLength;
281 uint32_t dwNdpIndex;
282} USBNCMNTH32;
283#pragma pack()
284AssertCompileSize(USBNCMNTH32, 16);
285typedef USBNCMNTH32 *PUSBNCMNTH32;
286typedef const USBNCMNTH32 *PCUSBNCMNTH32;
287
288#define USBNCMNTH32_SIGNATURE UINT32_C(0x686d636e)
289
290
291#pragma pack(1)
292typedef struct USBNCMNDP32
293{
294 uint32_t dwSignature;
295 uint16_t wLength;
296 uint16_t wReserved6;
297 uint32_t dwNextNdpIndex;
298 uint32_t dwReserved12;
299 uint32_t dwDatagramIndex0;
300 uint32_t dwDatagramLength0;
301 uint32_t dwDatagramIndex1;
302 uint32_t dwDatagramLength1;
303 /* More pairs of dwDatagramIndex/dwDatagramLength can follow. */
304} USBNCMNDP32;
305#pragma pack()
306AssertCompileSize(USBNCMNDP32, 32);
307typedef USBNCMNDP32 *PUSBNCMNDP32;
308typedef const USBNCMNDP32 *PCUSBNCMNDP32;
309
310#define USBNCMNDP32_SIGNATURE_NCM0 UINT32_C(0x304d434e)
311#define USBNCMNDP32_SIGNATURE_NCM1 UINT32_C(0x314d434e)
312
313
314/**
315 * Endpoint status data.
316 */
317typedef struct USBNETEP
318{
319 bool fHalted;
320} USBNETEP;
321/** Pointer to the endpoint status. */
322typedef USBNETEP *PUSBNETEP;
323
324
325/**
326 * A URB queue.
327 */
328typedef struct USBNETURBQUEUE
329{
330 /** The head pointer. */
331 PVUSBURB pHead;
332 /** Where to insert the next entry. */
333 PVUSBURB *ppTail;
334} USBNETURBQUEUE;
335/** Pointer to a URB queue. */
336typedef USBNETURBQUEUE *PUSBNETURBQUEUE;
337/** Pointer to a const URB queue. */
338typedef USBNETURBQUEUE const *PCUSBNETURBQUEUE;
339
340
341/**
342 * The USB Ethernet instance data.
343 */
344typedef struct USBNET
345{
346 /** Pointer back to the PDM USB Device instance structure. */
347 PPDMUSBINS pUsbIns;
348 /** Critical section protecting the device state. */
349 RTCRITSECT CritSect;
350
351 /** The current configuration.
352 * (0 - default, 1 - the only, i.e configured.) */
353 uint8_t bConfigurationValue;
354 /** Current alternate setting. */
355 uint8_t bAlternateSetting;
356 /** NTH sequence number. */
357 uint16_t idSequence;
358
359 /** Endpoint 0 is the default control pipe, 1 is the host->dev bulk pipe and 2
360 * is the dev->host one, and 3 is the interrupt dev -> host one. */
361 USBNETEP aEps[4];
362
363 /** The "hardware" MAC address. */
364 RTMAC MacConfigured;
365 /** The stringified MAC address. */
366 char aszMac[13]; /* Includes zero temrinator. */
367
368 /** USB descriptor strings. */
369 PDMUSBDESCCACHESTRING aUsbStringsEnUs[3];
370 /** USB languages. */
371 PDMUSBDESCCACHELANG UsbLang;
372 /** The dynamically generated USB descriptor cache. */
373 PDMUSBDESCCACHE UsbDescCache;
374
375 /** If set the link is currently up. */
376 bool fLinkUp;
377 /** If set the link is temporarily down because of a saved state load. */
378 bool fLinkTempDown;
379 /** Link Up(/Restore) Timer. */
380 TMTIMERHANDLE hTimerLinkUp;
381
382 bool fInitialLinkStatusSent;
383 bool fInitialSpeedChangeSent;
384
385 /** Pending to-host queue.
386 * The URBs waiting here are pending the completion of the current request and
387 * data or status to become available.
388 */
389 USBNETURBQUEUE ToHostQueue;
390 /** Pending to-host interrupt queue.
391 * The URBs waiting here are pending the completion of the current request and
392 * data or status to become available.
393 */
394 USBNETURBQUEUE ToHostIntrQueue;
395 /** Done queue
396 * The URBs stashed here are waiting to be reaped. */
397 USBNETURBQUEUE DoneQueue;
398 /** Signalled when adding an URB to the done queue and fHaveDoneQueueWaiter
399 * is set. */
400 RTSEMEVENT hEvtDoneQueue;
401 /** Signalled when adding an URB to the to host queue and fHaveToHostQueueWaiter
402 * is set. */
403 RTSEMEVENT hEvtToHostQueue;
404 /** Someone is waiting on the done queue. */
405 bool fHaveDoneQueueWaiter;
406 /** Someone is waiting on the to host queue. */
407 volatile bool fHaveToHostQueueWaiter;
408
409 /** VM is currently suspended and we should ignore all external requests. */
410 volatile bool fSuspended;
411
412 /** Whether to signal the reset semaphore when the current request completes. */
413 bool fSignalResetSem;
414 /** Semaphore usbNetUsbReset waits on when a request is executing at reset
415 * time. Only signalled when fSignalResetSem is set. */
416 RTSEMEVENTMULTI hEvtReset;
417 /** The reset URB.
418 * This is waiting for SCSI request completion before finishing the reset. */
419 PVUSBURB pResetUrb;
420
421 STAMCOUNTER StatReceiveBytes;
422 STAMCOUNTER StatTransmitBytes;
423
424 uint32_t u32PktNo;
425 /**
426 * LUN\#0 data.
427 */
428 struct
429 {
430 /** LUN\#0 + status LUN: The base interface. */
431 PDMIBASE IBase;
432 /** LUN\#0: The network port interface. */
433 PDMINETWORKDOWN INetworkDown;
434 /** LUN\#0: The network config port interface. */
435 PDMINETWORKCONFIG INetworkConfig;
436
437 /** Pointer to the connector of the attached network driver. */
438 PPDMINETWORKUPR3 pINetwork;
439 /** Pointer to the attached network driver. */
440 R3PTRTYPE(PPDMIBASE) pIBase;
441 } Lun0;
442
443} USBNET;
444/** Pointer to the USB Ethernet instance data. */
445typedef USBNET *PUSBNET;
446
447
448/*********************************************************************************************************************************
449* Global Variables *
450*********************************************************************************************************************************/
451static const USBNCMFUNCDESC g_UsbNetFuncDesc =
452{
453 {
454 { 5, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_HEADER },
455 0x0110
456 },
457 {
458 { 5, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_UNION },
459 0,
460 1
461 },
462 {
463 { 13, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_ETHERNET_NETWORKING },
464 USBNET_STR_ID_MAC_ADDRESS,
465 0,
466 1514,
467 0,
468 0
469 },
470 {
471 { 6, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_NCM },
472 0x0100,
473 0
474 }
475};
476
477
478static const VUSBDESCIAD g_UsbNetInterfaceIad =
479{
480 sizeof(VUSBDESCIAD), // bLength;
481 VUSB_DT_INTERFACE_ASSOCIATION, // bDescriptorType;
482 0, // bFirstInterface;
483 2, // bInterfaceCount;
484 2, // bFunctionClass;
485 0x0d, // bFunctionSubClass;
486 0, // bFunctionProtocol;
487 0 // iFunction;
488};
489
490
491static const VUSBDESCENDPOINTEX g_aUsbNetEndpointDescsAlt1FS[3] =
492{
493 {
494 {
495 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
496 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
497 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
498 /* .bmAttributes = */ 2 /* bulk */,
499 /* .wMaxPacketSize = */ 64 /* maximum possible */,
500 /* .bInterval = */ 0 /* not applicable for bulk EP */
501 },
502 /* .pvMore = */ NULL,
503 /* .pvClass = */ NULL,
504 /* .cbClass = */ 0,
505 /* .pvSsepc = */ NULL,
506 /* .cbSsepc = */ 0
507 },
508 {
509 {
510 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
511 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
512 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
513 /* .bmAttributes = */ 2 /* bulk */,
514 /* .wMaxPacketSize = */ 64 /* maximum possible */,
515 /* .bInterval = */ 0 /* not applicable for bulk EP */
516 },
517 /* .pvMore = */ NULL,
518 /* .pvClass = */ NULL,
519 /* .cbClass = */ 0,
520 /* .pvSsepc = */ NULL,
521 /* .cbSsepc = */ 0
522 },
523 {
524 {
525 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
526 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
527 /* .bEndpointAddress = */ 0x83 /* ep=3, in */,
528 /* .bmAttributes = */ 3 /* interrupt */,
529 /* .wMaxPacketSize = */ 64,
530 /* .bInterval = */ 10,
531 },
532 /* .pvMore = */ NULL,
533 /* .pvClass = */ NULL,
534 /* .cbClass = */ 0
535 },
536};
537
538static const VUSBDESCENDPOINTEX g_aUsbNetEndpointDescsAlt1HS[3] =
539{
540 {
541 {
542 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
543 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
544 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
545 /* .bmAttributes = */ 2 /* bulk */,
546 /* .wMaxPacketSize = */ 512 /* HS bulk packet size */,
547 /* .bInterval = */ 0 /* no NAKs */
548 },
549 /* .pvMore = */ NULL,
550 /* .pvClass = */ NULL,
551 /* .cbClass = */ 0,
552 /* .pvSsepc = */ NULL,
553 /* .cbSsepc = */ 0
554 },
555 {
556 {
557 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
558 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
559 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
560 /* .bmAttributes = */ 2 /* bulk */,
561 /* .wMaxPacketSize = */ 512 /* HS bulk packet size */,
562 /* .bInterval = */ 0 /* no NAKs */
563 },
564 /* .pvMore = */ NULL,
565 /* .pvClass = */ NULL,
566 /* .cbClass = */ 0,
567 /* .pvSsepc = */ NULL,
568 /* .cbSsepc = */ 0
569 },
570 {
571 {
572 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
573 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
574 /* .bEndpointAddress = */ 0x83 /* ep=3, in */,
575 /* .bmAttributes = */ 3 /* interrupt */,
576 /* .wMaxPacketSize = */ 64,
577 /* .bInterval = */ 10,
578 },
579 /* .pvMore = */ NULL,
580 /* .pvClass = */ NULL,
581 /* .cbClass = */ 0
582 },
583};
584
585static const VUSBDESCSSEPCOMPANION g_aUsbNetEpCompanionSS =
586{
587 /* .bLength = */ sizeof(VUSBDESCSSEPCOMPANION),
588 /* .bDescriptorType = */ VUSB_DT_SS_ENDPOINT_COMPANION,
589 /* .bMaxBurst = */ 15 /* we can burst all the way */,
590 /* .bmAttributes = */ 0 /* no streams */,
591 /* .wBytesPerInterval = */ 0 /* not a periodic endpoint */
592};
593
594static const VUSBDESCENDPOINTEX g_aUsbNetEndpointDescsAlt1SS[3] =
595{
596 {
597 {
598 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
599 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
600 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
601 /* .bmAttributes = */ 2 /* bulk */,
602 /* .wMaxPacketSize = */ 1024 /* SS bulk packet size */,
603 /* .bInterval = */ 0 /* no NAKs */
604 },
605 /* .pvMore = */ NULL,
606 /* .pvClass = */ NULL,
607 /* .cbClass = */ 0,
608 /* .pvSsepc = */ &g_aUsbNetEpCompanionSS,
609 /* .cbSsepc = */ sizeof(g_aUsbNetEpCompanionSS)
610 },
611 {
612 {
613 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
614 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
615 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
616 /* .bmAttributes = */ 2 /* bulk */,
617 /* .wMaxPacketSize = */ 1024 /* SS bulk packet size */,
618 /* .bInterval = */ 0 /* no NAKs */
619 },
620 /* .pvMore = */ NULL,
621 /* .pvClass = */ NULL,
622 /* .cbClass = */ 0,
623 /* .pvSsepc = */ &g_aUsbNetEpCompanionSS,
624 /* .cbSsepc = */ sizeof(g_aUsbNetEpCompanionSS)
625 },
626 {
627 {
628 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
629 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
630 /* .bEndpointAddress = */ 0x83 /* ep=3, in */,
631 /* .bmAttributes = */ 3 /* interrupt */,
632 /* .wMaxPacketSize = */ 64,
633 /* .bInterval = */ 10,
634 },
635 /* .pvMore = */ NULL,
636 /* .pvClass = */ NULL,
637 /* .cbClass = */ 0,
638 /* .pvSsepc = */ &g_aUsbNetEpCompanionSS,
639 /* .cbSsepc = */ sizeof(g_aUsbNetEpCompanionSS)
640 },
641};
642
643
644static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescFS_0[] =
645{
646 {
647 {
648 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
649 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
650 /* .bInterfaceNumber = */ 0,
651 /* .bAlternateSetting = */ 0,
652 /* .bNumEndpoints = */ 1,
653 /* .bInterfaceClass = */ 2 /* Communications Device */,
654 /* .bInterfaceSubClass = */ 0x0d /* Communications Device Subclass / NCM */,
655 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
656 /* .iInterface = */ 0
657 },
658 /* .pvMore = */ NULL,
659 /* .pvClass = */ &g_UsbNetFuncDesc,
660 /* .cbClass = */ sizeof(g_UsbNetFuncDesc),
661 /* .paEndpoints = */ &g_aUsbNetEndpointDescsAlt1FS[2],
662 /* .pIAD = */ &g_UsbNetInterfaceIad,
663 /* .cbIAD = */ sizeof(g_UsbNetInterfaceIad)
664 }
665};
666
667static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescFS_1[] =
668{
669 {
670 {
671 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
672 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
673 /* .bInterfaceNumber = */ 1,
674 /* .bAlternateSetting = */ 0,
675 /* .bNumEndpoints = */ 0,
676 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
677 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
678 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
679 /* .iInterface = */ 0
680 },
681 /* .pvMore = */ NULL,
682 /* .pvClass = */ NULL,
683 /* .cbClass = */ 0,
684 NULL,
685 /* .pIAD = */ NULL,
686 /* .cbIAD = */ 0
687 },
688 {
689 {
690 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
691 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
692 /* .bInterfaceNumber = */ 1,
693 /* .bAlternateSetting = */ 1,
694 /* .bNumEndpoints = */ 2,
695 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
696 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
697 /* .bInterfaceProtocol = */ 1 /* No encapsulated commands / responses */,
698 /* .iInterface = */ 0
699 },
700 /* .pvMore = */ NULL,
701 /* .pvClass = */ NULL,
702 /* .cbClass = */ 0,
703 &g_aUsbNetEndpointDescsAlt1FS[0],
704 /* .pIAD = */ NULL, //&g_UsbNetInterfaceIad,
705 /* .cbIAD = */ 0, //sizeof(g_UsbNetInterfaceIad)
706 }
707};
708
709
710static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescHS_0[] =
711{
712 {
713 {
714 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
715 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
716 /* .bInterfaceNumber = */ 0,
717 /* .bAlternateSetting = */ 0,
718 /* .bNumEndpoints = */ 1,
719 /* .bInterfaceClass = */ 2 /* Communications Device */,
720 /* .bInterfaceSubClass = */ 0x0d /* Communications Device Subclass / NCM */,
721 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
722 /* .iInterface = */ 0
723 },
724 /* .pvMore = */ NULL,
725 /* .pvClass = */ &g_UsbNetFuncDesc,
726 /* .cbClass = */ sizeof(g_UsbNetFuncDesc),
727 /* .paEndpoints = */ &g_aUsbNetEndpointDescsAlt1HS[2],
728 /* .pIAD = */ &g_UsbNetInterfaceIad,
729 /* .cbIAD = */ sizeof(g_UsbNetInterfaceIad)
730 }
731};
732
733static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescHS_1[] =
734{
735 {
736 {
737 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
738 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
739 /* .bInterfaceNumber = */ 1,
740 /* .bAlternateSetting = */ 0,
741 /* .bNumEndpoints = */ 0,
742 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
743 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
744 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
745 /* .iInterface = */ 0
746 },
747 /* .pvMore = */ NULL,
748 /* .pvClass = */ NULL,
749 /* .cbClass = */ 0,
750 NULL,
751 /* .pIAD = */ NULL,
752 /* .cbIAD = */ 0
753 },
754 {
755 {
756 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
757 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
758 /* .bInterfaceNumber = */ 1,
759 /* .bAlternateSetting = */ 1,
760 /* .bNumEndpoints = */ 2,
761 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
762 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
763 /* .bInterfaceProtocol = */ 1 /* No encapsulated commands / responses */,
764 /* .iInterface = */ 0
765 },
766 /* .pvMore = */ NULL,
767 /* .pvClass = */ NULL,
768 /* .cbClass = */ 0,
769 &g_aUsbNetEndpointDescsAlt1HS[0],
770 /* .pIAD = */ NULL, //&g_UsbNetInterfaceIad,
771 /* .cbIAD = */ 0, //sizeof(g_UsbNetInterfaceIad)
772 }
773};
774
775
776static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescSS_0[] =
777{
778 {
779 {
780 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
781 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
782 /* .bInterfaceNumber = */ 0,
783 /* .bAlternateSetting = */ 0,
784 /* .bNumEndpoints = */ 1,
785 /* .bInterfaceClass = */ 2 /* Communications Device */,
786 /* .bInterfaceSubClass = */ 0x0d /* Communications Device Subclass / NCM */,
787 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
788 /* .iInterface = */ 0
789 },
790 /* .pvMore = */ NULL,
791 /* .pvClass = */ &g_UsbNetFuncDesc,
792 /* .cbClass = */ sizeof(g_UsbNetFuncDesc),
793 /* .paEndpoints = */ &g_aUsbNetEndpointDescsAlt1SS[2],
794 /* .pIAD = */ &g_UsbNetInterfaceIad,
795 /* .cbIAD = */ sizeof(g_UsbNetInterfaceIad)
796 }
797};
798
799static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescSS_1[] =
800{
801 {
802 {
803 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
804 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
805 /* .bInterfaceNumber = */ 1,
806 /* .bAlternateSetting = */ 0,
807 /* .bNumEndpoints = */ 0,
808 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
809 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
810 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
811 /* .iInterface = */ 0
812 },
813 /* .pvMore = */ NULL,
814 /* .pvClass = */ NULL,
815 /* .cbClass = */ 0,
816 NULL,
817 /* .pIAD = */ NULL,
818 /* .cbIAD = */ 0
819 },
820 {
821 {
822 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
823 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
824 /* .bInterfaceNumber = */ 1,
825 /* .bAlternateSetting = */ 1,
826 /* .bNumEndpoints = */ 2,
827 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
828 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
829 /* .bInterfaceProtocol = */ 1 /* No encapsulated commands / responses */,
830 /* .iInterface = */ 0
831 },
832 /* .pvMore = */ NULL,
833 /* .pvClass = */ NULL,
834 /* .cbClass = */ 0,
835 &g_aUsbNetEndpointDescsAlt1SS[0],
836 /* .pIAD = */ NULL, //&g_UsbNetInterfaceIad,
837 /* .cbIAD = */ 0, //sizeof(g_UsbNetInterfaceIad)
838 }
839};
840
841static const VUSBINTERFACE g_aUsbNetInterfacesFS[] =
842{
843 { g_aUsbNetInterfaceDescFS_0, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescFS_0) },
844 { g_aUsbNetInterfaceDescFS_1, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescFS_1) },
845};
846
847static const VUSBINTERFACE g_aUsbNetInterfacesHS[] =
848{
849 { g_aUsbNetInterfaceDescHS_0, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescHS_0) },
850 { g_aUsbNetInterfaceDescHS_1, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescHS_1) },
851};
852
853static const VUSBINTERFACE g_aUsbNetInterfacesSS[] =
854{
855 { g_aUsbNetInterfaceDescSS_0, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescSS_0) },
856 { g_aUsbNetInterfaceDescSS_1, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescSS_1) },
857};
858
859static const VUSBDESCCONFIGEX g_UsbNetConfigDescFS =
860{
861 {
862 /* .bLength = */ sizeof(VUSBDESCCONFIG),
863 /* .bDescriptorType = */ VUSB_DT_CONFIG,
864 /* .wTotalLength = */ 0 /* recalculated on read */,
865 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbNetInterfacesFS),
866 /* .bConfigurationValue =*/ 1,
867 /* .iConfiguration = */ 0,
868 /* .bmAttributes = */ RT_BIT(7),
869 /* .MaxPower = */ 50 /* 100mA */
870 },
871 NULL, /* pvMore */
872 NULL, /* pvClass */
873 0, /* cbClass */
874 &g_aUsbNetInterfacesFS[0],
875 NULL /* pvOriginal */
876};
877
878static const VUSBDESCCONFIGEX g_UsbNetConfigDescHS =
879{
880 {
881 /* .bLength = */ sizeof(VUSBDESCCONFIG),
882 /* .bDescriptorType = */ VUSB_DT_CONFIG,
883 /* .wTotalLength = */ 0 /* recalculated on read */,
884 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbNetInterfacesHS),
885 /* .bConfigurationValue =*/ 1,
886 /* .iConfiguration = */ 0,
887 /* .bmAttributes = */ RT_BIT(7),
888 /* .MaxPower = */ 50 /* 100mA */
889 },
890 NULL, /* pvMore */
891 NULL, /* pvClass */
892 0, /* cbClass */
893 &g_aUsbNetInterfacesHS[0],
894 NULL /* pvOriginal */
895};
896
897static const VUSBDESCCONFIGEX g_UsbNetConfigDescSS =
898{
899 {
900 /* .bLength = */ sizeof(VUSBDESCCONFIG),
901 /* .bDescriptorType = */ VUSB_DT_CONFIG,
902 /* .wTotalLength = */ 0 /* recalculated on read */,
903 /* .bNumInterfaces = */ 2,
904 /* .bConfigurationValue =*/ 1,
905 /* .iConfiguration = */ 0,
906 /* .bmAttributes = */ RT_BIT(7),
907 /* .MaxPower = */ 50 /* 100mA */
908 },
909 NULL, /* pvMore */
910 NULL, /* pvClass */
911 0, /* cbClass */
912 &g_aUsbNetInterfacesSS[0],
913 NULL /* pvOriginal */
914};
915
916static const VUSBDESCDEVICE g_UsbNetDeviceDesc20 =
917{
918 /* .bLength = */ sizeof(g_UsbNetDeviceDesc20),
919 /* .bDescriptorType = */ VUSB_DT_DEVICE,
920 /* .bcdUsb = */ 0x200, /* USB 2.0 */
921 /* .bDeviceClass = */ 2 /* Class specified in the interface desc. */,
922 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
923 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
924 /* .bMaxPacketSize0 = */ 64,
925 /* .idVendor = */ VBOX_USB_VENDOR,
926 /* .idProduct = */ USBNET_PID,
927 /* .bcdDevice = */ 0x0100, /* 1.0 */
928 /* .iManufacturer = */ USBNET_STR_ID_MANUFACTURER,
929 /* .iProduct = */ USBNET_STR_ID_PRODUCT,
930 /* .iSerialNumber = */ 0,
931 /* .bNumConfigurations = */ 1
932};
933
934static const VUSBDESCDEVICE g_UsbNetDeviceDesc30 =
935{
936 /* .bLength = */ sizeof(g_UsbNetDeviceDesc30),
937 /* .bDescriptorType = */ VUSB_DT_DEVICE,
938 /* .bcdUsb = */ 0x300, /* USB 2.0 */
939 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
940 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
941 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
942 /* .bMaxPacketSize0 = */ 9 /* 512, the only option for USB3. */,
943 /* .idVendor = */ VBOX_USB_VENDOR,
944 /* .idProduct = */ USBNET_PID,
945 /* .bcdDevice = */ 0x0110, /* 1.10 */
946 /* .iManufacturer = */ USBNET_STR_ID_MANUFACTURER,
947 /* .iProduct = */ USBNET_STR_ID_PRODUCT,
948 /* .iSerialNumber = */ 0,
949 /* .bNumConfigurations = */ 1
950};
951
952static const VUSBDEVICEQUALIFIER g_UsbNetDeviceQualifier =
953{
954 /* .bLength = */ sizeof(g_UsbNetDeviceQualifier),
955 /* .bDescriptorType = */ VUSB_DT_DEVICE_QUALIFIER,
956 /* .bcdUsb = */ 0x200, /* USB 2.0 */
957 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
958 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
959 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
960 /* .bMaxPacketSize0 = */ 64,
961 /* .bNumConfigurations = */ 1,
962 /* .bReserved = */ 0
963};
964
965static const struct {
966 VUSBDESCBOS bos;
967 VUSBDESCSSDEVCAP sscap;
968} g_UsbNetBOS =
969{
970 {
971 /* .bLength = */ sizeof(g_UsbNetBOS.bos),
972 /* .bDescriptorType = */ VUSB_DT_BOS,
973 /* .wTotalLength = */ sizeof(g_UsbNetBOS),
974 /* .bNumDeviceCaps = */ 1
975 },
976 {
977 /* .bLength = */ sizeof(VUSBDESCSSDEVCAP),
978 /* .bDescriptorType = */ VUSB_DT_DEVICE_CAPABILITY,
979 /* .bDevCapabilityType = */ VUSB_DCT_SUPERSPEED_USB,
980 /* .bmAttributes = */ 0 /* No LTM. */,
981 /* .wSpeedsSupported = */ 0xe /* Any speed is good. */,
982 /* .bFunctionalitySupport = */ 2 /* Want HS at least. */,
983 /* .bU1DevExitLat = */ 0, /* We are blazingly fast. */
984 /* .wU2DevExitLat = */ 0
985 }
986};
987
988
989/*********************************************************************************************************************************
990* Internal Functions *
991*********************************************************************************************************************************/
992static int usbNetHandleBulkDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb);
993
994
995/**
996 * Initializes an URB queue.
997 *
998 * @param pQueue The URB queue.
999 */
1000static void usbNetQueueInit(PUSBNETURBQUEUE pQueue)
1001{
1002 pQueue->pHead = NULL;
1003 pQueue->ppTail = &pQueue->pHead;
1004}
1005
1006
1007
1008/**
1009 * Inserts an URB at the end of the queue.
1010 *
1011 * @param pQueue The URB queue.
1012 * @param pUrb The URB to insert.
1013 */
1014DECLINLINE(void) usbNetQueueAddTail(PUSBNETURBQUEUE pQueue, PVUSBURB pUrb)
1015{
1016 pUrb->Dev.pNext = NULL;
1017 *pQueue->ppTail = pUrb;
1018 pQueue->ppTail = &pUrb->Dev.pNext;
1019}
1020
1021
1022/**
1023 * Unlinks the head of the queue and returns it.
1024 *
1025 * @returns The head entry.
1026 * @param pQueue The URB queue.
1027 */
1028DECLINLINE(PVUSBURB) usbNetQueueRemoveHead(PUSBNETURBQUEUE pQueue)
1029{
1030 PVUSBURB pUrb = pQueue->pHead;
1031 if (pUrb)
1032 {
1033 PVUSBURB pNext = pUrb->Dev.pNext;
1034 pQueue->pHead = pNext;
1035 if (!pNext)
1036 pQueue->ppTail = &pQueue->pHead;
1037 else
1038 pUrb->Dev.pNext = NULL;
1039 }
1040 return pUrb;
1041}
1042
1043
1044/**
1045 * Removes an URB from anywhere in the queue.
1046 *
1047 * @returns true if found, false if not.
1048 * @param pQueue The URB queue.
1049 * @param pUrb The URB to remove.
1050 */
1051DECLINLINE(bool) usbNetQueueRemove(PUSBNETURBQUEUE pQueue, PVUSBURB pUrb)
1052{
1053 PVUSBURB pCur = pQueue->pHead;
1054 if (pCur == pUrb)
1055 pQueue->pHead = pUrb->Dev.pNext;
1056 else
1057 {
1058 while (pCur)
1059 {
1060 if (pCur->Dev.pNext == pUrb)
1061 {
1062 pCur->Dev.pNext = pUrb->Dev.pNext;
1063 break;
1064 }
1065 pCur = pCur->Dev.pNext;
1066 }
1067 if (!pCur)
1068 return false;
1069 }
1070 if (!pUrb->Dev.pNext)
1071 pQueue->ppTail = &pQueue->pHead;
1072 return true;
1073}
1074
1075
1076/**
1077 * Checks if the queue is empty or not.
1078 *
1079 * @returns true if it is, false if it isn't.
1080 * @param pQueue The URB queue.
1081 */
1082DECLINLINE(bool) usbNetQueueIsEmpty(PCUSBNETURBQUEUE pQueue)
1083{
1084 return pQueue->pHead == NULL;
1085}
1086
1087
1088/**
1089 * Links an URB into the done queue.
1090 *
1091 * @param pThis The USBNET instance.
1092 * @param pUrb The URB.
1093 */
1094static void usbNetLinkDone(PUSBNET pThis, PVUSBURB pUrb)
1095{
1096 usbNetQueueAddTail(&pThis->DoneQueue, pUrb);
1097
1098 if (pThis->fHaveDoneQueueWaiter)
1099 {
1100 int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
1101 AssertRC(rc);
1102 }
1103}
1104
1105
1106/**
1107 * Completes the URB with a stalled state, halting the pipe.
1108 */
1109static int usbNetCompleteStall(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb, const char *pszWhy)
1110{
1111 RT_NOREF(pszWhy);
1112 LogFunc(("/#%u/ pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
1113
1114 pUrb->enmStatus = VUSBSTATUS_STALL;
1115
1116 /** @todo figure out if the stall is global or pipe-specific or both. */
1117 if (pEp)
1118 pEp->fHalted = true;
1119 else
1120 {
1121 pThis->aEps[1].fHalted = true;
1122 pThis->aEps[2].fHalted = true;
1123 pThis->aEps[3].fHalted = true;
1124 }
1125
1126 usbNetLinkDone(pThis, pUrb);
1127 return VINF_SUCCESS;
1128}
1129
1130
1131/**
1132 * Completes the URB with a OK state.
1133 */
1134static int usbNetCompleteOk(PUSBNET pThis, PVUSBURB pUrb, size_t cbData)
1135{
1136 LogFlowFunc(("/#%u/ pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
1137
1138 pUrb->enmStatus = VUSBSTATUS_OK;
1139 pUrb->cbData = (uint32_t)cbData;
1140
1141 usbNetLinkDone(pThis, pUrb);
1142 return VINF_SUCCESS;
1143}
1144
1145
1146/**
1147 * Completes the URB after device successfully processed it. Optionally copies data
1148 * into the URB. May still generate an error if the URB is not big enough.
1149 */
1150static void usbNetCompleteNotificationOk(PUSBNET pThis, PVUSBURB pUrb, const void *pSrc, size_t cbSrc)
1151{
1152 LogFlowFunc(("/#%u/ pUrb=%p:%s (cbData=%#x) cbSrc=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->cbData, cbSrc));
1153
1154 pUrb->enmStatus = VUSBSTATUS_OK;
1155 if (pSrc) /* Can be NULL if not copying anything. */
1156 {
1157 Assert(cbSrc);
1158 uint8_t *pDst = pUrb->abData;
1159
1160 /* Returned data is written after the setup message in control URBs. */
1161 Assert (pUrb->enmType == VUSBXFERTYPE_INTR);
1162
1163 /* There is at least one byte of room in the URB. */
1164 size_t cbCopy = RT_MIN(pUrb->cbData, cbSrc);
1165 memcpy(pDst, pSrc, cbCopy);
1166 pUrb->cbData = (uint32_t)cbCopy;
1167 Log2Func(("/#%u/ Copied %zu bytes to pUrb->abData, source had %zu bytes\n", pThis->pUsbIns->iInstance, cbCopy, cbSrc));
1168
1169 /*
1170 * Need to check length differences. If cbSrc is less than what
1171 * the URB has space for, it'll be resolved as a short packet. But
1172 * if cbSrc is bigger, there is a real problem and the host needs
1173 * to see an overrun/babble error.
1174 */
1175 if (RT_UNLIKELY(cbSrc > cbCopy))
1176 pUrb->enmStatus = VUSBSTATUS_DATA_OVERRUN;
1177 }
1178 else
1179 Assert(cbSrc == 0); /* Make up your mind, caller! */
1180
1181 usbNetLinkDone(pThis, pUrb);
1182}
1183
1184
1185/**
1186 * Reset worker for usbNetUsbReset, usbNetUsbSetConfiguration and
1187 * usbNetUrbHandleDefaultPipe.
1188 *
1189 * @returns VBox status code.
1190 * @param pThis The MSD instance.
1191 * @param pUrb Set when usbNetUrbHandleDefaultPipe is the
1192 * caller.
1193 * @param fSetConfig Set when usbNetUsbSetConfiguration is the
1194 * caller.
1195 */
1196static int usbNetResetWorker(PUSBNET pThis, PVUSBURB pUrb, bool fSetConfig)
1197{
1198 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
1199 pThis->aEps[i].fHalted = false;
1200
1201 if (!pUrb && !fSetConfig) /* (only device reset) */
1202 pThis->bConfigurationValue = 0; /* default */
1203
1204 pThis->idSequence = 0;
1205
1206 /*
1207 * Ditch all pending URBs.
1208 */
1209 PVUSBURB pCurUrb;
1210 while ((pCurUrb = usbNetQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
1211 {
1212 pCurUrb->enmStatus = VUSBSTATUS_CRC;
1213 usbNetLinkDone(pThis, pCurUrb);
1214 }
1215
1216 while ((pCurUrb = usbNetQueueRemoveHead(&pThis->ToHostIntrQueue)) != NULL)
1217 {
1218 pCurUrb->enmStatus = VUSBSTATUS_CRC;
1219 usbNetLinkDone(pThis, pCurUrb);
1220 }
1221
1222 pCurUrb = pThis->pResetUrb;
1223 if (pCurUrb)
1224 {
1225 pThis->pResetUrb = NULL;
1226 pCurUrb->enmStatus = VUSBSTATUS_CRC;
1227 usbNetLinkDone(pThis, pCurUrb);
1228 }
1229
1230 if (pUrb)
1231 return usbNetCompleteOk(pThis, pUrb, 0);
1232 return VINF_SUCCESS;
1233}
1234
1235
1236/**
1237 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1238 */
1239static DECLCALLBACK(void *) usbNetLun0QueryInterface(PPDMIBASE pInterface, const char *pszIID)
1240{
1241 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.IBase);
1242 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
1243 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->Lun0.INetworkConfig);
1244 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->Lun0.INetworkDown);
1245 return NULL;
1246}
1247
1248
1249static DECLCALLBACK(int) usbNetNetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
1250{
1251 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkDown);
1252 int rc = VINF_SUCCESS;
1253 LogFlowFunc(("/#%u/ pInterface=%p cMillies=%u\n", pThis->pUsbIns->iInstance, pInterface, cMillies));
1254
1255 RTCritSectEnter(&pThis->CritSect);
1256 pThis->fHaveToHostQueueWaiter = usbNetQueueIsEmpty(&pThis->ToHostQueue) && !pThis->fSuspended;
1257 RTCritSectLeave(&pThis->CritSect);
1258 /*
1259 * It is ok to read fHaveToHostQueueWaiter outside of the critical section because:
1260 * 1) There is only one receive thread that calls this function;
1261 * 2) This is the only function that modifies fHaveToHostQueueWaiter.
1262 */
1263 while (ASMAtomicReadBool(&pThis->fHaveToHostQueueWaiter))
1264 {
1265 rc = RTSemEventWait(pThis->hEvtToHostQueue, cMillies);
1266
1267 RTCritSectEnter(&pThis->CritSect);
1268 pThis->fHaveToHostQueueWaiter = usbNetQueueIsEmpty(&pThis->ToHostQueue) && !pThis->fSuspended;
1269 RTCritSectLeave(&pThis->CritSect);
1270 Log6Func(("/#%u/ pInterface=%p received hEvtToHostQueue, %s need to wait\n",
1271 pThis->pUsbIns->iInstance, pInterface, pThis->fHaveToHostQueueWaiter ? "still" : "no"));
1272 }
1273 LogFlowFunc(("/#%u/ pInterface=%p returned %u\n", pThis->pUsbIns->iInstance, pInterface, rc));
1274 return rc;
1275}
1276
1277#ifdef LOG_ENABLED
1278
1279DECLINLINE(void) usbNetProtocolDump(const uint8_t *cpPacket, uint32_t cb)
1280{
1281 RT_NOREF(cb);
1282 uint8_t protocol;
1283 uint16_t offset = sizeof(RTNETETHERHDR);
1284 uint16_t uEthType = RT_N2H_U16(*(uint16_t*)(cpPacket+12));
1285 if (uEthType == RTNET_ETHERTYPE_VLAN)
1286 {
1287 uEthType = RT_N2H_U16(*(uint16_t*)(cpPacket+16));
1288 offset += 4;
1289 }
1290 if (uEthType == RTNET_ETHERTYPE_ARP)
1291 {
1292 Log4(("\tARP\n"));
1293 return;
1294 }
1295 else if (uEthType == RTNET_ETHERTYPE_IPV4)
1296 {
1297 PRTNETIPV4 pHdr = (PRTNETIPV4)(cpPacket + offset);
1298 offset += pHdr->ip_hl * 4;
1299 protocol = pHdr->ip_p;
1300 Log4(("\tIPv4: %RTnaipv4 => %RTnaipv4\n", pHdr->ip_src, pHdr->ip_dst));
1301 }
1302 else if (uEthType == RTNET_ETHERTYPE_IPV6)
1303 {
1304 PRTNETIPV6 pHdr = (PRTNETIPV6)(cpPacket + offset);
1305 protocol = pHdr->ip6_nxt;
1306 offset += sizeof(RTNETIPV6);
1307 if (protocol == 0 || protocol == 60)
1308 {
1309 /* Skip hop-by-hop and destination options */
1310 while (cpPacket[offset] == 0 || cpPacket[offset] == 60)
1311 offset += 8 * (1 + cpPacket[offset+1]);
1312 protocol = cpPacket[offset];
1313 offset += 8 * (1 + cpPacket[offset+1]);
1314 }
1315 Log4(("\tIPv6: %RTnaipv6 => %RTnaipv6\n", pHdr->ip6_src, pHdr->ip6_dst));
1316 }
1317 else
1318 {
1319 Log4(("\tEthernet: 0x%04x\n", uEthType));
1320 return;
1321 }
1322 switch (protocol)
1323 {
1324 case 1: Log4(("\tICMP\n")); break;
1325 case 2: Log4(("\tIGMP\n")); break;
1326 case 58: Log4(("\tICMPv6\n")); break;
1327
1328 case 6:
1329 {
1330 PRTNETTCP pTcp = (PRTNETTCP)(cpPacket + offset);
1331 Log4(("\tTCP: %u => %u, seq=%u ack=%u\n", RT_N2H_U16(pTcp->th_sport), RT_N2H_U16(pTcp->th_dport),
1332 RT_N2H_U32(pTcp->th_seq), RT_N2H_U32(pTcp->th_ack)));
1333 }
1334 break;
1335 case 17:
1336 {
1337 PRTNETUDP pUdp = (PRTNETUDP)(cpPacket + offset);
1338 Log4(("\tUDP: %u => %u\n", RT_N2H_U16(pUdp->uh_sport), RT_N2H_U16(pUdp->uh_dport)));
1339 }
1340 break;
1341 default:
1342 Log4(("\tUnknown (%u)", protocol));
1343 break;
1344 }
1345}
1346
1347DECLINLINE(void) usbNetPacketDump(PUSBNET pThis, const void *pvBuf, size_t cb, const char *pcszText)
1348{
1349 const uint8_t *cpPacket = (const uint8_t *)pvBuf;
1350 if (cb < 14)
1351 Log3(("/#%u/ %s packet #%d is too small (%u bytes):\n%.*Rhxd\n",
1352 pThis->pUsbIns->iInstance, pcszText, ++pThis->u32PktNo, (uint32_t)cb, (uint32_t)cb, cpPacket));
1353 else
1354 {
1355 Log3(("/#%u/ %s packet #%d, %u bytes, %RTmac => %RTmac\n",
1356 pThis->pUsbIns->iInstance, pcszText, ++pThis->u32PktNo, (uint32_t)cb, cpPacket+6, cpPacket));
1357 if (LogIs4Enabled())
1358 usbNetProtocolDump(cpPacket, (uint32_t)cb);
1359 Log5(("%.*Rhxd\n", (uint32_t)cb, cpPacket));
1360 }
1361}
1362
1363#else
1364#define usbNetPacketDump(pUsbIns, pvBuf, cb, pcszText)
1365#endif
1366
1367/**
1368 * Receive data and pass it to lwIP for processing.
1369 *
1370 * @returns VBox status code
1371 * @param pInterface PDM network port interface pointer.
1372 * @param pvBuf Pointer to frame data.
1373 * @param cb Frame size.
1374 */
1375static DECLCALLBACK(int) usbNetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
1376{
1377 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkDown);
1378
1379 LogFlowFunc(("/#%u/ pInterface=%p cb=%u\n", pThis->pUsbIns->iInstance, pInterface, cb));
1380 RTCritSectEnter(&pThis->CritSect);
1381
1382 if (usbNetQueueIsEmpty(&pThis->ToHostQueue) || pThis->fSuspended)
1383 {
1384 RTCritSectLeave(&pThis->CritSect);
1385 LogFlowFunc(("/#%u/ return %Rrc due to %s\n", pThis->pUsbIns->iInstance, VINF_SUCCESS, pThis->fSuspended ? "being suspended" : "empty host queue"));
1386 return VINF_SUCCESS;
1387 }
1388
1389 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->ToHostQueue);
1390 PUSBNETEP pEp = &pThis->aEps[2];
1391
1392 if (RT_UNLIKELY(pEp->fHalted))
1393 {
1394 usbNetCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1395 RTCritSectLeave(&pThis->CritSect);
1396 return VINF_SUCCESS;
1397 }
1398
1399 if (pUrb->cbData < sizeof(USBNCMNTH16) + sizeof(USBNCMNDP16) + cb)
1400 {
1401 LogFunc(("/#%u/ Receive URB too small (%#x vs %#x)\n", pThis->pUsbIns->iInstance, pUrb->cbData,
1402 sizeof(USBNCMNTH16) + sizeof(USBNCMNDP16) + cb));
1403 pUrb->enmStatus = VUSBSTATUS_DATA_OVERRUN;
1404 usbNetLinkDone(pThis, pUrb);
1405 RTCritSectLeave(&pThis->CritSect);
1406 return VINF_SUCCESS;
1407 }
1408
1409 usbNetPacketDump(pThis, pvBuf, cb, "<-- Rx");
1410
1411 PUSBNCMNTH16 pNth16 = (PUSBNCMNTH16)&pUrb->abData[0];
1412 PUSBNCMNDP16 pNdp16 = (PUSBNCMNDP16)(pNth16 + 1);
1413
1414 /* Build NTH16. */
1415 pNth16->dwSignature = USBNCMNTH16_SIGNATURE;
1416 pNth16->wHeaderLength = sizeof(*pNth16);
1417 pNth16->wSequence = pThis->idSequence++;
1418 pNth16->wBlockLength = (uint16_t)(sizeof(*pNth16) + sizeof(*pNdp16) + cb);
1419 pNth16->wNdpIndex = sizeof(*pNth16);
1420
1421 /* Build NDP16. */
1422 pNdp16->dwSignature = USBNCMNDP16_SIGNATURE_NCM0;
1423 pNdp16->wLength = sizeof(*pNdp16);
1424 pNdp16->wNextNdpIndex = 0;
1425 pNdp16->DataGram0.wDatagramIndex = sizeof(*pNth16) + sizeof(*pNdp16);
1426 pNdp16->DataGram0.wDatagramLength = (uint16_t)cb;
1427 pNdp16->DataGram1.wDatagramIndex = 0;
1428 pNdp16->DataGram1.wDatagramLength = 0;
1429
1430 /* Copy frame over. */
1431 memcpy(pNdp16 + 1, pvBuf, cb);
1432
1433 pUrb->cbData = (uint32_t)(sizeof(*pNth16) + sizeof(*pNdp16) + cb);
1434 usbNetLinkDone(pThis, pUrb);
1435 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb);
1436 RTCritSectLeave(&pThis->CritSect);
1437
1438 LogFlowFunc(("/#%u/ return %Rrc\n", pThis->pUsbIns->iInstance, VINF_SUCCESS));
1439 return VINF_SUCCESS;
1440}
1441
1442/**
1443 * @interface_method_impl{PDMINETWORKDOWN,pfnXmitPending}
1444 */
1445static DECLCALLBACK(void) usbNetNetworkDown_XmitPending(PPDMINETWORKDOWN pInterface)
1446{
1447 RT_NOREF(pInterface);
1448#ifdef LOG_ENABLED
1449 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkDown);
1450 LogFlowFunc(("/#%u/ pInterface=%p\n", pThis->pUsbIns->iInstance, pInterface));
1451#endif
1452}
1453
1454
1455/* -=-=-=-=-=- USBNET::INetworkConfig -=-=-=-=-=- */
1456
1457/**
1458 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetMac}
1459 */
1460static DECLCALLBACK(int) usbNetGetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
1461{
1462 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1463
1464 LogFlowFunc(("/#%u/\n", pThis->pUsbIns->iInstance));
1465 memcpy(pMac, &pThis->MacConfigured, sizeof(*pMac));
1466 return VINF_SUCCESS;
1467}
1468
1469
1470/**
1471 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState}
1472 */
1473static DECLCALLBACK(PDMNETWORKLINKSTATE) usbNetGetLinkState(PPDMINETWORKCONFIG pInterface)
1474{
1475 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1476
1477 LogFlowFunc(("/#%u/\n", pThis->pUsbIns->iInstance));
1478 if (pThis->fLinkUp && !pThis->fLinkTempDown)
1479 return PDMNETWORKLINKSTATE_UP;
1480 if (!pThis->fLinkUp)
1481 return PDMNETWORKLINKSTATE_DOWN;
1482 if (pThis->fLinkTempDown)
1483 return PDMNETWORKLINKSTATE_DOWN_RESUME;
1484 AssertMsgFailed(("Invalid link state!\n"));
1485 return PDMNETWORKLINKSTATE_INVALID;
1486}
1487
1488
1489DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState);
1490
1491/**
1492 * @callback_method_impl{FNTMTIMERUSB}
1493 *
1494 * By the time the host resumes after sleep the network environment may have changed considerably.
1495 * We handle this by temporarily lowering the link state. This callback brings the link back up.
1496 */
1497static DECLCALLBACK(void) usbNetTimerLinkUp(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, void *pvUser)
1498{
1499 PUSBNET pThis = (PUSBNET)pvUser;
1500 RT_NOREF(pUsbIns, hTimer);
1501
1502 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
1503
1504 /** @todo Do we really care for potential races with link state? */
1505 pThis->fLinkTempDown = false;
1506 if (!pThis->fLinkUp)
1507 usbNetLinkStateNotify(pThis, PDMNETWORKLINKSTATE_UP);
1508}
1509
1510
1511/**
1512 * @interface_method_impl{PDMINETWORKCONFIG,pfnSetLinkState}
1513 */
1514static DECLCALLBACK(int) usbNetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
1515{
1516 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1517
1518 bool fLinkUp = enmState == PDMNETWORKLINKSTATE_UP;
1519
1520 LogFlowFunc(("/#%u/ enmState=%d\n", pThis->pUsbIns->iInstance, enmState));
1521 AssertMsgReturn(enmState > PDMNETWORKLINKSTATE_INVALID && enmState <= PDMNETWORKLINKSTATE_DOWN_RESUME,
1522 ("Invalid link state: enmState=%d\n", enmState), VERR_INVALID_PARAMETER);
1523
1524 if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
1525 {
1526 pThis->fLinkTempDown = true;
1527 /* Do not bother to notify anyone if the link has been down */
1528 PDMUsbHlpTimerSetMillies(pThis->pUsbIns, pThis->hTimerLinkUp, 500); /* 0.5 sec */
1529 }
1530 /* has the state changed? */
1531 if (pThis->fLinkUp != fLinkUp)
1532 {
1533 pThis->fLinkUp = fLinkUp;
1534 usbNetLinkStateNotify(pThis, enmState);
1535 }
1536 return VINF_SUCCESS;
1537}
1538
1539
1540
1541/**
1542 * @interface_method_impl{PDMUSBREG,pfnUrbReap}
1543 */
1544static DECLCALLBACK(PVUSBURB) usbNetUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
1545{
1546 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1547 LogFlowFunc(("/#%u/ cMillies=%u\n", pUsbIns->iInstance, cMillies));
1548
1549 RTCritSectEnter(&pThis->CritSect);
1550
1551 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->DoneQueue);
1552 if (!pUrb && cMillies)
1553 {
1554 /* Wait */
1555 pThis->fHaveDoneQueueWaiter = true;
1556 RTCritSectLeave(&pThis->CritSect);
1557
1558 RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
1559
1560 RTCritSectEnter(&pThis->CritSect);
1561 pThis->fHaveDoneQueueWaiter = false;
1562
1563 pUrb = usbNetQueueRemoveHead(&pThis->DoneQueue);
1564 }
1565
1566 RTCritSectLeave(&pThis->CritSect);
1567
1568 if (pUrb)
1569 Log2Func(("/#%u/ pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1570 return pUrb;
1571}
1572
1573
1574/**
1575 * @interface_method_impl{PDMUSBREG,pfnWakeup}
1576 */
1577static DECLCALLBACK(int) usbNetWakeup(PPDMUSBINS pUsbIns)
1578{
1579 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1580 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
1581
1582 return RTSemEventSignal(pThis->hEvtDoneQueue);
1583}
1584
1585
1586/**
1587 * @interface_method_impl{PDMUSBREG,pfnUrbCancel}
1588 */
1589static DECLCALLBACK(int) usbNetUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1590{
1591 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1592 LogFlowFunc(("/#%u/ pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1593 RTCritSectEnter(&pThis->CritSect);
1594
1595 /*
1596 * Remove the URB from the to-host queue and move it onto the done queue.
1597 */
1598 if (usbNetQueueRemove(&pThis->ToHostQueue, pUrb))
1599 usbNetLinkDone(pThis, pUrb);
1600
1601 if (usbNetQueueRemove(&pThis->ToHostIntrQueue, pUrb))
1602 usbNetLinkDone(pThis, pUrb);
1603
1604 RTCritSectLeave(&pThis->CritSect);
1605 return VINF_SUCCESS;
1606}
1607
1608
1609/**
1610 * Handle requests sent to the outbound (to device) bulk pipe.
1611 */
1612static int usbNetHandleBulkHostToDev(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1613{
1614 /*
1615 * Stall the request if the pipe is halted.
1616 */
1617 if (RT_UNLIKELY(pEp->fHalted))
1618 return usbNetCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1619
1620 /*
1621 * Process the transfer.
1622 */
1623 PCUSBNCMNTH16 pNth16 = (PCUSBNCMNTH16)&pUrb->abData[0];
1624 if (pUrb->cbData < sizeof(*pNth16))
1625 {
1626 LogFunc(("/#%u/ Bad NTH16: cbData=%#x < min=%#x\n", pThis->pUsbIns->iInstance, pUrb->cbData, sizeof(*pNth16) ));
1627 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NTH16");
1628 }
1629 if (pNth16->dwSignature != USBNCMNTH16_SIGNATURE)
1630 {
1631 LogFunc(("/#%u/ NTH16: Invalid dwSignature value: %#x\n", pThis->pUsbIns->iInstance, pNth16->dwSignature));
1632 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1633 }
1634 Log2Func(("/#%u/ NTH16: wHeaderLength=%#x wSequence=%#x wBlockLength=%#x wNdpIndex=%#x cbData=%#x fShortNotOk=%RTbool\n", pThis->pUsbIns->iInstance,
1635 pNth16->wHeaderLength, pNth16->wSequence, pNth16->wBlockLength, pNth16->wNdpIndex, pUrb->cbData, pUrb->fShortNotOk));
1636 if (pNth16->wHeaderLength != sizeof(*pNth16))
1637 {
1638 LogFunc(("/#%u/ NTH16: Bad wHeaderLength value: %#x\n", pThis->pUsbIns->iInstance, pNth16->wHeaderLength));
1639 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1640
1641 }
1642 if (pNth16->wBlockLength > pUrb->cbData)
1643 {
1644 LogFunc(("/#%u/ NTH16: Bad wBlockLength value: %#x\n", pThis->pUsbIns->iInstance, pNth16->wBlockLength));
1645 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1646 }
1647
1648 if (pNth16->wNdpIndex < sizeof(*pNth16))
1649 {
1650 LogFunc(("/#%u/ NTH16: wNdpIndex is too small: %#x (%u), at least required %#x\n", pThis->pUsbIns->iInstance,
1651 pNth16->wNdpIndex, pNth16->wNdpIndex, sizeof(*pNth16) ));
1652 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1653 }
1654
1655 /* Walk the NDPs and process the datagrams. */
1656 uint16_t offNdp16Next = pNth16->wNdpIndex;
1657 while (offNdp16Next)
1658 {
1659 if (offNdp16Next >= pUrb->cbData)
1660 {
1661 LogFunc(("/#%u/ Bad NDP16: offNdp16Next=%#x >= cbData=%#x\n", pThis->pUsbIns->iInstance, offNdp16Next, pUrb->cbData));
1662 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NDP16");
1663 }
1664
1665 size_t cbNdpMax = pUrb->cbData - offNdp16Next;
1666 PCUSBNCMNDP16 pNdp16 = (PCUSBNCMNDP16)&pUrb->abData[pNth16->wNdpIndex];
1667 if (cbNdpMax < sizeof(*pNdp16))
1668 {
1669 LogFunc(("/#%u/ Bad NDP16: cbNdpMax=%#x < min=%#x\n", pThis->pUsbIns->iInstance, cbNdpMax, sizeof(*pNdp16) ));
1670 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NDP16");
1671 }
1672
1673 if ( pNdp16->dwSignature != USBNCMNDP16_SIGNATURE_NCM0
1674 && pNdp16->dwSignature != USBNCMNDP16_SIGNATURE_NCM1)
1675 {
1676 LogFunc(("/#%u/ NDP16: Invalid dwSignature value: %#x\n", pThis->pUsbIns->iInstance, pNdp16->dwSignature));
1677 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1678 }
1679
1680 if ( pNdp16->wLength < sizeof(*pNdp16)
1681 || (pNdp16->wLength & 0x3)
1682 || pNdp16->wLength > cbNdpMax)
1683 {
1684 LogFunc(("/#%u/ NDP16: Invalid size value: %#x, req. (min %#x max %#x)\n", pThis->pUsbIns->iInstance,
1685 pNdp16->wLength, sizeof(*pNdp16), cbNdpMax));
1686 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1687 }
1688
1689 if (pNdp16->dwSignature == USBNCMNDP16_SIGNATURE_NCM0)
1690 {
1691 PCUSBNCMNDP16DGRAM pDGram = &pNdp16->DataGram0;
1692 size_t cEntries = 2 + (pNdp16->wLength - (sizeof(*pNdp16))) / sizeof(*pDGram);
1693
1694 int rc = pThis->Lun0.pINetwork->pfnBeginXmit(pThis->Lun0.pINetwork, true /* fOnWorkerThread */);
1695 if (RT_FAILURE(rc))
1696 return usbNetCompleteStall(pThis, NULL, pUrb, "BeginXmit failed");
1697
1698 for (uint32_t i = 0; i < cEntries; i++)
1699 {
1700 /* Either 0 element marks end of list. */
1701 if ( pDGram->wDatagramIndex == 0
1702 || pDGram->wDatagramLength == 0)
1703 break;
1704
1705 if ( pDGram->wDatagramIndex < sizeof(*pNth16)
1706 || pDGram->wDatagramIndex >= pUrb->cbData)
1707 {
1708 LogFunc(("/#%u/ DGRAM16: Invalid wDatagramIndex value: %#x\n", pThis->pUsbIns->iInstance, pDGram->wDatagramIndex));
1709 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad DGRAM16");
1710 }
1711
1712 if (pUrb->cbData - pDGram->wDatagramIndex < pDGram->wDatagramLength)
1713 {
1714 LogFunc(("/#%u/ DGRAM16: Invalid wDatagramLength value: %#x (max %#x)\n", pThis->pUsbIns->iInstance,
1715 pDGram->wDatagramLength, pUrb->cbData - pDGram->wDatagramIndex));
1716 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad DGRAM16");
1717 }
1718
1719 PPDMSCATTERGATHER pSgBuf;
1720 rc = pThis->Lun0.pINetwork->pfnAllocBuf(pThis->Lun0.pINetwork, pDGram->wDatagramLength, NULL /*pGso*/, &pSgBuf);
1721 if (RT_SUCCESS(rc) && pSgBuf)
1722 {
1723 uint8_t *pbBuf = (uint8_t *)pSgBuf->aSegs[0].pvSeg;
1724 memcpy(pbBuf, &pUrb->abData[pDGram->wDatagramIndex], pDGram->wDatagramLength);
1725 usbNetPacketDump(pThis, pbBuf, pDGram->wDatagramLength, "--> Tx");
1726 pSgBuf->cbUsed = pDGram->wDatagramLength;
1727 rc = pThis->Lun0.pINetwork->pfnSendBuf(pThis->Lun0.pINetwork, pSgBuf, true /* fOnWorkerThread */);
1728 if (RT_FAILURE(rc))
1729 return usbNetCompleteStall(pThis, NULL, pUrb, "SendBuf failed");
1730 STAM_REL_COUNTER_ADD(&pThis->StatTransmitBytes, pDGram->wDatagramLength);
1731 }
1732 else
1733 return usbNetCompleteStall(pThis, NULL, pUrb, "AllocBuf failed");
1734
1735 pDGram++;
1736 }
1737
1738 pThis->Lun0.pINetwork->pfnEndXmit(pThis->Lun0.pINetwork);
1739 }
1740 else
1741 {
1742 LogFunc(("/#%u/ NDP16: Not implemented\n", pThis->pUsbIns->iInstance));
1743 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1744 }
1745
1746 offNdp16Next = pNdp16->wNextNdpIndex;
1747 }
1748
1749 return usbNetCompleteOk(pThis, pUrb, pUrb->cbData);
1750}
1751
1752
1753/**
1754 * Handle requests sent to the inbound (to host) bulk pipe.
1755 */
1756static int usbNetHandleBulkDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1757{
1758 /*
1759 * Stall the request if the pipe is halted OR if there is no
1760 * pending request yet.
1761 */
1762 if (RT_UNLIKELY(pEp->fHalted))
1763 return usbNetCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
1764
1765 usbNetQueueAddTail(&pThis->ToHostQueue, pUrb);
1766 if (pThis->fHaveToHostQueueWaiter)
1767 RTSemEventSignal(pThis->hEvtToHostQueue);
1768
1769 LogFlowFunc(("/#%u/ Added %p:%s to the to-host queue\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1770 return VINF_SUCCESS;
1771}
1772
1773
1774/**
1775 * Handle requests sent to the inbound (to host) interrupt pipe.
1776 */
1777static int usbNetHandleIntrDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1778{
1779 /* Stall the request if the pipe is halted. */
1780 if (RT_UNLIKELY(pEp->fHalted))
1781 return usbNetCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
1782
1783 /* CONNECTION_SPEED_CHANGE is sent first, followed by NETWORK_CONNECTION. See [NCM10] (section 7.1) */
1784 if (!pThis->fInitialSpeedChangeSent)
1785 {
1786 USBCDCNOTIFICICATIONSPEEDCHG SpeedChange;
1787 SpeedChange.Hdr.bmRequestType = 0xa1;
1788 SpeedChange.Hdr.bNotificationCode = USB_CDC_NOTIFICATION_CODE_CONNECTION_SPEED_CHANGE;
1789 SpeedChange.Hdr.wValue = 0;
1790 SpeedChange.Hdr.wIndex = 0;
1791 SpeedChange.Hdr.wLength = 8;
1792 SpeedChange.DLBitRate = UINT32_MAX;
1793 SpeedChange.ULBitRate = UINT32_MAX;
1794 usbNetCompleteNotificationOk(pThis, pUrb, &SpeedChange, sizeof(SpeedChange));
1795 pThis->fInitialSpeedChangeSent = true;
1796 }
1797 else if (!pThis->fInitialLinkStatusSent)
1798 {
1799 USBCDCNOTIFICICATION LinkNotification;
1800 LinkNotification.bmRequestType = 0xa1;
1801 LinkNotification.bNotificationCode = USB_CDC_NOTIFICATION_CODE_NETWORK_CONNECTION;
1802 LinkNotification.wValue = pThis->fLinkUp ? 1 : 0;
1803 LinkNotification.wIndex = 0;
1804 LinkNotification.wLength = 0;
1805 usbNetCompleteNotificationOk(pThis, pUrb, &LinkNotification, sizeof(LinkNotification));
1806 pThis->fInitialLinkStatusSent = true;
1807 }
1808 else
1809 usbNetQueueAddTail(&pThis->ToHostIntrQueue, pUrb);
1810
1811 LogFlowFunc(("/#%u/ Added %p:%s to the to-host interrupt queue\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1812 return VINF_SUCCESS;
1813}
1814
1815
1816/**
1817 * Notifies both the guest and the network/driver of link state changes.
1818 *
1819 * @param pThis The UsbNet instance.
1820 * @param enmLinkState The new link state.
1821 */
1822DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState)
1823{
1824 LogFlowFunc(("/#%u/ enmLinkState=%d\n", pThis->pUsbIns->iInstance, enmLinkState));
1825 RTCritSectEnter(&pThis->CritSect);
1826 /* Trigger notifications */
1827 pThis->fInitialLinkStatusSent = false;
1828 pThis->fInitialSpeedChangeSent = false;
1829 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->ToHostIntrQueue);
1830 /* If there is a request pending, use it. Otherwise the host should poll us soon. */
1831 if (pUrb)
1832 usbNetHandleIntrDevToHost(pThis, &pThis->aEps[3], pUrb);
1833 RTCritSectLeave(&pThis->CritSect);
1834 /* Always notify our network when notifying the guest. */
1835 if (pThis->Lun0.pINetwork)
1836 pThis->Lun0.pINetwork->pfnNotifyLinkChanged(pThis->Lun0.pINetwork, enmLinkState);
1837}
1838
1839
1840/**
1841 * Handles request send to the default control pipe.
1842 */
1843static int usbNetHandleDefaultPipe(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1844{
1845 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1846 AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
1847
1848 if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
1849 {
1850 switch (pSetup->bRequest)
1851 {
1852 case VUSB_REQ_GET_DESCRIPTOR:
1853 {
1854 if (pSetup->bmRequestType != (VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST))
1855 {
1856 LogFunc(("/#%u/ Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pThis->pUsbIns->iInstance, pSetup->bmRequestType));
1857 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
1858 }
1859
1860 switch (pSetup->wValue >> 8)
1861 {
1862 uint32_t cbCopy;
1863
1864 case VUSB_DT_STRING:
1865 LogFunc(("/#%u/ GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pThis->pUsbIns->iInstance, pSetup->wValue, pSetup->wIndex));
1866 break;
1867 case VUSB_DT_DEVICE_QUALIFIER:
1868 LogFunc(("/#%u/ GET_DESCRIPTOR DT_DEVICE_QUALIFIER wValue=%#x wIndex=%#x\n", pThis->pUsbIns->iInstance, pSetup->wValue, pSetup->wIndex));
1869 /* Returned data is written after the setup message. */
1870 cbCopy = pUrb->cbData - sizeof(*pSetup);
1871 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbNetDeviceQualifier));
1872 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbNetDeviceQualifier, cbCopy);
1873 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1874 case VUSB_DT_BOS:
1875 LogFunc(("/#%u/ GET_DESCRIPTOR DT_BOS wValue=%#x wIndex=%#x\n", pThis->pUsbIns->iInstance, pSetup->wValue, pSetup->wIndex));
1876 /* Returned data is written after the setup message. */
1877 cbCopy = pUrb->cbData - sizeof(*pSetup);
1878 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbNetBOS));
1879 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbNetBOS, cbCopy);
1880 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1881 default:
1882 LogFunc(("/#%u/ GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pThis->pUsbIns->iInstance, pSetup->wValue, pSetup->wIndex));
1883 break;
1884 }
1885 break;
1886 }
1887
1888 case VUSB_REQ_GET_STATUS:
1889 {
1890 uint16_t wRet = 0;
1891 size_t cbCopy = 0;
1892
1893 if (pSetup->wLength != 2)
1894 {
1895 LogRelFlow(("UsbNet: Bad GET_STATUS req: wLength=%#x\n",
1896 pSetup->wLength));
1897 break;
1898 }
1899 Assert(pSetup->wValue == 0);
1900 switch (pSetup->bmRequestType)
1901 {
1902 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1903 {
1904 Assert(pSetup->wIndex == 0);
1905 LogRelFlow(("UsbNet: GET_STATUS (device)\n"));
1906 wRet = 0; /* Not self-powered, no remote wakeup. */
1907 cbCopy = pUrb->cbData - sizeof(*pSetup);
1908 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1909 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1910 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1911 }
1912
1913 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1914 {
1915 if (pSetup->wIndex == 0)
1916 {
1917 cbCopy = pUrb->cbData - sizeof(*pSetup);
1918 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1919 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1920 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1921 }
1922 LogRelFlow(("UsbNet: GET_STATUS (interface) invalid, wIndex=%#x\n", pSetup->wIndex));
1923 break;
1924 }
1925
1926 case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1927 {
1928 if (pSetup->wIndex < RT_ELEMENTS(pThis->aEps))
1929 {
1930 wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
1931 cbCopy = pUrb->cbData - sizeof(*pSetup);
1932 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1933 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1934 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1935 }
1936 LogRelFlow(("UsbNet: GET_STATUS (endpoint) invalid, wIndex=%#x\n", pSetup->wIndex));
1937 break;
1938 }
1939
1940 default:
1941 LogRelFlow(("UsbNet: Bad GET_STATUS req: bmRequestType=%#x\n",
1942 pSetup->bmRequestType));
1943 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
1944 }
1945 break;
1946 }
1947
1948 case 0x31:
1949 break;
1950
1951 case VUSB_REQ_CLEAR_FEATURE:
1952 break;
1953 }
1954
1955 /** @todo implement this. */
1956 LogFunc(("/#%u/ Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", pThis->pUsbIns->iInstance,
1957 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1958
1959 usbNetCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
1960 }
1961 else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS)
1962 {
1963 switch (pSetup->bRequest)
1964 {
1965 case VUSB_REQ_GET_NTB_PARAMETERS:
1966 {
1967 if (pSetup->bmRequestType != (VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_HOST))
1968 {
1969 LogFunc(("/#%u/ Bad GET_NTB_PARAMETERS req: bmRequestType=%#x\n", pThis->pUsbIns->iInstance, pSetup->bmRequestType));
1970 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_NTB_PARAMETERS");
1971 }
1972
1973 USBNCMNTBPARAMS NtbParams;
1974
1975 NtbParams.wLength = sizeof(NtbParams);
1976 NtbParams.bmNtbFormatsSupported = RT_BIT(0);
1977 NtbParams.dwNtbInMaxSize = _4K;
1978 NtbParams.wNdpInDivisor = 4;
1979 NtbParams.wNdpInPayloadRemainder = 4;
1980 NtbParams.wNdpInAlignment = 4;
1981 NtbParams.u16Rsvd0 = 0;
1982 NtbParams.dwNtbOutMaxSize = _4K;
1983 NtbParams.wNdpOutDivisor = 4;
1984 NtbParams.wNdpOutPayloadRemainder = 4;
1985 NtbParams.wNdpOutAlignment = 4;
1986 NtbParams.wNtpOutMaxDatagrams = 1;
1987
1988 uint32_t cbCopy = pUrb->cbData - sizeof(*pSetup);
1989 cbCopy = RT_MIN(cbCopy, sizeof(NtbParams));
1990 memcpy(&pUrb->abData[sizeof(*pSetup)], &NtbParams, cbCopy);
1991 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1992 }
1993
1994 case VUSB_REQ_CLEAR_FEATURE:
1995 break;
1996 }
1997
1998 usbNetCompleteStall(pThis, pEp, pUrb, "CLASS_REQ");
1999 }
2000 else
2001 {
2002 LogFunc(("/#%u/ Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", pThis->pUsbIns->iInstance,
2003 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
2004 return usbNetCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
2005 }
2006
2007 return VINF_SUCCESS;
2008}
2009
2010
2011/**
2012 * @interface_method_impl{PDMUSBREG,pfnUrbQueue}
2013 */
2014static DECLCALLBACK(int) usbNetQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
2015{
2016 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2017 LogFlowFunc(("/#%u/ pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
2018 RTCritSectEnter(&pThis->CritSect);
2019
2020 /*
2021 * Parse on a per end-point basis.
2022 */
2023 int rc;
2024 switch (pUrb->EndPt)
2025 {
2026 case 0:
2027 rc = usbNetHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
2028 break;
2029
2030 case 0x81:
2031 AssertFailed();
2032 RT_FALL_THRU();
2033 case 0x01:
2034 rc = usbNetHandleBulkDevToHost(pThis, &pThis->aEps[1], pUrb);
2035 break;
2036
2037 case 0x02:
2038 rc = usbNetHandleBulkHostToDev(pThis, &pThis->aEps[2], pUrb);
2039 break;
2040
2041 case 0x03:
2042 rc = usbNetHandleIntrDevToHost(pThis, &pThis->aEps[3], pUrb);
2043 break;
2044
2045 default:
2046 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
2047 rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
2048 break;
2049 }
2050
2051 RTCritSectLeave(&pThis->CritSect);
2052 return rc;
2053}
2054
2055
2056/**
2057 * @interface_method_impl{PDMUSBREG,pfnUsbClearHaltedEndpoint}
2058 */
2059static DECLCALLBACK(int) usbNetUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
2060{
2061 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2062 LogFlowFunc(("/#%u/ uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
2063
2064 if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
2065 {
2066 RTCritSectEnter(&pThis->CritSect);
2067 pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
2068 RTCritSectLeave(&pThis->CritSect);
2069 }
2070
2071 return VINF_SUCCESS;
2072}
2073
2074
2075/**
2076 * @interface_method_impl{PDMUSBREG,pfnUsbSetInterface}
2077 */
2078static DECLCALLBACK(int) usbNetUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
2079{
2080 RT_NOREF(bInterfaceNumber);
2081 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2082 LogFlowFunc(("/#%u/ bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
2083 Assert(bAlternateSetting == 0 || bAlternateSetting == 1);
2084 if (pThis->bAlternateSetting != bAlternateSetting)
2085 {
2086 if (bAlternateSetting == 0)
2087 {
2088 /* This is some kind of reset. */
2089 usbNetResetWorker(pThis, NULL, true /*fSetConfig*/);
2090 }
2091 else
2092 {
2093 Assert(bAlternateSetting == 1);
2094 /* Switching from configuration to data mode, need to send notifications. */
2095 pThis->fInitialLinkStatusSent = false;
2096 pThis->fInitialSpeedChangeSent = false;
2097 }
2098 pThis->bAlternateSetting = bAlternateSetting;
2099 }
2100 return VINF_SUCCESS;
2101}
2102
2103
2104/**
2105 * @interface_method_impl{PDMUSBREG,pfnUsbSetConfiguration}
2106 */
2107static DECLCALLBACK(int) usbNetUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
2108 const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
2109{
2110 RT_NOREF(pvOldCfgDesc, pvOldIfState, pvNewCfgDesc);
2111 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2112 LogFlowFunc(("/#%u/ bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
2113 Assert(bConfigurationValue == 1);
2114 RTCritSectEnter(&pThis->CritSect);
2115
2116 /*
2117 * If the same config is applied more than once, it's a kind of reset.
2118 */
2119 if (pThis->bConfigurationValue == bConfigurationValue)
2120 usbNetResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
2121 pThis->bConfigurationValue = bConfigurationValue;
2122
2123 RTCritSectLeave(&pThis->CritSect);
2124 return VINF_SUCCESS;
2125}
2126
2127
2128/**
2129 * @interface_method_impl{PDMUSBREG,pfnUsbGetDescriptorCache}
2130 */
2131static DECLCALLBACK(PCPDMUSBDESCCACHE) usbNetUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
2132{
2133 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2134 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2135 return &pThis->UsbDescCache;
2136}
2137
2138
2139/**
2140 * @interface_method_impl{PDMUSBREG,pfnUsbReset}
2141 */
2142static DECLCALLBACK(int) usbNetUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
2143{
2144 RT_NOREF(fResetOnLinux);
2145 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2146 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2147 RTCritSectEnter(&pThis->CritSect);
2148
2149 int rc = usbNetResetWorker(pThis, NULL, false /*fSetConfig*/);
2150
2151 RTCritSectLeave(&pThis->CritSect);
2152 return rc;
2153}
2154
2155
2156/**
2157 * @interface_method_impl{PDMUSBREG,pfnDriverAttach}
2158 */
2159static DECLCALLBACK(int) usbNetDriverAttach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
2160{
2161 RT_NOREF(fFlags);
2162 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2163
2164 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2165
2166 AssertMsg(iLUN == 0, ("UsbNet: No other LUN than 0 is supported\n"));
2167 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
2168 ("UsbNet: Device does not support hotplugging\n"));
2169
2170 /* the usual paranoia */
2171 AssertRelease(!pThis->Lun0.pIBase);
2172 AssertRelease(!pThis->Lun0.pINetwork);
2173
2174 /*
2175 * Try attach the network driver.
2176 */
2177 int rc = PDMUsbHlpDriverAttach(pUsbIns, iLUN, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, NULL);
2178 if (RT_SUCCESS(rc))
2179 {
2180 /* Get network interface. */
2181 pThis->Lun0.pINetwork = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMINETWORKUP);
2182 AssertMsgReturn(pThis->Lun0.pINetwork, ("Missing network interface below\n"), VERR_PDM_MISSING_INTERFACE);
2183 }
2184 else
2185 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", iLUN, rc));
2186
2187 if (RT_FAILURE(rc))
2188 {
2189 pThis->Lun0.pIBase = NULL;
2190 pThis->Lun0.pINetwork = NULL;
2191 }
2192
2193 return rc;
2194}
2195
2196
2197/**
2198 * @interface_method_impl{PDMUSBREG,pfnDriverDetach}
2199 */
2200static DECLCALLBACK(void) usbNetDriverDetach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
2201{
2202 RT_NOREF(iLUN, fFlags);
2203 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2204
2205 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2206
2207 AssertMsg(iLUN == 0, ("UsbNet: No other LUN than 0 is supported\n"));
2208 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
2209 ("UsbNet: Device does not support hotplugging\n"));
2210
2211 /*
2212 * Zero some important members.
2213 */
2214 pThis->Lun0.pIBase = NULL;
2215 pThis->Lun0.pINetwork = NULL;
2216}
2217
2218
2219/**
2220 * @interface_method_impl{PDMUSBREG,pfnVMReset}
2221 */
2222static DECLCALLBACK(void) usbNetVMReset(PPDMUSBINS pUsbIns)
2223{
2224 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2225
2226 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2227 int rc = usbNetResetWorker(pThis, NULL, false /*fSetConfig*/);
2228 AssertRC(rc);
2229}
2230
2231
2232 /**
2233 * @interface_method_impl{PDMUSBREG,pfnVMSuspend}
2234 */
2235static DECLCALLBACK(void) usbNetVMSuspend(PPDMUSBINS pUsbIns)
2236{
2237 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2238#ifdef LOG_ENABLED
2239 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
2240 VMSUSPENDREASON enmReason = pHlp->pfnVMGetSuspendReason(pUsbIns);
2241 LogFlowFunc(("/#%u/ enmReason=%u\n", pUsbIns->iInstance, enmReason));
2242#endif
2243 RTCritSectEnter(&pThis->CritSect);
2244 pThis->fSuspended = true;
2245 /* Unblock receive thread */
2246 RTSemEventSignal(pThis->hEvtToHostQueue);
2247 RTCritSectLeave(&pThis->CritSect);
2248}
2249
2250
2251/**
2252 * @interface_method_impl{PDMUSBREG,pfnVMResume}
2253 */
2254static DECLCALLBACK(void) usbNetVMResume(PPDMUSBINS pUsbIns)
2255{
2256 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2257#ifdef LOG_ENABLED
2258 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
2259 VMRESUMEREASON enmReason = pHlp->pfnVMGetResumeReason(pUsbIns);
2260 LogFlowFunc(("/#%u/ enmReason=%u\n", pUsbIns->iInstance, enmReason));
2261#endif
2262 RTCritSectEnter(&pThis->CritSect);
2263 pThis->fSuspended = false;
2264 RTCritSectLeave(&pThis->CritSect);
2265}
2266
2267
2268/**
2269 * @interface_method_impl{PDMUSBREG,pfnDestruct}
2270 */
2271static DECLCALLBACK(void) usbNetDestruct(PPDMUSBINS pUsbIns)
2272{
2273 PDMUSB_CHECK_VERSIONS_RETURN_VOID(pUsbIns);
2274 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2275 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2276
2277 PDMUsbHlpTimerDestroy(pUsbIns, pThis->hTimerLinkUp);
2278
2279 if (RTCritSectIsInitialized(&pThis->CritSect))
2280 {
2281 RTCritSectEnter(&pThis->CritSect);
2282 RTCritSectLeave(&pThis->CritSect);
2283 RTCritSectDelete(&pThis->CritSect);
2284 }
2285
2286 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
2287 {
2288 RTSemEventDestroy(pThis->hEvtDoneQueue);
2289 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2290 }
2291
2292 if (pThis->hEvtToHostQueue != NIL_RTSEMEVENT)
2293 {
2294 RTSemEventDestroy(pThis->hEvtToHostQueue);
2295 pThis->hEvtToHostQueue = NIL_RTSEMEVENT;
2296 }
2297
2298 if (pThis->hEvtReset != NIL_RTSEMEVENTMULTI)
2299 {
2300 RTSemEventMultiDestroy(pThis->hEvtReset);
2301 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2302 }
2303}
2304
2305
2306/**
2307 * @interface_method_impl{PDMUSBREG,pfnConstruct}
2308 */
2309static DECLCALLBACK(int) usbNetConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
2310{
2311 RT_NOREF(pCfgGlobal);
2312 PDMUSB_CHECK_VERSIONS_RETURN(pUsbIns);
2313 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2314 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
2315
2316 LogFlowFunc(("/#%u/\n", iInstance));
2317
2318 pThis->u32PktNo = 1;
2319 /*
2320 * Perform the basic structure initialization first so the destructor
2321 * will not misbehave.
2322 */
2323 pThis->pUsbIns = pUsbIns;
2324 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2325 pThis->hEvtToHostQueue = NIL_RTSEMEVENT;
2326 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2327 /* IBase */
2328 pThis->Lun0.IBase.pfnQueryInterface = usbNetLun0QueryInterface;
2329 /* INetworkPort */
2330 pThis->Lun0.INetworkDown.pfnWaitReceiveAvail = usbNetNetworkDown_WaitReceiveAvail;
2331 pThis->Lun0.INetworkDown.pfnReceive = usbNetNetworkDown_Receive;
2332 pThis->Lun0.INetworkDown.pfnXmitPending = usbNetNetworkDown_XmitPending;
2333 /* INetworkConfig */
2334 pThis->Lun0.INetworkConfig.pfnGetMac = usbNetGetMac;
2335 pThis->Lun0.INetworkConfig.pfnGetLinkState = usbNetGetLinkState;
2336 pThis->Lun0.INetworkConfig.pfnSetLinkState = usbNetSetLinkState;
2337
2338 usbNetQueueInit(&pThis->ToHostQueue);
2339 usbNetQueueInit(&pThis->ToHostIntrQueue);
2340 usbNetQueueInit(&pThis->DoneQueue);
2341
2342 int rc = RTCritSectInit(&pThis->CritSect);
2343 AssertRCReturn(rc, rc);
2344
2345 rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
2346 AssertRCReturn(rc, rc);
2347
2348 rc = RTSemEventCreate(&pThis->hEvtToHostQueue);
2349 AssertRCReturn(rc, rc);
2350
2351 rc = RTSemEventMultiCreate(&pThis->hEvtReset);
2352 AssertRCReturn(rc, rc);
2353
2354 /*
2355 * Validate and read the configuration.
2356 */
2357 rc = pHlp->pfnCFGMValidateConfig(pCfg, "/",
2358 "MAC|"
2359 "CableConnected|"
2360 "LinkUpDelay"
2361 , "Config", "UsbNet", iInstance);
2362 if (RT_FAILURE(rc))
2363 return rc;
2364
2365 /*
2366 * Read the configuration.
2367 */
2368 rc = pHlp->pfnCFGMQueryBytes(pCfg, "MAC", &pThis->MacConfigured, sizeof(pThis->MacConfigured));
2369 if (RT_FAILURE(rc))
2370 return PDMUSB_SET_ERROR(pUsbIns, rc,
2371 N_("Configuration error: Failed to get the \"MAC\" value"));
2372 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "CableConnected", &pThis->fLinkUp, true);
2373 if (RT_FAILURE(rc))
2374 return PDMUSB_SET_ERROR(pUsbIns, rc,
2375 N_("Configuration error: Failed to get the \"CableConnected\" value"));
2376
2377 /*
2378 * Attach the network driver.
2379 */
2380 rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, "Network Port");
2381 if (RT_FAILURE(rc))
2382 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("USBNET failed to attach network driver"));
2383 pThis->Lun0.pINetwork = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMINETWORKUP);
2384 if (!pThis->Lun0.pINetwork)
2385 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
2386 N_("USBNET failed to query the PDMINETWORKUP from the driver below it"));
2387
2388 /*
2389 * Create the timer for delaying of bringing the link up.
2390 */
2391 rc = PDMUsbHlpTimerCreate(pUsbIns, TMCLOCK_VIRTUAL, usbNetTimerLinkUp, pThis,
2392 TMTIMER_FLAGS_DEFAULT_CRIT_SECT,
2393 "Link Up", &pThis->hTimerLinkUp);
2394 AssertRCReturn(rc, rc);
2395
2396 /*
2397 * Build the USB descriptors.
2398 */
2399 pThis->aUsbStringsEnUs[0].idx = USBNET_STR_ID_MANUFACTURER;
2400 pThis->aUsbStringsEnUs[0].psz = "VirtualBox";
2401
2402 pThis->aUsbStringsEnUs[1].idx = USBNET_STR_ID_PRODUCT;
2403 pThis->aUsbStringsEnUs[1].psz = "USB Ethernet";
2404
2405 /* Build the MAC address. */
2406 ssize_t cch = RTStrPrintf2(&pThis->aszMac[0], sizeof(pThis->aszMac), "%#.6Rhxs", &pThis->MacConfigured);
2407 AssertReturn(cch + 1 == sizeof(pThis->aszMac), VERR_INTERNAL_ERROR_4);
2408
2409 pThis->aUsbStringsEnUs[2].idx = USBNET_STR_ID_MAC_ADDRESS;
2410 pThis->aUsbStringsEnUs[2].psz = &pThis->aszMac[0];
2411
2412 pThis->UsbLang.idLang = 0x0409; /* en_US. */
2413 pThis->UsbLang.cStrings = RT_ELEMENTS(pThis->aUsbStringsEnUs);
2414 pThis->UsbLang.paStrings = &pThis->aUsbStringsEnUs[0];
2415
2416 pThis->UsbDescCache.paLanguages = &pThis->UsbLang;
2417 pThis->UsbDescCache.cLanguages = 1;
2418 pThis->UsbDescCache.fUseCachedDescriptors = true;
2419 pThis->UsbDescCache.fUseCachedStringsDescriptors = true;
2420
2421 switch (pUsbIns->enmSpeed)
2422 {
2423 case VUSB_SPEED_SUPER:
2424 case VUSB_SPEED_SUPERPLUS:
2425 {
2426 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc30;
2427 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescSS;
2428 break;
2429 }
2430 case VUSB_SPEED_HIGH:
2431 {
2432 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc20;
2433 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescHS;
2434 break;
2435 }
2436 case VUSB_SPEED_FULL:
2437 case VUSB_SPEED_LOW:
2438 {
2439 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc20;
2440 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescFS;
2441 break;
2442 }
2443 default:
2444 AssertFailedReturn(VERR_INVALID_PARAMETER);
2445 }
2446
2447 /*
2448 * Register statistics.
2449 * The /Public/ bits are official and used by session info in the GUI.
2450 */
2451 PDMUsbHlpSTAMRegisterF(pUsbIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
2452 "Amount of data received", "/Public/NetAdapter/%u/BytesReceived", iInstance);
2453 PDMUsbHlpSTAMRegisterF(pUsbIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
2454 "Amount of data transmitted", "/Public/NetAdapter/%u/BytesTransmitted", iInstance);
2455 PDMUsbHlpSTAMRegisterF(pUsbIns, &pUsbIns->iInstance, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
2456 "Device instance number", "/Public/NetAdapter/%u/%s", iInstance, pUsbIns->pReg->szName);
2457
2458 return VINF_SUCCESS;
2459}
2460
2461
2462/**
2463 * The USB Communications Device Class, Network Control Model (CDC NCM) registration record.
2464 */
2465const PDMUSBREG g_UsbNet =
2466{
2467 /* u32Version */
2468 PDM_USBREG_VERSION,
2469 /* szName */
2470 "UsbNet",
2471 /* pszDescription */
2472 "USB Communications Device Class, one LUN.",
2473 /* fFlags */
2474 PDM_USBREG_HIGHSPEED_CAPABLE /*| PDM_USBREG_SUPERSPEED_CAPABLE */,
2475 /* cMaxInstances */
2476 ~0U,
2477 /* cbInstance */
2478 sizeof(USBNET),
2479 /* pfnConstruct */
2480 usbNetConstruct,
2481 /* pfnDestruct */
2482 usbNetDestruct,
2483 /* pfnVMInitComplete */
2484 NULL,
2485 /* pfnVMPowerOn */
2486 NULL,
2487 /* pfnVMReset */
2488 usbNetVMReset,
2489 /* pfnVMSuspend */
2490 usbNetVMSuspend,
2491 /* pfnVMResume */
2492 usbNetVMResume,
2493 /* pfnVMPowerOff */
2494 NULL,
2495 /* pfnHotPlugged */
2496 NULL,
2497 /* pfnHotUnplugged */
2498 NULL,
2499 /* pfnDriverAttach */
2500 usbNetDriverAttach,
2501 /* pfnDriverDetach */
2502 usbNetDriverDetach,
2503 /* pfnQueryInterface */
2504 NULL,
2505 /* pfnUsbReset */
2506 usbNetUsbReset,
2507 /* pfnUsbGetDescriptorCache */
2508 usbNetUsbGetDescriptorCache,
2509 /* pfnUsbSetConfiguration */
2510 usbNetUsbSetConfiguration,
2511 /* pfnUsbSetInterface */
2512 usbNetUsbSetInterface,
2513 /* pfnUsbClearHaltedEndpoint */
2514 usbNetUsbClearHaltedEndpoint,
2515 /* pfnUrbNew */
2516 NULL/*usbNetUrbNew*/,
2517 /* pfnQueue */
2518 usbNetQueue,
2519 /* pfnUrbCancel */
2520 usbNetUrbCancel,
2521 /* pfnUrbReap */
2522 usbNetUrbReap,
2523 /* pfnWakeup */
2524 usbNetWakeup,
2525 /* u32TheEnd */
2526 PDM_USBREG_VERSION
2527};
2528
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette