VirtualBox

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

Last change on this file since 108371 was 108371, checked in by vboxsync, 3 months ago

UsbNet: Minor logging enhancements, including packet dumping/numbering bugref:10779

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 89.4 KB
Line 
1/* $Id: UsbNet.cpp 108371 2025-02-25 13:57:42Z 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.215389.xyz.
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
1253 LogFlowFunc(("/#%u/ pInterface=%p cMillies=%u\n", pThis->pUsbIns->iInstance, pInterface, cMillies));
1254 RTCritSectEnter(&pThis->CritSect);
1255 if (!usbNetQueueIsEmpty(&pThis->ToHostQueue) || pThis->fSuspended)
1256 {
1257 RTCritSectLeave(&pThis->CritSect);
1258 return VINF_SUCCESS;
1259 }
1260 pThis->fHaveToHostQueueWaiter = true;
1261 RTCritSectLeave(&pThis->CritSect);
1262
1263 LogFlowFunc(("/#%u/ pInterface=%p waiting for hEvtToHostQueue\n", pThis->pUsbIns->iInstance, pInterface));
1264 int rc = RTSemEventWait(pThis->hEvtToHostQueue, cMillies);
1265 ASMAtomicXchgBool(&pThis->fHaveToHostQueueWaiter, false);
1266 LogFlowFunc(("/#%u/ pInterface=%p received hEvtToHostQueue\n", pThis->pUsbIns->iInstance, pInterface));
1267 return rc;
1268}
1269
1270#ifdef LOG_ENABLED
1271
1272DECLINLINE(void) usbNetProtocolDump(const uint8_t *cpPacket, uint32_t cb)
1273{
1274 RT_NOREF(cb);
1275 uint8_t protocol;
1276 uint16_t offset = sizeof(RTNETETHERHDR);
1277 uint16_t uEthType = RT_N2H_U16(*(uint16_t*)(cpPacket+12));
1278 if (uEthType == RTNET_ETHERTYPE_VLAN)
1279 {
1280 uEthType = RT_N2H_U16(*(uint16_t*)(cpPacket+16));
1281 offset += 4;
1282 }
1283 if (uEthType == RTNET_ETHERTYPE_ARP)
1284 {
1285 Log4(("\tARP\n"));
1286 return;
1287 }
1288 else if (uEthType == RTNET_ETHERTYPE_IPV4)
1289 {
1290 PRTNETIPV4 pHdr = (PRTNETIPV4)(cpPacket + offset);
1291 offset += pHdr->ip_hl * 4;
1292 protocol = pHdr->ip_p;
1293 Log4(("\tIPv4: %RTnaipv4 => %RTnaipv4\n", pHdr->ip_src, pHdr->ip_dst));
1294 }
1295 else if (uEthType == RTNET_ETHERTYPE_IPV6)
1296 {
1297 PRTNETIPV6 pHdr = (PRTNETIPV6)(cpPacket + offset);
1298 protocol = pHdr->ip6_nxt;
1299 offset += sizeof(RTNETIPV6);
1300 if (protocol == 0 || protocol == 60)
1301 {
1302 /* Skip hop-by-hop and destination options */
1303 while (cpPacket[offset] == 0 || cpPacket[offset] == 60)
1304 offset += 8 * (1 + cpPacket[offset+1]);
1305 protocol = cpPacket[offset];
1306 offset += 8 * (1 + cpPacket[offset+1]);
1307 }
1308 Log4(("\tIPv6: %RTnaipv6 => %RTnaipv6\n", pHdr->ip6_src, pHdr->ip6_dst));
1309 }
1310 else
1311 {
1312 Log4(("\tEthernet: 0x%04x\n", uEthType));
1313 return;
1314 }
1315 switch (protocol)
1316 {
1317 case 1: Log4(("\tICMP\n")); break;
1318 case 2: Log4(("\tIGMP\n")); break;
1319 case 58: Log4(("\tICMPv6\n")); break;
1320
1321 case 6:
1322 {
1323 PRTNETTCP pTcp = (PRTNETTCP)(cpPacket + offset);
1324 Log4(("\tTCP: %u => %u, seq=%u ack=%u\n", RT_N2H_U16(pTcp->th_sport), RT_N2H_U16(pTcp->th_dport),
1325 RT_N2H_U32(pTcp->th_seq), RT_N2H_U32(pTcp->th_ack)));
1326 }
1327 break;
1328 case 17:
1329 {
1330 PRTNETUDP pUdp = (PRTNETUDP)(cpPacket + offset);
1331 Log4(("\tUDP: %u => %u\n", RT_N2H_U16(pUdp->uh_sport), RT_N2H_U16(pUdp->uh_dport)));
1332 }
1333 break;
1334 default:
1335 Log4(("\tUnknown (%u)", protocol));
1336 break;
1337 }
1338}
1339
1340DECLINLINE(void) usbNetPacketDump(PUSBNET pThis, const void *pvBuf, size_t cb, const char *pcszText)
1341{
1342 const uint8_t *cpPacket = (const uint8_t *)pvBuf;
1343 if (cb < 14)
1344 Log3(("/#%u/ %s packet #%d is too small (%u bytes):\n%.*Rhxd\n",
1345 pThis->pUsbIns->iInstance, pcszText, ++pThis->u32PktNo, (uint32_t)cb, (uint32_t)cb, cpPacket));
1346 else
1347 {
1348 Log3(("/#%u/ %s packet #%d, %u bytes, %RTmac => %RTmac\n",
1349 pThis->pUsbIns->iInstance, pcszText, ++pThis->u32PktNo, (uint32_t)cb, cpPacket+6, cpPacket));
1350 if (LogIs4Enabled())
1351 usbNetProtocolDump(cpPacket, (uint32_t)cb);
1352 Log5(("%.*Rhxd\n", (uint32_t)cb, cpPacket));
1353 }
1354}
1355
1356#else
1357#define usbNetPacketDump(pUsbIns, pvBuf, cb, pcszText)
1358#endif
1359
1360/**
1361 * Receive data and pass it to lwIP for processing.
1362 *
1363 * @returns VBox status code
1364 * @param pInterface PDM network port interface pointer.
1365 * @param pvBuf Pointer to frame data.
1366 * @param cb Frame size.
1367 */
1368static DECLCALLBACK(int) usbNetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
1369{
1370 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkDown);
1371
1372 LogFlowFunc(("/#%u/ pInterface=%p cb=%u\n", pThis->pUsbIns->iInstance, pInterface, cb));
1373 RTCritSectEnter(&pThis->CritSect);
1374
1375 if (usbNetQueueIsEmpty(&pThis->ToHostQueue) || pThis->fSuspended)
1376 {
1377 RTCritSectLeave(&pThis->CritSect);
1378 LogFlowFunc(("/#%u/ return %Rrc due to %s\n", pThis->pUsbIns->iInstance, VINF_SUCCESS, pThis->fSuspended ? "being suspended" : "empty host queue"));
1379 return VINF_SUCCESS;
1380 }
1381
1382 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->ToHostQueue);
1383 PUSBNETEP pEp = &pThis->aEps[2];
1384
1385 if (RT_UNLIKELY(pEp->fHalted))
1386 {
1387 usbNetCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1388 RTCritSectLeave(&pThis->CritSect);
1389 return VINF_SUCCESS;
1390 }
1391
1392 if (pUrb->cbData < sizeof(USBNCMNTH16) + sizeof(USBNCMNDP16) + cb)
1393 {
1394 LogFunc(("/#%u/ Receive URB too small (%#x vs %#x)\n", pThis->pUsbIns->iInstance, pUrb->cbData,
1395 sizeof(USBNCMNTH16) + sizeof(USBNCMNDP16) + cb));
1396 pUrb->enmStatus = VUSBSTATUS_DATA_OVERRUN;
1397 usbNetLinkDone(pThis, pUrb);
1398 RTCritSectLeave(&pThis->CritSect);
1399 return VINF_SUCCESS;
1400 }
1401
1402 usbNetPacketDump(pThis, pvBuf, cb, "<-- Rx");
1403
1404 PUSBNCMNTH16 pNth16 = (PUSBNCMNTH16)&pUrb->abData[0];
1405 PUSBNCMNDP16 pNdp16 = (PUSBNCMNDP16)(pNth16 + 1);
1406
1407 /* Build NTH16. */
1408 pNth16->dwSignature = USBNCMNTH16_SIGNATURE;
1409 pNth16->wHeaderLength = sizeof(*pNth16);
1410 pNth16->wSequence = pThis->idSequence++;
1411 pNth16->wBlockLength = (uint16_t)(sizeof(*pNth16) + sizeof(*pNdp16) + cb);
1412 pNth16->wNdpIndex = sizeof(*pNth16);
1413
1414 /* Build NDP16. */
1415 pNdp16->dwSignature = USBNCMNDP16_SIGNATURE_NCM0;
1416 pNdp16->wLength = sizeof(*pNdp16);
1417 pNdp16->wNextNdpIndex = 0;
1418 pNdp16->DataGram0.wDatagramIndex = sizeof(*pNth16) + sizeof(*pNdp16);
1419 pNdp16->DataGram0.wDatagramLength = (uint16_t)cb;
1420 pNdp16->DataGram1.wDatagramIndex = 0;
1421 pNdp16->DataGram1.wDatagramLength = 0;
1422
1423 /* Copy frame over. */
1424 memcpy(pNdp16 + 1, pvBuf, cb);
1425
1426 pUrb->cbData = (uint32_t)(sizeof(*pNth16) + sizeof(*pNdp16) + cb);
1427 usbNetLinkDone(pThis, pUrb);
1428 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb);
1429 RTCritSectLeave(&pThis->CritSect);
1430
1431 LogFlowFunc(("/#%u/ return %Rrc\n", pThis->pUsbIns->iInstance, VINF_SUCCESS));
1432 return VINF_SUCCESS;
1433}
1434
1435/**
1436 * @interface_method_impl{PDMINETWORKDOWN,pfnXmitPending}
1437 */
1438static DECLCALLBACK(void) usbNetNetworkDown_XmitPending(PPDMINETWORKDOWN pInterface)
1439{
1440 RT_NOREF(pInterface);
1441#ifdef LOG_ENABLED
1442 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkDown);
1443 LogFlowFunc(("/#%u/ pInterface=%p\n", pThis->pUsbIns->iInstance, pInterface));
1444#endif
1445}
1446
1447
1448/* -=-=-=-=-=- USBNET::INetworkConfig -=-=-=-=-=- */
1449
1450/**
1451 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetMac}
1452 */
1453static DECLCALLBACK(int) usbNetGetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
1454{
1455 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1456
1457 LogFlowFunc(("/#%u/\n", pThis->pUsbIns->iInstance));
1458 memcpy(pMac, &pThis->MacConfigured, sizeof(*pMac));
1459 return VINF_SUCCESS;
1460}
1461
1462
1463/**
1464 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState}
1465 */
1466static DECLCALLBACK(PDMNETWORKLINKSTATE) usbNetGetLinkState(PPDMINETWORKCONFIG pInterface)
1467{
1468 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1469
1470 LogFlowFunc(("/#%u/\n", pThis->pUsbIns->iInstance));
1471 if (pThis->fLinkUp && !pThis->fLinkTempDown)
1472 return PDMNETWORKLINKSTATE_UP;
1473 if (!pThis->fLinkUp)
1474 return PDMNETWORKLINKSTATE_DOWN;
1475 if (pThis->fLinkTempDown)
1476 return PDMNETWORKLINKSTATE_DOWN_RESUME;
1477 AssertMsgFailed(("Invalid link state!\n"));
1478 return PDMNETWORKLINKSTATE_INVALID;
1479}
1480
1481
1482DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState);
1483
1484/**
1485 * @callback_method_impl{FNTMTIMERUSB}
1486 *
1487 * By the time the host resumes after sleep the network environment may have changed considerably.
1488 * We handle this by temporarily lowering the link state. This callback brings the link back up.
1489 */
1490static DECLCALLBACK(void) usbNetTimerLinkUp(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, void *pvUser)
1491{
1492 PUSBNET pThis = (PUSBNET)pvUser;
1493 RT_NOREF(pUsbIns, hTimer);
1494
1495 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
1496
1497 /** @todo Do we really care for potential races with link state? */
1498 pThis->fLinkTempDown = false;
1499 if (!pThis->fLinkUp)
1500 usbNetLinkStateNotify(pThis, PDMNETWORKLINKSTATE_UP);
1501}
1502
1503
1504/**
1505 * @interface_method_impl{PDMINETWORKCONFIG,pfnSetLinkState}
1506 */
1507static DECLCALLBACK(int) usbNetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
1508{
1509 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1510
1511 bool fLinkUp = enmState == PDMNETWORKLINKSTATE_UP;
1512
1513 LogFlowFunc(("/#%u/ enmState=%d\n", pThis->pUsbIns->iInstance, enmState));
1514 AssertMsgReturn(enmState > PDMNETWORKLINKSTATE_INVALID && enmState <= PDMNETWORKLINKSTATE_DOWN_RESUME,
1515 ("Invalid link state: enmState=%d\n", enmState), VERR_INVALID_PARAMETER);
1516
1517 if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
1518 {
1519 pThis->fLinkTempDown = true;
1520 /* Do not bother to notify anyone if the link has been down */
1521 PDMUsbHlpTimerSetMillies(pThis->pUsbIns, pThis->hTimerLinkUp, 500); /* 0.5 sec */
1522 }
1523 /* has the state changed? */
1524 if (pThis->fLinkUp != fLinkUp)
1525 {
1526 pThis->fLinkUp = fLinkUp;
1527 usbNetLinkStateNotify(pThis, enmState);
1528 }
1529 return VINF_SUCCESS;
1530}
1531
1532
1533
1534/**
1535 * @interface_method_impl{PDMUSBREG,pfnUrbReap}
1536 */
1537static DECLCALLBACK(PVUSBURB) usbNetUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
1538{
1539 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1540 LogFlowFunc(("/#%u/ cMillies=%u\n", pUsbIns->iInstance, cMillies));
1541
1542 RTCritSectEnter(&pThis->CritSect);
1543
1544 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->DoneQueue);
1545 if (!pUrb && cMillies)
1546 {
1547 /* Wait */
1548 pThis->fHaveDoneQueueWaiter = true;
1549 RTCritSectLeave(&pThis->CritSect);
1550
1551 RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
1552
1553 RTCritSectEnter(&pThis->CritSect);
1554 pThis->fHaveDoneQueueWaiter = false;
1555
1556 pUrb = usbNetQueueRemoveHead(&pThis->DoneQueue);
1557 }
1558
1559 RTCritSectLeave(&pThis->CritSect);
1560
1561 if (pUrb)
1562 Log2Func(("/#%u/ pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1563 return pUrb;
1564}
1565
1566
1567/**
1568 * @interface_method_impl{PDMUSBREG,pfnWakeup}
1569 */
1570static DECLCALLBACK(int) usbNetWakeup(PPDMUSBINS pUsbIns)
1571{
1572 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1573 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
1574
1575 return RTSemEventSignal(pThis->hEvtDoneQueue);
1576}
1577
1578
1579/**
1580 * @interface_method_impl{PDMUSBREG,pfnUrbCancel}
1581 */
1582static DECLCALLBACK(int) usbNetUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1583{
1584 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1585 LogFlowFunc(("/#%u/ pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1586 RTCritSectEnter(&pThis->CritSect);
1587
1588 /*
1589 * Remove the URB from the to-host queue and move it onto the done queue.
1590 */
1591 if (usbNetQueueRemove(&pThis->ToHostQueue, pUrb))
1592 usbNetLinkDone(pThis, pUrb);
1593
1594 if (usbNetQueueRemove(&pThis->ToHostIntrQueue, pUrb))
1595 usbNetLinkDone(pThis, pUrb);
1596
1597 RTCritSectLeave(&pThis->CritSect);
1598 return VINF_SUCCESS;
1599}
1600
1601
1602/**
1603 * Handle requests sent to the outbound (to device) bulk pipe.
1604 */
1605static int usbNetHandleBulkHostToDev(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1606{
1607 /*
1608 * Stall the request if the pipe is halted.
1609 */
1610 if (RT_UNLIKELY(pEp->fHalted))
1611 return usbNetCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1612
1613 /*
1614 * Process the transfer.
1615 */
1616 PCUSBNCMNTH16 pNth16 = (PCUSBNCMNTH16)&pUrb->abData[0];
1617 if (pUrb->cbData < sizeof(*pNth16))
1618 {
1619 LogFunc(("/#%u/ Bad NTH16: cbData=%#x < min=%#x\n", pThis->pUsbIns->iInstance, pUrb->cbData, sizeof(*pNth16) ));
1620 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NTH16");
1621 }
1622 if (pNth16->dwSignature != USBNCMNTH16_SIGNATURE)
1623 {
1624 LogFunc(("/#%u/ NTH16: Invalid dwSignature value: %#x\n", pNth16->dwSignature));
1625 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1626 }
1627 Log2Func(("/#%u/ NTH16: wHeaderLength=%#x wSequence=%#x wBlockLength=%#x wNdpIndex=%#x cbData=%#x fShortNotOk=%RTbool\n", pThis->pUsbIns->iInstance,
1628 pNth16->wHeaderLength, pNth16->wSequence, pNth16->wBlockLength, pNth16->wNdpIndex, pUrb->cbData, pUrb->fShortNotOk));
1629 if (pNth16->wHeaderLength != sizeof(*pNth16))
1630 {
1631 LogFunc(("/#%u/ NTH16: Bad wHeaderLength value: %#x\n", pThis->pUsbIns->iInstance, pNth16->wHeaderLength));
1632 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1633
1634 }
1635 if (pNth16->wBlockLength > pUrb->cbData)
1636 {
1637 LogFunc(("/#%u/ NTH16: Bad wBlockLength value: %#x\n", pThis->pUsbIns->iInstance, pNth16->wBlockLength));
1638 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1639 }
1640
1641 if (pNth16->wNdpIndex < sizeof(*pNth16))
1642 {
1643 LogFunc(("/#%u/ NTH16: wNdpIndex is too small: %#x (%u), at least required %#x\n", pThis->pUsbIns->iInstance,
1644 pNth16->wNdpIndex, pNth16->wNdpIndex, sizeof(*pNth16) ));
1645 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1646 }
1647
1648 /* Walk the NDPs and process the datagrams. */
1649 uint16_t offNdp16Next = pNth16->wNdpIndex;
1650 while (offNdp16Next)
1651 {
1652 if (offNdp16Next >= pUrb->cbData)
1653 {
1654 LogFunc(("/#%u/ Bad NDP16: offNdp16Next=%#x >= cbData=%#x\n", pThis->pUsbIns->iInstance, offNdp16Next, pUrb->cbData));
1655 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NDP16");
1656 }
1657
1658 size_t cbNdpMax = pUrb->cbData - offNdp16Next;
1659 PCUSBNCMNDP16 pNdp16 = (PCUSBNCMNDP16)&pUrb->abData[pNth16->wNdpIndex];
1660 if (cbNdpMax < sizeof(*pNdp16))
1661 {
1662 LogFunc(("/#%u/ Bad NDP16: cbNdpMax=%#x < min=%#x\n", pThis->pUsbIns->iInstance, cbNdpMax, sizeof(*pNdp16) ));
1663 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NDP16");
1664 }
1665
1666 if ( pNdp16->dwSignature != USBNCMNDP16_SIGNATURE_NCM0
1667 && pNdp16->dwSignature != USBNCMNDP16_SIGNATURE_NCM1)
1668 {
1669 LogFunc(("/#%u/ NDP16: Invalid dwSignature value: %#x\n", pThis->pUsbIns->iInstance, pNdp16->dwSignature));
1670 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1671 }
1672
1673 if ( pNdp16->wLength < sizeof(*pNdp16)
1674 || (pNdp16->wLength & 0x3)
1675 || pNdp16->wLength > cbNdpMax)
1676 {
1677 LogFunc(("/#%u/ NDP16: Invalid size value: %#x, req. (min %#x max %#x)\n", pThis->pUsbIns->iInstance,
1678 pNdp16->wLength, sizeof(*pNdp16), cbNdpMax));
1679 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1680 }
1681
1682 if (pNdp16->dwSignature == USBNCMNDP16_SIGNATURE_NCM0)
1683 {
1684 PCUSBNCMNDP16DGRAM pDGram = &pNdp16->DataGram0;
1685 size_t cEntries = 2 + (pNdp16->wLength - (sizeof(*pNdp16))) / sizeof(*pDGram);
1686
1687 int rc = pThis->Lun0.pINetwork->pfnBeginXmit(pThis->Lun0.pINetwork, true /* fOnWorkerThread */);
1688 if (RT_FAILURE(rc))
1689 return usbNetCompleteStall(pThis, NULL, pUrb, "BeginXmit failed");
1690
1691 for (uint32_t i = 0; i < cEntries; i++)
1692 {
1693 /* Either 0 element marks end of list. */
1694 if ( pDGram->wDatagramIndex == 0
1695 || pDGram->wDatagramLength == 0)
1696 break;
1697
1698 if ( pDGram->wDatagramIndex < sizeof(*pNth16)
1699 || pDGram->wDatagramIndex >= pUrb->cbData)
1700 {
1701 LogFunc(("/#%u/ DGRAM16: Invalid wDatagramIndex value: %#x\n", pThis->pUsbIns->iInstance, pDGram->wDatagramIndex));
1702 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad DGRAM16");
1703 }
1704
1705 if (pUrb->cbData - pDGram->wDatagramIndex < pDGram->wDatagramLength)
1706 {
1707 LogFunc(("/#%u/ DGRAM16: Invalid wDatagramLength value: %#x (max %#x)\n", pThis->pUsbIns->iInstance,
1708 pDGram->wDatagramLength, pUrb->cbData - pDGram->wDatagramIndex));
1709 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad DGRAM16");
1710 }
1711
1712 PPDMSCATTERGATHER pSgBuf;
1713 rc = pThis->Lun0.pINetwork->pfnAllocBuf(pThis->Lun0.pINetwork, pDGram->wDatagramLength, NULL /*pGso*/, &pSgBuf);
1714 if (RT_SUCCESS(rc))
1715 {
1716 uint8_t *pbBuf = pSgBuf ? (uint8_t *)pSgBuf->aSegs[0].pvSeg : NULL;
1717 memcpy(pbBuf, &pUrb->abData[pDGram->wDatagramIndex], pDGram->wDatagramLength);
1718 usbNetPacketDump(pThis, pbBuf, pDGram->wDatagramLength, "--> Tx");
1719 pSgBuf->cbUsed = pDGram->wDatagramLength;
1720 rc = pThis->Lun0.pINetwork->pfnSendBuf(pThis->Lun0.pINetwork, pSgBuf, true /* fOnWorkerThread */);
1721 if (RT_FAILURE(rc))
1722 return usbNetCompleteStall(pThis, NULL, pUrb, "SendBuf failed");
1723 STAM_REL_COUNTER_ADD(&pThis->StatTransmitBytes, pDGram->wDatagramLength);
1724 }
1725 else
1726 return usbNetCompleteStall(pThis, NULL, pUrb, "AllocBuf failed");
1727
1728 pDGram++;
1729 }
1730
1731 pThis->Lun0.pINetwork->pfnEndXmit(pThis->Lun0.pINetwork);
1732 }
1733 else
1734 {
1735 LogFunc(("/#%u/ NDP16: Not implemented\n", pThis->pUsbIns->iInstance));
1736 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1737 }
1738
1739 offNdp16Next = pNdp16->wNextNdpIndex;
1740 }
1741
1742 return usbNetCompleteOk(pThis, pUrb, pUrb->cbData);
1743}
1744
1745
1746/**
1747 * Handle requests sent to the inbound (to host) bulk pipe.
1748 */
1749static int usbNetHandleBulkDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1750{
1751 /*
1752 * Stall the request if the pipe is halted OR if there is no
1753 * pending request yet.
1754 */
1755 if (RT_UNLIKELY(pEp->fHalted))
1756 return usbNetCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
1757
1758 usbNetQueueAddTail(&pThis->ToHostQueue, pUrb);
1759 if (pThis->fHaveToHostQueueWaiter)
1760 RTSemEventSignal(pThis->hEvtToHostQueue);
1761
1762 LogFlowFunc(("/#%u/ Added %p:%s to the to-host queue\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1763 return VINF_SUCCESS;
1764}
1765
1766
1767/**
1768 * Handle requests sent to the inbound (to host) interrupt pipe.
1769 */
1770static int usbNetHandleIntrDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1771{
1772 /* Stall the request if the pipe is halted. */
1773 if (RT_UNLIKELY(pEp->fHalted))
1774 return usbNetCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
1775
1776 /* CONNECTION_SPEED_CHANGE is sent first, followed by NETWORK_CONNECTION. See [NCM10] (section 7.1) */
1777 if (!pThis->fInitialSpeedChangeSent)
1778 {
1779 USBCDCNOTIFICICATIONSPEEDCHG SpeedChange;
1780 SpeedChange.Hdr.bmRequestType = 0xa1;
1781 SpeedChange.Hdr.bNotificationCode = USB_CDC_NOTIFICATION_CODE_CONNECTION_SPEED_CHANGE;
1782 SpeedChange.Hdr.wValue = 0;
1783 SpeedChange.Hdr.wIndex = 0;
1784 SpeedChange.Hdr.wLength = 8;
1785 SpeedChange.DLBitRate = UINT32_MAX;
1786 SpeedChange.ULBitRate = UINT32_MAX;
1787 usbNetCompleteNotificationOk(pThis, pUrb, &SpeedChange, sizeof(SpeedChange));
1788 pThis->fInitialSpeedChangeSent = true;
1789 }
1790 else if (!pThis->fInitialLinkStatusSent)
1791 {
1792 USBCDCNOTIFICICATION LinkNotification;
1793 LinkNotification.bmRequestType = 0xa1;
1794 LinkNotification.bNotificationCode = USB_CDC_NOTIFICATION_CODE_NETWORK_CONNECTION;
1795 LinkNotification.wValue = pThis->fLinkUp ? 1 : 0;
1796 LinkNotification.wIndex = 0;
1797 LinkNotification.wLength = 0;
1798 usbNetCompleteNotificationOk(pThis, pUrb, &LinkNotification, sizeof(LinkNotification));
1799 pThis->fInitialLinkStatusSent = true;
1800 }
1801 else
1802 usbNetQueueAddTail(&pThis->ToHostIntrQueue, pUrb);
1803
1804 LogFlowFunc(("/#%u/ Added %p:%s to the to-host interrupt queue\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1805 return VINF_SUCCESS;
1806}
1807
1808
1809/**
1810 * Notifies both the guest and the network/driver of link state changes.
1811 *
1812 * @param pThis The UsbNet instance.
1813 * @param enmLinkState The new link state.
1814 */
1815DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState)
1816{
1817 LogFlowFunc(("/#%u/ enmLinkState=%d\n", pThis->pUsbIns->iInstance, enmLinkState));
1818 RTCritSectEnter(&pThis->CritSect);
1819 /* Trigger notifications */
1820 pThis->fInitialLinkStatusSent = false;
1821 pThis->fInitialSpeedChangeSent = false;
1822 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->ToHostIntrQueue);
1823 /* If there is a request pending, use it. Otherwise the host should poll us soon. */
1824 if (pUrb)
1825 usbNetHandleIntrDevToHost(pThis, &pThis->aEps[3], pUrb);
1826 RTCritSectLeave(&pThis->CritSect);
1827 /* Always notify our network when notifying the guest. */
1828 if (pThis->Lun0.pINetwork)
1829 pThis->Lun0.pINetwork->pfnNotifyLinkChanged(pThis->Lun0.pINetwork, enmLinkState);
1830}
1831
1832
1833/**
1834 * Handles request send to the default control pipe.
1835 */
1836static int usbNetHandleDefaultPipe(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1837{
1838 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1839 AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
1840
1841 if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
1842 {
1843 switch (pSetup->bRequest)
1844 {
1845 case VUSB_REQ_GET_DESCRIPTOR:
1846 {
1847 if (pSetup->bmRequestType != (VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST))
1848 {
1849 LogFunc(("/#%u/ Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pThis->pUsbIns->iInstance, pSetup->bmRequestType));
1850 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
1851 }
1852
1853 switch (pSetup->wValue >> 8)
1854 {
1855 uint32_t cbCopy;
1856
1857 case VUSB_DT_STRING:
1858 LogFunc(("/#%u/ GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pThis->pUsbIns->iInstance, pSetup->wValue, pSetup->wIndex));
1859 break;
1860 case VUSB_DT_DEVICE_QUALIFIER:
1861 LogFunc(("/#%u/ GET_DESCRIPTOR DT_DEVICE_QUALIFIER wValue=%#x wIndex=%#x\n", pThis->pUsbIns->iInstance, pSetup->wValue, pSetup->wIndex));
1862 /* Returned data is written after the setup message. */
1863 cbCopy = pUrb->cbData - sizeof(*pSetup);
1864 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbNetDeviceQualifier));
1865 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbNetDeviceQualifier, cbCopy);
1866 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1867 case VUSB_DT_BOS:
1868 LogFunc(("/#%u/ GET_DESCRIPTOR DT_BOS 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_UsbNetBOS));
1872 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbNetBOS, cbCopy);
1873 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1874 default:
1875 LogFunc(("/#%u/ GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pThis->pUsbIns->iInstance, pSetup->wValue, pSetup->wIndex));
1876 break;
1877 }
1878 break;
1879 }
1880
1881 case VUSB_REQ_GET_STATUS:
1882 {
1883 uint16_t wRet = 0;
1884 size_t cbCopy = 0;
1885
1886 if (pSetup->wLength != 2)
1887 {
1888 LogRelFlow(("UsbNet: Bad GET_STATUS req: wLength=%#x\n",
1889 pSetup->wLength));
1890 break;
1891 }
1892 Assert(pSetup->wValue == 0);
1893 switch (pSetup->bmRequestType)
1894 {
1895 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1896 {
1897 Assert(pSetup->wIndex == 0);
1898 LogRelFlow(("UsbNet: GET_STATUS (device)\n"));
1899 wRet = 0; /* Not self-powered, no remote wakeup. */
1900 cbCopy = pUrb->cbData - sizeof(*pSetup);
1901 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1902 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1903 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1904 }
1905
1906 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1907 {
1908 if (pSetup->wIndex == 0)
1909 {
1910 cbCopy = pUrb->cbData - sizeof(*pSetup);
1911 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1912 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1913 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1914 }
1915 LogRelFlow(("UsbNet: GET_STATUS (interface) invalid, wIndex=%#x\n", pSetup->wIndex));
1916 break;
1917 }
1918
1919 case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1920 {
1921 if (pSetup->wIndex < RT_ELEMENTS(pThis->aEps))
1922 {
1923 wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
1924 cbCopy = pUrb->cbData - sizeof(*pSetup);
1925 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1926 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1927 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1928 }
1929 LogRelFlow(("UsbNet: GET_STATUS (endpoint) invalid, wIndex=%#x\n", pSetup->wIndex));
1930 break;
1931 }
1932
1933 default:
1934 LogRelFlow(("UsbNet: Bad GET_STATUS req: bmRequestType=%#x\n",
1935 pSetup->bmRequestType));
1936 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
1937 }
1938 break;
1939 }
1940
1941 case 0x31:
1942 break;
1943
1944 case VUSB_REQ_CLEAR_FEATURE:
1945 break;
1946 }
1947
1948 /** @todo implement this. */
1949 LogFunc(("/#%u/ Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", pThis->pUsbIns->iInstance,
1950 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1951
1952 usbNetCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
1953 }
1954 else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS)
1955 {
1956 switch (pSetup->bRequest)
1957 {
1958 case VUSB_REQ_GET_NTB_PARAMETERS:
1959 {
1960 if (pSetup->bmRequestType != (VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_HOST))
1961 {
1962 LogFunc(("/#%u/ Bad GET_NTB_PARAMETERS req: bmRequestType=%#x\n", pThis->pUsbIns->iInstance, pSetup->bmRequestType));
1963 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_NTB_PARAMETERS");
1964 }
1965
1966 USBNCMNTBPARAMS NtbParams;
1967
1968 NtbParams.wLength = sizeof(NtbParams);
1969 NtbParams.bmNtbFormatsSupported = RT_BIT(0);
1970 NtbParams.dwNtbInMaxSize = _4K;
1971 NtbParams.wNdpInDivisor = 4;
1972 NtbParams.wNdpInPayloadRemainder = 4;
1973 NtbParams.wNdpInAlignment = 4;
1974 NtbParams.u16Rsvd0 = 0;
1975 NtbParams.dwNtbOutMaxSize = _4K;
1976 NtbParams.wNdpOutDivisor = 4;
1977 NtbParams.wNdpOutPayloadRemainder = 4;
1978 NtbParams.wNdpOutAlignment = 4;
1979 NtbParams.wNtpOutMaxDatagrams = 1;
1980
1981 uint32_t cbCopy = pUrb->cbData - sizeof(*pSetup);
1982 cbCopy = RT_MIN(cbCopy, sizeof(NtbParams));
1983 memcpy(&pUrb->abData[sizeof(*pSetup)], &NtbParams, cbCopy);
1984 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1985 }
1986
1987 case VUSB_REQ_CLEAR_FEATURE:
1988 break;
1989 }
1990
1991 usbNetCompleteStall(pThis, pEp, pUrb, "CLASS_REQ");
1992 }
1993 else
1994 {
1995 LogFunc(("/#%u/ Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", pThis->pUsbIns->iInstance,
1996 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1997 return usbNetCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
1998 }
1999
2000 return VINF_SUCCESS;
2001}
2002
2003
2004/**
2005 * @interface_method_impl{PDMUSBREG,pfnUrbQueue}
2006 */
2007static DECLCALLBACK(int) usbNetQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
2008{
2009 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2010 LogFlowFunc(("/#%u/ pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
2011 RTCritSectEnter(&pThis->CritSect);
2012
2013 /*
2014 * Parse on a per end-point basis.
2015 */
2016 int rc;
2017 switch (pUrb->EndPt)
2018 {
2019 case 0:
2020 rc = usbNetHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
2021 break;
2022
2023 case 0x81:
2024 AssertFailed();
2025 RT_FALL_THRU();
2026 case 0x01:
2027 rc = usbNetHandleBulkDevToHost(pThis, &pThis->aEps[1], pUrb);
2028 break;
2029
2030 case 0x02:
2031 rc = usbNetHandleBulkHostToDev(pThis, &pThis->aEps[2], pUrb);
2032 break;
2033
2034 case 0x03:
2035 rc = usbNetHandleIntrDevToHost(pThis, &pThis->aEps[3], pUrb);
2036 break;
2037
2038 default:
2039 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
2040 rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
2041 break;
2042 }
2043
2044 RTCritSectLeave(&pThis->CritSect);
2045 return rc;
2046}
2047
2048
2049/**
2050 * @interface_method_impl{PDMUSBREG,pfnUsbClearHaltedEndpoint}
2051 */
2052static DECLCALLBACK(int) usbNetUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
2053{
2054 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2055 LogFlowFunc(("/#%u/ uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
2056
2057 if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
2058 {
2059 RTCritSectEnter(&pThis->CritSect);
2060 pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
2061 RTCritSectLeave(&pThis->CritSect);
2062 }
2063
2064 return VINF_SUCCESS;
2065}
2066
2067
2068/**
2069 * @interface_method_impl{PDMUSBREG,pfnUsbSetInterface}
2070 */
2071static DECLCALLBACK(int) usbNetUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
2072{
2073 RT_NOREF(bInterfaceNumber);
2074 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2075 LogFlowFunc(("/#%u/ bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
2076 Assert(bAlternateSetting == 0 || bAlternateSetting == 1);
2077 if (pThis->bAlternateSetting != bAlternateSetting)
2078 {
2079 if (bAlternateSetting == 0)
2080 {
2081 /* This is some kind of reset. */
2082 usbNetResetWorker(pThis, NULL, true /*fSetConfig*/);
2083 }
2084 else
2085 {
2086 Assert(bAlternateSetting == 1);
2087 /* Switching from configuration to data mode, need to send notifications. */
2088 pThis->fInitialLinkStatusSent = false;
2089 pThis->fInitialSpeedChangeSent = false;
2090 }
2091 pThis->bAlternateSetting = bAlternateSetting;
2092 }
2093 return VINF_SUCCESS;
2094}
2095
2096
2097/**
2098 * @interface_method_impl{PDMUSBREG,pfnUsbSetConfiguration}
2099 */
2100static DECLCALLBACK(int) usbNetUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
2101 const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
2102{
2103 RT_NOREF(pvOldCfgDesc, pvOldIfState, pvNewCfgDesc);
2104 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2105 LogFlowFunc(("/#%u/ bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
2106 Assert(bConfigurationValue == 1);
2107 RTCritSectEnter(&pThis->CritSect);
2108
2109 /*
2110 * If the same config is applied more than once, it's a kind of reset.
2111 */
2112 if (pThis->bConfigurationValue == bConfigurationValue)
2113 usbNetResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
2114 pThis->bConfigurationValue = bConfigurationValue;
2115
2116 RTCritSectLeave(&pThis->CritSect);
2117 return VINF_SUCCESS;
2118}
2119
2120
2121/**
2122 * @interface_method_impl{PDMUSBREG,pfnUsbGetDescriptorCache}
2123 */
2124static DECLCALLBACK(PCPDMUSBDESCCACHE) usbNetUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
2125{
2126 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2127 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2128 return &pThis->UsbDescCache;
2129}
2130
2131
2132/**
2133 * @interface_method_impl{PDMUSBREG,pfnUsbReset}
2134 */
2135static DECLCALLBACK(int) usbNetUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
2136{
2137 RT_NOREF(fResetOnLinux);
2138 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2139 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2140 RTCritSectEnter(&pThis->CritSect);
2141
2142 int rc = usbNetResetWorker(pThis, NULL, false /*fSetConfig*/);
2143
2144 RTCritSectLeave(&pThis->CritSect);
2145 return rc;
2146}
2147
2148
2149/**
2150 * @interface_method_impl{PDMUSBREG,pfnDriverAttach}
2151 */
2152static DECLCALLBACK(int) usbNetDriverAttach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
2153{
2154 RT_NOREF(fFlags);
2155 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2156
2157 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2158
2159 AssertMsg(iLUN == 0, ("UsbNet: No other LUN than 0 is supported\n"));
2160 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
2161 ("UsbNet: Device does not support hotplugging\n"));
2162
2163 /* the usual paranoia */
2164 AssertRelease(!pThis->Lun0.pIBase);
2165 AssertRelease(!pThis->Lun0.pINetwork);
2166
2167 /*
2168 * Try attach the network driver.
2169 */
2170 int rc = PDMUsbHlpDriverAttach(pUsbIns, iLUN, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, NULL);
2171 if (RT_SUCCESS(rc))
2172 {
2173 /* Get network interface. */
2174 pThis->Lun0.pINetwork = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMINETWORKUP);
2175 AssertMsgReturn(pThis->Lun0.pINetwork, ("Missing network interface below\n"), VERR_PDM_MISSING_INTERFACE);
2176 }
2177 else
2178 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", iLUN, rc));
2179
2180 if (RT_FAILURE(rc))
2181 {
2182 pThis->Lun0.pIBase = NULL;
2183 pThis->Lun0.pINetwork = NULL;
2184 }
2185
2186 return rc;
2187}
2188
2189
2190/**
2191 * @interface_method_impl{PDMUSBREG,pfnDriverDetach}
2192 */
2193static DECLCALLBACK(void) usbNetDriverDetach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
2194{
2195 RT_NOREF(iLUN, fFlags);
2196 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2197
2198 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2199
2200 AssertMsg(iLUN == 0, ("UsbNet: No other LUN than 0 is supported\n"));
2201 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
2202 ("UsbNet: Device does not support hotplugging\n"));
2203
2204 /*
2205 * Zero some important members.
2206 */
2207 pThis->Lun0.pIBase = NULL;
2208 pThis->Lun0.pINetwork = NULL;
2209}
2210
2211
2212/**
2213 * @interface_method_impl{PDMUSBREG,pfnVMReset}
2214 */
2215static DECLCALLBACK(void) usbNetVMReset(PPDMUSBINS pUsbIns)
2216{
2217 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2218
2219 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2220 int rc = usbNetResetWorker(pThis, NULL, false /*fSetConfig*/);
2221 AssertRC(rc);
2222}
2223
2224
2225 /**
2226 * @interface_method_impl{PDMUSBREG,pfnVMSuspend}
2227 */
2228static DECLCALLBACK(void) usbNetVMSuspend(PPDMUSBINS pUsbIns)
2229{
2230 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2231#ifdef LOG_ENABLED
2232 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
2233 VMSUSPENDREASON enmReason = pHlp->pfnVMGetSuspendReason(pUsbIns);
2234 LogFlowFunc(("/#%u/ enmReason=%u\n", pUsbIns->iInstance, enmReason));
2235#endif
2236 RTCritSectEnter(&pThis->CritSect);
2237 pThis->fSuspended = true;
2238 /* Unblock receive thread */
2239 RTSemEventSignal(pThis->hEvtToHostQueue);
2240 RTCritSectLeave(&pThis->CritSect);
2241}
2242
2243
2244/**
2245 * @interface_method_impl{PDMUSBREG,pfnVMResume}
2246 */
2247static DECLCALLBACK(void) usbNetVMResume(PPDMUSBINS pUsbIns)
2248{
2249 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2250#ifdef LOG_ENABLED
2251 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
2252 VMRESUMEREASON enmReason = pHlp->pfnVMGetResumeReason(pUsbIns);
2253 LogFlowFunc(("/#%u/ enmReason=%u\n", pUsbIns->iInstance, enmReason));
2254#endif
2255 RTCritSectEnter(&pThis->CritSect);
2256 pThis->fSuspended = false;
2257 RTCritSectLeave(&pThis->CritSect);
2258}
2259
2260
2261/**
2262 * @interface_method_impl{PDMUSBREG,pfnDestruct}
2263 */
2264static DECLCALLBACK(void) usbNetDestruct(PPDMUSBINS pUsbIns)
2265{
2266 PDMUSB_CHECK_VERSIONS_RETURN_VOID(pUsbIns);
2267 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2268 LogFlowFunc(("/#%u/\n", pUsbIns->iInstance));
2269
2270 PDMUsbHlpTimerDestroy(pUsbIns, pThis->hTimerLinkUp);
2271
2272 if (RTCritSectIsInitialized(&pThis->CritSect))
2273 {
2274 RTCritSectEnter(&pThis->CritSect);
2275 RTCritSectLeave(&pThis->CritSect);
2276 RTCritSectDelete(&pThis->CritSect);
2277 }
2278
2279 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
2280 {
2281 RTSemEventDestroy(pThis->hEvtDoneQueue);
2282 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2283 }
2284
2285 if (pThis->hEvtToHostQueue != NIL_RTSEMEVENT)
2286 {
2287 RTSemEventDestroy(pThis->hEvtToHostQueue);
2288 pThis->hEvtToHostQueue = NIL_RTSEMEVENT;
2289 }
2290
2291 if (pThis->hEvtReset != NIL_RTSEMEVENTMULTI)
2292 {
2293 RTSemEventMultiDestroy(pThis->hEvtReset);
2294 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2295 }
2296}
2297
2298
2299/**
2300 * @interface_method_impl{PDMUSBREG,pfnConstruct}
2301 */
2302static DECLCALLBACK(int) usbNetConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
2303{
2304 RT_NOREF(pCfgGlobal);
2305 PDMUSB_CHECK_VERSIONS_RETURN(pUsbIns);
2306 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2307 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
2308
2309 LogFlowFunc(("/#%u/\n", iInstance));
2310
2311 pThis->u32PktNo = 1;
2312 /*
2313 * Perform the basic structure initialization first so the destructor
2314 * will not misbehave.
2315 */
2316 pThis->pUsbIns = pUsbIns;
2317 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2318 pThis->hEvtToHostQueue = NIL_RTSEMEVENT;
2319 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2320 /* IBase */
2321 pThis->Lun0.IBase.pfnQueryInterface = usbNetLun0QueryInterface;
2322 /* INetworkPort */
2323 pThis->Lun0.INetworkDown.pfnWaitReceiveAvail = usbNetNetworkDown_WaitReceiveAvail;
2324 pThis->Lun0.INetworkDown.pfnReceive = usbNetNetworkDown_Receive;
2325 pThis->Lun0.INetworkDown.pfnXmitPending = usbNetNetworkDown_XmitPending;
2326 /* INetworkConfig */
2327 pThis->Lun0.INetworkConfig.pfnGetMac = usbNetGetMac;
2328 pThis->Lun0.INetworkConfig.pfnGetLinkState = usbNetGetLinkState;
2329 pThis->Lun0.INetworkConfig.pfnSetLinkState = usbNetSetLinkState;
2330
2331 usbNetQueueInit(&pThis->ToHostQueue);
2332 usbNetQueueInit(&pThis->ToHostIntrQueue);
2333 usbNetQueueInit(&pThis->DoneQueue);
2334
2335 int rc = RTCritSectInit(&pThis->CritSect);
2336 AssertRCReturn(rc, rc);
2337
2338 rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
2339 AssertRCReturn(rc, rc);
2340
2341 rc = RTSemEventCreate(&pThis->hEvtToHostQueue);
2342 AssertRCReturn(rc, rc);
2343
2344 rc = RTSemEventMultiCreate(&pThis->hEvtReset);
2345 AssertRCReturn(rc, rc);
2346
2347 /*
2348 * Validate and read the configuration.
2349 */
2350 rc = pHlp->pfnCFGMValidateConfig(pCfg, "/",
2351 "MAC|"
2352 "CableConnected|"
2353 "LinkUpDelay"
2354 , "Config", "UsbNet", iInstance);
2355 if (RT_FAILURE(rc))
2356 return rc;
2357
2358 /*
2359 * Read the configuration.
2360 */
2361 rc = pHlp->pfnCFGMQueryBytes(pCfg, "MAC", &pThis->MacConfigured, sizeof(pThis->MacConfigured));
2362 if (RT_FAILURE(rc))
2363 return PDMUSB_SET_ERROR(pUsbIns, rc,
2364 N_("Configuration error: Failed to get the \"MAC\" value"));
2365 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "CableConnected", &pThis->fLinkUp, true);
2366 if (RT_FAILURE(rc))
2367 return PDMUSB_SET_ERROR(pUsbIns, rc,
2368 N_("Configuration error: Failed to get the \"CableConnected\" value"));
2369
2370 /*
2371 * Attach the network driver.
2372 */
2373 rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, "Network Port");
2374 if (RT_FAILURE(rc))
2375 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("USBNET failed to attach network driver"));
2376 pThis->Lun0.pINetwork = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMINETWORKUP);
2377 if (!pThis->Lun0.pINetwork)
2378 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
2379 N_("USBNET failed to query the PDMINETWORKUP from the driver below it"));
2380
2381 /*
2382 * Create the timer for delaying of bringing the link up.
2383 */
2384 rc = PDMUsbHlpTimerCreate(pUsbIns, TMCLOCK_VIRTUAL, usbNetTimerLinkUp, pThis,
2385 TMTIMER_FLAGS_DEFAULT_CRIT_SECT,
2386 "Link Up", &pThis->hTimerLinkUp);
2387 AssertRCReturn(rc, rc);
2388
2389 /*
2390 * Build the USB descriptors.
2391 */
2392 pThis->aUsbStringsEnUs[0].idx = USBNET_STR_ID_MANUFACTURER;
2393 pThis->aUsbStringsEnUs[0].psz = "VirtualBox";
2394
2395 pThis->aUsbStringsEnUs[1].idx = USBNET_STR_ID_PRODUCT;
2396 pThis->aUsbStringsEnUs[1].psz = "USB Ethernet";
2397
2398 /* Build the MAC address. */
2399 ssize_t cch = RTStrPrintf2(&pThis->aszMac[0], sizeof(pThis->aszMac), "%#.6Rhxs", &pThis->MacConfigured);
2400 AssertReturn(cch + 1 == sizeof(pThis->aszMac), VERR_INTERNAL_ERROR_4);
2401
2402 pThis->aUsbStringsEnUs[2].idx = USBNET_STR_ID_MAC_ADDRESS;
2403 pThis->aUsbStringsEnUs[2].psz = &pThis->aszMac[0];
2404
2405 pThis->UsbLang.idLang = 0x0409; /* en_US. */
2406 pThis->UsbLang.cStrings = RT_ELEMENTS(pThis->aUsbStringsEnUs);
2407 pThis->UsbLang.paStrings = &pThis->aUsbStringsEnUs[0];
2408
2409 pThis->UsbDescCache.paLanguages = &pThis->UsbLang;
2410 pThis->UsbDescCache.cLanguages = 1;
2411 pThis->UsbDescCache.fUseCachedDescriptors = true;
2412 pThis->UsbDescCache.fUseCachedStringsDescriptors = true;
2413
2414 switch (pUsbIns->enmSpeed)
2415 {
2416 case VUSB_SPEED_SUPER:
2417 case VUSB_SPEED_SUPERPLUS:
2418 {
2419 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc30;
2420 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescSS;
2421 break;
2422 }
2423 case VUSB_SPEED_HIGH:
2424 {
2425 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc20;
2426 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescHS;
2427 break;
2428 }
2429 case VUSB_SPEED_FULL:
2430 case VUSB_SPEED_LOW:
2431 {
2432 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc20;
2433 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescFS;
2434 break;
2435 }
2436 default:
2437 AssertFailedReturn(VERR_INVALID_PARAMETER);
2438 }
2439
2440 /*
2441 * Register statistics.
2442 * The /Public/ bits are official and used by session info in the GUI.
2443 */
2444 PDMUsbHlpSTAMRegisterF(pUsbIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
2445 "Amount of data received", "/Public/NetAdapter/%u/BytesReceived", iInstance);
2446 PDMUsbHlpSTAMRegisterF(pUsbIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
2447 "Amount of data transmitted", "/Public/NetAdapter/%u/BytesTransmitted", iInstance);
2448 PDMUsbHlpSTAMRegisterF(pUsbIns, &pUsbIns->iInstance, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
2449 "Device instance number", "/Public/NetAdapter/%u/%s", iInstance, pUsbIns->pReg->szName);
2450
2451 return VINF_SUCCESS;
2452}
2453
2454
2455/**
2456 * The USB Communications Device Class, Network Control Model (CDC NCM) registration record.
2457 */
2458const PDMUSBREG g_UsbNet =
2459{
2460 /* u32Version */
2461 PDM_USBREG_VERSION,
2462 /* szName */
2463 "UsbNet",
2464 /* pszDescription */
2465 "USB Communications Device Class, one LUN.",
2466 /* fFlags */
2467 PDM_USBREG_HIGHSPEED_CAPABLE /*| PDM_USBREG_SUPERSPEED_CAPABLE */,
2468 /* cMaxInstances */
2469 ~0U,
2470 /* cbInstance */
2471 sizeof(USBNET),
2472 /* pfnConstruct */
2473 usbNetConstruct,
2474 /* pfnDestruct */
2475 usbNetDestruct,
2476 /* pfnVMInitComplete */
2477 NULL,
2478 /* pfnVMPowerOn */
2479 NULL,
2480 /* pfnVMReset */
2481 usbNetVMReset,
2482 /* pfnVMSuspend */
2483 usbNetVMSuspend,
2484 /* pfnVMResume */
2485 usbNetVMResume,
2486 /* pfnVMPowerOff */
2487 NULL,
2488 /* pfnHotPlugged */
2489 NULL,
2490 /* pfnHotUnplugged */
2491 NULL,
2492 /* pfnDriverAttach */
2493 usbNetDriverAttach,
2494 /* pfnDriverDetach */
2495 usbNetDriverDetach,
2496 /* pfnQueryInterface */
2497 NULL,
2498 /* pfnUsbReset */
2499 usbNetUsbReset,
2500 /* pfnUsbGetDescriptorCache */
2501 usbNetUsbGetDescriptorCache,
2502 /* pfnUsbSetConfiguration */
2503 usbNetUsbSetConfiguration,
2504 /* pfnUsbSetInterface */
2505 usbNetUsbSetInterface,
2506 /* pfnUsbClearHaltedEndpoint */
2507 usbNetUsbClearHaltedEndpoint,
2508 /* pfnUrbNew */
2509 NULL/*usbNetUrbNew*/,
2510 /* pfnQueue */
2511 usbNetQueue,
2512 /* pfnUrbCancel */
2513 usbNetUrbCancel,
2514 /* pfnUrbReap */
2515 usbNetUrbReap,
2516 /* pfnWakeup */
2517 usbNetWakeup,
2518 /* u32TheEnd */
2519 PDM_USBREG_VERSION
2520};
2521
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