VirtualBox

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

Last change on this file since 107317 was 107317, checked in by vboxsync, 5 weeks ago

UsbNet: bugref:10779 Public statistics, also added missing PDMUsbHlpSTAMRegisterF to pdmusb.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 83.7 KB
Line 
1/* $Id: UsbNet.cpp 107317 2024-12-13 13:21:33Z 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 /** Whether to signal the reset semaphore when the current request completes. */
410 bool fSignalResetSem;
411 /** Semaphore usbNetUsbReset waits on when a request is executing at reset
412 * time. Only signalled when fSignalResetSem is set. */
413 RTSEMEVENTMULTI hEvtReset;
414 /** The reset URB.
415 * This is waiting for SCSI request completion before finishing the reset. */
416 PVUSBURB pResetUrb;
417
418 STAMCOUNTER StatReceiveBytes;
419 STAMCOUNTER StatTransmitBytes;
420
421 /**
422 * LUN\#0 data.
423 */
424 struct
425 {
426 /** LUN\#0 + status LUN: The base interface. */
427 PDMIBASE IBase;
428 /** LUN\#0: The network port interface. */
429 PDMINETWORKDOWN INetworkDown;
430 /** LUN\#0: The network config port interface. */
431 PDMINETWORKCONFIG INetworkConfig;
432
433 /** Pointer to the connector of the attached network driver. */
434 PPDMINETWORKUPR3 pINetwork;
435 /** Pointer to the attached network driver. */
436 R3PTRTYPE(PPDMIBASE) pIBase;
437 } Lun0;
438
439} USBNET;
440/** Pointer to the USB Ethernet instance data. */
441typedef USBNET *PUSBNET;
442
443
444/*********************************************************************************************************************************
445* Global Variables *
446*********************************************************************************************************************************/
447static const USBNCMFUNCDESC g_UsbNetFuncDesc =
448{
449 {
450 { 5, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_HEADER },
451 0x0110
452 },
453 {
454 { 5, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_UNION },
455 0,
456 1
457 },
458 {
459 { 13, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_ETHERNET_NETWORKING },
460 USBNET_STR_ID_MAC_ADDRESS,
461 0,
462 1514,
463 0,
464 0
465 },
466 {
467 { 6, USB_CDC_DESCRIPTOR_TYPE_INTERFACE, USB_CDC_DESCRIPTOR_SUB_TYPE_NCM },
468 0x0100,
469 0
470 }
471};
472
473
474static const VUSBDESCIAD g_UsbNetInterfaceIad =
475{
476 sizeof(VUSBDESCIAD), // bLength;
477 VUSB_DT_INTERFACE_ASSOCIATION, // bDescriptorType;
478 0, // bFirstInterface;
479 2, // bInterfaceCount;
480 2, // bFunctionClass;
481 0x0d, // bFunctionSubClass;
482 0, // bFunctionProtocol;
483 0 // iFunction;
484};
485
486
487static const VUSBDESCENDPOINTEX g_aUsbNetEndpointDescsAlt1FS[3] =
488{
489 {
490 {
491 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
492 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
493 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
494 /* .bmAttributes = */ 2 /* bulk */,
495 /* .wMaxPacketSize = */ 64 /* maximum possible */,
496 /* .bInterval = */ 0 /* not applicable for bulk EP */
497 },
498 /* .pvMore = */ NULL,
499 /* .pvClass = */ NULL,
500 /* .cbClass = */ 0,
501 /* .pvSsepc = */ NULL,
502 /* .cbSsepc = */ 0
503 },
504 {
505 {
506 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
507 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
508 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
509 /* .bmAttributes = */ 2 /* bulk */,
510 /* .wMaxPacketSize = */ 64 /* maximum possible */,
511 /* .bInterval = */ 0 /* not applicable for bulk EP */
512 },
513 /* .pvMore = */ NULL,
514 /* .pvClass = */ NULL,
515 /* .cbClass = */ 0,
516 /* .pvSsepc = */ NULL,
517 /* .cbSsepc = */ 0
518 },
519 {
520 {
521 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
522 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
523 /* .bEndpointAddress = */ 0x83 /* ep=3, in */,
524 /* .bmAttributes = */ 3 /* interrupt */,
525 /* .wMaxPacketSize = */ 64,
526 /* .bInterval = */ 10,
527 },
528 /* .pvMore = */ NULL,
529 /* .pvClass = */ NULL,
530 /* .cbClass = */ 0
531 },
532};
533
534static const VUSBDESCENDPOINTEX g_aUsbNetEndpointDescsAlt1HS[3] =
535{
536 {
537 {
538 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
539 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
540 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
541 /* .bmAttributes = */ 2 /* bulk */,
542 /* .wMaxPacketSize = */ 512 /* HS bulk packet size */,
543 /* .bInterval = */ 0 /* no NAKs */
544 },
545 /* .pvMore = */ NULL,
546 /* .pvClass = */ NULL,
547 /* .cbClass = */ 0,
548 /* .pvSsepc = */ NULL,
549 /* .cbSsepc = */ 0
550 },
551 {
552 {
553 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
554 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
555 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
556 /* .bmAttributes = */ 2 /* bulk */,
557 /* .wMaxPacketSize = */ 512 /* HS bulk packet size */,
558 /* .bInterval = */ 0 /* no NAKs */
559 },
560 /* .pvMore = */ NULL,
561 /* .pvClass = */ NULL,
562 /* .cbClass = */ 0,
563 /* .pvSsepc = */ NULL,
564 /* .cbSsepc = */ 0
565 },
566 {
567 {
568 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
569 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
570 /* .bEndpointAddress = */ 0x83 /* ep=3, in */,
571 /* .bmAttributes = */ 3 /* interrupt */,
572 /* .wMaxPacketSize = */ 64,
573 /* .bInterval = */ 10,
574 },
575 /* .pvMore = */ NULL,
576 /* .pvClass = */ NULL,
577 /* .cbClass = */ 0
578 },
579};
580
581static const VUSBDESCSSEPCOMPANION g_aUsbNetEpCompanionSS =
582{
583 /* .bLength = */ sizeof(VUSBDESCSSEPCOMPANION),
584 /* .bDescriptorType = */ VUSB_DT_SS_ENDPOINT_COMPANION,
585 /* .bMaxBurst = */ 15 /* we can burst all the way */,
586 /* .bmAttributes = */ 0 /* no streams */,
587 /* .wBytesPerInterval = */ 0 /* not a periodic endpoint */
588};
589
590static const VUSBDESCENDPOINTEX g_aUsbNetEndpointDescsAlt1SS[3] =
591{
592 {
593 {
594 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
595 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
596 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
597 /* .bmAttributes = */ 2 /* bulk */,
598 /* .wMaxPacketSize = */ 1024 /* SS bulk packet size */,
599 /* .bInterval = */ 0 /* no NAKs */
600 },
601 /* .pvMore = */ NULL,
602 /* .pvClass = */ NULL,
603 /* .cbClass = */ 0,
604 /* .pvSsepc = */ &g_aUsbNetEpCompanionSS,
605 /* .cbSsepc = */ sizeof(g_aUsbNetEpCompanionSS)
606 },
607 {
608 {
609 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
610 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
611 /* .bEndpointAddress = */ 0x02 /* ep=2, out */,
612 /* .bmAttributes = */ 2 /* bulk */,
613 /* .wMaxPacketSize = */ 1024 /* SS bulk packet size */,
614 /* .bInterval = */ 0 /* no NAKs */
615 },
616 /* .pvMore = */ NULL,
617 /* .pvClass = */ NULL,
618 /* .cbClass = */ 0,
619 /* .pvSsepc = */ &g_aUsbNetEpCompanionSS,
620 /* .cbSsepc = */ sizeof(g_aUsbNetEpCompanionSS)
621 },
622 {
623 {
624 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
625 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
626 /* .bEndpointAddress = */ 0x83 /* ep=3, in */,
627 /* .bmAttributes = */ 3 /* interrupt */,
628 /* .wMaxPacketSize = */ 64,
629 /* .bInterval = */ 10,
630 },
631 /* .pvMore = */ NULL,
632 /* .pvClass = */ NULL,
633 /* .cbClass = */ 0,
634 /* .pvSsepc = */ &g_aUsbNetEpCompanionSS,
635 /* .cbSsepc = */ sizeof(g_aUsbNetEpCompanionSS)
636 },
637};
638
639
640static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescFS_0[] =
641{
642 {
643 {
644 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
645 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
646 /* .bInterfaceNumber = */ 0,
647 /* .bAlternateSetting = */ 0,
648 /* .bNumEndpoints = */ 1,
649 /* .bInterfaceClass = */ 2 /* Communications Device */,
650 /* .bInterfaceSubClass = */ 0x0d /* Communications Device Subclass / NCM */,
651 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
652 /* .iInterface = */ 0
653 },
654 /* .pvMore = */ NULL,
655 /* .pvClass = */ &g_UsbNetFuncDesc,
656 /* .cbClass = */ sizeof(g_UsbNetFuncDesc),
657 /* .paEndpoints = */ &g_aUsbNetEndpointDescsAlt1FS[2],
658 /* .pIAD = */ &g_UsbNetInterfaceIad,
659 /* .cbIAD = */ sizeof(g_UsbNetInterfaceIad)
660 }
661};
662
663static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescFS_1[] =
664{
665 {
666 {
667 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
668 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
669 /* .bInterfaceNumber = */ 1,
670 /* .bAlternateSetting = */ 0,
671 /* .bNumEndpoints = */ 0,
672 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
673 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
674 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
675 /* .iInterface = */ 0
676 },
677 /* .pvMore = */ NULL,
678 /* .pvClass = */ NULL,
679 /* .cbClass = */ 0,
680 NULL,
681 /* .pIAD = */ NULL,
682 /* .cbIAD = */ 0
683 },
684 {
685 {
686 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
687 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
688 /* .bInterfaceNumber = */ 1,
689 /* .bAlternateSetting = */ 1,
690 /* .bNumEndpoints = */ 2,
691 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
692 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
693 /* .bInterfaceProtocol = */ 1 /* No encapsulated commands / responses */,
694 /* .iInterface = */ 0
695 },
696 /* .pvMore = */ NULL,
697 /* .pvClass = */ NULL,
698 /* .cbClass = */ 0,
699 &g_aUsbNetEndpointDescsAlt1FS[0],
700 /* .pIAD = */ NULL, //&g_UsbNetInterfaceIad,
701 /* .cbIAD = */ 0, //sizeof(g_UsbNetInterfaceIad)
702 }
703};
704
705
706static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescHS_0[] =
707{
708 {
709 {
710 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
711 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
712 /* .bInterfaceNumber = */ 0,
713 /* .bAlternateSetting = */ 0,
714 /* .bNumEndpoints = */ 1,
715 /* .bInterfaceClass = */ 2 /* Communications Device */,
716 /* .bInterfaceSubClass = */ 0x0d /* Communications Device Subclass / NCM */,
717 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
718 /* .iInterface = */ 0
719 },
720 /* .pvMore = */ NULL,
721 /* .pvClass = */ &g_UsbNetFuncDesc,
722 /* .cbClass = */ sizeof(g_UsbNetFuncDesc),
723 /* .paEndpoints = */ &g_aUsbNetEndpointDescsAlt1HS[2],
724 /* .pIAD = */ &g_UsbNetInterfaceIad,
725 /* .cbIAD = */ sizeof(g_UsbNetInterfaceIad)
726 }
727};
728
729static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescHS_1[] =
730{
731 {
732 {
733 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
734 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
735 /* .bInterfaceNumber = */ 1,
736 /* .bAlternateSetting = */ 0,
737 /* .bNumEndpoints = */ 0,
738 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
739 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
740 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
741 /* .iInterface = */ 0
742 },
743 /* .pvMore = */ NULL,
744 /* .pvClass = */ NULL,
745 /* .cbClass = */ 0,
746 NULL,
747 /* .pIAD = */ NULL,
748 /* .cbIAD = */ 0
749 },
750 {
751 {
752 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
753 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
754 /* .bInterfaceNumber = */ 1,
755 /* .bAlternateSetting = */ 1,
756 /* .bNumEndpoints = */ 2,
757 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
758 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
759 /* .bInterfaceProtocol = */ 1 /* No encapsulated commands / responses */,
760 /* .iInterface = */ 0
761 },
762 /* .pvMore = */ NULL,
763 /* .pvClass = */ NULL,
764 /* .cbClass = */ 0,
765 &g_aUsbNetEndpointDescsAlt1HS[0],
766 /* .pIAD = */ NULL, //&g_UsbNetInterfaceIad,
767 /* .cbIAD = */ 0, //sizeof(g_UsbNetInterfaceIad)
768 }
769};
770
771
772static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescSS_0[] =
773{
774 {
775 {
776 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
777 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
778 /* .bInterfaceNumber = */ 0,
779 /* .bAlternateSetting = */ 0,
780 /* .bNumEndpoints = */ 1,
781 /* .bInterfaceClass = */ 2 /* Communications Device */,
782 /* .bInterfaceSubClass = */ 0x0d /* Communications Device Subclass / NCM */,
783 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
784 /* .iInterface = */ 0
785 },
786 /* .pvMore = */ NULL,
787 /* .pvClass = */ &g_UsbNetFuncDesc,
788 /* .cbClass = */ sizeof(g_UsbNetFuncDesc),
789 /* .paEndpoints = */ &g_aUsbNetEndpointDescsAlt1SS[2],
790 /* .pIAD = */ &g_UsbNetInterfaceIad,
791 /* .cbIAD = */ sizeof(g_UsbNetInterfaceIad)
792 }
793};
794
795static const VUSBDESCINTERFACEEX g_aUsbNetInterfaceDescSS_1[] =
796{
797 {
798 {
799 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
800 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
801 /* .bInterfaceNumber = */ 1,
802 /* .bAlternateSetting = */ 0,
803 /* .bNumEndpoints = */ 0,
804 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
805 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
806 /* .bInterfaceProtocol = */ 0 /* No encapsulated commands / responses */,
807 /* .iInterface = */ 0
808 },
809 /* .pvMore = */ NULL,
810 /* .pvClass = */ NULL,
811 /* .cbClass = */ 0,
812 NULL,
813 /* .pIAD = */ NULL,
814 /* .cbIAD = */ 0
815 },
816 {
817 {
818 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
819 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
820 /* .bInterfaceNumber = */ 1,
821 /* .bAlternateSetting = */ 1,
822 /* .bNumEndpoints = */ 2,
823 /* .bInterfaceClass = */ 0x0a /* Communications Device */,
824 /* .bInterfaceSubClass = */ 0 /* Communications Device Subclass / NCM */,
825 /* .bInterfaceProtocol = */ 1 /* No encapsulated commands / responses */,
826 /* .iInterface = */ 0
827 },
828 /* .pvMore = */ NULL,
829 /* .pvClass = */ NULL,
830 /* .cbClass = */ 0,
831 &g_aUsbNetEndpointDescsAlt1SS[0],
832 /* .pIAD = */ NULL, //&g_UsbNetInterfaceIad,
833 /* .cbIAD = */ 0, //sizeof(g_UsbNetInterfaceIad)
834 }
835};
836
837static const VUSBINTERFACE g_aUsbNetInterfacesFS[] =
838{
839 { g_aUsbNetInterfaceDescFS_0, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescFS_0) },
840 { g_aUsbNetInterfaceDescFS_1, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescFS_1) },
841};
842
843static const VUSBINTERFACE g_aUsbNetInterfacesHS[] =
844{
845 { g_aUsbNetInterfaceDescHS_0, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescHS_0) },
846 { g_aUsbNetInterfaceDescHS_1, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescHS_1) },
847};
848
849static const VUSBINTERFACE g_aUsbNetInterfacesSS[] =
850{
851 { g_aUsbNetInterfaceDescSS_0, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescSS_0) },
852 { g_aUsbNetInterfaceDescSS_1, /* .cSettings = */ RT_ELEMENTS(g_aUsbNetInterfaceDescSS_1) },
853};
854
855static const VUSBDESCCONFIGEX g_UsbNetConfigDescFS =
856{
857 {
858 /* .bLength = */ sizeof(VUSBDESCCONFIG),
859 /* .bDescriptorType = */ VUSB_DT_CONFIG,
860 /* .wTotalLength = */ 0 /* recalculated on read */,
861 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbNetInterfacesFS),
862 /* .bConfigurationValue =*/ 1,
863 /* .iConfiguration = */ 0,
864 /* .bmAttributes = */ RT_BIT(7),
865 /* .MaxPower = */ 50 /* 100mA */
866 },
867 NULL, /* pvMore */
868 NULL, /* pvClass */
869 0, /* cbClass */
870 &g_aUsbNetInterfacesFS[0],
871 NULL /* pvOriginal */
872};
873
874static const VUSBDESCCONFIGEX g_UsbNetConfigDescHS =
875{
876 {
877 /* .bLength = */ sizeof(VUSBDESCCONFIG),
878 /* .bDescriptorType = */ VUSB_DT_CONFIG,
879 /* .wTotalLength = */ 0 /* recalculated on read */,
880 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbNetInterfacesHS),
881 /* .bConfigurationValue =*/ 1,
882 /* .iConfiguration = */ 0,
883 /* .bmAttributes = */ RT_BIT(7),
884 /* .MaxPower = */ 50 /* 100mA */
885 },
886 NULL, /* pvMore */
887 NULL, /* pvClass */
888 0, /* cbClass */
889 &g_aUsbNetInterfacesHS[0],
890 NULL /* pvOriginal */
891};
892
893static const VUSBDESCCONFIGEX g_UsbNetConfigDescSS =
894{
895 {
896 /* .bLength = */ sizeof(VUSBDESCCONFIG),
897 /* .bDescriptorType = */ VUSB_DT_CONFIG,
898 /* .wTotalLength = */ 0 /* recalculated on read */,
899 /* .bNumInterfaces = */ 2,
900 /* .bConfigurationValue =*/ 1,
901 /* .iConfiguration = */ 0,
902 /* .bmAttributes = */ RT_BIT(7),
903 /* .MaxPower = */ 50 /* 100mA */
904 },
905 NULL, /* pvMore */
906 NULL, /* pvClass */
907 0, /* cbClass */
908 &g_aUsbNetInterfacesSS[0],
909 NULL /* pvOriginal */
910};
911
912static const VUSBDESCDEVICE g_UsbNetDeviceDesc20 =
913{
914 /* .bLength = */ sizeof(g_UsbNetDeviceDesc20),
915 /* .bDescriptorType = */ VUSB_DT_DEVICE,
916 /* .bcdUsb = */ 0x200, /* USB 2.0 */
917 /* .bDeviceClass = */ 2 /* Class specified in the interface desc. */,
918 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
919 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
920 /* .bMaxPacketSize0 = */ 64,
921 /* .idVendor = */ VBOX_USB_VENDOR,
922 /* .idProduct = */ USBNET_PID,
923 /* .bcdDevice = */ 0x0100, /* 1.0 */
924 /* .iManufacturer = */ USBNET_STR_ID_MANUFACTURER,
925 /* .iProduct = */ USBNET_STR_ID_PRODUCT,
926 /* .iSerialNumber = */ 0,
927 /* .bNumConfigurations = */ 1
928};
929
930static const VUSBDESCDEVICE g_UsbNetDeviceDesc30 =
931{
932 /* .bLength = */ sizeof(g_UsbNetDeviceDesc30),
933 /* .bDescriptorType = */ VUSB_DT_DEVICE,
934 /* .bcdUsb = */ 0x300, /* USB 2.0 */
935 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
936 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
937 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
938 /* .bMaxPacketSize0 = */ 9 /* 512, the only option for USB3. */,
939 /* .idVendor = */ VBOX_USB_VENDOR,
940 /* .idProduct = */ USBNET_PID,
941 /* .bcdDevice = */ 0x0110, /* 1.10 */
942 /* .iManufacturer = */ USBNET_STR_ID_MANUFACTURER,
943 /* .iProduct = */ USBNET_STR_ID_PRODUCT,
944 /* .iSerialNumber = */ 0,
945 /* .bNumConfigurations = */ 1
946};
947
948static const VUSBDEVICEQUALIFIER g_UsbNetDeviceQualifier =
949{
950 /* .bLength = */ sizeof(g_UsbNetDeviceQualifier),
951 /* .bDescriptorType = */ VUSB_DT_DEVICE_QUALIFIER,
952 /* .bcdUsb = */ 0x200, /* USB 2.0 */
953 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
954 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
955 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
956 /* .bMaxPacketSize0 = */ 64,
957 /* .bNumConfigurations = */ 1,
958 /* .bReserved = */ 0
959};
960
961static const struct {
962 VUSBDESCBOS bos;
963 VUSBDESCSSDEVCAP sscap;
964} g_UsbNetBOS =
965{
966 {
967 /* .bLength = */ sizeof(g_UsbNetBOS.bos),
968 /* .bDescriptorType = */ VUSB_DT_BOS,
969 /* .wTotalLength = */ sizeof(g_UsbNetBOS),
970 /* .bNumDeviceCaps = */ 1
971 },
972 {
973 /* .bLength = */ sizeof(VUSBDESCSSDEVCAP),
974 /* .bDescriptorType = */ VUSB_DT_DEVICE_CAPABILITY,
975 /* .bDevCapabilityType = */ VUSB_DCT_SUPERSPEED_USB,
976 /* .bmAttributes = */ 0 /* No LTM. */,
977 /* .wSpeedsSupported = */ 0xe /* Any speed is good. */,
978 /* .bFunctionalitySupport = */ 2 /* Want HS at least. */,
979 /* .bU1DevExitLat = */ 0, /* We are blazingly fast. */
980 /* .wU2DevExitLat = */ 0
981 }
982};
983
984
985/*********************************************************************************************************************************
986* Internal Functions *
987*********************************************************************************************************************************/
988static int usbNetHandleBulkDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb);
989
990
991/**
992 * Initializes an URB queue.
993 *
994 * @param pQueue The URB queue.
995 */
996static void usbNetQueueInit(PUSBNETURBQUEUE pQueue)
997{
998 pQueue->pHead = NULL;
999 pQueue->ppTail = &pQueue->pHead;
1000}
1001
1002
1003
1004/**
1005 * Inserts an URB at the end of the queue.
1006 *
1007 * @param pQueue The URB queue.
1008 * @param pUrb The URB to insert.
1009 */
1010DECLINLINE(void) usbNetQueueAddTail(PUSBNETURBQUEUE pQueue, PVUSBURB pUrb)
1011{
1012 pUrb->Dev.pNext = NULL;
1013 *pQueue->ppTail = pUrb;
1014 pQueue->ppTail = &pUrb->Dev.pNext;
1015}
1016
1017
1018/**
1019 * Unlinks the head of the queue and returns it.
1020 *
1021 * @returns The head entry.
1022 * @param pQueue The URB queue.
1023 */
1024DECLINLINE(PVUSBURB) usbNetQueueRemoveHead(PUSBNETURBQUEUE pQueue)
1025{
1026 PVUSBURB pUrb = pQueue->pHead;
1027 if (pUrb)
1028 {
1029 PVUSBURB pNext = pUrb->Dev.pNext;
1030 pQueue->pHead = pNext;
1031 if (!pNext)
1032 pQueue->ppTail = &pQueue->pHead;
1033 else
1034 pUrb->Dev.pNext = NULL;
1035 }
1036 return pUrb;
1037}
1038
1039
1040/**
1041 * Removes an URB from anywhere in the queue.
1042 *
1043 * @returns true if found, false if not.
1044 * @param pQueue The URB queue.
1045 * @param pUrb The URB to remove.
1046 */
1047DECLINLINE(bool) usbNetQueueRemove(PUSBNETURBQUEUE pQueue, PVUSBURB pUrb)
1048{
1049 PVUSBURB pCur = pQueue->pHead;
1050 if (pCur == pUrb)
1051 pQueue->pHead = pUrb->Dev.pNext;
1052 else
1053 {
1054 while (pCur)
1055 {
1056 if (pCur->Dev.pNext == pUrb)
1057 {
1058 pCur->Dev.pNext = pUrb->Dev.pNext;
1059 break;
1060 }
1061 pCur = pCur->Dev.pNext;
1062 }
1063 if (!pCur)
1064 return false;
1065 }
1066 if (!pUrb->Dev.pNext)
1067 pQueue->ppTail = &pQueue->pHead;
1068 return true;
1069}
1070
1071
1072/**
1073 * Checks if the queue is empty or not.
1074 *
1075 * @returns true if it is, false if it isn't.
1076 * @param pQueue The URB queue.
1077 */
1078DECLINLINE(bool) usbNetQueueIsEmpty(PCUSBNETURBQUEUE pQueue)
1079{
1080 return pQueue->pHead == NULL;
1081}
1082
1083
1084/**
1085 * Links an URB into the done queue.
1086 *
1087 * @param pThis The USBNET instance.
1088 * @param pUrb The URB.
1089 */
1090static void usbNetLinkDone(PUSBNET pThis, PVUSBURB pUrb)
1091{
1092 usbNetQueueAddTail(&pThis->DoneQueue, pUrb);
1093
1094 if (pThis->fHaveDoneQueueWaiter)
1095 {
1096 int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
1097 AssertRC(rc);
1098 }
1099}
1100
1101
1102/**
1103 * Completes the URB with a stalled state, halting the pipe.
1104 */
1105static int usbNetCompleteStall(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb, const char *pszWhy)
1106{
1107 RT_NOREF(pszWhy);
1108 Log(("usbNetCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
1109
1110 pUrb->enmStatus = VUSBSTATUS_STALL;
1111
1112 /** @todo figure out if the stall is global or pipe-specific or both. */
1113 if (pEp)
1114 pEp->fHalted = true;
1115 else
1116 {
1117 pThis->aEps[1].fHalted = true;
1118 pThis->aEps[2].fHalted = true;
1119 pThis->aEps[3].fHalted = true;
1120 }
1121
1122 usbNetLinkDone(pThis, pUrb);
1123 return VINF_SUCCESS;
1124}
1125
1126
1127/**
1128 * Completes the URB with a OK state.
1129 */
1130static int usbNetCompleteOk(PUSBNET pThis, PVUSBURB pUrb, size_t cbData)
1131{
1132 Log(("usbNetCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
1133
1134 pUrb->enmStatus = VUSBSTATUS_OK;
1135 pUrb->cbData = (uint32_t)cbData;
1136
1137 usbNetLinkDone(pThis, pUrb);
1138 return VINF_SUCCESS;
1139}
1140
1141
1142/**
1143 * Completes the URB after device successfully processed it. Optionally copies data
1144 * into the URB. May still generate an error if the URB is not big enough.
1145 */
1146static void usbNetCompleteNotificationOk(PUSBNET pThis, PVUSBURB pUrb, const void *pSrc, size_t cbSrc)
1147{
1148 Log(("usbNetCompleteNotificationOk/#%u: pUrb=%p:%s (cbData=%#x) cbSrc=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->cbData, cbSrc));
1149
1150 pUrb->enmStatus = VUSBSTATUS_OK;
1151 if (pSrc) /* Can be NULL if not copying anything. */
1152 {
1153 Assert(cbSrc);
1154 uint8_t *pDst = pUrb->abData;
1155
1156 /* Returned data is written after the setup message in control URBs. */
1157 Assert (pUrb->enmType == VUSBXFERTYPE_INTR);
1158
1159 /* There is at least one byte of room in the URB. */
1160 size_t cbCopy = RT_MIN(pUrb->cbData, cbSrc);
1161 memcpy(pDst, pSrc, cbCopy);
1162 pUrb->cbData = (uint32_t)cbCopy;
1163 Log(("Copied %zu bytes to pUrb->abData, source had %zu bytes\n", cbCopy, cbSrc));
1164
1165 /*
1166 * Need to check length differences. If cbSrc is less than what
1167 * the URB has space for, it'll be resolved as a short packet. But
1168 * if cbSrc is bigger, there is a real problem and the host needs
1169 * to see an overrun/babble error.
1170 */
1171 if (RT_UNLIKELY(cbSrc > cbCopy))
1172 pUrb->enmStatus = VUSBSTATUS_DATA_OVERRUN;
1173 }
1174 else
1175 Assert(cbSrc == 0); /* Make up your mind, caller! */
1176
1177 usbNetLinkDone(pThis, pUrb);
1178}
1179
1180
1181/**
1182 * Reset worker for usbNetUsbReset, usbNetUsbSetConfiguration and
1183 * usbNetUrbHandleDefaultPipe.
1184 *
1185 * @returns VBox status code.
1186 * @param pThis The MSD instance.
1187 * @param pUrb Set when usbNetUrbHandleDefaultPipe is the
1188 * caller.
1189 * @param fSetConfig Set when usbNetUsbSetConfiguration is the
1190 * caller.
1191 */
1192static int usbNetResetWorker(PUSBNET pThis, PVUSBURB pUrb, bool fSetConfig)
1193{
1194 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
1195 pThis->aEps[i].fHalted = false;
1196
1197 if (!pUrb && !fSetConfig) /* (only device reset) */
1198 pThis->bConfigurationValue = 0; /* default */
1199
1200 pThis->idSequence = 0;
1201
1202 /*
1203 * Ditch all pending URBs.
1204 */
1205 PVUSBURB pCurUrb;
1206 while ((pCurUrb = usbNetQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
1207 {
1208 pCurUrb->enmStatus = VUSBSTATUS_CRC;
1209 usbNetLinkDone(pThis, pCurUrb);
1210 }
1211
1212 while ((pCurUrb = usbNetQueueRemoveHead(&pThis->ToHostIntrQueue)) != NULL)
1213 {
1214 pCurUrb->enmStatus = VUSBSTATUS_CRC;
1215 usbNetLinkDone(pThis, pCurUrb);
1216 }
1217
1218 pCurUrb = pThis->pResetUrb;
1219 if (pCurUrb)
1220 {
1221 pThis->pResetUrb = NULL;
1222 pCurUrb->enmStatus = VUSBSTATUS_CRC;
1223 usbNetLinkDone(pThis, pCurUrb);
1224 }
1225
1226 if (pUrb)
1227 return usbNetCompleteOk(pThis, pUrb, 0);
1228 return VINF_SUCCESS;
1229}
1230
1231
1232/**
1233 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1234 */
1235static DECLCALLBACK(void *) usbNetLun0QueryInterface(PPDMIBASE pInterface, const char *pszIID)
1236{
1237 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.IBase);
1238 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
1239 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKCONFIG, &pThis->Lun0.INetworkConfig);
1240 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->Lun0.INetworkDown);
1241 return NULL;
1242}
1243
1244
1245static DECLCALLBACK(int) usbNetNetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
1246{
1247 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkDown);
1248
1249 RTCritSectEnter(&pThis->CritSect);
1250 if (!usbNetQueueIsEmpty(&pThis->ToHostQueue))
1251 {
1252 RTCritSectLeave(&pThis->CritSect);
1253 return VINF_SUCCESS;
1254 }
1255 pThis->fHaveToHostQueueWaiter = true;
1256 RTCritSectLeave(&pThis->CritSect);
1257
1258 int rc = RTSemEventWait(pThis->hEvtToHostQueue, cMillies);
1259 ASMAtomicXchgBool(&pThis->fHaveToHostQueueWaiter, false);
1260 return rc;
1261}
1262
1263
1264/**
1265 * Receive data and pass it to lwIP for processing.
1266 *
1267 * @returns VBox status code
1268 * @param pInterface PDM network port interface pointer.
1269 * @param pvBuf Pointer to frame data.
1270 * @param cb Frame size.
1271 */
1272static DECLCALLBACK(int) usbNetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
1273{
1274 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkDown);
1275
1276 RTCritSectEnter(&pThis->CritSect);
1277
1278 if (usbNetQueueIsEmpty(&pThis->ToHostQueue))
1279 {
1280 RTCritSectLeave(&pThis->CritSect);
1281 return VINF_SUCCESS;
1282 }
1283
1284 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->ToHostQueue);
1285 PUSBNETEP pEp = &pThis->aEps[2];
1286
1287 if (RT_UNLIKELY(pEp->fHalted))
1288 {
1289 usbNetCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1290 RTCritSectLeave(&pThis->CritSect);
1291 return VINF_SUCCESS;
1292 }
1293
1294 if (pUrb->cbData < sizeof(USBNCMNTH16) + sizeof(USBNCMNDP16) + cb)
1295 {
1296 Log(("UsbNet: Receive URB too small (%#x vs %#x)\n", pUrb->cbData, sizeof(USBNCMNTH16) + sizeof(USBNCMNDP16) + cb));
1297 pUrb->enmStatus = VUSBSTATUS_DATA_OVERRUN;
1298 usbNetLinkDone(pThis, pUrb);
1299 RTCritSectLeave(&pThis->CritSect);
1300 return VINF_SUCCESS;
1301 }
1302
1303 PUSBNCMNTH16 pNth16 = (PUSBNCMNTH16)&pUrb->abData[0];
1304 PUSBNCMNDP16 pNdp16 = (PUSBNCMNDP16)(pNth16 + 1);
1305
1306 /* Build NTH16. */
1307 pNth16->dwSignature = USBNCMNTH16_SIGNATURE;
1308 pNth16->wHeaderLength = sizeof(*pNth16);
1309 pNth16->wSequence = pThis->idSequence++;
1310 pNth16->wBlockLength = (uint16_t)(sizeof(*pNth16) + sizeof(*pNdp16) + cb);
1311 pNth16->wNdpIndex = sizeof(*pNth16);
1312
1313 /* Build NDP16. */
1314 pNdp16->dwSignature = USBNCMNDP16_SIGNATURE_NCM0;
1315 pNdp16->wLength = sizeof(*pNdp16);
1316 pNdp16->wNextNdpIndex = 0;
1317 pNdp16->DataGram0.wDatagramIndex = sizeof(*pNth16) + sizeof(*pNdp16);
1318 pNdp16->DataGram0.wDatagramLength = (uint16_t)cb;
1319 pNdp16->DataGram1.wDatagramIndex = 0;
1320 pNdp16->DataGram1.wDatagramLength = 0;
1321
1322 /* Copy frame over. */
1323 memcpy(pNdp16 + 1, pvBuf, cb);
1324
1325 pUrb->cbData = (uint32_t)(sizeof(*pNth16) + sizeof(*pNdp16) + cb);
1326 usbNetLinkDone(pThis, pUrb);
1327 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb);
1328 RTCritSectLeave(&pThis->CritSect);
1329
1330 LogFlow(("%s: return %Rrc\n", __FUNCTION__, VINF_SUCCESS));
1331 return VINF_SUCCESS;
1332}
1333
1334/**
1335 * @interface_method_impl{PDMINETWORKDOWN,pfnXmitPending}
1336 */
1337static DECLCALLBACK(void) usbNetNetworkDown_XmitPending(PPDMINETWORKDOWN pInterface)
1338{
1339 RT_NOREF(pInterface);
1340}
1341
1342
1343/* -=-=-=-=-=- USBNET::INetworkConfig -=-=-=-=-=- */
1344
1345/**
1346 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetMac}
1347 */
1348static DECLCALLBACK(int) usbNetGetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
1349{
1350 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1351
1352 LogFlowFunc(("#%d\n", pThis->pUsbIns->iInstance));
1353 memcpy(pMac, &pThis->MacConfigured, sizeof(*pMac));
1354 return VINF_SUCCESS;
1355}
1356
1357
1358/**
1359 * @interface_method_impl{PDMINETWORKCONFIG,pfnGetLinkState}
1360 */
1361static DECLCALLBACK(PDMNETWORKLINKSTATE) usbNetGetLinkState(PPDMINETWORKCONFIG pInterface)
1362{
1363 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1364
1365 if (pThis->fLinkUp && !pThis->fLinkTempDown)
1366 return PDMNETWORKLINKSTATE_UP;
1367 if (!pThis->fLinkUp)
1368 return PDMNETWORKLINKSTATE_DOWN;
1369 if (pThis->fLinkTempDown)
1370 return PDMNETWORKLINKSTATE_DOWN_RESUME;
1371 AssertMsgFailed(("Invalid link state!\n"));
1372 return PDMNETWORKLINKSTATE_INVALID;
1373}
1374
1375
1376DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState);
1377
1378/**
1379 * @callback_method_impl{FNTMTIMERUSB}
1380 *
1381 * By the time the host resumes after sleep the network environment may have changed considerably.
1382 * We handle this by temporarily lowering the link state. This callback brings the link back up.
1383 */
1384static DECLCALLBACK(void) usbNetTimerLinkUp(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, void *pvUser)
1385{
1386 PUSBNET pThis = (PUSBNET)pvUser;
1387 RT_NOREF(pUsbIns, hTimer);
1388
1389 LogFlowFunc(("#%d\n", pUsbIns->iInstance));
1390
1391 /** @todo Do we really care for potential races with link state? */
1392 pThis->fLinkTempDown = false;
1393 if (!pThis->fLinkUp)
1394 usbNetLinkStateNotify(pThis, PDMNETWORKLINKSTATE_UP);
1395}
1396
1397
1398/**
1399 * @interface_method_impl{PDMINETWORKCONFIG,pfnSetLinkState}
1400 */
1401static DECLCALLBACK(int) usbNetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
1402{
1403 PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
1404
1405 bool fLinkUp = enmState == PDMNETWORKLINKSTATE_UP;
1406
1407 LogFlowFunc(("#%d enmState=%d\n", pThis->pUsbIns->iInstance, enmState));
1408 AssertMsgReturn(enmState > PDMNETWORKLINKSTATE_INVALID && enmState <= PDMNETWORKLINKSTATE_DOWN_RESUME,
1409 ("Invalid link state: enmState=%d\n", enmState), VERR_INVALID_PARAMETER);
1410
1411 if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
1412 {
1413 pThis->fLinkTempDown = true;
1414 /* Do not bother to notify anyone if the link has been down */
1415 PDMUsbHlpTimerSetMillies(pThis->pUsbIns, pThis->hTimerLinkUp, 500); /* 0.5 sec */
1416 }
1417 /* has the state changed? */
1418 if (pThis->fLinkUp != fLinkUp)
1419 {
1420 pThis->fLinkUp = fLinkUp;
1421 usbNetLinkStateNotify(pThis, enmState);
1422 }
1423 return VINF_SUCCESS;
1424}
1425
1426
1427
1428/**
1429 * @interface_method_impl{PDMUSBREG,pfnUrbReap}
1430 */
1431static DECLCALLBACK(PVUSBURB) usbNetUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
1432{
1433 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1434 LogFlow(("usbNetUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
1435
1436 RTCritSectEnter(&pThis->CritSect);
1437
1438 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->DoneQueue);
1439 if (!pUrb && cMillies)
1440 {
1441 /* Wait */
1442 pThis->fHaveDoneQueueWaiter = true;
1443 RTCritSectLeave(&pThis->CritSect);
1444
1445 RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
1446
1447 RTCritSectEnter(&pThis->CritSect);
1448 pThis->fHaveDoneQueueWaiter = false;
1449
1450 pUrb = usbNetQueueRemoveHead(&pThis->DoneQueue);
1451 }
1452
1453 RTCritSectLeave(&pThis->CritSect);
1454
1455 if (pUrb)
1456 Log(("usbNetUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1457 return pUrb;
1458}
1459
1460
1461/**
1462 * @interface_method_impl{PDMUSBREG,pfnWakeup}
1463 */
1464static DECLCALLBACK(int) usbNetWakeup(PPDMUSBINS pUsbIns)
1465{
1466 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1467 LogFlow(("usbNetUrbReap/#%u:\n", pUsbIns->iInstance));
1468
1469 return RTSemEventSignal(pThis->hEvtDoneQueue);
1470}
1471
1472
1473/**
1474 * @interface_method_impl{PDMUSBREG,pfnUrbCancel}
1475 */
1476static DECLCALLBACK(int) usbNetUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1477{
1478 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1479 LogFlow(("usbNetUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1480 RTCritSectEnter(&pThis->CritSect);
1481
1482 /*
1483 * Remove the URB from the to-host queue and move it onto the done queue.
1484 */
1485 if (usbNetQueueRemove(&pThis->ToHostQueue, pUrb))
1486 usbNetLinkDone(pThis, pUrb);
1487
1488 if (usbNetQueueRemove(&pThis->ToHostIntrQueue, pUrb))
1489 usbNetLinkDone(pThis, pUrb);
1490
1491 RTCritSectLeave(&pThis->CritSect);
1492 return VINF_SUCCESS;
1493}
1494
1495
1496/**
1497 * Handle requests sent to the outbound (to device) bulk pipe.
1498 */
1499static int usbNetHandleBulkHostToDev(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1500{
1501 /*
1502 * Stall the request if the pipe is halted.
1503 */
1504 if (RT_UNLIKELY(pEp->fHalted))
1505 return usbNetCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1506
1507 /*
1508 * Process the transfer.
1509 */
1510 PCUSBNCMNTH16 pNth16 = (PCUSBNCMNTH16)&pUrb->abData[0];
1511 if (pUrb->cbData < sizeof(*pNth16))
1512 {
1513 Log(("UsbNet: Bad NTH16: cbData=%#x < min=%#x\n", pUrb->cbData, sizeof(*pNth16) ));
1514 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NTH16");
1515 }
1516 if (pNth16->dwSignature != USBNCMNTH16_SIGNATURE)
1517 {
1518 Log(("UsbNet: NTH16: Invalid dwSignature value: %#x\n", pNth16->dwSignature));
1519 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1520 }
1521 Log(("UsbNet: NTH16: wHeaderLength=%#x wSequence=%#x wBlockLength=%#x wNdpIndex=%#x cbData=%#x fShortNotOk=%RTbool\n",
1522 pNth16->wHeaderLength, pNth16->wSequence, pNth16->wBlockLength, pNth16->wNdpIndex, pUrb->cbData, pUrb->fShortNotOk));
1523 if (pNth16->wHeaderLength != sizeof(*pNth16))
1524 {
1525 Log(("UsbNet: NTH16: Bad wHeaderLength value: %#x\n", pNth16->wHeaderLength));
1526 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1527
1528 }
1529 if (pNth16->wBlockLength > pUrb->cbData)
1530 {
1531 Log(("UsbNet: NTH16: Bad wBlockLength value: %#x\n", pNth16->wBlockLength));
1532 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1533 }
1534
1535 if (pNth16->wNdpIndex < sizeof(*pNth16))
1536 {
1537 Log(("UsbNet: NTH16: wNdpIndex is too small: %#x (%u), at least required %#x\n",
1538 pNth16->wNdpIndex, pNth16->wNdpIndex, sizeof(*pNth16) ));
1539 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NTH16");
1540 }
1541
1542 /* Walk the NDPs and process the datagrams. */
1543 uint16_t offNdp16Next = pNth16->wNdpIndex;
1544 while (offNdp16Next)
1545 {
1546 if (offNdp16Next >= pUrb->cbData)
1547 {
1548 Log(("UsbNet: Bad NDP16: offNdp16Next=%#x >= cbData=%#x\n", offNdp16Next, pUrb->cbData));
1549 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NDP16");
1550 }
1551
1552 size_t cbNdpMax = pUrb->cbData - offNdp16Next;
1553 PCUSBNCMNDP16 pNdp16 = (PCUSBNCMNDP16)&pUrb->abData[pNth16->wNdpIndex];
1554 if (cbNdpMax < sizeof(*pNdp16))
1555 {
1556 Log(("UsbNet: Bad NDP16: cbNdpMax=%#x < min=%#x\n", cbNdpMax, sizeof(*pNdp16) ));
1557 return usbNetCompleteStall(pThis, NULL, pUrb, "BAD NDP16");
1558 }
1559
1560 if ( pNdp16->dwSignature != USBNCMNDP16_SIGNATURE_NCM0
1561 && pNdp16->dwSignature != USBNCMNDP16_SIGNATURE_NCM1)
1562 {
1563 Log(("UsbNet: NDP16: Invalid dwSignature value: %#x\n", pNdp16->dwSignature));
1564 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1565 }
1566
1567 if ( pNdp16->wLength < sizeof(*pNdp16)
1568 || (pNdp16->wLength & 0x3)
1569 || pNdp16->wLength > cbNdpMax)
1570 {
1571 Log(("UsbNet: NDP16: Invalid size value: %#x, req. (min %#x max %#x)\n",
1572 pNdp16->wLength, sizeof(*pNdp16), cbNdpMax));
1573 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1574 }
1575
1576 if (pNdp16->dwSignature == USBNCMNDP16_SIGNATURE_NCM0)
1577 {
1578 PCUSBNCMNDP16DGRAM pDGram = &pNdp16->DataGram0;
1579 size_t cEntries = 2 + (pNdp16->wLength - (sizeof(*pNdp16))) / sizeof(*pDGram);
1580
1581 int rc = pThis->Lun0.pINetwork->pfnBeginXmit(pThis->Lun0.pINetwork, true /* fOnWorkerThread */);
1582 if (RT_FAILURE(rc))
1583 return usbNetCompleteStall(pThis, NULL, pUrb, "BeginXmit failed");
1584
1585 for (uint32_t i = 0; i < cEntries; i++)
1586 {
1587 /* Either 0 element marks end of list. */
1588 if ( pDGram->wDatagramIndex == 0
1589 || pDGram->wDatagramLength == 0)
1590 break;
1591
1592 if ( pDGram->wDatagramIndex < sizeof(*pNth16)
1593 || pDGram->wDatagramIndex >= pUrb->cbData)
1594 {
1595 Log(("UsbNet: DGRAM16: Invalid wDatagramIndex value: %#x\n", pDGram->wDatagramIndex));
1596 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad DGRAM16");
1597 }
1598
1599 if (pUrb->cbData - pDGram->wDatagramIndex < pDGram->wDatagramLength)
1600 {
1601 Log(("UsbNet: DGRAM16: Invalid wDatagramLength value: %#x (max %#x)\n",
1602 pDGram->wDatagramLength, pUrb->cbData - pDGram->wDatagramIndex));
1603 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad DGRAM16");
1604 }
1605
1606 PPDMSCATTERGATHER pSgBuf;
1607 rc = pThis->Lun0.pINetwork->pfnAllocBuf(pThis->Lun0.pINetwork, pDGram->wDatagramLength, NULL /*pGso*/, &pSgBuf);
1608 if (RT_SUCCESS(rc))
1609 {
1610 uint8_t *pbBuf = pSgBuf ? (uint8_t *)pSgBuf->aSegs[0].pvSeg : NULL;
1611 memcpy(pbBuf, &pUrb->abData[pDGram->wDatagramIndex], pDGram->wDatagramLength);
1612 pSgBuf->cbUsed = pDGram->wDatagramLength;
1613 rc = pThis->Lun0.pINetwork->pfnSendBuf(pThis->Lun0.pINetwork, pSgBuf, true /* fOnWorkerThread */);
1614 if (RT_FAILURE(rc))
1615 return usbNetCompleteStall(pThis, NULL, pUrb, "SendBuf failed");
1616 STAM_REL_COUNTER_ADD(&pThis->StatTransmitBytes, pDGram->wDatagramLength);
1617 }
1618 else
1619 return usbNetCompleteStall(pThis, NULL, pUrb, "AllocBuf failed");
1620
1621 pDGram++;
1622 }
1623
1624 pThis->Lun0.pINetwork->pfnEndXmit(pThis->Lun0.pINetwork);
1625 }
1626 else
1627 {
1628 Log(("UsbNet: NDP16: Not implemented\n"));
1629 return usbNetCompleteStall(pThis, NULL, pUrb, "Bad NDP16");
1630 }
1631
1632 offNdp16Next = pNdp16->wNextNdpIndex;
1633 }
1634
1635 return usbNetCompleteOk(pThis, pUrb, pUrb->cbData);
1636}
1637
1638
1639/**
1640 * Handle requests sent to the inbound (to host) bulk pipe.
1641 */
1642static int usbNetHandleBulkDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1643{
1644 /*
1645 * Stall the request if the pipe is halted OR if there is no
1646 * pending request yet.
1647 */
1648 if (RT_UNLIKELY(pEp->fHalted))
1649 return usbNetCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
1650
1651 usbNetQueueAddTail(&pThis->ToHostQueue, pUrb);
1652 if (pThis->fHaveToHostQueueWaiter)
1653 RTSemEventSignal(pThis->hEvtToHostQueue);
1654
1655 LogFlow(("usbNetHandleBulkDevToHost: Added %p:%s to the to-host queue\n", pUrb, pUrb->pszDesc));
1656 return VINF_SUCCESS;
1657}
1658
1659
1660/**
1661 * Handle requests sent to the inbound (to host) interrupt pipe.
1662 */
1663static int usbNetHandleIntrDevToHost(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1664{
1665 /* Stall the request if the pipe is halted. */
1666 if (RT_UNLIKELY(pEp->fHalted))
1667 return usbNetCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
1668
1669 /* CONNECTION_SPEED_CHANGE is sent first, followed by NETWORK_CONNECTION. See [NCM10] (section 7.1) */
1670 if (!pThis->fInitialSpeedChangeSent)
1671 {
1672 USBCDCNOTIFICICATIONSPEEDCHG SpeedChange;
1673 SpeedChange.Hdr.bmRequestType = 0xa1;
1674 SpeedChange.Hdr.bNotificationCode = USB_CDC_NOTIFICATION_CODE_CONNECTION_SPEED_CHANGE;
1675 SpeedChange.Hdr.wValue = 0;
1676 SpeedChange.Hdr.wIndex = 0;
1677 SpeedChange.Hdr.wLength = 8;
1678 SpeedChange.DLBitRate = UINT32_MAX;
1679 SpeedChange.ULBitRate = UINT32_MAX;
1680 usbNetCompleteNotificationOk(pThis, pUrb, &SpeedChange, sizeof(SpeedChange));
1681 pThis->fInitialSpeedChangeSent = true;
1682 }
1683 else if (!pThis->fInitialLinkStatusSent)
1684 {
1685 USBCDCNOTIFICICATION LinkNotification;
1686 LinkNotification.bmRequestType = 0xa1;
1687 LinkNotification.bNotificationCode = USB_CDC_NOTIFICATION_CODE_NETWORK_CONNECTION;
1688 LinkNotification.wValue = pThis->fLinkUp ? 1 : 0;
1689 LinkNotification.wIndex = 0;
1690 LinkNotification.wLength = 0;
1691 usbNetCompleteNotificationOk(pThis, pUrb, &LinkNotification, sizeof(LinkNotification));
1692 pThis->fInitialLinkStatusSent = true;
1693 }
1694 else
1695 usbNetQueueAddTail(&pThis->ToHostIntrQueue, pUrb);
1696
1697 LogFlow(("usbNetHandleIntrDevToHost: Added %p:%s to the to-host interrupt queue\n", pUrb, pUrb->pszDesc));
1698 return VINF_SUCCESS;
1699}
1700
1701
1702/**
1703 * Notifies both the guest and the network/driver of link state changes.
1704 *
1705 * @param pThis The UsbNet instance.
1706 * @param enmLinkState The new link state.
1707 */
1708DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState)
1709{
1710 LogFlowFunc(("#%d enmLinkState=%d\n", pThis->pUsbIns->iInstance, enmLinkState));
1711 RTCritSectEnter(&pThis->CritSect);
1712 /* Trigger notifications */
1713 pThis->fInitialLinkStatusSent = false;
1714 pThis->fInitialSpeedChangeSent = false;
1715 PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->ToHostIntrQueue);
1716 /* If there is a request pending, use it. Otherwise the host should poll us soon. */
1717 if (pUrb)
1718 usbNetHandleIntrDevToHost(pThis, &pThis->aEps[3], pUrb);
1719 RTCritSectLeave(&pThis->CritSect);
1720 /* Always notify our network when notifying the guest. */
1721 if (pThis->Lun0.pINetwork)
1722 pThis->Lun0.pINetwork->pfnNotifyLinkChanged(pThis->Lun0.pINetwork, enmLinkState);
1723}
1724
1725
1726/**
1727 * Handles request send to the default control pipe.
1728 */
1729static int usbNetHandleDefaultPipe(PUSBNET pThis, PUSBNETEP pEp, PVUSBURB pUrb)
1730{
1731 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1732 AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
1733
1734 if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
1735 {
1736 switch (pSetup->bRequest)
1737 {
1738 case VUSB_REQ_GET_DESCRIPTOR:
1739 {
1740 if (pSetup->bmRequestType != (VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST))
1741 {
1742 Log(("UsbNet: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pSetup->bmRequestType));
1743 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
1744 }
1745
1746 switch (pSetup->wValue >> 8)
1747 {
1748 uint32_t cbCopy;
1749
1750 case VUSB_DT_STRING:
1751 Log(("UsbNet: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1752 break;
1753 case VUSB_DT_DEVICE_QUALIFIER:
1754 Log(("UsbNet: GET_DESCRIPTOR DT_DEVICE_QUALIFIER wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1755 /* Returned data is written after the setup message. */
1756 cbCopy = pUrb->cbData - sizeof(*pSetup);
1757 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbNetDeviceQualifier));
1758 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbNetDeviceQualifier, cbCopy);
1759 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1760 case VUSB_DT_BOS:
1761 Log(("UsbNet: GET_DESCRIPTOR DT_BOS wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1762 /* Returned data is written after the setup message. */
1763 cbCopy = pUrb->cbData - sizeof(*pSetup);
1764 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbNetBOS));
1765 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbNetBOS, cbCopy);
1766 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1767 default:
1768 Log(("UsbNet: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1769 break;
1770 }
1771 break;
1772 }
1773
1774 case VUSB_REQ_GET_STATUS:
1775 {
1776 uint16_t wRet = 0;
1777 size_t cbCopy = 0;
1778
1779 if (pSetup->wLength != 2)
1780 {
1781 LogRelFlow(("UsbNet: Bad GET_STATUS req: wLength=%#x\n",
1782 pSetup->wLength));
1783 break;
1784 }
1785 Assert(pSetup->wValue == 0);
1786 switch (pSetup->bmRequestType)
1787 {
1788 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1789 {
1790 Assert(pSetup->wIndex == 0);
1791 LogRelFlow(("UsbNet: GET_STATUS (device)\n"));
1792 wRet = 0; /* Not self-powered, no remote wakeup. */
1793 cbCopy = pUrb->cbData - sizeof(*pSetup);
1794 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1795 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1796 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1797 }
1798
1799 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1800 {
1801 if (pSetup->wIndex == 0)
1802 {
1803 cbCopy = pUrb->cbData - sizeof(*pSetup);
1804 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1805 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1806 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1807 }
1808 LogRelFlow(("UsbNet: GET_STATUS (interface) invalid, wIndex=%#x\n", pSetup->wIndex));
1809 break;
1810 }
1811
1812 case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1813 {
1814 if (pSetup->wIndex < RT_ELEMENTS(pThis->aEps))
1815 {
1816 wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
1817 cbCopy = pUrb->cbData - sizeof(*pSetup);
1818 cbCopy = RT_MIN(cbCopy, sizeof(wRet));
1819 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, cbCopy);
1820 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1821 }
1822 LogRelFlow(("UsbNet: GET_STATUS (endpoint) invalid, wIndex=%#x\n", pSetup->wIndex));
1823 break;
1824 }
1825
1826 default:
1827 LogRelFlow(("UsbNet: Bad GET_STATUS req: bmRequestType=%#x\n",
1828 pSetup->bmRequestType));
1829 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
1830 }
1831 break;
1832 }
1833
1834 case 0x31:
1835 break;
1836
1837 case VUSB_REQ_CLEAR_FEATURE:
1838 break;
1839 }
1840
1841 /** @todo implement this. */
1842 Log(("UsbNet: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1843 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1844
1845 usbNetCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
1846 }
1847 else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS)
1848 {
1849 switch (pSetup->bRequest)
1850 {
1851 case VUSB_REQ_GET_NTB_PARAMETERS:
1852 {
1853 if (pSetup->bmRequestType != (VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_HOST))
1854 {
1855 Log(("UsbNet: Bad GET_NTB_PARAMETERS req: bmRequestType=%#x\n", pSetup->bmRequestType));
1856 return usbNetCompleteStall(pThis, pEp, pUrb, "Bad GET_NTB_PARAMETERS");
1857 }
1858
1859 USBNCMNTBPARAMS NtbParams;
1860
1861 NtbParams.wLength = sizeof(NtbParams);
1862 NtbParams.bmNtbFormatsSupported = RT_BIT(0);
1863 NtbParams.dwNtbInMaxSize = _4K;
1864 NtbParams.wNdpInDivisor = 4;
1865 NtbParams.wNdpInPayloadRemainder = 4;
1866 NtbParams.wNdpInAlignment = 4;
1867 NtbParams.u16Rsvd0 = 0;
1868 NtbParams.dwNtbOutMaxSize = _4K;
1869 NtbParams.wNdpOutDivisor = 4;
1870 NtbParams.wNdpOutPayloadRemainder = 4;
1871 NtbParams.wNdpOutAlignment = 4;
1872 NtbParams.wNtpOutMaxDatagrams = 1;
1873
1874 uint32_t cbCopy = pUrb->cbData - sizeof(*pSetup);
1875 cbCopy = RT_MIN(cbCopy, sizeof(NtbParams));
1876 memcpy(&pUrb->abData[sizeof(*pSetup)], &NtbParams, cbCopy);
1877 return usbNetCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1878 }
1879
1880 case VUSB_REQ_CLEAR_FEATURE:
1881 break;
1882 }
1883
1884 usbNetCompleteStall(pThis, pEp, pUrb, "CLASS_REQ");
1885 }
1886 else
1887 {
1888 Log(("UsbNet: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1889 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1890 return usbNetCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
1891 }
1892
1893 return VINF_SUCCESS;
1894}
1895
1896
1897/**
1898 * @interface_method_impl{PDMUSBREG,pfnUrbQueue}
1899 */
1900static DECLCALLBACK(int) usbNetQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1901{
1902 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1903 LogFlow(("usbNetQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
1904 RTCritSectEnter(&pThis->CritSect);
1905
1906 /*
1907 * Parse on a per end-point basis.
1908 */
1909 int rc;
1910 switch (pUrb->EndPt)
1911 {
1912 case 0:
1913 rc = usbNetHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
1914 break;
1915
1916 case 0x81:
1917 AssertFailed();
1918 RT_FALL_THRU();
1919 case 0x01:
1920 rc = usbNetHandleBulkDevToHost(pThis, &pThis->aEps[1], pUrb);
1921 break;
1922
1923 case 0x02:
1924 rc = usbNetHandleBulkHostToDev(pThis, &pThis->aEps[2], pUrb);
1925 break;
1926
1927 case 0x03:
1928 rc = usbNetHandleIntrDevToHost(pThis, &pThis->aEps[3], pUrb);
1929 break;
1930
1931 default:
1932 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
1933 rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
1934 break;
1935 }
1936
1937 RTCritSectLeave(&pThis->CritSect);
1938 return rc;
1939}
1940
1941
1942/**
1943 * @interface_method_impl{PDMUSBREG,pfnUsbClearHaltedEndpoint}
1944 */
1945static DECLCALLBACK(int) usbNetUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
1946{
1947 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1948 LogFlow(("usbNetUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
1949
1950 if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
1951 {
1952 RTCritSectEnter(&pThis->CritSect);
1953 pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
1954 RTCritSectLeave(&pThis->CritSect);
1955 }
1956
1957 return VINF_SUCCESS;
1958}
1959
1960
1961/**
1962 * @interface_method_impl{PDMUSBREG,pfnUsbSetInterface}
1963 */
1964static DECLCALLBACK(int) usbNetUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
1965{
1966 RT_NOREF(bInterfaceNumber);
1967 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1968 LogFlow(("usbNetUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
1969 Assert(bAlternateSetting == 0 || bAlternateSetting == 1);
1970 if (pThis->bAlternateSetting != bAlternateSetting)
1971 {
1972 if (bAlternateSetting == 0)
1973 {
1974 /* This is some kind of reset. */
1975 usbNetResetWorker(pThis, NULL, true /*fSetConfig*/);
1976 }
1977 else
1978 {
1979 Assert(bAlternateSetting == 1);
1980 /* Switching from configuration to data mode, need to send notifications. */
1981 pThis->fInitialLinkStatusSent = false;
1982 pThis->fInitialSpeedChangeSent = false;
1983 }
1984 pThis->bAlternateSetting = bAlternateSetting;
1985 }
1986 return VINF_SUCCESS;
1987}
1988
1989
1990/**
1991 * @interface_method_impl{PDMUSBREG,pfnUsbSetConfiguration}
1992 */
1993static DECLCALLBACK(int) usbNetUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
1994 const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
1995{
1996 RT_NOREF(pvOldCfgDesc, pvOldIfState, pvNewCfgDesc);
1997 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
1998 LogFlow(("usbNetUsbSetConfiguration/#%u: bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
1999 Assert(bConfigurationValue == 1);
2000 RTCritSectEnter(&pThis->CritSect);
2001
2002 /*
2003 * If the same config is applied more than once, it's a kind of reset.
2004 */
2005 if (pThis->bConfigurationValue == bConfigurationValue)
2006 usbNetResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
2007 pThis->bConfigurationValue = bConfigurationValue;
2008
2009 RTCritSectLeave(&pThis->CritSect);
2010 return VINF_SUCCESS;
2011}
2012
2013
2014/**
2015 * @interface_method_impl{PDMUSBREG,pfnUsbGetDescriptorCache}
2016 */
2017static DECLCALLBACK(PCPDMUSBDESCCACHE) usbNetUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
2018{
2019 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2020 LogFlow(("usbNetUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
2021 return &pThis->UsbDescCache;
2022}
2023
2024
2025/**
2026 * @interface_method_impl{PDMUSBREG,pfnUsbReset}
2027 */
2028static DECLCALLBACK(int) usbNetUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
2029{
2030 RT_NOREF(fResetOnLinux);
2031 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2032 LogFlow(("usbNetUsbReset/#%u:\n", pUsbIns->iInstance));
2033 RTCritSectEnter(&pThis->CritSect);
2034
2035 int rc = usbNetResetWorker(pThis, NULL, false /*fSetConfig*/);
2036
2037 RTCritSectLeave(&pThis->CritSect);
2038 return rc;
2039}
2040
2041
2042/**
2043 * @interface_method_impl{PDMUSBREG,pfnDriverAttach}
2044 */
2045static DECLCALLBACK(int) usbNetDriverAttach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
2046{
2047 RT_NOREF(fFlags);
2048 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2049
2050 LogFlow(("usbNetDriverAttach/#%u:\n", pUsbIns->iInstance));
2051
2052 AssertMsg(iLUN == 0, ("UsbNet: No other LUN than 0 is supported\n"));
2053 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
2054 ("UsbNet: Device does not support hotplugging\n"));
2055
2056 /* the usual paranoia */
2057 AssertRelease(!pThis->Lun0.pIBase);
2058 AssertRelease(!pThis->Lun0.pINetwork);
2059
2060 /*
2061 * Try attach the network driver.
2062 */
2063 int rc = PDMUsbHlpDriverAttach(pUsbIns, iLUN, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, NULL);
2064 if (RT_SUCCESS(rc))
2065 {
2066 /* Get network interface. */
2067 pThis->Lun0.pINetwork = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMINETWORKUP);
2068 AssertMsgReturn(pThis->Lun0.pINetwork, ("Missing network interface below\n"), VERR_PDM_MISSING_INTERFACE);
2069 }
2070 else
2071 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", iLUN, rc));
2072
2073 if (RT_FAILURE(rc))
2074 {
2075 pThis->Lun0.pIBase = NULL;
2076 pThis->Lun0.pINetwork = NULL;
2077 }
2078
2079 return rc;
2080}
2081
2082
2083/**
2084 * @interface_method_impl{PDMUSBREG,pfnDriverDetach}
2085 */
2086static DECLCALLBACK(void) usbNetDriverDetach(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags)
2087{
2088 RT_NOREF(iLUN, fFlags);
2089 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2090
2091 LogFlow(("usbNetDriverDetach/#%u:\n", pUsbIns->iInstance));
2092
2093 AssertMsg(iLUN == 0, ("UsbNet: No other LUN than 0 is supported\n"));
2094 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
2095 ("UsbNet: Device does not support hotplugging\n"));
2096
2097 /*
2098 * Zero some important members.
2099 */
2100 pThis->Lun0.pIBase = NULL;
2101 pThis->Lun0.pINetwork = NULL;
2102}
2103
2104
2105/**
2106 * @interface_method_impl{PDMUSBREG,pfnVMReset}
2107 */
2108static DECLCALLBACK(void) usbNetVMReset(PPDMUSBINS pUsbIns)
2109{
2110 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2111
2112 int rc = usbNetResetWorker(pThis, NULL, false /*fSetConfig*/);
2113 AssertRC(rc);
2114}
2115
2116
2117/**
2118 * @interface_method_impl{PDMUSBREG,pfnDestruct}
2119 */
2120static DECLCALLBACK(void) usbNetDestruct(PPDMUSBINS pUsbIns)
2121{
2122 PDMUSB_CHECK_VERSIONS_RETURN_VOID(pUsbIns);
2123 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2124 LogFlow(("usbNetDestruct/#%u:\n", pUsbIns->iInstance));
2125
2126 PDMUsbHlpTimerDestroy(pUsbIns, pThis->hTimerLinkUp);
2127
2128 if (RTCritSectIsInitialized(&pThis->CritSect))
2129 {
2130 RTCritSectEnter(&pThis->CritSect);
2131 RTCritSectLeave(&pThis->CritSect);
2132 RTCritSectDelete(&pThis->CritSect);
2133 }
2134
2135 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
2136 {
2137 RTSemEventDestroy(pThis->hEvtDoneQueue);
2138 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2139 }
2140
2141 if (pThis->hEvtToHostQueue != NIL_RTSEMEVENT)
2142 {
2143 RTSemEventDestroy(pThis->hEvtToHostQueue);
2144 pThis->hEvtToHostQueue = NIL_RTSEMEVENT;
2145 }
2146
2147 if (pThis->hEvtReset != NIL_RTSEMEVENTMULTI)
2148 {
2149 RTSemEventMultiDestroy(pThis->hEvtReset);
2150 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2151 }
2152}
2153
2154
2155/**
2156 * @interface_method_impl{PDMUSBREG,pfnConstruct}
2157 */
2158static DECLCALLBACK(int) usbNetConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
2159{
2160 RT_NOREF(pCfgGlobal);
2161 PDMUSB_CHECK_VERSIONS_RETURN(pUsbIns);
2162 PUSBNET pThis = PDMINS_2_DATA(pUsbIns, PUSBNET);
2163 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
2164
2165 Log(("usbNetConstruct/#%u:\n", iInstance));
2166
2167 /*
2168 * Perform the basic structure initialization first so the destructor
2169 * will not misbehave.
2170 */
2171 pThis->pUsbIns = pUsbIns;
2172 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2173 pThis->hEvtToHostQueue = NIL_RTSEMEVENT;
2174 pThis->hEvtReset = NIL_RTSEMEVENTMULTI;
2175 /* IBase */
2176 pThis->Lun0.IBase.pfnQueryInterface = usbNetLun0QueryInterface;
2177 /* INetworkPort */
2178 pThis->Lun0.INetworkDown.pfnWaitReceiveAvail = usbNetNetworkDown_WaitReceiveAvail;
2179 pThis->Lun0.INetworkDown.pfnReceive = usbNetNetworkDown_Receive;
2180 pThis->Lun0.INetworkDown.pfnXmitPending = usbNetNetworkDown_XmitPending;
2181 /* INetworkConfig */
2182 pThis->Lun0.INetworkConfig.pfnGetMac = usbNetGetMac;
2183 pThis->Lun0.INetworkConfig.pfnGetLinkState = usbNetGetLinkState;
2184 pThis->Lun0.INetworkConfig.pfnSetLinkState = usbNetSetLinkState;
2185
2186 usbNetQueueInit(&pThis->ToHostQueue);
2187 usbNetQueueInit(&pThis->ToHostIntrQueue);
2188 usbNetQueueInit(&pThis->DoneQueue);
2189
2190 int rc = RTCritSectInit(&pThis->CritSect);
2191 AssertRCReturn(rc, rc);
2192
2193 rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
2194 AssertRCReturn(rc, rc);
2195
2196 rc = RTSemEventCreate(&pThis->hEvtToHostQueue);
2197 AssertRCReturn(rc, rc);
2198
2199 rc = RTSemEventMultiCreate(&pThis->hEvtReset);
2200 AssertRCReturn(rc, rc);
2201
2202 /*
2203 * Validate and read the configuration.
2204 */
2205 rc = pHlp->pfnCFGMValidateConfig(pCfg, "/",
2206 "MAC|"
2207 "CableConnected|"
2208 "LinkUpDelay"
2209 , "Config", "UsbNet", iInstance);
2210 if (RT_FAILURE(rc))
2211 return rc;
2212
2213 /*
2214 * Read the configuration.
2215 */
2216 rc = pHlp->pfnCFGMQueryBytes(pCfg, "MAC", &pThis->MacConfigured, sizeof(pThis->MacConfigured));
2217 if (RT_FAILURE(rc))
2218 return PDMUSB_SET_ERROR(pUsbIns, rc,
2219 N_("Configuration error: Failed to get the \"MAC\" value"));
2220 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "CableConnected", &pThis->fLinkUp, true);
2221 if (RT_FAILURE(rc))
2222 return PDMUSB_SET_ERROR(pUsbIns, rc,
2223 N_("Configuration error: Failed to get the \"CableConnected\" value"));
2224
2225 /*
2226 * Attach the network driver.
2227 */
2228 rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pIBase, "Network Port");
2229 if (RT_FAILURE(rc))
2230 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("USBNET failed to attach network driver"));
2231 pThis->Lun0.pINetwork = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pIBase, PDMINETWORKUP);
2232 if (!pThis->Lun0.pINetwork)
2233 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
2234 N_("USBNET failed to query the PDMINETWORKUP from the driver below it"));
2235
2236 /*
2237 * Create the timer for delaying of bringing the link up.
2238 */
2239 rc = PDMUsbHlpTimerCreate(pUsbIns, TMCLOCK_VIRTUAL, usbNetTimerLinkUp, pThis,
2240 TMTIMER_FLAGS_DEFAULT_CRIT_SECT,
2241 "Link Up", &pThis->hTimerLinkUp);
2242
2243 /*
2244 * Build the USB descriptors.
2245 */
2246 pThis->aUsbStringsEnUs[0].idx = USBNET_STR_ID_MANUFACTURER;
2247 pThis->aUsbStringsEnUs[0].psz = "VirtualBox";
2248
2249 pThis->aUsbStringsEnUs[1].idx = USBNET_STR_ID_PRODUCT;
2250 pThis->aUsbStringsEnUs[1].psz = "USB Ethernet";
2251
2252 /* Build the MAC address. */
2253 ssize_t cch = RTStrPrintf2(&pThis->aszMac[0], sizeof(pThis->aszMac), "%#.6Rhxs", &pThis->MacConfigured);
2254 AssertReturn(cch + 1 == sizeof(pThis->aszMac), VERR_INTERNAL_ERROR_4);
2255
2256 pThis->aUsbStringsEnUs[2].idx = USBNET_STR_ID_MAC_ADDRESS;
2257 pThis->aUsbStringsEnUs[2].psz = &pThis->aszMac[0];
2258
2259 pThis->UsbLang.idLang = 0x0409; /* en_US. */
2260 pThis->UsbLang.cStrings = RT_ELEMENTS(pThis->aUsbStringsEnUs);
2261 pThis->UsbLang.paStrings = &pThis->aUsbStringsEnUs[0];
2262
2263 pThis->UsbDescCache.paLanguages = &pThis->UsbLang;
2264 pThis->UsbDescCache.cLanguages = 1;
2265 pThis->UsbDescCache.fUseCachedDescriptors = true;
2266 pThis->UsbDescCache.fUseCachedStringsDescriptors = true;
2267
2268 switch (pUsbIns->enmSpeed)
2269 {
2270 case VUSB_SPEED_SUPER:
2271 case VUSB_SPEED_SUPERPLUS:
2272 {
2273 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc30;
2274 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescSS;
2275 break;
2276 }
2277 case VUSB_SPEED_HIGH:
2278 {
2279 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc20;
2280 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescHS;
2281 break;
2282 }
2283 case VUSB_SPEED_FULL:
2284 case VUSB_SPEED_LOW:
2285 {
2286 pThis->UsbDescCache.pDevice = &g_UsbNetDeviceDesc20;
2287 pThis->UsbDescCache.paConfigs = &g_UsbNetConfigDescFS;
2288 break;
2289 }
2290 default:
2291 AssertFailedReturn(VERR_INVALID_PARAMETER);
2292 }
2293
2294 /*
2295 * Register statistics.
2296 * The /Public/ bits are official and used by session info in the GUI.
2297 */
2298 PDMUsbHlpSTAMRegisterF(pUsbIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
2299 "Amount of data received", "/Public/NetAdapter/%u/BytesReceived", iInstance);
2300 PDMUsbHlpSTAMRegisterF(pUsbIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
2301 "Amount of data transmitted", "/Public/NetAdapter/%u/BytesTransmitted", iInstance);
2302 PDMUsbHlpSTAMRegisterF(pUsbIns, &pUsbIns->iInstance, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
2303 "Device instance number", "/Public/NetAdapter/%u/%s", iInstance, pUsbIns->pReg->szName);
2304
2305 return VINF_SUCCESS;
2306}
2307
2308
2309/**
2310 * The USB Communications Device Class, Network Control Model (CDC NCM) registration record.
2311 */
2312const PDMUSBREG g_UsbNet =
2313{
2314 /* u32Version */
2315 PDM_USBREG_VERSION,
2316 /* szName */
2317 "UsbNet",
2318 /* pszDescription */
2319 "USB Communications Device Class, one LUN.",
2320 /* fFlags */
2321 PDM_USBREG_HIGHSPEED_CAPABLE /*| PDM_USBREG_SUPERSPEED_CAPABLE */,
2322 /* cMaxInstances */
2323 ~0U,
2324 /* cbInstance */
2325 sizeof(USBNET),
2326 /* pfnConstruct */
2327 usbNetConstruct,
2328 /* pfnDestruct */
2329 usbNetDestruct,
2330 /* pfnVMInitComplete */
2331 NULL,
2332 /* pfnVMPowerOn */
2333 NULL,
2334 /* pfnVMReset */
2335 usbNetVMReset,
2336 /* pfnVMSuspend */
2337 NULL,
2338 /* pfnVMResume */
2339 NULL,
2340 /* pfnVMPowerOff */
2341 NULL,
2342 /* pfnHotPlugged */
2343 NULL,
2344 /* pfnHotUnplugged */
2345 NULL,
2346 /* pfnDriverAttach */
2347 usbNetDriverAttach,
2348 /* pfnDriverDetach */
2349 usbNetDriverDetach,
2350 /* pfnQueryInterface */
2351 NULL,
2352 /* pfnUsbReset */
2353 usbNetUsbReset,
2354 /* pfnUsbGetDescriptorCache */
2355 usbNetUsbGetDescriptorCache,
2356 /* pfnUsbSetConfiguration */
2357 usbNetUsbSetConfiguration,
2358 /* pfnUsbSetInterface */
2359 usbNetUsbSetInterface,
2360 /* pfnUsbClearHaltedEndpoint */
2361 usbNetUsbClearHaltedEndpoint,
2362 /* pfnUrbNew */
2363 NULL/*usbNetUrbNew*/,
2364 /* pfnQueue */
2365 usbNetQueue,
2366 /* pfnUrbCancel */
2367 usbNetUrbCancel,
2368 /* pfnUrbReap */
2369 usbNetUrbReap,
2370 /* pfnWakeup */
2371 usbNetWakeup,
2372 /* u32TheEnd */
2373 PDM_USBREG_VERSION
2374};
2375
Note: See TracBrowser for help on using the repository browser.

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