VirtualBox

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

最後變更 在這個檔案從108236是 107875,由 vboxsync 提交於 8 週 前

UsbNet: bugref:10779 Logging tidying

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

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