VirtualBox

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

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

UsbNet: bugref:10779 Implemented link state handling

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