VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/VUSBUrb.cpp@ 53067

Last change on this file since 53067 was 53067, checked in by vboxsync, 10 years ago

Add possibility to configure a single USB traffic sniffer for a complete roothub (must be configured through extra data)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 82.8 KB
Line 
1/* $Id: VUSBUrb.cpp 53067 2014-10-15 13:10:29Z vboxsync $ */
2/** @file
3 * Virtual USB - URBs.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_DRV_VUSB
22#include <VBox/vmm/pdm.h>
23#include <VBox/vmm/vmapi.h>
24#include <VBox/err.h>
25#include <iprt/alloc.h>
26#include <VBox/log.h>
27#include <iprt/time.h>
28#include <iprt/thread.h>
29#include <iprt/semaphore.h>
30#include <iprt/string.h>
31#include <iprt/assert.h>
32#include <iprt/asm.h>
33#include <iprt/env.h>
34#include "VUSBInternal.h"
35
36
37
38/*******************************************************************************
39* Global Variables *
40*******************************************************************************/
41/** Strings for the CTLSTAGE enum values. */
42const char * const g_apszCtlStates[4] =
43{
44 "SETUP",
45 "DATA",
46 "STATUS",
47 "N/A"
48};
49
50
51/*******************************************************************************
52* Internal Functions *
53*******************************************************************************/
54static PVUSBCTRLEXTRA vusbMsgAllocExtraData(PVUSBURB pUrb);
55
56
57#ifdef LOG_ENABLED
58DECLINLINE(const char *) vusbUrbStatusName(VUSBSTATUS enmStatus)
59{
60 /** Strings for the URB statuses. */
61 static const char * const s_apszNames[] =
62 {
63 "OK",
64 "STALL",
65 "ERR_DNR",
66 "ERR_CRC",
67 "DATA_UNDERRUN",
68 "DATA_OVERRUN",
69 "NOT_ACCESSED",
70 "7", "8", "9", "10", "11", "12", "13", "14", "15"
71 };
72
73 return enmStatus < (int)RT_ELEMENTS(s_apszNames)
74 ? s_apszNames[enmStatus]
75 : enmStatus == VUSBSTATUS_INVALID
76 ? "INVALID"
77 : "??";
78}
79
80DECLINLINE(const char *) vusbUrbDirName(VUSBDIRECTION enmDir)
81{
82 /** Strings for the URB directions. */
83 static const char * const s_apszNames[] =
84 {
85 "setup",
86 "in",
87 "out"
88 };
89
90 return enmDir < (int)RT_ELEMENTS(s_apszNames)
91 ? s_apszNames[enmDir]
92 : "??";
93}
94
95DECLINLINE(const char *) vusbUrbTypeName(VUSBXFERTYPE enmType)
96{
97 /** Strings for the URB types. */
98 static const char * const s_apszName[] =
99 {
100 "control-part",
101 "isochronous",
102 "bulk",
103 "interrupt",
104 "control"
105 };
106
107 return enmType < (int)RT_ELEMENTS(s_apszName)
108 ? s_apszName[enmType]
109 : "??";
110}
111
112DECLINLINE(const char *) GetScsiErrCd(uint8_t ScsiErr)
113{
114 switch (ScsiErr)
115 {
116 case 0: return "?";
117 }
118 return "?";
119}
120
121DECLINLINE(const char *) GetScsiKCQ(uint8_t Key, uint8_t ASC, uint8_t ASCQ)
122{
123 switch (Key)
124 {
125 case 0:
126 switch (RT_MAKE_U16(ASC, ASCQ))
127 {
128 case RT_MAKE_U16(0x00, 0x00): return "No error";
129 }
130 break;
131
132 case 1:
133 return "Soft Error";
134
135 case 2:
136 return "Not Ready";
137
138 case 3:
139 return "Medium Error";
140
141 case 4:
142 return "Hard Error";
143
144 case 5:
145 return "Illegal Request";
146
147 case 6:
148 return "Unit Attention";
149
150 case 7:
151 return "Write Protected";
152
153 case 0xb:
154 return "Aborted Command";
155 }
156 return "?";
157}
158
159
160/**
161 * Logs an URB.
162 *
163 * Note that pUrb->pUsbIns, pUrb->VUsb.pDev and pUrb->VUsb.pDev->pUsbIns can all be NULL.
164 */
165void vusbUrbTrace(PVUSBURB pUrb, const char *pszMsg, bool fComplete)
166{
167 PVUSBDEV pDev = pUrb->VUsb.pDev; /* Can be NULL when called from usbProxyConstruct and friends. */
168 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
169 const uint8_t *pbData = pUrb->abData;
170 uint32_t cbData = pUrb->cbData;
171 PCVUSBSETUP pSetup = NULL;
172 bool fDescriptors = false;
173 static size_t s_cchMaxMsg = 10;
174 size_t cchMsg = strlen(pszMsg);
175 if (cchMsg > s_cchMaxMsg)
176 s_cchMaxMsg = cchMsg;
177
178 Log(("%s: %*s: pDev=%p[%s] rc=%s a=%i e=%u d=%s t=%s cb=%#x(%d) Ed=%08x cTds=%d Td0=%08x ts=%RU64 (%RU64 ns ago) %s\n",
179 pUrb->pszDesc, s_cchMaxMsg, pszMsg,
180 pDev,
181 pUrb->pUsbIns ? pUrb->pUsbIns->pszName : "",
182 vusbUrbStatusName(pUrb->enmStatus),
183 pDev ? pDev->u8Address : -1,
184 pUrb->EndPt,
185 vusbUrbDirName(pUrb->enmDir),
186 vusbUrbTypeName(pUrb->enmType),
187 pUrb->cbData,
188 pUrb->cbData,
189 pUrb->Hci.EdAddr,
190 pUrb->Hci.cTds,
191 pUrb->Hci.cTds ? pUrb->Hci.paTds[0].TdAddr : ~(uint32_t)0,
192 pUrb->VUsb.u64SubmitTS,
193 RTTimeNanoTS() - pUrb->VUsb.u64SubmitTS,
194 pUrb->fShortNotOk ? "ShortNotOk" : "ShortOk"));
195
196#ifndef DEBUG_bird
197 if ( pUrb->enmType == VUSBXFERTYPE_CTRL
198 && pUrb->enmStatus == VUSBSTATUS_OK)
199 return;
200#endif
201
202 if ( pUrb->enmType == VUSBXFERTYPE_MSG
203 || ( pUrb->enmDir == VUSBDIRECTION_SETUP
204 && pUrb->enmType == VUSBXFERTYPE_CTRL
205 && cbData))
206 {
207 static const char * const s_apszReqDirs[] = {"host2dev", "dev2host"};
208 static const char * const s_apszReqTypes[] = {"std", "class", "vendor", "reserved"};
209 static const char * const s_apszReqRecipients[] = {"dev", "if", "endpoint", "other"};
210 static const char * const s_apszRequests[] =
211 {
212 "GET_STATUS", "CLEAR_FEATURE", "2?", "SET_FEATURE",
213 "4?", "SET_ADDRESS", "GET_DESCRIPTOR", "SET_DESCRIPTOR",
214 "GET_CONFIGURATION", "SET_CONFIGURATION", "GET_INTERFACE", "SET_INTERFACE",
215 "SYNCH_FRAME"
216 };
217 pSetup = (PVUSBSETUP)pUrb->abData;
218 pbData += sizeof(*pSetup);
219 cbData -= sizeof(*pSetup);
220
221 Log(("%s: %*s: CTRL: bmRequestType=0x%.2x (%s %s %s) bRequest=0x%.2x (%s) wValue=0x%.4x wIndex=0x%.4x wLength=0x%.4x\n",
222 pUrb->pszDesc, s_cchMaxMsg, pszMsg,
223 pSetup->bmRequestType, s_apszReqDirs[pSetup->bmRequestType >> 7], s_apszReqTypes[(pSetup->bmRequestType >> 5) & 0x3],
224 (unsigned)(pSetup->bmRequestType & 0xf) < RT_ELEMENTS(s_apszReqRecipients) ? s_apszReqRecipients[pSetup->bmRequestType & 0xf] : "??",
225 pSetup->bRequest, pSetup->bRequest < RT_ELEMENTS(s_apszRequests) ? s_apszRequests[pSetup->bRequest] : "??",
226 pSetup->wValue, pSetup->wIndex, pSetup->wLength));
227
228 if ( pSetup->bRequest == VUSB_REQ_GET_DESCRIPTOR
229 && fComplete
230 && pUrb->enmStatus == VUSBSTATUS_OK
231 && ((pSetup->bmRequestType >> 5) & 0x3) < 2 /* vendor */)
232 fDescriptors = true;
233 }
234 else if ( fComplete
235 && pUrb->enmDir == VUSBDIRECTION_IN
236 && pUrb->enmType == VUSBXFERTYPE_CTRL
237 && pUrb->enmStatus == VUSBSTATUS_OK
238 && pPipe->pCtrl
239 && pPipe->pCtrl->enmStage == CTLSTAGE_DATA
240 && cbData > 0)
241 {
242 pSetup = pPipe->pCtrl->pMsg;
243 if (pSetup->bRequest == VUSB_REQ_GET_DESCRIPTOR)
244 fDescriptors = true;
245 }
246
247 /*
248 * Dump descriptors.
249 */
250 if (fDescriptors)
251 {
252 const uint8_t *pb = pbData;
253 const uint8_t *pbEnd = pbData + cbData;
254 while (pb + 1 < pbEnd)
255 {
256 const unsigned cbLeft = pbEnd - pb;
257 const unsigned cbLength = *pb;
258 unsigned cb = cbLength;
259 uint8_t bDescriptorType = pb[1];
260
261 /* length out of bounds? */
262 if (cbLength > cbLeft)
263 {
264 cb = cbLeft;
265 if (cbLength != 0xff) /* ignore this */
266 Log(("URB: %*s: DESC: warning descriptor length goes beyond the end of the URB! cbLength=%d cbLeft=%d\n",
267 s_cchMaxMsg, pszMsg, cbLength, cbLeft));
268 }
269
270 if (cb >= 2)
271 {
272 Log(("URB: %*s: DESC: %04x: %25s = %#04x (%d)\n"
273 "URB: %*s: %04x: %25s = %#04x (",
274 s_cchMaxMsg, pszMsg, pb - pbData, "bLength", cbLength, cbLength,
275 s_cchMaxMsg, pszMsg, pb - pbData + 1, "bDescriptorType", bDescriptorType));
276
277 #pragma pack(1)
278 #define BYTE_FIELD(strct, memb) \
279 if ((unsigned)RT_OFFSETOF(strct, memb) < cb) \
280 Log(("URB: %*s: %04x: %25s = %#04x\n", s_cchMaxMsg, pszMsg, \
281 pb + RT_OFFSETOF(strct, memb) - pbData, #memb, pb[RT_OFFSETOF(strct, memb)]))
282 #define BYTE_FIELD_START(strct, memb) do { \
283 if ((unsigned)RT_OFFSETOF(strct, memb) < cb) \
284 { \
285 Log(("URB: %*s: %04x: %25s = %#04x", s_cchMaxMsg, pszMsg, \
286 pb + RT_OFFSETOF(strct, memb) - pbData, #memb, pb[RT_OFFSETOF(strct, memb)]))
287 #define BYTE_FIELD_END(strct, memb) \
288 Log(("\n")); \
289 } } while (0)
290 #define WORD_FIELD(strct, memb) \
291 if ((unsigned)RT_OFFSETOF(strct, memb) + 1 < cb) \
292 Log(("URB: %*s: %04x: %25s = %#06x\n", s_cchMaxMsg, pszMsg, \
293 pb + RT_OFFSETOF(strct, memb) - pbData, #memb, *(uint16_t *)&pb[RT_OFFSETOF(strct, memb)]))
294 #define BCD_FIELD(strct, memb) \
295 if ((unsigned)RT_OFFSETOF(strct, memb) + 1 < cb) \
296 Log(("URB: %*s: %04x: %25s = %#06x (%02x.%02x)\n", s_cchMaxMsg, pszMsg, \
297 pb + RT_OFFSETOF(strct, memb) - pbData, #memb, *(uint16_t *)&pb[RT_OFFSETOF(strct, memb)], \
298 pb[RT_OFFSETOF(strct, memb) + 1], pb[RT_OFFSETOF(strct, memb)]))
299 #define SIZE_CHECK(strct) \
300 if (cb > sizeof(strct)) \
301 Log(("URB: %*s: %04x: WARNING %d extra byte(s) %.*Rhxs\n", s_cchMaxMsg, pszMsg, \
302 pb + sizeof(strct) - pbData, cb - sizeof(strct), cb - sizeof(strct), pb + sizeof(strct))); \
303 else if (cb < sizeof(strct)) \
304 Log(("URB: %*s: %04x: WARNING %d missing byte(s)! Expected size %d.\n", s_cchMaxMsg, pszMsg, \
305 pb + cb - pbData, sizeof(strct) - cb, sizeof(strct)))
306
307 /* on type */
308 switch (bDescriptorType)
309 {
310 case VUSB_DT_DEVICE:
311 {
312 struct dev_desc
313 {
314 uint8_t bLength;
315 uint8_t bDescriptorType;
316 uint16_t bcdUSB;
317 uint8_t bDeviceClass;
318 uint8_t bDeviceSubClass;
319 uint8_t bDeviceProtocol;
320 uint8_t bMaxPacketSize0;
321 uint16_t idVendor;
322 uint16_t idProduct;
323 uint16_t bcdDevice;
324 uint8_t iManufacturer;
325 uint8_t iProduct;
326 uint8_t iSerialNumber;
327 uint8_t bNumConfigurations;
328 } *pDesc = (struct dev_desc *)pb; NOREF(pDesc);
329 Log(("DEV)\n"));
330 BCD_FIELD( struct dev_desc, bcdUSB);
331 BYTE_FIELD(struct dev_desc, bDeviceClass);
332 BYTE_FIELD(struct dev_desc, bDeviceSubClass);
333 BYTE_FIELD(struct dev_desc, bDeviceProtocol);
334 BYTE_FIELD(struct dev_desc, bMaxPacketSize0);
335 WORD_FIELD(struct dev_desc, idVendor);
336 WORD_FIELD(struct dev_desc, idProduct);
337 BCD_FIELD( struct dev_desc, bcdDevice);
338 BYTE_FIELD(struct dev_desc, iManufacturer);
339 BYTE_FIELD(struct dev_desc, iProduct);
340 BYTE_FIELD(struct dev_desc, iSerialNumber);
341 BYTE_FIELD(struct dev_desc, bNumConfigurations);
342 SIZE_CHECK(struct dev_desc);
343 break;
344 }
345
346 case VUSB_DT_CONFIG:
347 {
348 struct cfg_desc
349 {
350 uint8_t bLength;
351 uint8_t bDescriptorType;
352 uint16_t wTotalLength;
353 uint8_t bNumInterfaces;
354 uint8_t bConfigurationValue;
355 uint8_t iConfiguration;
356 uint8_t bmAttributes;
357 uint8_t MaxPower;
358 } *pDesc = (struct cfg_desc *)pb; NOREF(pDesc);
359 Log(("CFG)\n"));
360 WORD_FIELD(struct cfg_desc, wTotalLength);
361 BYTE_FIELD(struct cfg_desc, bNumInterfaces);
362 BYTE_FIELD(struct cfg_desc, bConfigurationValue);
363 BYTE_FIELD(struct cfg_desc, iConfiguration);
364 BYTE_FIELD_START(struct cfg_desc, bmAttributes);
365 static const char * const s_apszTransType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
366 static const char * const s_apszSyncType[4] = { "NoSync", "Asynchronous", "Adaptive", "Synchronous" };
367 static const char * const s_apszUsageType[4] = { "Data ep", "Feedback ep.", "Implicit feedback Data ep.", "Reserved" };
368 Log((" %s - %s - %s", s_apszTransType[(pDesc->bmAttributes & 0x3)],
369 s_apszSyncType[((pDesc->bmAttributes >> 2) & 0x3)], s_apszUsageType[((pDesc->bmAttributes >> 4) & 0x3)]));
370 BYTE_FIELD_END(struct cfg_desc, bmAttributes);
371 BYTE_FIELD(struct cfg_desc, MaxPower);
372 SIZE_CHECK(struct cfg_desc);
373 break;
374 }
375
376 case VUSB_DT_STRING:
377 if (!pSetup->wIndex)
378 {
379 /* langid array */
380 uint16_t *pu16 = (uint16_t *)pb + 1;
381 Log(("LANGIDs)\n"));
382 while ((uintptr_t)pu16 + 2 - (uintptr_t)pb <= cb)
383 {
384 Log(("URB: %*s: %04x: wLANGID[%#x] = %#06x\n",
385 s_cchMaxMsg, pszMsg, (uint8_t *)pu16 - pbData, pu16 - (uint16_t *)pb, *pu16));
386 pu16++;
387 }
388 if (cb & 1)
389 Log(("URB: %*s: %04x: WARNING descriptor size is odd! extra byte: %02\n",
390 s_cchMaxMsg, pszMsg, (uint8_t *)pu16 - pbData, *(uint8_t *)pu16));
391 }
392 else
393 {
394 /** a string. */
395 Log(("STRING)\n"));
396 if (cb > 2)
397 Log(("URB: %*s: %04x: Length=%d String=%.*ls\n",
398 s_cchMaxMsg, pszMsg, pb - pbData, cb - 2, cb / 2 - 1, pb + 2));
399 else
400 Log(("URB: %*s: %04x: Length=0!\n", s_cchMaxMsg, pszMsg, pb - pbData));
401 }
402 break;
403
404 case VUSB_DT_INTERFACE:
405 {
406 struct if_desc
407 {
408 uint8_t bLength;
409 uint8_t bDescriptorType;
410 uint8_t bInterfaceNumber;
411 uint8_t bAlternateSetting;
412 uint8_t bNumEndpoints;
413 uint8_t bInterfaceClass;
414 uint8_t bInterfaceSubClass;
415 uint8_t bInterfaceProtocol;
416 uint8_t iInterface;
417 } *pDesc = (struct if_desc *)pb; NOREF(pDesc);
418 Log(("IF)\n"));
419 BYTE_FIELD(struct if_desc, bInterfaceNumber);
420 BYTE_FIELD(struct if_desc, bAlternateSetting);
421 BYTE_FIELD(struct if_desc, bNumEndpoints);
422 BYTE_FIELD(struct if_desc, bInterfaceClass);
423 BYTE_FIELD(struct if_desc, bInterfaceSubClass);
424 BYTE_FIELD(struct if_desc, bInterfaceProtocol);
425 BYTE_FIELD(struct if_desc, iInterface);
426 SIZE_CHECK(struct if_desc);
427 break;
428 }
429
430 case VUSB_DT_ENDPOINT:
431 {
432 struct ep_desc
433 {
434 uint8_t bLength;
435 uint8_t bDescriptorType;
436 uint8_t bEndpointAddress;
437 uint8_t bmAttributes;
438 uint16_t wMaxPacketSize;
439 uint8_t bInterval;
440 } *pDesc = (struct ep_desc *)pb; NOREF(pDesc);
441 Log(("EP)\n"));
442 BYTE_FIELD(struct ep_desc, bEndpointAddress);
443 BYTE_FIELD(struct ep_desc, bmAttributes);
444 WORD_FIELD(struct ep_desc, wMaxPacketSize);
445 BYTE_FIELD(struct ep_desc, bInterval);
446 SIZE_CHECK(struct ep_desc);
447 break;
448 }
449
450 case VUSB_DT_DEVICE_QUALIFIER:
451 {
452 struct dq_desc
453 {
454 uint8_t bLength;
455 uint8_t bDescriptorType;
456 uint16_t bcdUSB;
457 uint8_t bDeviceClass;
458 uint8_t bDeviceSubClass;
459 uint8_t bDeviceProtocol;
460 uint8_t bMaxPacketSize0;
461 uint8_t bNumConfigurations;
462 uint8_t bReserved;
463 } *pDQDesc = (struct dq_desc *)pb; NOREF(pDQDesc);
464 Log(("DEVQ)\n"));
465 BCD_FIELD( struct dq_desc, bcdUSB);
466 BYTE_FIELD(struct dq_desc, bDeviceClass);
467 BYTE_FIELD(struct dq_desc, bDeviceSubClass);
468 BYTE_FIELD(struct dq_desc, bDeviceProtocol);
469 BYTE_FIELD(struct dq_desc, bMaxPacketSize0);
470 BYTE_FIELD(struct dq_desc, bNumConfigurations);
471 BYTE_FIELD(struct dq_desc, bReserved);
472 SIZE_CHECK(struct dq_desc);
473 break;
474 }
475
476 case VUSB_DT_OTHER_SPEED_CFG:
477 {
478 struct oth_cfg_desc
479 {
480 uint8_t bLength;
481 uint8_t bDescriptorType;
482 uint16_t wTotalLength;
483 uint8_t bNumInterfaces;
484 uint8_t bConfigurationValue;
485 uint8_t iConfiguration;
486 uint8_t bmAttributes;
487 uint8_t MaxPower;
488 } *pDesc = (struct oth_cfg_desc *)pb; NOREF(pDesc);
489 Log(("OCFG)\n"));
490 WORD_FIELD(struct oth_cfg_desc, wTotalLength);
491 BYTE_FIELD(struct oth_cfg_desc, bNumInterfaces);
492 BYTE_FIELD(struct oth_cfg_desc, bConfigurationValue);
493 BYTE_FIELD(struct oth_cfg_desc, iConfiguration);
494 BYTE_FIELD_START(struct oth_cfg_desc, bmAttributes);
495 static const char * const s_apszTransType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
496 static const char * const s_apszSyncType[4] = { "NoSync", "Asynchronous", "Adaptive", "Synchronous" };
497 static const char * const s_apszUsageType[4] = { "Data ep", "Feedback ep.", "Implicit feedback Data ep.", "Reserved" };
498 Log((" %s - %s - %s", s_apszTransType[(pDesc->bmAttributes & 0x3)],
499 s_apszSyncType[((pDesc->bmAttributes >> 2) & 0x3)], s_apszUsageType[((pDesc->bmAttributes >> 4) & 0x3)]));
500 BYTE_FIELD_END(struct oth_cfg_desc, bmAttributes);
501 BYTE_FIELD(struct oth_cfg_desc, MaxPower);
502 SIZE_CHECK(struct oth_cfg_desc);
503 break;
504 }
505
506 case 0x21:
507 {
508 struct hid_desc
509 {
510 uint8_t bLength;
511 uint8_t bDescriptorType;
512 uint16_t bcdHid;
513 uint8_t bCountry;
514 uint8_t bNumDescriptors;
515 uint8_t bReportType;
516 uint16_t wReportLength;
517 } *pDesc = (struct hid_desc *)pb; NOREF(pDesc);
518 Log(("EP)\n"));
519 BCD_FIELD( struct hid_desc, bcdHid);
520 BYTE_FIELD(struct hid_desc, bCountry);
521 BYTE_FIELD(struct hid_desc, bNumDescriptors);
522 BYTE_FIELD(struct hid_desc, bReportType);
523 WORD_FIELD(struct hid_desc, wReportLength);
524 SIZE_CHECK(struct hid_desc);
525 break;
526 }
527
528 case 0xff:
529 Log(("UNKNOWN-ignore)\n"));
530 break;
531
532 default:
533 Log(("UNKNOWN)!!!\n"));
534 break;
535 }
536
537 #undef BYTE_FIELD
538 #undef WORD_FIELD
539 #undef BCD_FIELD
540 #undef SIZE_CHECK
541 #pragma pack()
542 }
543 else
544 {
545 Log(("URB: %*s: DESC: %04x: bLength=%d bDescriptorType=%d - invalid length\n",
546 s_cchMaxMsg, pszMsg, pb - pbData, cb, bDescriptorType));
547 break;
548 }
549
550 /* next */
551 pb += cb;
552 }
553 }
554
555 /*
556 * SCSI
557 */
558 if ( pUrb->enmType == VUSBXFERTYPE_BULK
559 && pUrb->enmDir == VUSBDIRECTION_OUT
560 && pUrb->cbData >= 12
561 && !memcmp(pUrb->abData, "USBC", 4))
562 {
563 const struct usbc
564 {
565 uint32_t Signature;
566 uint32_t Tag;
567 uint32_t DataTransferLength;
568 uint8_t Flags;
569 uint8_t Lun;
570 uint8_t Length;
571 uint8_t CDB[13];
572 } *pUsbC = (struct usbc *)pUrb->abData;
573 Log(("URB: %*s: SCSI: Tag=%#x DataTransferLength=%#x Flags=%#x Lun=%#x Length=%#x CDB=%.*Rhxs\n",
574 s_cchMaxMsg, pszMsg, pUsbC->Tag, pUsbC->DataTransferLength, pUsbC->Flags, pUsbC->Lun,
575 pUsbC->Length, pUsbC->Length, pUsbC->CDB));
576 const uint8_t *pb = &pUsbC->CDB[0];
577 switch (pb[0])
578 {
579 case 0x00: /* test unit read */
580 Log(("URB: %*s: SCSI: TEST_UNIT_READY LUN=%d Ctrl=%#RX8\n",
581 s_cchMaxMsg, pszMsg, pb[1] >> 5, pb[5]));
582 break;
583 case 0x03: /* Request Sense command */
584 Log(("URB: %*s: SCSI: REQUEST_SENSE LUN=%d AlcLen=%#RX16 Ctrl=%#RX8\n",
585 s_cchMaxMsg, pszMsg, pb[1] >> 5, pb[4], pb[5]));
586 break;
587 case 0x12: /* Inquiry command. */
588 Log(("URB: %*s: SCSI: INQUIRY EVPD=%d LUN=%d PgCd=%#RX8 AlcLen=%#RX8 Ctrl=%#RX8\n",
589 s_cchMaxMsg, pszMsg, pb[1] & 1, pb[1] >> 5, pb[2], pb[4], pb[5]));
590 break;
591 case 0x1a: /* Mode Sense(6) command */
592 Log(("URB: %*s: SCSI: MODE_SENSE6 LUN=%d DBD=%d PC=%d PgCd=%#RX8 AlcLen=%#RX8 Ctrl=%#RX8\n",
593 s_cchMaxMsg, pszMsg, pb[1] >> 5, !!(pb[1] & RT_BIT(3)), pb[2] >> 6, pb[2] & 0x3f, pb[4], pb[5]));
594 break;
595 case 0x5a:
596 Log(("URB: %*s: SCSI: MODE_SENSE10 LUN=%d DBD=%d PC=%d PgCd=%#RX8 AlcLen=%#RX16 Ctrl=%#RX8\n",
597 s_cchMaxMsg, pszMsg, pb[1] >> 5, !!(pb[1] & RT_BIT(3)), pb[2] >> 6, pb[2] & 0x3f,
598 RT_MAKE_U16(pb[8], pb[7]), pb[9]));
599 break;
600 case 0x25: /* Read Capacity(6) command. */
601 Log(("URB: %*s: SCSI: READ_CAPACITY\n",
602 s_cchMaxMsg, pszMsg));
603 break;
604 case 0x28: /* Read(10) command. */
605 Log(("URB: %*s: SCSI: READ10 RelAdr=%d FUA=%d DPO=%d LUN=%d LBA=%#RX32 Len=%#RX16 Ctrl=%#RX8\n",
606 s_cchMaxMsg, pszMsg,
607 pb[1] & 1, !!(pb[1] & RT_BIT(3)), !!(pb[1] & RT_BIT(4)), pb[1] >> 5,
608 RT_MAKE_U32_FROM_U8(pb[5], pb[4], pb[3], pb[2]),
609 RT_MAKE_U16(pb[8], pb[7]), pb[9]));
610 break;
611 case 0xa8: /* Read(12) command. */
612 Log(("URB: %*s: SCSI: READ12 RelAdr=%d FUA=%d DPO=%d LUN=%d LBA=%#RX32 Len=%#RX32 Ctrl=%#RX8\n",
613 s_cchMaxMsg, pszMsg,
614 pb[1] & 1, !!(pb[1] & RT_BIT(3)), !!(pb[1] & RT_BIT(4)), pb[1] >> 5,
615 RT_MAKE_U32_FROM_U8(pb[5], pb[4], pb[3], pb[2]),
616 RT_MAKE_U32_FROM_U8(pb[9], pb[8], pb[7], pb[6]),
617 pb[11]));
618 break;
619 case 0x3e: /* Read Long command. */
620 Log(("URB: %*s: SCSI: READ LONG RelAdr=%d Correct=%d LUN=%d LBA=%#RX16 ByteLen=%#RX16 Ctrl=%#RX8\n",
621 s_cchMaxMsg, pszMsg,
622 pb[1] & 1, !!(pb[1] & RT_BIT(1)), pb[1] >> 5,
623 RT_MAKE_U16(pb[3], pb[2]), RT_MAKE_U16(pb[6], pb[5]),
624 pb[11]));
625 break;
626 case 0x2a: /* Write(10) command. */
627 Log(("URB: %*s: SCSI: WRITE10 RelAdr=%d EBP=%d FUA=%d DPO=%d LUN=%d LBA=%#RX32 Len=%#RX16 Ctrl=%#RX8\n",
628 s_cchMaxMsg, pszMsg,
629 pb[1] & 1, !!(pb[1] & RT_BIT(2)), !!(pb[1] & RT_BIT(3)),
630 !!(pb[1] & RT_BIT(4)), pb[1] >> 5,
631 RT_MAKE_U32_FROM_U8(pb[5], pb[4], pb[3], pb[2]),
632 RT_MAKE_U16(pb[8], pb[7]), pb[9]));
633 break;
634 case 0xaa: /* Write(12) command. */
635 Log(("URB: %*s: SCSI: WRITE12 RelAdr=%d EBP=%d FUA=%d DPO=%d LUN=%d LBA=%#RX32 Len=%#RX32 Ctrl=%#RX8\n",
636 s_cchMaxMsg, pszMsg,
637 pb[1] & 1, !!(pb[1] & RT_BIT(3)), !!(pb[1] & RT_BIT(4)),
638 !!(pb[1] & RT_BIT(4)), pb[1] >> 5,
639 RT_MAKE_U32_FROM_U8(pb[5], pb[4], pb[3], pb[2]),
640 RT_MAKE_U32_FROM_U8(pb[9], pb[8], pb[7], pb[6]),
641 pb[11]));
642 break;
643 case 0x3f: /* Write Long command. */
644 Log(("URB: %*s: SCSI: WRITE LONG RelAdr=%d LUN=%d LBA=%#RX16 ByteLen=%#RX16 Ctrl=%#RX8\n",
645 s_cchMaxMsg, pszMsg,
646 pb[1] & 1, pb[1] >> 5,
647 RT_MAKE_U16(pb[3], pb[2]), RT_MAKE_U16(pb[6], pb[5]),
648 pb[11]));
649 break;
650 case 0x35: /* Synchronize Cache(10) command. */
651 Log(("URB: %*s: SCSI: SYNCHRONIZE_CACHE10\n",
652 s_cchMaxMsg, pszMsg));
653 break;
654 case 0xa0: /* Report LUNs command. */
655 Log(("URB: %*s: SCSI: REPORT_LUNS\n",
656 s_cchMaxMsg, pszMsg));
657 break;
658 default:
659 Log(("URB: %*s: SCSI: cmd=%#x\n",
660 s_cchMaxMsg, pszMsg, pb[0]));
661 break;
662 }
663 if (pDev)
664 pDev->Urb.u8ScsiCmd = pb[0];
665 }
666 else if ( fComplete
667 && pUrb->enmType == VUSBXFERTYPE_BULK
668 && pUrb->enmDir == VUSBDIRECTION_IN
669 && pUrb->cbData >= 12
670 && !memcmp(pUrb->abData, "USBS", 4))
671 {
672 const struct usbs
673 {
674 uint32_t Signature;
675 uint32_t Tag;
676 uint32_t DataResidue;
677 uint8_t Status;
678 uint8_t CDB[3];
679 } *pUsbS = (struct usbs *)pUrb->abData;
680 static const char * const s_apszStatuses[] = { "PASSED", "FAILED", "PHASE ERROR", "RESERVED" };
681 Log(("URB: %*s: SCSI: Tag=%#x DataResidue=%#RX32 Status=%#RX8 %s\n",
682 s_cchMaxMsg, pszMsg, pUsbS->Tag, pUsbS->DataResidue, pUsbS->Status,
683 s_apszStatuses[pUsbS->Status < RT_ELEMENTS(s_apszStatuses) ? pUsbS->Status : RT_ELEMENTS(s_apszStatuses) - 1]));
684 if (pDev)
685 pDev->Urb.u8ScsiCmd = 0xff;
686 }
687 else if ( fComplete
688 && pUrb->enmType == VUSBXFERTYPE_BULK
689 && pUrb->enmDir == VUSBDIRECTION_IN
690 && pDev
691 && pDev->Urb.u8ScsiCmd != 0xff)
692 {
693 const uint8_t *pb = pUrb->abData;
694 switch (pDev->Urb.u8ScsiCmd)
695 {
696 case 0x03: /* REQUEST_SENSE */
697 Log(("URB: %*s: SCSI: RESPONSE: REQUEST_SENSE (%s)\n",
698 s_cchMaxMsg, pszMsg, pb[0] & 7 ? "scsi compliant" : "not scsi compliant"));
699 Log(("URB: %*s: SCSI: ErrCd=%#RX8 (%s) Seg=%#RX8 Filemark=%d EOM=%d ILI=%d\n",
700 s_cchMaxMsg, pszMsg, pb[0] & 0x7f, GetScsiErrCd(pb[0] & 0x7f), pb[1],
701 pb[2] >> 7, !!(pb[2] & RT_BIT(6)), !!(pb[2] & RT_BIT(5))));
702 Log(("URB: %*s: SCSI: SenseKey=%#x ASC=%#RX8 ASCQ=%#RX8 : %s\n",
703 s_cchMaxMsg, pszMsg, pb[2] & 0xf, pb[12], pb[13],
704 GetScsiKCQ(pb[2] & 0xf, pb[12], pb[13])));
705 /** @todo more later */
706 break;
707
708 case 0x12: /* INQUIRY. */
709 {
710 unsigned cb = pb[4] + 5;
711 Log(("URB: %*s: SCSI: RESPONSE: INQUIRY\n"
712 "URB: %*s: SCSI: PeripheralQualifier=%d PeripheralType=%#RX8 RMB=%d DevTypeMod=%#RX8\n",
713 s_cchMaxMsg, pszMsg, s_cchMaxMsg, pszMsg,
714 pb[0] >> 5, pb[0] & 0x1f, pb[1] >> 7, pb[1] & 0x7f));
715 Log(("URB: %*s: SCSI: ISOVer=%d ECMAVer=%d ANSIVer=%d\n",
716 s_cchMaxMsg, pszMsg, pb[2] >> 6, (pb[2] >> 3) & 7, pb[2] & 7));
717 Log(("URB: %*s: SCSI: AENC=%d TrmlOP=%d RespDataFmt=%d (%s) AddLen=%d\n",
718 s_cchMaxMsg, pszMsg, pb[3] >> 7, (pb[3] >> 6) & 1,
719 pb[3] & 0xf, pb[3] & 0xf ? "legacy" : "scsi", pb[4]));
720 if (cb < 8)
721 break;
722 Log(("URB: %*s: SCSI: RelAdr=%d WBus32=%d WBus16=%d Sync=%d Linked=%d CmdQue=%d SftRe=%d\n",
723 s_cchMaxMsg, pszMsg, pb[7] >> 7, !!(pb[7] >> 6), !!(pb[7] >> 5), !!(pb[7] >> 4),
724 !!(pb[7] >> 3), !!(pb[7] >> 1), pb[7] & 1));
725 if (cb < 16)
726 break;
727 Log(("URB: %*s: SCSI: VendorId=%.8s\n", s_cchMaxMsg, pszMsg, &pb[8]));
728 if (cb < 32)
729 break;
730 Log(("URB: %*s: SCSI: ProductId=%.16s\n", s_cchMaxMsg, pszMsg, &pb[16]));
731 if (cb < 36)
732 break;
733 Log(("URB: %*s: SCSI: ProdRevLvl=%.4s\n", s_cchMaxMsg, pszMsg, &pb[32]));
734 if (cb > 36)
735 Log(("URB: %*s: SCSI: VendorSpecific=%.*s\n",
736 s_cchMaxMsg, pszMsg, RT_MIN(cb - 36, 20), &pb[36]));
737 if (cb > 96)
738 Log(("URB: %*s: SCSI: VendorParam=%.*Rhxs\n",
739 s_cchMaxMsg, pszMsg, cb - 96, &pb[96]));
740 break;
741 }
742
743 case 0x25: /* Read Capacity(6) command. */
744 Log(("URB: %*s: SCSI: RESPONSE: READ_CAPACITY\n"
745 "URB: %*s: SCSI: LBA=%#RX32 BlockLen=%#RX32\n",
746 s_cchMaxMsg, pszMsg, s_cchMaxMsg, pszMsg,
747 RT_MAKE_U32_FROM_U8(pb[3], pb[2], pb[1], pb[0]),
748 RT_MAKE_U32_FROM_U8(pb[7], pb[6], pb[5], pb[4])));
749 break;
750 }
751
752 pDev->Urb.u8ScsiCmd = 0xff;
753 }
754
755 /*
756 * The Quickcam control pipe.
757 */
758 if ( pSetup
759 && ((pSetup->bmRequestType >> 5) & 0x3) >= 2 /* vendor */
760 && (fComplete || !(pSetup->bmRequestType >> 7))
761 && pDev
762 && pDev->pDescCache
763 && pDev->pDescCache->pDevice
764 && pDev->pDescCache->pDevice->idVendor == 0x046d
765 && ( pDev->pDescCache->pDevice->idProduct == 0x8f6
766 || pDev->pDescCache->pDevice->idProduct == 0x8f5
767 || pDev->pDescCache->pDevice->idProduct == 0x8f0)
768 )
769 {
770 pbData = (const uint8_t *)(pSetup + 1);
771 cbData = pUrb->cbData - sizeof(*pSetup);
772
773 if ( pSetup->bRequest == 0x04
774 && pSetup->wIndex == 0
775 && (cbData == 1 || cbData == 2))
776 {
777 /* the value */
778 unsigned uVal = pbData[0];
779 if (cbData > 1)
780 uVal |= (unsigned)pbData[1] << 8;
781
782 const char *pszReg = NULL;
783 switch (pSetup->wValue)
784 {
785 case 0: pszReg = "i2c init"; break;
786 case 0x0423: pszReg = "STV_REG23"; break;
787 case 0x0509: pszReg = "RED something"; break;
788 case 0x050a: pszReg = "GREEN something"; break;
789 case 0x050b: pszReg = "BLUE something"; break;
790 case 0x143f: pszReg = "COMMIT? INIT DONE?"; break;
791 case 0x1440: pszReg = "STV_ISO_ENABLE"; break;
792 case 0x1442: pszReg = uVal & (RT_BIT(7)|RT_BIT(5)) ? "BUTTON PRESSED" : "BUTTON" ; break;
793 case 0x1443: pszReg = "STV_SCAN_RATE"; break;
794 case 0x1445: pszReg = "LED?"; break;
795 case 0x1500: pszReg = "STV_REG00"; break;
796 case 0x1501: pszReg = "STV_REG01"; break;
797 case 0x1502: pszReg = "STV_REG02"; break;
798 case 0x1503: pszReg = "STV_REG03"; break;
799 case 0x1504: pszReg = "STV_REG04"; break;
800 case 0x15c1: pszReg = "STV_ISO_SIZE"; break;
801 case 0x15c3: pszReg = "STV_Y_CTRL"; break;
802 case 0x1680: pszReg = "STV_X_CTRL"; break;
803 case 0xe00a: pszReg = "ProductId"; break;
804 default: pszReg = "[no clue]"; break;
805 }
806 if (pszReg)
807 Log(("URB: %*s: QUICKCAM: %s %#x (%d) %s '%s' (%#x)\n",
808 s_cchMaxMsg, pszMsg,
809 (pSetup->bmRequestType >> 7) ? "read" : "write", uVal, uVal, (pSetup->bmRequestType >> 7) ? "from" : "to",
810 pszReg, pSetup->wValue));
811 }
812 else if (cbData)
813 Log(("URB: %*s: QUICKCAM: Unknown request: bRequest=%#x bmRequestType=%#x wValue=%#x wIndex=%#x: %.*Rhxs\n", s_cchMaxMsg, pszMsg,
814 pSetup->bRequest, pSetup->bmRequestType, pSetup->wValue, pSetup->wIndex, cbData, pbData));
815 else
816 Log(("URB: %*s: QUICKCAM: Unknown request: bRequest=%#x bmRequestType=%#x wValue=%#x wIndex=%#x: (no data)\n", s_cchMaxMsg, pszMsg,
817 pSetup->bRequest, pSetup->bmRequestType, pSetup->wValue, pSetup->wIndex));
818 }
819
820#if 1
821 if ( cbData /** @todo Fix RTStrFormatV to communicate .* so formatter doesn't apply defaults when cbData=0. */
822 && (fComplete
823 ? pUrb->enmDir != VUSBDIRECTION_OUT
824 : pUrb->enmDir == VUSBDIRECTION_OUT))
825 Log3(("%16.*Rhxd\n", cbData, pbData));
826#endif
827 if (pUrb->enmType == VUSBXFERTYPE_MSG && pUrb->VUsb.pCtrlUrb)
828 vusbUrbTrace(pUrb->VUsb.pCtrlUrb, "NESTED MSG", fComplete);
829}
830#endif /* LOG_ENABLED */
831
832
833/**
834 * Complete a SETUP stage URB.
835 *
836 * This is used both for dev2host and host2dev kind of transfers.
837 * It is used by both the sync and async control paths.
838 */
839static void vusbMsgSetupCompletion(PVUSBURB pUrb)
840{
841 PVUSBDEV pDev = pUrb->VUsb.pDev;
842 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
843 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
844 PVUSBSETUP pSetup = pExtra->pMsg;
845
846 LogFlow(("%s: vusbMsgSetupCompletion: cbData=%d wLength=%#x cbLeft=%d pPipe=%p stage %s->DATA\n",
847 pUrb->pszDesc, pUrb->cbData, pSetup->wLength, pExtra->cbLeft, pPipe, g_apszCtlStates[pExtra->enmStage])); NOREF(pSetup);
848 pExtra->enmStage = CTLSTAGE_DATA;
849 pUrb->enmStatus = VUSBSTATUS_OK;
850}
851
852/**
853 * Complete a DATA stage URB.
854 *
855 * This is used both for dev2host and host2dev kind of transfers.
856 * It is used by both the sync and async control paths.
857 */
858static void vusbMsgDataCompletion(PVUSBURB pUrb)
859{
860 PVUSBDEV pDev = pUrb->VUsb.pDev;
861 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
862 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
863 PVUSBSETUP pSetup = pExtra->pMsg;
864
865 LogFlow(("%s: vusbMsgDataCompletion: cbData=%d wLength=%#x cbLeft=%d pPipe=%p stage DATA\n",
866 pUrb->pszDesc, pUrb->cbData, pSetup->wLength, pExtra->cbLeft, pPipe)); NOREF(pSetup);
867
868 pUrb->enmStatus = VUSBSTATUS_OK;
869}
870
871/**
872 * Complete a STATUS stage URB.
873 *
874 * This is used both for dev2host and host2dev kind of transfers.
875 * It is used by both the sync and async control paths.
876 */
877static void vusbMsgStatusCompletion(PVUSBURB pUrb)
878{
879 PVUSBDEV pDev = pUrb->VUsb.pDev;
880 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
881 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
882
883 if (pExtra->fOk)
884 {
885 /*
886 * vusbDevStdReqSetAddress requests are deferred.
887 */
888 if (pDev->u8NewAddress != VUSB_INVALID_ADDRESS)
889 {
890 vusbDevSetAddress(pDev, pDev->u8NewAddress);
891 pDev->u8NewAddress = VUSB_INVALID_ADDRESS;
892 }
893
894 LogFlow(("%s: vusbMsgStatusCompletion: pDev=%p[%s] pPipe=%p err=OK stage %s->SETUP\n",
895 pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, pPipe, g_apszCtlStates[pExtra->enmStage]));
896 pUrb->enmStatus = VUSBSTATUS_OK;
897 }
898 else
899 {
900 LogFlow(("%s: vusbMsgStatusCompletion: pDev=%p[%s] pPipe=%p err=STALL stage %s->SETUP\n",
901 pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, pPipe, g_apszCtlStates[pExtra->enmStage]));
902 pUrb->enmStatus = VUSBSTATUS_STALL;
903 }
904
905 /*
906 * Done with this message sequence.
907 */
908 pExtra->pbCur = NULL;
909 pExtra->enmStage = CTLSTAGE_SETUP;
910}
911
912/**
913 * This is a worker function for vusbMsgCompletion and
914 * vusbMsgSubmitSynchronously used to complete the original URB.
915 *
916 * @param pUrb The URB originating from the HCI.
917 */
918static void vusbCtrlCompletion(PVUSBURB pUrb)
919{
920 PVUSBDEV pDev = pUrb->VUsb.pDev;
921 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
922 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
923 LogFlow(("%s: vusbCtrlCompletion: pDev=%p[%s]\n", pUrb->pszDesc, pDev, pDev->pUsbIns->pszName));
924
925 switch (pExtra->enmStage)
926 {
927 case CTLSTAGE_SETUP:
928 vusbMsgSetupCompletion(pUrb);
929 break;
930 case CTLSTAGE_DATA:
931 vusbMsgDataCompletion(pUrb);
932 break;
933 case CTLSTAGE_STATUS:
934 vusbMsgStatusCompletion(pUrb);
935 break;
936 }
937}
938
939/**
940 * Called from vusbUrbCompletionRh when it encounters a
941 * message type URB.
942 *
943 * @param pUrb The URB within the control pipe extra state data.
944 */
945static void vusbMsgCompletion(PVUSBURB pUrb)
946{
947 PVUSBDEV pDev = pUrb->VUsb.pDev;
948 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
949
950 RTCritSectEnter(&pPipe->CritSectCtrl);
951 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
952
953#ifdef LOG_ENABLED
954 LogFlow(("%s: vusbMsgCompletion: pDev=%p[%s]\n", pUrb->pszDesc, pDev, pDev->pUsbIns->pszName));
955 vusbUrbTrace(pUrb, "vusbMsgCompletion", true);
956#endif
957 Assert(&pExtra->Urb == pUrb);
958
959
960 if (pUrb->enmStatus == VUSBSTATUS_OK)
961 pExtra->fOk = true;
962 else
963 pExtra->fOk = false;
964 pExtra->cbLeft = pUrb->cbData - sizeof(VUSBSETUP);
965
966 /*
967 * Complete the original URB.
968 */
969 PVUSBURB pCtrlUrb = pUrb->VUsb.pCtrlUrb;
970 pCtrlUrb->enmState = VUSBURBSTATE_REAPED;
971 vusbCtrlCompletion(pCtrlUrb);
972
973 /*
974 * 'Free' the message URB, i.e. put it back to the allocated state.
975 */
976 Assert( pUrb->enmState == VUSBURBSTATE_REAPED
977 || pUrb->enmState == VUSBURBSTATE_CANCELLED);
978 if (pUrb->enmState != VUSBURBSTATE_CANCELLED)
979 pUrb->enmState = VUSBURBSTATE_ALLOCATED;
980 RTCritSectLeave(&pPipe->CritSectCtrl);
981
982 /* Complete the original control URB on the root hub now. */
983 vusbUrbCompletionRh(pCtrlUrb);
984}
985
986/**
987 * Deal with URB errors, talking thru the RH to the HCI.
988 *
989 * @returns true if it could be retried.
990 * @returns false if it should be completed with failure.
991 * @param pUrb The URB in question.
992 */
993int vusbUrbErrorRh(PVUSBURB pUrb)
994{
995 PVUSBDEV pDev = pUrb->VUsb.pDev;
996 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
997 AssertPtrReturn(pRh, VERR_VUSB_DEVICE_NOT_ATTACHED);
998 LogFlow(("%s: vusbUrbErrorRh: pDev=%p[%s] rh=%p\n", pUrb->pszDesc, pDev, pDev->pUsbIns ? pDev->pUsbIns->pszName : "", pRh));
999 return pRh->pIRhPort->pfnXferError(pRh->pIRhPort, pUrb);
1000}
1001
1002/**
1003 * Does URB completion on roothub level.
1004 *
1005 * @param pUrb The URB to complete.
1006 */
1007void vusbUrbCompletionRh(PVUSBURB pUrb)
1008{
1009 LogFlow(("%s: vusbUrbCompletionRh: type=%s status=%s\n",
1010 pUrb->pszDesc, vusbUrbTypeName(pUrb->enmType), vusbUrbStatusName(pUrb->enmStatus)));
1011 AssertMsg( pUrb->enmState == VUSBURBSTATE_REAPED
1012 || pUrb->enmState == VUSBURBSTATE_CANCELLED, ("%d\n", pUrb->enmState));
1013
1014 if (pUrb->VUsb.pDev->hSniffer)
1015 {
1016 int rc = VUSBSnifferRecordEvent(pUrb->VUsb.pDev->hSniffer, pUrb,
1017 pUrb->enmStatus == VUSBSTATUS_OK
1018 ? VUSBSNIFFEREVENT_COMPLETE
1019 : VUSBSNIFFEREVENT_ERROR_COMPLETE);
1020 if (RT_FAILURE(rc))
1021 LogRel(("VUSB: Capturing URB completion event failed with %Rrc\n", rc));
1022 }
1023
1024#ifdef VBOX_WITH_STATISTICS
1025 /*
1026 * Total and per-type submit statistics.
1027 */
1028 PVUSBROOTHUB pRh = vusbDevGetRh(pUrb->VUsb.pDev);
1029 AssertPtrReturnVoid(pRh);
1030
1031 /* If there is a sniffer on the roothub record the completed URB there too. */
1032 if (pRh->hSniffer != VUSBSNIFFER_NIL)
1033 {
1034 int rc = VUSBSnifferRecordEvent(pRh->hSniffer, pUrb,
1035 pUrb->enmStatus == VUSBSTATUS_OK
1036 ? VUSBSNIFFEREVENT_COMPLETE
1037 : VUSBSNIFFEREVENT_ERROR_COMPLETE);
1038 if (RT_FAILURE(rc))
1039 LogRel(("VUSB: Capturing URB completion event on the root hub failed with %Rrc\n", rc));
1040 }
1041
1042 if (pUrb->enmType != VUSBXFERTYPE_MSG)
1043 {
1044 Assert(pUrb->enmType >= 0 && pUrb->enmType < (int)RT_ELEMENTS(pRh->aTypes));
1045
1046 if ( pUrb->enmStatus == VUSBSTATUS_OK
1047 || pUrb->enmStatus == VUSBSTATUS_DATA_UNDERRUN
1048 || pUrb->enmStatus == VUSBSTATUS_DATA_OVERRUN)
1049 {
1050 if (pUrb->enmType == VUSBXFERTYPE_ISOC)
1051 {
1052 for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
1053 {
1054 const unsigned cb = pUrb->aIsocPkts[i].cb;
1055 if (cb)
1056 {
1057 STAM_COUNTER_ADD(&pRh->Total.StatActBytes, cb);
1058 STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActBytes, cb);
1059 STAM_COUNTER_ADD(&pRh->aStatIsocDetails[i].Bytes, cb);
1060 if (pUrb->enmDir == VUSBDIRECTION_IN)
1061 {
1062 STAM_COUNTER_ADD(&pRh->Total.StatActReadBytes, cb);
1063 STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActReadBytes, cb);
1064 }
1065 else
1066 {
1067 STAM_COUNTER_ADD(&pRh->Total.StatActWriteBytes, cb);
1068 STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActWriteBytes, cb);
1069 }
1070 STAM_COUNTER_INC(&pRh->StatIsocActPkts);
1071 STAM_COUNTER_INC(&pRh->StatIsocActReadPkts);
1072 }
1073 STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Pkts);
1074 switch (pUrb->aIsocPkts[i].enmStatus)
1075 {
1076 case VUSBSTATUS_OK:
1077 if (cb) STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Ok);
1078 else STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Ok0); break;
1079 case VUSBSTATUS_DATA_UNDERRUN:
1080 if (cb) STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataUnderrun);
1081 else STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataUnderrun0); break;
1082 case VUSBSTATUS_DATA_OVERRUN: STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataOverrun); break;
1083 case VUSBSTATUS_NOT_ACCESSED: STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].NotAccessed); break;
1084 default: STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Misc); break;
1085 }
1086 }
1087 }
1088 else
1089 {
1090 STAM_COUNTER_ADD(&pRh->Total.StatActBytes, pUrb->cbData);
1091 STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActBytes, pUrb->cbData);
1092 if (pUrb->enmDir == VUSBDIRECTION_IN)
1093 {
1094 STAM_COUNTER_ADD(&pRh->Total.StatActReadBytes, pUrb->cbData);
1095 STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActReadBytes, pUrb->cbData);
1096 }
1097 else
1098 {
1099 STAM_COUNTER_ADD(&pRh->Total.StatActWriteBytes, pUrb->cbData);
1100 STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActWriteBytes, pUrb->cbData);
1101 }
1102 }
1103 }
1104 else
1105 {
1106 /* (Note. this also counts the cancelled packets) */
1107 STAM_COUNTER_INC(&pRh->Total.StatUrbsFailed);
1108 STAM_COUNTER_INC(&pRh->aTypes[pUrb->enmType].StatUrbsFailed);
1109 }
1110 }
1111#endif /* VBOX_WITH_STATISTICS */
1112
1113 /*
1114 * Msg transfers are special virtual transfers associated with
1115 * vusb, not the roothub
1116 */
1117 switch (pUrb->enmType)
1118 {
1119 case VUSBXFERTYPE_MSG:
1120 vusbMsgCompletion(pUrb);
1121 return;
1122 case VUSBXFERTYPE_ISOC:
1123 /* Don't bother with error callback for isochronous URBs. */
1124 break;
1125
1126#if 1 /** @todo r=bird: OHCI say "If the Transfer Descriptor is being
1127 * retired because of an error, the Host Controller must update
1128 * the Halt bit of the Endpoint Descriptor."
1129 *
1130 * So, I'll subject all transfertypes to the same halt stuff now. It could
1131 * just happen to fix the logitech disconnect trap in win2k.
1132 */
1133 default:
1134#endif
1135 case VUSBXFERTYPE_BULK:
1136 if (pUrb->enmStatus != VUSBSTATUS_OK)
1137 vusbUrbErrorRh(pUrb);
1138 break;
1139 }
1140#ifdef LOG_ENABLED
1141 vusbUrbTrace(pUrb, "vusbUrbCompletionRh", true);
1142#endif
1143#ifndef VBOX_WITH_STATISTICS
1144 PVUSBROOTHUB pRh = vusbDevGetRh(pUrb->VUsb.pDev);
1145 AssertPtrReturnVoid(pRh);
1146#endif
1147
1148 pRh->pIRhPort->pfnXferCompletion(pRh->pIRhPort, pUrb);
1149 if (pUrb->enmState == VUSBURBSTATE_REAPED)
1150 {
1151 LogFlow(("%s: vusbUrbCompletionRh: Freeing URB\n", pUrb->pszDesc));
1152 pUrb->VUsb.pfnFree(pUrb);
1153 }
1154}
1155
1156
1157/**
1158 * Certain control requests must not ever be forwarded to the device because
1159 * they are required by the vusb core in order to maintain the vusb internal
1160 * data structures.
1161 */
1162DECLINLINE(bool) vusbUrbIsRequestSafe(PCVUSBSETUP pSetup, PVUSBURB pUrb)
1163{
1164 if ((pSetup->bmRequestType & VUSB_REQ_MASK) != VUSB_REQ_STANDARD)
1165 return true;
1166
1167 switch (pSetup->bRequest)
1168 {
1169 case VUSB_REQ_CLEAR_FEATURE:
1170 return pUrb->EndPt != 0 /* not default control pipe */
1171 || pSetup->wValue != 0 /* not ENDPOINT_HALT */
1172 || !pUrb->pUsbIns->pReg->pfnUsbClearHaltedEndpoint; /* not special need for backend */
1173 case VUSB_REQ_SET_ADDRESS:
1174 case VUSB_REQ_SET_CONFIGURATION:
1175 case VUSB_REQ_GET_CONFIGURATION:
1176 case VUSB_REQ_SET_INTERFACE:
1177 case VUSB_REQ_GET_INTERFACE:
1178 return false;
1179
1180 /*
1181 * If the device wishes it, we'll use the cached device and
1182 * configuration descriptors. (We return false when we want to use the
1183 * cache. Yeah, it's a bit weird to read.)
1184 */
1185 case VUSB_REQ_GET_DESCRIPTOR:
1186 if ( !pUrb->VUsb.pDev->pDescCache->fUseCachedDescriptors
1187 || (pSetup->bmRequestType & VUSB_RECIP_MASK) != VUSB_TO_DEVICE)
1188 return true;
1189 switch (pSetup->wValue >> 8)
1190 {
1191 case VUSB_DT_DEVICE:
1192 case VUSB_DT_CONFIG:
1193 return false;
1194 case VUSB_DT_STRING:
1195 return !pUrb->VUsb.pDev->pDescCache->fUseCachedStringsDescriptors;
1196 default:
1197 return true;
1198 }
1199
1200 default:
1201 return true;
1202 }
1203}
1204
1205
1206/**
1207 * Queues an URB for asynchronous transfer.
1208 * A list of asynchronous URBs is kept by the roothub.
1209 *
1210 * @returns VBox status code (from pfnUrbQueue).
1211 * @param pUrb The URB.
1212 */
1213int vusbUrbQueueAsyncRh(PVUSBURB pUrb)
1214{
1215#ifdef LOG_ENABLED
1216 vusbUrbTrace(pUrb, "vusbUrbQueueAsyncRh", false);
1217#endif
1218
1219 /* Immediately return in case of error.
1220 * XXX There is still a race: The Rh might vanish after this point! */
1221 PVUSBDEV pDev = pUrb->VUsb.pDev;
1222 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
1223 if (!pRh)
1224 {
1225 Log(("vusbUrbQueueAsyncRh returning VERR_OBJECT_DESTROYED\n"));
1226 return VERR_OBJECT_DESTROYED;
1227 }
1228
1229 RTCritSectEnter(&pDev->CritSectAsyncUrbs);
1230 int rc = pUrb->pUsbIns->pReg->pfnUrbQueue(pUrb->pUsbIns, pUrb);
1231 if (RT_FAILURE(rc))
1232 {
1233 LogFlow(("%s: vusbUrbQueueAsyncRh: returns %Rrc (queue_urb)\n", pUrb->pszDesc, rc));
1234 RTCritSectLeave(&pDev->CritSectAsyncUrbs);
1235 return rc;
1236 }
1237
1238 ASMAtomicIncU32(&pDev->aPipes[pUrb->EndPt].async);
1239
1240 /* Queue the pUrb on the roothub */
1241 pUrb->VUsb.pNext = pDev->pAsyncUrbHead;
1242 if (pDev->pAsyncUrbHead)
1243 pDev->pAsyncUrbHead->VUsb.ppPrev = &pUrb->VUsb.pNext;
1244 pDev->pAsyncUrbHead = pUrb;
1245 pUrb->VUsb.ppPrev = &pDev->pAsyncUrbHead;
1246 RTCritSectLeave(&pDev->CritSectAsyncUrbs);
1247
1248 return VINF_SUCCESS;
1249}
1250
1251
1252/**
1253 * Send a control message *synchronously*.
1254 * @return
1255 */
1256static void vusbMsgSubmitSynchronously(PVUSBURB pUrb, bool fSafeRequest)
1257{
1258 PVUSBDEV pDev = pUrb->VUsb.pDev;
1259 Assert(pDev);
1260 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
1261 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
1262 PVUSBSETUP pSetup = pExtra->pMsg;
1263 LogFlow(("%s: vusbMsgSubmitSynchronously: pDev=%p[%s]\n", pUrb->pszDesc, pDev, pDev->pUsbIns ? pDev->pUsbIns->pszName : ""));
1264
1265 uint8_t *pbData = (uint8_t *)pExtra->pMsg + sizeof(*pSetup);
1266 uint32_t cbData = pSetup->wLength;
1267 bool fOk = false;
1268 if (!fSafeRequest)
1269 fOk = vusbDevStandardRequest(pDev, pUrb->EndPt, pSetup, pbData, &cbData);
1270 else
1271 AssertMsgFailed(("oops\n"));
1272
1273 pUrb->enmState = VUSBURBSTATE_REAPED;
1274 if (fOk)
1275 {
1276 pSetup->wLength = cbData;
1277 pUrb->enmStatus = VUSBSTATUS_OK;
1278 pExtra->fOk = true;
1279 }
1280 else
1281 {
1282 pUrb->enmStatus = VUSBSTATUS_STALL;
1283 pExtra->fOk = false;
1284 }
1285 pExtra->cbLeft = cbData; /* used by IN only */
1286
1287 vusbCtrlCompletion(pUrb);
1288 vusbUrbCompletionRh(pUrb);
1289
1290 /*
1291 * 'Free' the message URB, i.e. put it back to the allocated state.
1292 */
1293 pExtra->Urb.enmState = VUSBURBSTATE_ALLOCATED;
1294}
1295
1296/**
1297 * Callback for dealing with device reset.
1298 */
1299void vusbMsgResetExtraData(PVUSBCTRLEXTRA pExtra)
1300{
1301 if (!pExtra)
1302 return;
1303 pExtra->enmStage = CTLSTAGE_SETUP;
1304 if (pExtra->Urb.enmState != VUSBURBSTATE_CANCELLED)
1305 pExtra->Urb.enmState = VUSBURBSTATE_ALLOCATED;
1306}
1307
1308
1309/**
1310 * Callback to free a cancelled message URB.
1311 *
1312 * This is yet another place we're we have to performance acrobatics to
1313 * deal with cancelled URBs. sigh.
1314 *
1315 * The deal here is that we never free message URBs since they are integrated
1316 * into the message pipe state. But since cancel can leave URBs unreaped and in
1317 * a state which require them not to be freed, we'll have to do two things.
1318 * First, if a new message URB is processed we'll have to get a new message
1319 * pipe state. Second, we cannot just free the damn state structure because
1320 * that might lead to heap corruption since it might still be in-flight.
1321 *
1322 * The URB embedded into the message pipe control structure will start in an
1323 * ALLOCATED state. When submitted it will be go to the IN-FLIGHT state. When
1324 * reaped it will go from REAPED to ALLOCATED. When completed in the CANCELLED
1325 * state it will remain in that state (as does normal URBs).
1326 *
1327 * If a new message urb comes up while it's in the CANCELLED state, we will
1328 * orphan it and it will be freed here in vusbMsgFreeUrb. We indicate this
1329 * by setting VUsb.pvFreeCtx to NULL.
1330 *
1331 * If we have to free the message state structure because of device destruction,
1332 * configuration changes, or similar, we will orphan the message pipe state in
1333 * the same way by setting VUsb.pvFreeCtx to NULL and let this function free it.
1334 *
1335 * @param pUrb
1336 */
1337static DECLCALLBACK(void) vusbMsgFreeUrb(PVUSBURB pUrb)
1338{
1339 vusbUrbAssert(pUrb);
1340 PVUSBCTRLEXTRA pExtra = (PVUSBCTRLEXTRA)((uint8_t *)pUrb - RT_OFFSETOF(VUSBCTRLEXTRA, Urb));
1341 if ( pUrb->enmState == VUSBURBSTATE_CANCELLED
1342 && !pUrb->VUsb.pvFreeCtx)
1343 {
1344 LogFlow(("vusbMsgFreeUrb: Freeing orphan: %p (pUrb=%p)\n", pExtra, pUrb));
1345 RTMemFree(pExtra);
1346 }
1347 else
1348 {
1349 Assert(pUrb->VUsb.pvFreeCtx == &pExtra->Urb);
1350 pUrb->enmState = VUSBURBSTATE_ALLOCATED;
1351 }
1352}
1353
1354/**
1355 * Frees the extra state data associated with a message pipe.
1356 *
1357 * @param pExtra The data.
1358 */
1359void vusbMsgFreeExtraData(PVUSBCTRLEXTRA pExtra)
1360{
1361 if (!pExtra)
1362 return;
1363 if (pExtra->Urb.enmState != VUSBURBSTATE_CANCELLED)
1364 {
1365 pExtra->Urb.u32Magic = 0;
1366 pExtra->Urb.enmState = VUSBURBSTATE_FREE;
1367 if (pExtra->Urb.pszDesc)
1368 RTStrFree(pExtra->Urb.pszDesc);
1369 RTMemFree(pExtra);
1370 }
1371 else
1372 pExtra->Urb.VUsb.pvFreeCtx = NULL; /* see vusbMsgFreeUrb */
1373}
1374
1375/**
1376 * Allocates the extra state data required for a control pipe.
1377 *
1378 * @returns Pointer to the allocated and initialized state data.
1379 * @returns NULL on out of memory condition.
1380 * @param pUrb A URB we can copy default data from.
1381 */
1382static PVUSBCTRLEXTRA vusbMsgAllocExtraData(PVUSBURB pUrb)
1383{
1384/** @todo reuse these? */
1385 PVUSBCTRLEXTRA pExtra;
1386 const size_t cbMax = sizeof(pExtra->Urb.abData) + sizeof(VUSBSETUP);
1387 pExtra = (PVUSBCTRLEXTRA)RTMemAllocZ(RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[cbMax]));
1388 if (pExtra)
1389 {
1390 pExtra->enmStage = CTLSTAGE_SETUP;
1391 //pExtra->fOk = false;
1392 pExtra->pMsg = (PVUSBSETUP)pExtra->Urb.abData;
1393 pExtra->pbCur = (uint8_t *)(pExtra->pMsg + 1);
1394 //pExtra->cbLeft = 0;
1395 pExtra->cbMax = cbMax;
1396
1397 //pExtra->Urb.Dev.pvProxyUrb = NULL;
1398 pExtra->Urb.u32Magic = VUSBURB_MAGIC;
1399 pExtra->Urb.enmState = VUSBURBSTATE_ALLOCATED;
1400#ifdef LOG_ENABLED
1401 RTStrAPrintf(&pExtra->Urb.pszDesc, "URB %p msg->%p", &pExtra->Urb, pUrb);
1402#endif
1403 //pExtra->Urb.VUsb.pCtrlUrb = NULL;
1404 //pExtra->Urb.VUsb.pNext = NULL;
1405 //pExtra->Urb.VUsb.ppPrev = NULL;
1406 pExtra->Urb.VUsb.pDev = pUrb->VUsb.pDev;
1407 pExtra->Urb.VUsb.pfnFree = vusbMsgFreeUrb;
1408 pExtra->Urb.VUsb.pvFreeCtx = &pExtra->Urb;
1409 //pExtra->Urb.Hci = {0};
1410 //pExtra->Urb.Dev.pvProxyUrb = NULL;
1411 pExtra->Urb.pUsbIns = pUrb->pUsbIns;
1412 pExtra->Urb.DstAddress = pUrb->DstAddress;
1413 pExtra->Urb.EndPt = pUrb->EndPt;
1414 pExtra->Urb.enmType = VUSBXFERTYPE_MSG;
1415 pExtra->Urb.enmDir = VUSBDIRECTION_INVALID;
1416 //pExtra->Urb.fShortNotOk = false;
1417 pExtra->Urb.enmStatus = VUSBSTATUS_INVALID;
1418 //pExtra->Urb.cbData = 0;
1419 vusbUrbAssert(&pExtra->Urb);
1420 }
1421 return pExtra;
1422}
1423
1424/**
1425 * Sets up the message.
1426 *
1427 * The message is associated with the pipe, in what's currently called
1428 * control pipe extra state data (pointed to by pPipe->pCtrl). If this
1429 * is a OUT message, we will no go on collecting data URB. If it's a
1430 * IN message, we'll send it and then queue any incoming data for the
1431 * URBs collecting it.
1432 *
1433 * @returns Success indicator.
1434 */
1435static bool vusbMsgSetup(PVUSBPIPE pPipe, const void *pvBuf, uint32_t cbBuf)
1436{
1437 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
1438 const VUSBSETUP *pSetupIn = (PVUSBSETUP)pvBuf;
1439
1440 /*
1441 * Validate length.
1442 */
1443 if (cbBuf < sizeof(VUSBSETUP))
1444 {
1445 LogFlow(("vusbMsgSetup: pPipe=%p cbBuf=%u < %u (failure) !!!\n",
1446 pPipe, cbBuf, sizeof(VUSBSETUP)));
1447 return false;
1448 }
1449
1450 /*
1451 * Check if we've got an cancelled message URB. Allocate a new one in that case.
1452 */
1453 if (pExtra->Urb.enmState == VUSBURBSTATE_CANCELLED)
1454 {
1455 void *pvNew = RTMemDup(pExtra, RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[pExtra->cbMax]));
1456 if (!pvNew)
1457 {
1458 Log(("vusbMsgSetup: out of memory!!! cbReq=%u\n", RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[pExtra->cbMax])));
1459 return false;
1460 }
1461 pExtra->Urb.VUsb.pvFreeCtx = NULL;
1462 LogFlow(("vusbMsgSetup: Replacing canceled pExtra=%p with %p.\n", pExtra, pvNew));
1463 pPipe->pCtrl = pExtra = (PVUSBCTRLEXTRA)pvNew;
1464 pExtra->pMsg = (PVUSBSETUP)pExtra->Urb.abData;
1465 pExtra->Urb.enmState = VUSBURBSTATE_ALLOCATED;
1466 }
1467
1468 /*
1469 * Check that we've got sufficient space in the message URB.
1470 */
1471 if (pExtra->cbMax < cbBuf + pSetupIn->wLength)
1472 {
1473 uint32_t cbReq = RT_ALIGN_32(cbBuf + pSetupIn->wLength, 1024);
1474 PVUSBCTRLEXTRA pNew = (PVUSBCTRLEXTRA)RTMemRealloc(pExtra, RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[cbReq]));
1475 if (!pNew)
1476 {
1477 Log(("vusbMsgSetup: out of memory!!! cbReq=%u %u\n",
1478 cbReq, RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[cbReq])));
1479 return false;
1480 }
1481 if (pExtra != pNew)
1482 {
1483 pNew->pMsg = (PVUSBSETUP)pNew->Urb.abData;
1484 pExtra = pNew;
1485 }
1486 pExtra->cbMax = cbReq;
1487 }
1488 Assert(pExtra->Urb.enmState == VUSBURBSTATE_ALLOCATED);
1489
1490 /*
1491 * Copy the setup data and prepare for data.
1492 */
1493 PVUSBSETUP pSetup = pExtra->pMsg;
1494 pExtra->fSubmitted = false;
1495 pExtra->Urb.enmState = VUSBURBSTATE_IN_FLIGHT;
1496 pExtra->pbCur = (uint8_t *)(pSetup + 1);
1497 pSetup->bmRequestType = pSetupIn->bmRequestType;
1498 pSetup->bRequest = pSetupIn->bRequest;
1499 pSetup->wValue = RT_LE2H_U16(pSetupIn->wValue);
1500 pSetup->wIndex = RT_LE2H_U16(pSetupIn->wIndex);
1501 pSetup->wLength = RT_LE2H_U16(pSetupIn->wLength);
1502
1503 LogFlow(("vusbMsgSetup(%p,,%d): bmRequestType=%#04x bRequest=%#04x wValue=%#06x wIndex=%#06x wLength=0x%.4x\n",
1504 pPipe, cbBuf, pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1505 return true;
1506}
1507
1508/**
1509 * Build the message URB from the given control URB and accompanying message
1510 * pipe state which we grab from the device for the URB.
1511 *
1512 * @param pUrb The URB to submit.
1513 */
1514static void vusbMsgDoTransfer(PVUSBURB pUrb, PVUSBSETUP pSetup, PVUSBCTRLEXTRA pExtra, PVUSBPIPE pPipe, PVUSBDEV pDev)
1515{
1516 /*
1517 * Mark this transfer as sent (cleared at setup time).
1518 */
1519 Assert(!pExtra->fSubmitted);
1520 pExtra->fSubmitted = true;
1521
1522 /*
1523 * Do we have to do this synchronously?
1524 */
1525 bool fSafeRequest = vusbUrbIsRequestSafe(pSetup, pUrb);
1526 if (!fSafeRequest)
1527 {
1528 vusbMsgSubmitSynchronously(pUrb, fSafeRequest);
1529 return;
1530 }
1531
1532 /*
1533 * Do it asynchronously.
1534 */
1535 LogFlow(("%s: vusbMsgDoTransfer: ep=%d pMsgUrb=%p pPipe=%p stage=%s\n",
1536 pUrb->pszDesc, pUrb->EndPt, &pExtra->Urb, pPipe, g_apszCtlStates[pExtra->enmStage]));
1537 Assert(pExtra->Urb.enmType == VUSBXFERTYPE_MSG);
1538 Assert(pExtra->Urb.EndPt == pUrb->EndPt);
1539 pExtra->Urb.enmDir = (pSetup->bmRequestType & VUSB_DIR_TO_HOST) ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT;
1540 pExtra->Urb.cbData = pSetup->wLength + sizeof(*pSetup);
1541 pExtra->Urb.VUsb.pCtrlUrb = pUrb;
1542 int rc = vusbUrbQueueAsyncRh(&pExtra->Urb);
1543 if (RT_FAILURE(rc))
1544 {
1545 /*
1546 * If we fail submitting it, will not retry but fail immediately.
1547 *
1548 * This keeps things simple. The host OS will have retried if
1549 * it's a proxied device, and if it's a virtual one it really means
1550 * it if it's failing a control message.
1551 */
1552 LogFlow(("%s: vusbMsgDoTransfer: failed submitting urb! failing it with %s (rc=%Rrc)!!!\n",
1553 pUrb->pszDesc, rc == VERR_VUSB_DEVICE_NOT_ATTACHED ? "DNR" : "CRC", rc));
1554 pExtra->Urb.enmStatus = rc == VERR_VUSB_DEVICE_NOT_ATTACHED ? VUSBSTATUS_DNR : VUSBSTATUS_CRC;
1555 pExtra->Urb.enmState = VUSBURBSTATE_REAPED;
1556 vusbMsgCompletion(&pExtra->Urb);
1557 }
1558}
1559
1560/**
1561 * Fails a URB request with a pipe STALL error.
1562 *
1563 * @returns VINF_SUCCESS indicating that we've completed the URB.
1564 * @param pUrb The URB in question.
1565 */
1566static int vusbMsgStall(PVUSBURB pUrb)
1567{
1568 PVUSBPIPE pPipe = &pUrb->VUsb.pDev->aPipes[pUrb->EndPt];
1569 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
1570 LogFlow(("%s: vusbMsgStall: pPipe=%p err=STALL stage %s->SETUP\n",
1571 pUrb->pszDesc, pPipe, g_apszCtlStates[pExtra->enmStage]));
1572
1573 pExtra->pbCur = NULL;
1574 pExtra->enmStage = CTLSTAGE_SETUP;
1575 pUrb->enmState = VUSBURBSTATE_REAPED;
1576 pUrb->enmStatus = VUSBSTATUS_STALL;
1577 vusbUrbCompletionRh(pUrb);
1578 return VINF_SUCCESS;
1579}
1580
1581/**
1582 * Submit a control message.
1583 *
1584 * Here we implement the USB defined traffic that occurs in message pipes
1585 * (aka control endpoints). We want to provide a single function for device
1586 * drivers so that they don't all have to reimplement the usb logic for
1587 * themselves. This means we need to keep a little bit of state information
1588 * because control transfers occur over multiple bus transactions. We may
1589 * also need to buffer data over multiple data stages.
1590 *
1591 * @returns VBox status code.
1592 * @param pUrb The URB to submit.
1593 */
1594static int vusbUrbSubmitCtrl(PVUSBURB pUrb)
1595{
1596#ifdef LOG_ENABLED
1597 vusbUrbTrace(pUrb, "vusbUrbSubmitCtrl", false);
1598#endif
1599 PVUSBDEV pDev = pUrb->VUsb.pDev;
1600 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
1601
1602 RTCritSectEnter(&pPipe->CritSectCtrl);
1603 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
1604
1605 if (!pExtra && !(pExtra = pPipe->pCtrl = vusbMsgAllocExtraData(pUrb)))
1606 {
1607 RTCritSectLeave(&pPipe->CritSectCtrl);
1608 return VERR_VUSB_NO_URB_MEMORY;
1609 }
1610 PVUSBSETUP pSetup = pExtra->pMsg;
1611
1612 AssertMsgReturn(!pPipe->async, ("%u\n", pPipe->async), VERR_GENERAL_FAILURE);
1613
1614
1615 /*
1616 * A setup packet always resets the transaction and the
1617 * end of data transmission is signified by change in
1618 * data direction.
1619 */
1620 if (pUrb->enmDir == VUSBDIRECTION_SETUP)
1621 {
1622 LogFlow(("%s: vusbUrbSubmitCtrl: pPipe=%p state %s->SETUP\n",
1623 pUrb->pszDesc, pPipe, g_apszCtlStates[pExtra->enmStage]));
1624 pExtra->enmStage = CTLSTAGE_SETUP;
1625 }
1626 else if ( pExtra->enmStage == CTLSTAGE_DATA
1627 /* (the STATUS stage direction goes the other way) */
1628 && !!(pSetup->bmRequestType & VUSB_DIR_TO_HOST) != (pUrb->enmDir == VUSBDIRECTION_IN))
1629 {
1630 LogFlow(("%s: vusbUrbSubmitCtrl: pPipe=%p state %s->STATUS\n",
1631 pUrb->pszDesc, pPipe, g_apszCtlStates[pExtra->enmStage]));
1632 pExtra->enmStage = CTLSTAGE_STATUS;
1633 }
1634
1635 /*
1636 * Act according to the current message stage.
1637 */
1638 switch (pExtra->enmStage)
1639 {
1640 case CTLSTAGE_SETUP:
1641 /*
1642 * When stall handshake is returned, all subsequent packets
1643 * must generate stall until a setup packet arrives.
1644 */
1645 if (pUrb->enmDir != VUSBDIRECTION_SETUP)
1646 {
1647 Log(("%s: vusbUrbSubmitCtrl: Stall at setup stage (dir=%#x)!!\n", pUrb->pszDesc, pUrb->enmDir));
1648 vusbMsgStall(pUrb);
1649 break;
1650 }
1651
1652 /* Store setup details, return DNR if corrupt */
1653 if (!vusbMsgSetup(pPipe, pUrb->abData, pUrb->cbData))
1654 {
1655 pUrb->enmState = VUSBURBSTATE_REAPED;
1656 pUrb->enmStatus = VUSBSTATUS_DNR;
1657 vusbUrbCompletionRh(pUrb);
1658 break;
1659 }
1660 if (pPipe->pCtrl != pExtra)
1661 {
1662 pExtra = pPipe->pCtrl;
1663 pSetup = pExtra->pMsg;
1664 }
1665
1666 /* pre-buffer our output if it's device-to-host */
1667 if (pSetup->bmRequestType & VUSB_DIR_TO_HOST)
1668 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1669 else if (pSetup->wLength)
1670 {
1671 LogFlow(("%s: vusbUrbSubmitCtrl: stage=SETUP - to dev: need data\n", pUrb->pszDesc));
1672 pUrb->enmState = VUSBURBSTATE_REAPED;
1673 vusbMsgSetupCompletion(pUrb);
1674 vusbUrbCompletionRh(pUrb);
1675 }
1676 /*
1677 * If there is no DATA stage, we must send it now since there are
1678 * no requirement of a STATUS stage.
1679 */
1680 else
1681 {
1682 LogFlow(("%s: vusbUrbSubmitCtrl: stage=SETUP - to dev: sending\n", pUrb->pszDesc));
1683 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1684 }
1685 break;
1686
1687 case CTLSTAGE_DATA:
1688 {
1689 /*
1690 * If a data stage exceeds the target buffer indicated in
1691 * setup return stall, if data stage returns stall there
1692 * will be no status stage.
1693 */
1694 uint8_t *pbData = (uint8_t *)(pExtra->pMsg + 1);
1695 if (&pExtra->pbCur[pUrb->cbData] > &pbData[pSetup->wLength])
1696 {
1697 if (!pSetup->wLength) /* happens during iPhone detection with iTunes (correct?) */
1698 {
1699 Log(("%s: vusbUrbSubmitCtrl: pSetup->wLength == 0!! (iPhone)\n", pUrb->pszDesc));
1700 pSetup->wLength = pUrb->cbData;
1701 }
1702
1703 /* Variable length data transfers */
1704 if ( (pSetup->bmRequestType & VUSB_DIR_TO_HOST)
1705 || pSetup->wLength == 0
1706 || (pUrb->cbData % pSetup->wLength) == 0) /* magic which need explaining... */
1707 {
1708 uint8_t *pbEnd = pbData + pSetup->wLength;
1709 int cbLeft = pbEnd - pExtra->pbCur;
1710 LogFlow(("%s: vusbUrbSubmitCtrl: Var DATA, pUrb->cbData %d -> %d\n", pUrb->pszDesc, pUrb->cbData, cbLeft));
1711 pUrb->cbData = cbLeft;
1712 }
1713 else
1714 {
1715 Log(("%s: vusbUrbSubmitCtrl: Stall at data stage!!\n", pUrb->pszDesc));
1716 vusbMsgStall(pUrb);
1717 break;
1718 }
1719 }
1720
1721 if (pUrb->enmDir == VUSBDIRECTION_IN)
1722 {
1723 /* put data received from the device. */
1724 const uint32_t cbRead = RT_MIN(pUrb->cbData, pExtra->cbLeft);
1725 memcpy(pUrb->abData, pExtra->pbCur, cbRead);
1726
1727 /* advance */
1728 pExtra->pbCur += cbRead;
1729 if (pUrb->cbData == cbRead)
1730 pExtra->cbLeft -= pUrb->cbData;
1731 else
1732 {
1733 /* adjust the pUrb->cbData to reflect the number of bytes containing actual data. */
1734 LogFlow(("%s: vusbUrbSubmitCtrl: adjusting last DATA pUrb->cbData, %d -> %d\n",
1735 pUrb->pszDesc, pUrb->cbData, pExtra->cbLeft));
1736 pUrb->cbData = cbRead;
1737 pExtra->cbLeft = 0;
1738 }
1739 }
1740 else
1741 {
1742 /* get data for sending when completed. */
1743 memcpy(pExtra->pbCur, pUrb->abData, pUrb->cbData);
1744
1745 /* advance */
1746 pExtra->pbCur += pUrb->cbData;
1747
1748 /*
1749 * If we've got the necessary data, we'll send it now since there are
1750 * no requirement of a STATUS stage.
1751 */
1752 if ( !pExtra->fSubmitted
1753 && pExtra->pbCur - pbData >= pSetup->wLength)
1754 {
1755 LogFlow(("%s: vusbUrbSubmitCtrl: stage=DATA - to dev: sending\n", pUrb->pszDesc));
1756 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1757 break;
1758 }
1759 }
1760
1761 pUrb->enmState = VUSBURBSTATE_REAPED;
1762 vusbMsgDataCompletion(pUrb);
1763 vusbUrbCompletionRh(pUrb);
1764 break;
1765 }
1766
1767 case CTLSTAGE_STATUS:
1768 if ( (pSetup->bmRequestType & VUSB_DIR_TO_HOST)
1769 || pExtra->fSubmitted)
1770 {
1771 Assert(pExtra->fSubmitted);
1772 pUrb->enmState = VUSBURBSTATE_REAPED;
1773 vusbMsgStatusCompletion(pUrb);
1774 vusbUrbCompletionRh(pUrb);
1775 }
1776 else
1777 {
1778 LogFlow(("%s: vusbUrbSubmitCtrl: stage=STATUS - to dev: sending\n", pUrb->pszDesc));
1779 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1780 }
1781 break;
1782 }
1783
1784 RTCritSectLeave(&pPipe->CritSectCtrl);
1785 return VINF_SUCCESS;
1786}
1787
1788
1789/**
1790 * Submit a interrupt URB.
1791 *
1792 * @returns VBox status code.
1793 * @param pUrb The URB to submit.
1794 */
1795static int vusbUrbSubmitInterrupt(PVUSBURB pUrb)
1796{
1797 LogFlow(("%s: vusbUrbSubmitInterrupt: (sync)\n", pUrb->pszDesc));
1798 return vusbUrbQueueAsyncRh(pUrb);
1799}
1800
1801
1802/**
1803 * Submit a bulk URB.
1804 *
1805 * @returns VBox status code.
1806 * @param pUrb The URB to submit.
1807 */
1808static int vusbUrbSubmitBulk(PVUSBURB pUrb)
1809{
1810 LogFlow(("%s: vusbUrbSubmitBulk: (async)\n", pUrb->pszDesc));
1811 return vusbUrbQueueAsyncRh(pUrb);
1812}
1813
1814
1815/**
1816 * Submit an isochronous URB.
1817 *
1818 * @returns VBox status code.
1819 * @param pUrb The URB to submit.
1820 */
1821static int vusbUrbSubmitIsochronous(PVUSBURB pUrb)
1822{
1823 LogFlow(("%s: vusbUrbSubmitIsochronous: (async)\n", pUrb->pszDesc));
1824 return vusbUrbQueueAsyncRh(pUrb);
1825}
1826
1827
1828/**
1829 * Fail a URB with a 'hard-error' sort of error.
1830 *
1831 * @return VINF_SUCCESS (the Urb status indicates the error).
1832 * @param pUrb The URB.
1833 */
1834int vusbUrbSubmitHardError(PVUSBURB pUrb)
1835{
1836 /* FIXME: Find out the correct return code from the spec */
1837 pUrb->enmState = VUSBURBSTATE_REAPED;
1838 pUrb->enmStatus = VUSBSTATUS_DNR;
1839 vusbUrbCompletionRh(pUrb);
1840 return VINF_SUCCESS;
1841}
1842
1843
1844/**
1845 * Submit a URB.
1846 */
1847int vusbUrbSubmit(PVUSBURB pUrb)
1848{
1849 vusbUrbAssert(pUrb);
1850 Assert(pUrb->enmState == VUSBURBSTATE_ALLOCATED);
1851 PVUSBDEV pDev = pUrb->VUsb.pDev;
1852 PVUSBPIPE pPipe = NULL;
1853 Assert(pDev);
1854
1855 /*
1856 * Check that the device is in a valid state.
1857 */
1858 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1859 if (enmState == VUSB_DEVICE_STATE_RESET)
1860 {
1861 LogRel(("VUSB: %s: power off ignored, the device is resetting!\n", pDev->pUsbIns->pszName));
1862 pUrb->enmStatus = VUSBSTATUS_DNR;
1863 /* This will postpone the TDs until we're done with the resetting. */
1864 return VERR_VUSB_DEVICE_IS_RESETTING;
1865 }
1866
1867#ifdef LOG_ENABLED
1868 /* stamp it */
1869 pUrb->VUsb.u64SubmitTS = RTTimeNanoTS();
1870#endif
1871
1872 /** @todo Check max packet size here too? */
1873
1874 /*
1875 * Validate the pipe.
1876 */
1877 if (pUrb->EndPt >= VUSB_PIPE_MAX)
1878 {
1879 Log(("%s: pDev=%p[%s]: SUBMIT: ep %i >= %i!!!\n", pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, pUrb->EndPt, VUSB_PIPE_MAX));
1880 return vusbUrbSubmitHardError(pUrb);
1881 }
1882 PCVUSBDESCENDPOINTEX pEndPtDesc;
1883 switch (pUrb->enmDir)
1884 {
1885 case VUSBDIRECTION_IN:
1886 pEndPtDesc = pDev->aPipes[pUrb->EndPt].in;
1887 pPipe = &pDev->aPipes[pUrb->EndPt];
1888 break;
1889 case VUSBDIRECTION_SETUP:
1890 case VUSBDIRECTION_OUT:
1891 default:
1892 pEndPtDesc = pDev->aPipes[pUrb->EndPt].out;
1893 break;
1894 }
1895 if (!pEndPtDesc)
1896 {
1897 Log(("%s: pDev=%p[%s]: SUBMIT: no endpoint!!! dir=%s e=%i\n",
1898 pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, vusbUrbDirName(pUrb->enmDir), pUrb->EndPt));
1899 return vusbUrbSubmitHardError(pUrb);
1900 }
1901
1902 /*
1903 * Check for correct transfer types.
1904 * Our type codes are the same - what a coincidence.
1905 */
1906 if ((pEndPtDesc->Core.bmAttributes & 0x3) != pUrb->enmType)
1907 {
1908 Log(("%s: pDev=%p[%s]: SUBMIT: %s transfer requested for %#x endpoint on DstAddress=%i ep=%i dir=%s\n",
1909 pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, vusbUrbTypeName(pUrb->enmType), pEndPtDesc->Core.bmAttributes,
1910 pUrb->DstAddress, pUrb->EndPt, vusbUrbDirName(pUrb->enmDir)));
1911 return vusbUrbSubmitHardError(pUrb);
1912 }
1913
1914 /*
1915 * If there's a URB in the read-ahead buffer, use it.
1916 */
1917 int rc;
1918
1919 if (pDev->hSniffer)
1920 {
1921 rc = VUSBSnifferRecordEvent(pDev->hSniffer, pUrb, VUSBSNIFFEREVENT_SUBMIT);
1922 if (RT_FAILURE(rc))
1923 LogRel(("VUSB: Capturing URB submit event failed with %Rrc\n", rc));
1924 }
1925
1926#ifdef VBOX_WITH_USB
1927 if (pPipe && pPipe->hReadAhead)
1928 {
1929 rc = vusbUrbSubmitBufferedRead(pUrb, pPipe->hReadAhead);
1930 return rc;
1931 }
1932#endif
1933
1934 /*
1935 * Take action based on type.
1936 */
1937 pUrb->enmState = VUSBURBSTATE_IN_FLIGHT;
1938 switch (pUrb->enmType)
1939 {
1940 case VUSBXFERTYPE_CTRL:
1941 rc = vusbUrbSubmitCtrl(pUrb);
1942 break;
1943 case VUSBXFERTYPE_BULK:
1944 rc = vusbUrbSubmitBulk(pUrb);
1945 break;
1946 case VUSBXFERTYPE_INTR:
1947 rc = vusbUrbSubmitInterrupt(pUrb);
1948 break;
1949 case VUSBXFERTYPE_ISOC:
1950 rc = vusbUrbSubmitIsochronous(pUrb);
1951 break;
1952 default:
1953 AssertMsgFailed(("Unexpected pUrb type %d\n", pUrb->enmType));
1954 return vusbUrbSubmitHardError(pUrb);
1955 }
1956
1957 /*
1958 * The device was detached, so we fail everything.
1959 * (We should really detach and destroy the device, but we'll have to wait till Main reacts.)
1960 */
1961 if (rc == VERR_VUSB_DEVICE_NOT_ATTACHED)
1962 rc = vusbUrbSubmitHardError(pUrb);
1963 /*
1964 * We don't increment error count if async URBs are in flight, in
1965 * this case we just assume we need to throttle back, this also
1966 * makes sure we don't halt bulk endpoints at the wrong time.
1967 */
1968 else if ( RT_FAILURE(rc)
1969 && !ASMAtomicReadU32(&pDev->aPipes[pUrb->EndPt].async)
1970 /* && pUrb->enmType == VUSBXFERTYPE_BULK ?? */
1971 && !vusbUrbErrorRh(pUrb))
1972 {
1973 /* don't retry it anymore. */
1974 pUrb->enmState = VUSBURBSTATE_REAPED;
1975 pUrb->enmStatus = VUSBSTATUS_CRC;
1976 vusbUrbCompletionRh(pUrb);
1977 return VINF_SUCCESS;
1978 }
1979
1980 return rc;
1981}
1982
1983
1984/**
1985 * Reap in-flight URBs.
1986 *
1987 * @param pHead Pointer to the head of the URB list.
1988 * @param cMillies Number of milliseconds to block in each reap operation.
1989 * Use 0 to not block at all.
1990 */
1991void vusbUrbDoReapAsync(PVUSBURB pHead, RTMSINTERVAL cMillies)
1992{
1993 PVUSBURB pUrb = pHead;
1994 while (pUrb)
1995 {
1996 vusbUrbAssert(pUrb);
1997 PVUSBURB pUrbNext = pUrb->VUsb.pNext;
1998 PVUSBDEV pDev = pUrb->VUsb.pDev;
1999
2000 /* Don't touch resetting devices - paranoid safety precaution. */
2001 if (vusbDevGetState(pDev) != VUSB_DEVICE_STATE_RESET)
2002 {
2003 /*
2004 * Reap most URBs pending on a single device.
2005 */
2006 PVUSBURB pRipe;
2007
2008 /**
2009 * This is workaround for race(should be fixed) detach on one EMT thread and frame boundary timer on other
2010 * and leaked URBs (shouldn't be affected by leaked URBs).
2011 */
2012 Assert(pDev->pUsbIns);
2013 while ( pDev->pUsbIns
2014 && ((pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, cMillies)) != NULL))
2015 {
2016 vusbUrbAssert(pRipe);
2017 if (pRipe == pUrbNext)
2018 pUrbNext = pUrbNext->VUsb.pNext;
2019 vusbUrbRipe(pRipe);
2020 }
2021 }
2022
2023 /* next */
2024 pUrb = pUrbNext;
2025 }
2026}
2027
2028/**
2029 * Reap URBs on a per device level.
2030 *
2031 * @returns nothing.
2032 * @param pDev The device instance to reap URBs for.
2033 * @param cMillies Number of milliseconds to block in each reap operation.
2034 * Use 0 to not block at all.
2035 */
2036void vusbUrbDoReapAsyncDev(PVUSBDEV pDev, RTMSINTERVAL cMillies)
2037{
2038 Assert(pDev->enmState != VUSB_DEVICE_STATE_RESET);
2039
2040 /*
2041 * Reap most URBs pending on a single device.
2042 */
2043 PVUSBURB pRipe;
2044
2045 /**
2046 * This is workaround for race(should be fixed) detach on one EMT thread and frame boundary timer on other
2047 * and leaked URBs (shouldn't be affected by leaked URBs).
2048 */
2049
2050 if (ASMAtomicXchgBool(&pDev->fWokenUp, false))
2051 return;
2052
2053 Assert(pDev->pUsbIns);
2054 while ( pDev->pUsbIns
2055 && ((pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, cMillies)) != NULL))
2056 {
2057 vusbUrbAssert(pRipe);
2058 vusbUrbRipe(pRipe);
2059 if (ASMAtomicXchgBool(&pDev->fWokenUp, false))
2060 break;
2061 }
2062}
2063
2064/**
2065 * Completes the URB.
2066 */
2067static void vusbUrbCompletion(PVUSBURB pUrb)
2068{
2069 Assert(pUrb->VUsb.pDev->aPipes);
2070 ASMAtomicDecU32(&pUrb->VUsb.pDev->aPipes[pUrb->EndPt].async);
2071
2072 if (pUrb->enmState == VUSBURBSTATE_REAPED)
2073 vusbUrbUnlink(pUrb);
2074#ifdef VBOX_WITH_USB
2075 // Read-ahead URBs are handled differently
2076 if (pUrb->Hci.pNext != NULL)
2077 vusbUrbCompletionReadAhead(pUrb);
2078 else
2079#endif
2080 vusbUrbCompletionRh(pUrb);
2081}
2082
2083/**
2084 * The worker for vusbUrbCancel() which is executed on the I/O thread.
2085 *
2086 * @returns nothing.
2087 * @param pUrb The URB to cancel.
2088 * @param enmMode The way the URB should be canceled.
2089 */
2090DECLHIDDEN(void) vusbUrbCancelWorker(PVUSBURB pUrb, CANCELMODE enmMode)
2091{
2092 vusbUrbAssert(pUrb);
2093#ifdef VBOX_WITH_STATISTICS
2094 PVUSBROOTHUB pRh = vusbDevGetRh(pUrb->VUsb.pDev);
2095#endif
2096 if (pUrb->enmState == VUSBURBSTATE_IN_FLIGHT)
2097 {
2098 LogFlow(("%s: vusbUrbCancel: Canceling in-flight\n", pUrb->pszDesc));
2099 STAM_COUNTER_INC(&pRh->Total.StatUrbsCancelled);
2100 if (pUrb->enmType != VUSBXFERTYPE_MSG)
2101 {
2102 STAM_STATS({Assert(pUrb->enmType >= 0 && pUrb->enmType < (int)RT_ELEMENTS(pRh->aTypes));});
2103 STAM_COUNTER_INC(&pRh->aTypes[pUrb->enmType].StatUrbsCancelled);
2104 }
2105
2106 pUrb->enmState = VUSBURBSTATE_CANCELLED;
2107 PPDMUSBINS pUsbIns = pUrb->pUsbIns;
2108 pUsbIns->pReg->pfnUrbCancel(pUsbIns, pUrb);
2109 Assert(pUrb->enmState == VUSBURBSTATE_CANCELLED || pUrb->enmState == VUSBURBSTATE_REAPED);
2110
2111 pUrb->enmStatus = VUSBSTATUS_CRC;
2112 vusbUrbCompletion(pUrb);
2113 }
2114 else if (pUrb->enmState == VUSBURBSTATE_REAPED)
2115 {
2116 LogFlow(("%s: vusbUrbCancel: Canceling reaped urb\n", pUrb->pszDesc));
2117 STAM_COUNTER_INC(&pRh->Total.StatUrbsCancelled);
2118 if (pUrb->enmType != VUSBXFERTYPE_MSG)
2119 {
2120 STAM_STATS({Assert(pUrb->enmType >= 0 && pUrb->enmType < (int)RT_ELEMENTS(pRh->aTypes));});
2121 STAM_COUNTER_INC(&pRh->aTypes[pUrb->enmType].StatUrbsCancelled);
2122 }
2123
2124 pUrb->enmStatus = VUSBSTATUS_CRC;
2125 vusbUrbCompletion(pUrb);
2126 }
2127 else
2128 {
2129 AssertMsg(pUrb->enmState == VUSBURBSTATE_CANCELLED, ("Invalid state %d, pUrb=%p\n", pUrb->enmState, pUrb));
2130 switch (enmMode)
2131 {
2132 default:
2133 AssertMsgFailed(("Invalid cancel mode\n"));
2134 case CANCELMODE_FAIL:
2135 pUrb->enmStatus = VUSBSTATUS_CRC;
2136 break;
2137 case CANCELMODE_UNDO:
2138 pUrb->enmStatus = VUSBSTATUS_UNDO;
2139 break;
2140
2141 }
2142 }
2143}
2144
2145/**
2146 * Cancels an URB with CRC failure.
2147 *
2148 * Cancelling an URB is a tricky thing. The USBProxy backend can not
2149 * all cancel it and we must keep the URB around until it's ripe and
2150 * can be reaped the normal way. However, we must complete the URB
2151 * now, before leaving this function. This is not nice. sigh.
2152 *
2153 * This function will cancel the URB if it's in-flight and complete
2154 * it. The device will in its pfnCancel method be given the chance to
2155 * say that the URB doesn't need reaping and should be unlinked.
2156 *
2157 * An URB which is in the cancel state after pfnCancel will remain in that
2158 * state and in the async list until its reaped. When it's finally reaped
2159 * it will be unlinked and freed without doing any completion.
2160 *
2161 * There are different modes of canceling an URB. When devices are being
2162 * disconnected etc., they will be completed with an error (CRC). However,
2163 * when the HC needs to temporarily halt communication with a device, the
2164 * URB/TD must be left alone if possible.
2165 *
2166 * @param pUrb The URB to cancel.
2167 * @param mode The way the URB should be canceled.
2168 */
2169void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode)
2170{
2171 int rc = vusbDevIoThreadExecSync(pUrb->VUsb.pDev, (PFNRT)vusbUrbCancelWorker, 2, pUrb, mode);
2172 AssertRC(rc);
2173}
2174
2175
2176/**
2177 * Async version of vusbUrbCancel() - doesn't wait for the cancelling to be complete.
2178 */
2179void vusbUrbCancelAsync(PVUSBURB pUrb, CANCELMODE mode)
2180{
2181 int rc = vusbDevIoThreadExec(pUrb->VUsb.pDev, 0 /* fFlags */, (PFNRT)vusbUrbCancelWorker, 2, pUrb, mode);
2182 AssertRC(rc);
2183}
2184
2185
2186/**
2187 * Deals with a ripe URB (i.e. after reaping it).
2188 *
2189 * If an URB is in the reaped or in-flight state, we'll
2190 * complete it. If it's cancelled, we'll simply free it.
2191 * Any other states should never get here.
2192 *
2193 * @param pUrb The URB.
2194 */
2195void vusbUrbRipe(PVUSBURB pUrb)
2196{
2197 if ( pUrb->enmState == VUSBURBSTATE_IN_FLIGHT
2198 || pUrb->enmState == VUSBURBSTATE_REAPED)
2199 {
2200 pUrb->enmState = VUSBURBSTATE_REAPED;
2201 vusbUrbCompletion(pUrb);
2202 }
2203 else if (pUrb->enmState == VUSBURBSTATE_CANCELLED)
2204 {
2205 vusbUrbUnlink(pUrb);
2206 LogFlow(("%s: vusbUrbRipe: Freeing cancelled URB\n", pUrb->pszDesc));
2207 pUrb->VUsb.pfnFree(pUrb);
2208 }
2209 else
2210 AssertMsgFailed(("Invalid URB state %d; %s\n", pUrb->enmState, pUrb->pszDesc));
2211}
2212
2213
2214/*
2215 * Local Variables:
2216 * mode: c
2217 * c-file-style: "bsd"
2218 * c-basic-offset: 4
2219 * tab-width: 4
2220 * indent-tabs-mode: s
2221 * End:
2222 */
2223
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