VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/UsbEth.cpp@ 107242

Last change on this file since 107242 was 107242, checked in by vboxsync, 6 weeks ago

UsbNet: bugref:10779 Simply renamed UsbEth to UsbNet (part 1)

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