VirtualBox

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

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

Commit r100743 and r100913 to trunk which should improve pass through of USB sound devices

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 83.3 KB
Line 
1/* $Id: VUSBUrb.cpp 56454 2015-06-16 13:57:21Z vboxsync $ */
2/** @file
3 * Virtual USB - URBs.
4 */
5
6/*
7 * Copyright (C) 2006-2015 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 {
980 pUrb->enmState = VUSBURBSTATE_ALLOCATED;
981 pUrb->fCompleting = false;
982 }
983 RTCritSectLeave(&pPipe->CritSectCtrl);
984
985 /* Complete the original control URB on the root hub now. */
986 vusbUrbCompletionRh(pCtrlUrb);
987}
988
989/**
990 * Deal with URB errors, talking thru the RH to the HCI.
991 *
992 * @returns true if it could be retried.
993 * @returns false if it should be completed with failure.
994 * @param pUrb The URB in question.
995 */
996int vusbUrbErrorRh(PVUSBURB pUrb)
997{
998 PVUSBDEV pDev = pUrb->VUsb.pDev;
999 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
1000 AssertPtrReturn(pRh, VERR_VUSB_DEVICE_NOT_ATTACHED);
1001 LogFlow(("%s: vusbUrbErrorRh: pDev=%p[%s] rh=%p\n", pUrb->pszDesc, pDev, pDev->pUsbIns ? pDev->pUsbIns->pszName : "", pRh));
1002 return pRh->pIRhPort->pfnXferError(pRh->pIRhPort, pUrb);
1003}
1004
1005/**
1006 * Does URB completion on roothub level.
1007 *
1008 * @param pUrb The URB to complete.
1009 */
1010void vusbUrbCompletionRh(PVUSBURB pUrb)
1011{
1012 LogFlow(("%s: vusbUrbCompletionRh: type=%s status=%s\n",
1013 pUrb->pszDesc, vusbUrbTypeName(pUrb->enmType), vusbUrbStatusName(pUrb->enmStatus)));
1014 AssertMsg( pUrb->enmState == VUSBURBSTATE_REAPED
1015 || pUrb->enmState == VUSBURBSTATE_CANCELLED, ("%d\n", pUrb->enmState));
1016
1017 if ( pUrb->VUsb.pDev
1018 && pUrb->VUsb.pDev->hSniffer)
1019 {
1020 int rc = VUSBSnifferRecordEvent(pUrb->VUsb.pDev->hSniffer, pUrb,
1021 pUrb->enmStatus == VUSBSTATUS_OK
1022 ? VUSBSNIFFEREVENT_COMPLETE
1023 : VUSBSNIFFEREVENT_ERROR_COMPLETE);
1024 if (RT_FAILURE(rc))
1025 LogRel(("VUSB: Capturing URB completion event failed with %Rrc\n", rc));
1026 }
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#ifdef VBOX_WITH_STATISTICS
1043 /*
1044 * Total and per-type submit statistics.
1045 */
1046 if (pUrb->enmType != VUSBXFERTYPE_MSG)
1047 {
1048 Assert(pUrb->enmType >= 0 && pUrb->enmType < (int)RT_ELEMENTS(pRh->aTypes));
1049
1050 if ( pUrb->enmStatus == VUSBSTATUS_OK
1051 || pUrb->enmStatus == VUSBSTATUS_DATA_UNDERRUN
1052 || pUrb->enmStatus == VUSBSTATUS_DATA_OVERRUN)
1053 {
1054 if (pUrb->enmType == VUSBXFERTYPE_ISOC)
1055 {
1056 for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
1057 {
1058 const unsigned cb = pUrb->aIsocPkts[i].cb;
1059 if (cb)
1060 {
1061 STAM_COUNTER_ADD(&pRh->Total.StatActBytes, cb);
1062 STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActBytes, cb);
1063 STAM_COUNTER_ADD(&pRh->aStatIsocDetails[i].Bytes, cb);
1064 if (pUrb->enmDir == VUSBDIRECTION_IN)
1065 {
1066 STAM_COUNTER_ADD(&pRh->Total.StatActReadBytes, cb);
1067 STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActReadBytes, cb);
1068 }
1069 else
1070 {
1071 STAM_COUNTER_ADD(&pRh->Total.StatActWriteBytes, cb);
1072 STAM_COUNTER_ADD(&pRh->aTypes[VUSBXFERTYPE_ISOC].StatActWriteBytes, cb);
1073 }
1074 STAM_COUNTER_INC(&pRh->StatIsocActPkts);
1075 STAM_COUNTER_INC(&pRh->StatIsocActReadPkts);
1076 }
1077 STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Pkts);
1078 switch (pUrb->aIsocPkts[i].enmStatus)
1079 {
1080 case VUSBSTATUS_OK:
1081 if (cb) STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Ok);
1082 else STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Ok0); break;
1083 case VUSBSTATUS_DATA_UNDERRUN:
1084 if (cb) STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataUnderrun);
1085 else STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataUnderrun0); break;
1086 case VUSBSTATUS_DATA_OVERRUN: STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].DataOverrun); break;
1087 case VUSBSTATUS_NOT_ACCESSED: STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].NotAccessed); break;
1088 default: STAM_COUNTER_INC(&pRh->aStatIsocDetails[i].Misc); break;
1089 }
1090 }
1091 }
1092 else
1093 {
1094 STAM_COUNTER_ADD(&pRh->Total.StatActBytes, pUrb->cbData);
1095 STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActBytes, pUrb->cbData);
1096 if (pUrb->enmDir == VUSBDIRECTION_IN)
1097 {
1098 STAM_COUNTER_ADD(&pRh->Total.StatActReadBytes, pUrb->cbData);
1099 STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActReadBytes, pUrb->cbData);
1100 }
1101 else
1102 {
1103 STAM_COUNTER_ADD(&pRh->Total.StatActWriteBytes, pUrb->cbData);
1104 STAM_COUNTER_ADD(&pRh->aTypes[pUrb->enmType].StatActWriteBytes, pUrb->cbData);
1105 }
1106 }
1107 }
1108 else
1109 {
1110 /* (Note. this also counts the cancelled packets) */
1111 STAM_COUNTER_INC(&pRh->Total.StatUrbsFailed);
1112 STAM_COUNTER_INC(&pRh->aTypes[pUrb->enmType].StatUrbsFailed);
1113 }
1114 }
1115#endif /* VBOX_WITH_STATISTICS */
1116
1117 /*
1118 * Msg transfers are special virtual transfers associated with
1119 * vusb, not the roothub
1120 */
1121 switch (pUrb->enmType)
1122 {
1123 case VUSBXFERTYPE_MSG:
1124 vusbMsgCompletion(pUrb);
1125 return;
1126 case VUSBXFERTYPE_ISOC:
1127 /* Don't bother with error callback for isochronous URBs. */
1128 break;
1129
1130#if 1 /** @todo r=bird: OHCI say "If the Transfer Descriptor is being
1131 * retired because of an error, the Host Controller must update
1132 * the Halt bit of the Endpoint Descriptor."
1133 *
1134 * So, I'll subject all transfertypes to the same halt stuff now. It could
1135 * just happen to fix the logitech disconnect trap in win2k.
1136 */
1137 default:
1138#endif
1139 case VUSBXFERTYPE_BULK:
1140 if (pUrb->enmStatus != VUSBSTATUS_OK)
1141 vusbUrbErrorRh(pUrb);
1142 break;
1143 }
1144#ifdef LOG_ENABLED
1145 vusbUrbTrace(pUrb, "vusbUrbCompletionRh", true);
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 pExtra->Urb.fCompleting = false;
1295}
1296
1297/**
1298 * Callback for dealing with device reset.
1299 */
1300void vusbMsgResetExtraData(PVUSBCTRLEXTRA pExtra)
1301{
1302 if (!pExtra)
1303 return;
1304 pExtra->enmStage = CTLSTAGE_SETUP;
1305 if (pExtra->Urb.enmState != VUSBURBSTATE_CANCELLED)
1306 {
1307 pExtra->Urb.enmState = VUSBURBSTATE_ALLOCATED;
1308 pExtra->Urb.fCompleting = false;
1309 }
1310}
1311
1312
1313/**
1314 * Callback to free a cancelled message URB.
1315 *
1316 * This is yet another place we're we have to performance acrobatics to
1317 * deal with cancelled URBs. sigh.
1318 *
1319 * The deal here is that we never free message URBs since they are integrated
1320 * into the message pipe state. But since cancel can leave URBs unreaped and in
1321 * a state which require them not to be freed, we'll have to do two things.
1322 * First, if a new message URB is processed we'll have to get a new message
1323 * pipe state. Second, we cannot just free the damn state structure because
1324 * that might lead to heap corruption since it might still be in-flight.
1325 *
1326 * The URB embedded into the message pipe control structure will start in an
1327 * ALLOCATED state. When submitted it will be go to the IN-FLIGHT state. When
1328 * reaped it will go from REAPED to ALLOCATED. When completed in the CANCELLED
1329 * state it will remain in that state (as does normal URBs).
1330 *
1331 * If a new message urb comes up while it's in the CANCELLED state, we will
1332 * orphan it and it will be freed here in vusbMsgFreeUrb. We indicate this
1333 * by setting VUsb.pvFreeCtx to NULL.
1334 *
1335 * If we have to free the message state structure because of device destruction,
1336 * configuration changes, or similar, we will orphan the message pipe state in
1337 * the same way by setting VUsb.pvFreeCtx to NULL and let this function free it.
1338 *
1339 * @param pUrb
1340 */
1341static DECLCALLBACK(void) vusbMsgFreeUrb(PVUSBURB pUrb)
1342{
1343 vusbUrbAssert(pUrb);
1344 PVUSBCTRLEXTRA pExtra = (PVUSBCTRLEXTRA)((uint8_t *)pUrb - RT_OFFSETOF(VUSBCTRLEXTRA, Urb));
1345 if ( pUrb->enmState == VUSBURBSTATE_CANCELLED
1346 && !pUrb->VUsb.pvFreeCtx)
1347 {
1348 LogFlow(("vusbMsgFreeUrb: Freeing orphan: %p (pUrb=%p)\n", pExtra, pUrb));
1349 RTMemFree(pExtra);
1350 }
1351 else
1352 {
1353 Assert(pUrb->VUsb.pvFreeCtx == &pExtra->Urb);
1354 pUrb->enmState = VUSBURBSTATE_ALLOCATED;
1355 pUrb->fCompleting = false;
1356 }
1357}
1358
1359/**
1360 * Frees the extra state data associated with a message pipe.
1361 *
1362 * @param pExtra The data.
1363 */
1364void vusbMsgFreeExtraData(PVUSBCTRLEXTRA pExtra)
1365{
1366 if (!pExtra)
1367 return;
1368 if (pExtra->Urb.enmState != VUSBURBSTATE_CANCELLED)
1369 {
1370 pExtra->Urb.u32Magic = 0;
1371 pExtra->Urb.enmState = VUSBURBSTATE_FREE;
1372 if (pExtra->Urb.pszDesc)
1373 RTStrFree(pExtra->Urb.pszDesc);
1374 RTMemFree(pExtra);
1375 }
1376 else
1377 pExtra->Urb.VUsb.pvFreeCtx = NULL; /* see vusbMsgFreeUrb */
1378}
1379
1380/**
1381 * Allocates the extra state data required for a control pipe.
1382 *
1383 * @returns Pointer to the allocated and initialized state data.
1384 * @returns NULL on out of memory condition.
1385 * @param pUrb A URB we can copy default data from.
1386 */
1387static PVUSBCTRLEXTRA vusbMsgAllocExtraData(PVUSBURB pUrb)
1388{
1389/** @todo reuse these? */
1390 PVUSBCTRLEXTRA pExtra;
1391 const size_t cbMax = sizeof(pExtra->Urb.abData) + sizeof(VUSBSETUP);
1392 pExtra = (PVUSBCTRLEXTRA)RTMemAllocZ(RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[cbMax]));
1393 if (pExtra)
1394 {
1395 pExtra->enmStage = CTLSTAGE_SETUP;
1396 //pExtra->fOk = false;
1397 pExtra->pMsg = (PVUSBSETUP)pExtra->Urb.abData;
1398 pExtra->pbCur = (uint8_t *)(pExtra->pMsg + 1);
1399 //pExtra->cbLeft = 0;
1400 pExtra->cbMax = cbMax;
1401
1402 //pExtra->Urb.Dev.pvProxyUrb = NULL;
1403 pExtra->Urb.u32Magic = VUSBURB_MAGIC;
1404 pExtra->Urb.enmState = VUSBURBSTATE_ALLOCATED;
1405 pExtra->Urb.fCompleting = false;
1406#ifdef LOG_ENABLED
1407 RTStrAPrintf(&pExtra->Urb.pszDesc, "URB %p msg->%p", &pExtra->Urb, pUrb);
1408#endif
1409 //pExtra->Urb.VUsb.pCtrlUrb = NULL;
1410 //pExtra->Urb.VUsb.pNext = NULL;
1411 //pExtra->Urb.VUsb.ppPrev = NULL;
1412 pExtra->Urb.VUsb.pDev = pUrb->VUsb.pDev;
1413 pExtra->Urb.VUsb.pfnFree = vusbMsgFreeUrb;
1414 pExtra->Urb.VUsb.pvFreeCtx = &pExtra->Urb;
1415 //pExtra->Urb.Hci = {0};
1416 //pExtra->Urb.Dev.pvProxyUrb = NULL;
1417 pExtra->Urb.pUsbIns = pUrb->pUsbIns;
1418 pExtra->Urb.DstAddress = pUrb->DstAddress;
1419 pExtra->Urb.EndPt = pUrb->EndPt;
1420 pExtra->Urb.enmType = VUSBXFERTYPE_MSG;
1421 pExtra->Urb.enmDir = VUSBDIRECTION_INVALID;
1422 //pExtra->Urb.fShortNotOk = false;
1423 pExtra->Urb.enmStatus = VUSBSTATUS_INVALID;
1424 //pExtra->Urb.cbData = 0;
1425 vusbUrbAssert(&pExtra->Urb);
1426 }
1427 return pExtra;
1428}
1429
1430/**
1431 * Sets up the message.
1432 *
1433 * The message is associated with the pipe, in what's currently called
1434 * control pipe extra state data (pointed to by pPipe->pCtrl). If this
1435 * is a OUT message, we will no go on collecting data URB. If it's a
1436 * IN message, we'll send it and then queue any incoming data for the
1437 * URBs collecting it.
1438 *
1439 * @returns Success indicator.
1440 */
1441static bool vusbMsgSetup(PVUSBPIPE pPipe, const void *pvBuf, uint32_t cbBuf)
1442{
1443 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
1444 const VUSBSETUP *pSetupIn = (PVUSBSETUP)pvBuf;
1445
1446 /*
1447 * Validate length.
1448 */
1449 if (cbBuf < sizeof(VUSBSETUP))
1450 {
1451 LogFlow(("vusbMsgSetup: pPipe=%p cbBuf=%u < %u (failure) !!!\n",
1452 pPipe, cbBuf, sizeof(VUSBSETUP)));
1453 return false;
1454 }
1455
1456 /*
1457 * Check if we've got an cancelled message URB. Allocate a new one in that case.
1458 */
1459 if (pExtra->Urb.enmState == VUSBURBSTATE_CANCELLED)
1460 {
1461 void *pvNew = RTMemDup(pExtra, RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[pExtra->cbMax]));
1462 if (!pvNew)
1463 {
1464 Log(("vusbMsgSetup: out of memory!!! cbReq=%u\n", RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[pExtra->cbMax])));
1465 return false;
1466 }
1467 pExtra->Urb.VUsb.pvFreeCtx = NULL;
1468 LogFlow(("vusbMsgSetup: Replacing canceled pExtra=%p with %p.\n", pExtra, pvNew));
1469 pPipe->pCtrl = pExtra = (PVUSBCTRLEXTRA)pvNew;
1470 pExtra->pMsg = (PVUSBSETUP)pExtra->Urb.abData;
1471 pExtra->Urb.enmState = VUSBURBSTATE_ALLOCATED;
1472 pExtra->Urb.fCompleting = false;
1473 }
1474
1475 /*
1476 * Check that we've got sufficient space in the message URB.
1477 */
1478 if (pExtra->cbMax < cbBuf + pSetupIn->wLength)
1479 {
1480 uint32_t cbReq = RT_ALIGN_32(cbBuf + pSetupIn->wLength, 1024);
1481 PVUSBCTRLEXTRA pNew = (PVUSBCTRLEXTRA)RTMemRealloc(pExtra, RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[cbReq]));
1482 if (!pNew)
1483 {
1484 Log(("vusbMsgSetup: out of memory!!! cbReq=%u %u\n",
1485 cbReq, RT_OFFSETOF(VUSBCTRLEXTRA, Urb.abData[cbReq])));
1486 return false;
1487 }
1488 if (pExtra != pNew)
1489 {
1490 pNew->pMsg = (PVUSBSETUP)pNew->Urb.abData;
1491 pExtra = pNew;
1492 }
1493 pExtra->cbMax = cbReq;
1494 }
1495 Assert(pExtra->Urb.enmState == VUSBURBSTATE_ALLOCATED);
1496
1497 /*
1498 * Copy the setup data and prepare for data.
1499 */
1500 PVUSBSETUP pSetup = pExtra->pMsg;
1501 pExtra->fSubmitted = false;
1502 pExtra->Urb.enmState = VUSBURBSTATE_IN_FLIGHT;
1503 pExtra->pbCur = (uint8_t *)(pSetup + 1);
1504 pSetup->bmRequestType = pSetupIn->bmRequestType;
1505 pSetup->bRequest = pSetupIn->bRequest;
1506 pSetup->wValue = RT_LE2H_U16(pSetupIn->wValue);
1507 pSetup->wIndex = RT_LE2H_U16(pSetupIn->wIndex);
1508 pSetup->wLength = RT_LE2H_U16(pSetupIn->wLength);
1509
1510 LogFlow(("vusbMsgSetup(%p,,%d): bmRequestType=%#04x bRequest=%#04x wValue=%#06x wIndex=%#06x wLength=0x%.4x\n",
1511 pPipe, cbBuf, pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1512 return true;
1513}
1514
1515/**
1516 * Build the message URB from the given control URB and accompanying message
1517 * pipe state which we grab from the device for the URB.
1518 *
1519 * @param pUrb The URB to submit.
1520 */
1521static void vusbMsgDoTransfer(PVUSBURB pUrb, PVUSBSETUP pSetup, PVUSBCTRLEXTRA pExtra, PVUSBPIPE pPipe, PVUSBDEV pDev)
1522{
1523 /*
1524 * Mark this transfer as sent (cleared at setup time).
1525 */
1526 Assert(!pExtra->fSubmitted);
1527 pExtra->fSubmitted = true;
1528
1529 /*
1530 * Do we have to do this synchronously?
1531 */
1532 bool fSafeRequest = vusbUrbIsRequestSafe(pSetup, pUrb);
1533 if (!fSafeRequest)
1534 {
1535 vusbMsgSubmitSynchronously(pUrb, fSafeRequest);
1536 return;
1537 }
1538
1539 /*
1540 * Do it asynchronously.
1541 */
1542 LogFlow(("%s: vusbMsgDoTransfer: ep=%d pMsgUrb=%p pPipe=%p stage=%s\n",
1543 pUrb->pszDesc, pUrb->EndPt, &pExtra->Urb, pPipe, g_apszCtlStates[pExtra->enmStage]));
1544 Assert(pExtra->Urb.enmType == VUSBXFERTYPE_MSG);
1545 Assert(pExtra->Urb.EndPt == pUrb->EndPt);
1546 pExtra->Urb.enmDir = (pSetup->bmRequestType & VUSB_DIR_TO_HOST) ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT;
1547 pExtra->Urb.cbData = pSetup->wLength + sizeof(*pSetup);
1548 pExtra->Urb.VUsb.pCtrlUrb = pUrb;
1549 int rc = vusbUrbQueueAsyncRh(&pExtra->Urb);
1550 if (RT_FAILURE(rc))
1551 {
1552 /*
1553 * If we fail submitting it, will not retry but fail immediately.
1554 *
1555 * This keeps things simple. The host OS will have retried if
1556 * it's a proxied device, and if it's a virtual one it really means
1557 * it if it's failing a control message.
1558 */
1559 LogFlow(("%s: vusbMsgDoTransfer: failed submitting urb! failing it with %s (rc=%Rrc)!!!\n",
1560 pUrb->pszDesc, rc == VERR_VUSB_DEVICE_NOT_ATTACHED ? "DNR" : "CRC", rc));
1561 pExtra->Urb.enmStatus = rc == VERR_VUSB_DEVICE_NOT_ATTACHED ? VUSBSTATUS_DNR : VUSBSTATUS_CRC;
1562 pExtra->Urb.enmState = VUSBURBSTATE_REAPED;
1563 vusbMsgCompletion(&pExtra->Urb);
1564 }
1565}
1566
1567/**
1568 * Fails a URB request with a pipe STALL error.
1569 *
1570 * @returns VINF_SUCCESS indicating that we've completed the URB.
1571 * @param pUrb The URB in question.
1572 */
1573static int vusbMsgStall(PVUSBURB pUrb)
1574{
1575 PVUSBPIPE pPipe = &pUrb->VUsb.pDev->aPipes[pUrb->EndPt];
1576 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
1577 LogFlow(("%s: vusbMsgStall: pPipe=%p err=STALL stage %s->SETUP\n",
1578 pUrb->pszDesc, pPipe, g_apszCtlStates[pExtra->enmStage]));
1579
1580 pExtra->pbCur = NULL;
1581 pExtra->enmStage = CTLSTAGE_SETUP;
1582 pUrb->enmState = VUSBURBSTATE_REAPED;
1583 pUrb->enmStatus = VUSBSTATUS_STALL;
1584 vusbUrbCompletionRh(pUrb);
1585 return VINF_SUCCESS;
1586}
1587
1588/**
1589 * Submit a control message.
1590 *
1591 * Here we implement the USB defined traffic that occurs in message pipes
1592 * (aka control endpoints). We want to provide a single function for device
1593 * drivers so that they don't all have to reimplement the usb logic for
1594 * themselves. This means we need to keep a little bit of state information
1595 * because control transfers occur over multiple bus transactions. We may
1596 * also need to buffer data over multiple data stages.
1597 *
1598 * @returns VBox status code.
1599 * @param pUrb The URB to submit.
1600 */
1601static int vusbUrbSubmitCtrl(PVUSBURB pUrb)
1602{
1603#ifdef LOG_ENABLED
1604 vusbUrbTrace(pUrb, "vusbUrbSubmitCtrl", false);
1605#endif
1606 PVUSBDEV pDev = pUrb->VUsb.pDev;
1607 PVUSBPIPE pPipe = &pDev->aPipes[pUrb->EndPt];
1608
1609 RTCritSectEnter(&pPipe->CritSectCtrl);
1610 PVUSBCTRLEXTRA pExtra = pPipe->pCtrl;
1611
1612 if (!pExtra && !(pExtra = pPipe->pCtrl = vusbMsgAllocExtraData(pUrb)))
1613 {
1614 RTCritSectLeave(&pPipe->CritSectCtrl);
1615 return VERR_VUSB_NO_URB_MEMORY;
1616 }
1617 PVUSBSETUP pSetup = pExtra->pMsg;
1618
1619 if (pPipe->async)
1620 {
1621 AssertMsgFailed(("%u\n", pPipe->async));
1622 RTCritSectLeave(&pPipe->CritSectCtrl);
1623 return VERR_GENERAL_FAILURE;
1624 }
1625
1626 /*
1627 * A setup packet always resets the transaction and the
1628 * end of data transmission is signified by change in
1629 * data direction.
1630 */
1631 if (pUrb->enmDir == VUSBDIRECTION_SETUP)
1632 {
1633 LogFlow(("%s: vusbUrbSubmitCtrl: pPipe=%p state %s->SETUP\n",
1634 pUrb->pszDesc, pPipe, g_apszCtlStates[pExtra->enmStage]));
1635 pExtra->enmStage = CTLSTAGE_SETUP;
1636 }
1637 else if ( pExtra->enmStage == CTLSTAGE_DATA
1638 /* (the STATUS stage direction goes the other way) */
1639 && !!(pSetup->bmRequestType & VUSB_DIR_TO_HOST) != (pUrb->enmDir == VUSBDIRECTION_IN))
1640 {
1641 LogFlow(("%s: vusbUrbSubmitCtrl: pPipe=%p state %s->STATUS\n",
1642 pUrb->pszDesc, pPipe, g_apszCtlStates[pExtra->enmStage]));
1643 pExtra->enmStage = CTLSTAGE_STATUS;
1644 }
1645
1646 /*
1647 * Act according to the current message stage.
1648 */
1649 switch (pExtra->enmStage)
1650 {
1651 case CTLSTAGE_SETUP:
1652 /*
1653 * When stall handshake is returned, all subsequent packets
1654 * must generate stall until a setup packet arrives.
1655 */
1656 if (pUrb->enmDir != VUSBDIRECTION_SETUP)
1657 {
1658 Log(("%s: vusbUrbSubmitCtrl: Stall at setup stage (dir=%#x)!!\n", pUrb->pszDesc, pUrb->enmDir));
1659 vusbMsgStall(pUrb);
1660 break;
1661 }
1662
1663 /* Store setup details, return DNR if corrupt */
1664 if (!vusbMsgSetup(pPipe, pUrb->abData, pUrb->cbData))
1665 {
1666 pUrb->enmState = VUSBURBSTATE_REAPED;
1667 pUrb->enmStatus = VUSBSTATUS_DNR;
1668 vusbUrbCompletionRh(pUrb);
1669 break;
1670 }
1671 if (pPipe->pCtrl != pExtra)
1672 {
1673 pExtra = pPipe->pCtrl;
1674 pSetup = pExtra->pMsg;
1675 }
1676
1677 /* pre-buffer our output if it's device-to-host */
1678 if (pSetup->bmRequestType & VUSB_DIR_TO_HOST)
1679 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1680 else if (pSetup->wLength)
1681 {
1682 LogFlow(("%s: vusbUrbSubmitCtrl: stage=SETUP - to dev: need data\n", pUrb->pszDesc));
1683 pUrb->enmState = VUSBURBSTATE_REAPED;
1684 vusbMsgSetupCompletion(pUrb);
1685 vusbUrbCompletionRh(pUrb);
1686 }
1687 /*
1688 * If there is no DATA stage, we must send it now since there are
1689 * no requirement of a STATUS stage.
1690 */
1691 else
1692 {
1693 LogFlow(("%s: vusbUrbSubmitCtrl: stage=SETUP - to dev: sending\n", pUrb->pszDesc));
1694 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1695 }
1696 break;
1697
1698 case CTLSTAGE_DATA:
1699 {
1700 /*
1701 * If a data stage exceeds the target buffer indicated in
1702 * setup return stall, if data stage returns stall there
1703 * will be no status stage.
1704 */
1705 uint8_t *pbData = (uint8_t *)(pExtra->pMsg + 1);
1706 if (&pExtra->pbCur[pUrb->cbData] > &pbData[pSetup->wLength])
1707 {
1708 if (!pSetup->wLength) /* happens during iPhone detection with iTunes (correct?) */
1709 {
1710 Log(("%s: vusbUrbSubmitCtrl: pSetup->wLength == 0!! (iPhone)\n", pUrb->pszDesc));
1711 pSetup->wLength = pUrb->cbData;
1712 }
1713
1714 /* Variable length data transfers */
1715 if ( (pSetup->bmRequestType & VUSB_DIR_TO_HOST)
1716 || pSetup->wLength == 0
1717 || (pUrb->cbData % pSetup->wLength) == 0) /* magic which need explaining... */
1718 {
1719 uint8_t *pbEnd = pbData + pSetup->wLength;
1720 int cbLeft = pbEnd - pExtra->pbCur;
1721 LogFlow(("%s: vusbUrbSubmitCtrl: Var DATA, pUrb->cbData %d -> %d\n", pUrb->pszDesc, pUrb->cbData, cbLeft));
1722 pUrb->cbData = cbLeft;
1723 }
1724 else
1725 {
1726 Log(("%s: vusbUrbSubmitCtrl: Stall at data stage!!\n", pUrb->pszDesc));
1727 vusbMsgStall(pUrb);
1728 break;
1729 }
1730 }
1731
1732 if (pUrb->enmDir == VUSBDIRECTION_IN)
1733 {
1734 /* put data received from the device. */
1735 const uint32_t cbRead = RT_MIN(pUrb->cbData, pExtra->cbLeft);
1736 memcpy(pUrb->abData, pExtra->pbCur, cbRead);
1737
1738 /* advance */
1739 pExtra->pbCur += cbRead;
1740 if (pUrb->cbData == cbRead)
1741 pExtra->cbLeft -= pUrb->cbData;
1742 else
1743 {
1744 /* adjust the pUrb->cbData to reflect the number of bytes containing actual data. */
1745 LogFlow(("%s: vusbUrbSubmitCtrl: adjusting last DATA pUrb->cbData, %d -> %d\n",
1746 pUrb->pszDesc, pUrb->cbData, pExtra->cbLeft));
1747 pUrb->cbData = cbRead;
1748 pExtra->cbLeft = 0;
1749 }
1750 }
1751 else
1752 {
1753 /* get data for sending when completed. */
1754 memcpy(pExtra->pbCur, pUrb->abData, pUrb->cbData);
1755
1756 /* advance */
1757 pExtra->pbCur += pUrb->cbData;
1758
1759 /*
1760 * If we've got the necessary data, we'll send it now since there are
1761 * no requirement of a STATUS stage.
1762 */
1763 if ( !pExtra->fSubmitted
1764 && pExtra->pbCur - pbData >= pSetup->wLength)
1765 {
1766 LogFlow(("%s: vusbUrbSubmitCtrl: stage=DATA - to dev: sending\n", pUrb->pszDesc));
1767 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1768 break;
1769 }
1770 }
1771
1772 pUrb->enmState = VUSBURBSTATE_REAPED;
1773 vusbMsgDataCompletion(pUrb);
1774 vusbUrbCompletionRh(pUrb);
1775 break;
1776 }
1777
1778 case CTLSTAGE_STATUS:
1779 if ( (pSetup->bmRequestType & VUSB_DIR_TO_HOST)
1780 || pExtra->fSubmitted)
1781 {
1782 Assert(pExtra->fSubmitted);
1783 pUrb->enmState = VUSBURBSTATE_REAPED;
1784 vusbMsgStatusCompletion(pUrb);
1785 vusbUrbCompletionRh(pUrb);
1786 }
1787 else
1788 {
1789 LogFlow(("%s: vusbUrbSubmitCtrl: stage=STATUS - to dev: sending\n", pUrb->pszDesc));
1790 vusbMsgDoTransfer(pUrb, pSetup, pExtra, pPipe, pDev);
1791 }
1792 break;
1793 }
1794
1795 RTCritSectLeave(&pPipe->CritSectCtrl);
1796 return VINF_SUCCESS;
1797}
1798
1799
1800/**
1801 * Submit a interrupt URB.
1802 *
1803 * @returns VBox status code.
1804 * @param pUrb The URB to submit.
1805 */
1806static int vusbUrbSubmitInterrupt(PVUSBURB pUrb)
1807{
1808 LogFlow(("%s: vusbUrbSubmitInterrupt: (sync)\n", pUrb->pszDesc));
1809 return vusbUrbQueueAsyncRh(pUrb);
1810}
1811
1812
1813/**
1814 * Submit a bulk URB.
1815 *
1816 * @returns VBox status code.
1817 * @param pUrb The URB to submit.
1818 */
1819static int vusbUrbSubmitBulk(PVUSBURB pUrb)
1820{
1821 LogFlow(("%s: vusbUrbSubmitBulk: (async)\n", pUrb->pszDesc));
1822 return vusbUrbQueueAsyncRh(pUrb);
1823}
1824
1825
1826/**
1827 * Submit an isochronous URB.
1828 *
1829 * @returns VBox status code.
1830 * @param pUrb The URB to submit.
1831 */
1832static int vusbUrbSubmitIsochronous(PVUSBURB pUrb)
1833{
1834 LogFlow(("%s: vusbUrbSubmitIsochronous: (async)\n", pUrb->pszDesc));
1835 return vusbUrbQueueAsyncRh(pUrb);
1836}
1837
1838
1839/**
1840 * Fail a URB with a 'hard-error' sort of error.
1841 *
1842 * @return VINF_SUCCESS (the Urb status indicates the error).
1843 * @param pUrb The URB.
1844 */
1845int vusbUrbSubmitHardError(PVUSBURB pUrb)
1846{
1847 /* FIXME: Find out the correct return code from the spec */
1848 pUrb->enmState = VUSBURBSTATE_REAPED;
1849 pUrb->enmStatus = VUSBSTATUS_DNR;
1850 vusbUrbCompletionRh(pUrb);
1851 return VINF_SUCCESS;
1852}
1853
1854
1855/**
1856 * Submit a URB.
1857 */
1858int vusbUrbSubmit(PVUSBURB pUrb)
1859{
1860 vusbUrbAssert(pUrb);
1861 Assert(pUrb->enmState == VUSBURBSTATE_ALLOCATED);
1862 PVUSBDEV pDev = pUrb->VUsb.pDev;
1863 PVUSBPIPE pPipe = NULL;
1864 Assert(pDev);
1865
1866 /*
1867 * Check that the device is in a valid state.
1868 */
1869 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1870 if (enmState == VUSB_DEVICE_STATE_RESET)
1871 {
1872 LogRel(("VUSB: %s: power off ignored, the device is resetting!\n", pDev->pUsbIns->pszName));
1873 pUrb->enmStatus = VUSBSTATUS_DNR;
1874 /* This will postpone the TDs until we're done with the resetting. */
1875 return VERR_VUSB_DEVICE_IS_RESETTING;
1876 }
1877
1878#ifdef LOG_ENABLED
1879 /* stamp it */
1880 pUrb->VUsb.u64SubmitTS = RTTimeNanoTS();
1881#endif
1882
1883 /** @todo Check max packet size here too? */
1884
1885 /*
1886 * Validate the pipe.
1887 */
1888 if (pUrb->EndPt >= VUSB_PIPE_MAX)
1889 {
1890 Log(("%s: pDev=%p[%s]: SUBMIT: ep %i >= %i!!!\n", pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, pUrb->EndPt, VUSB_PIPE_MAX));
1891 return vusbUrbSubmitHardError(pUrb);
1892 }
1893 PCVUSBDESCENDPOINTEX pEndPtDesc;
1894 switch (pUrb->enmDir)
1895 {
1896 case VUSBDIRECTION_IN:
1897 pEndPtDesc = pDev->aPipes[pUrb->EndPt].in;
1898 pPipe = &pDev->aPipes[pUrb->EndPt];
1899 break;
1900 case VUSBDIRECTION_SETUP:
1901 case VUSBDIRECTION_OUT:
1902 default:
1903 pEndPtDesc = pDev->aPipes[pUrb->EndPt].out;
1904 break;
1905 }
1906 if (!pEndPtDesc)
1907 {
1908 Log(("%s: pDev=%p[%s]: SUBMIT: no endpoint!!! dir=%s e=%i\n",
1909 pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, vusbUrbDirName(pUrb->enmDir), pUrb->EndPt));
1910 return vusbUrbSubmitHardError(pUrb);
1911 }
1912
1913 /*
1914 * Check for correct transfer types.
1915 * Our type codes are the same - what a coincidence.
1916 */
1917 if ((pEndPtDesc->Core.bmAttributes & 0x3) != pUrb->enmType)
1918 {
1919 Log(("%s: pDev=%p[%s]: SUBMIT: %s transfer requested for %#x endpoint on DstAddress=%i ep=%i dir=%s\n",
1920 pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, vusbUrbTypeName(pUrb->enmType), pEndPtDesc->Core.bmAttributes,
1921 pUrb->DstAddress, pUrb->EndPt, vusbUrbDirName(pUrb->enmDir)));
1922 return vusbUrbSubmitHardError(pUrb);
1923 }
1924
1925 /*
1926 * If there's a URB in the read-ahead buffer, use it.
1927 */
1928 int rc;
1929
1930 if (pDev->hSniffer)
1931 {
1932 rc = VUSBSnifferRecordEvent(pDev->hSniffer, pUrb, VUSBSNIFFEREVENT_SUBMIT);
1933 if (RT_FAILURE(rc))
1934 LogRel(("VUSB: Capturing URB submit event failed with %Rrc\n", rc));
1935 }
1936
1937#ifdef VBOX_WITH_USB
1938 if (pPipe && pPipe->hReadAhead)
1939 {
1940 rc = vusbUrbSubmitBufferedRead(pUrb, pPipe->hReadAhead);
1941 return rc;
1942 }
1943#endif
1944
1945 /*
1946 * Take action based on type.
1947 */
1948 pUrb->enmState = VUSBURBSTATE_IN_FLIGHT;
1949 switch (pUrb->enmType)
1950 {
1951 case VUSBXFERTYPE_CTRL:
1952 rc = vusbUrbSubmitCtrl(pUrb);
1953 break;
1954 case VUSBXFERTYPE_BULK:
1955 rc = vusbUrbSubmitBulk(pUrb);
1956 break;
1957 case VUSBXFERTYPE_INTR:
1958 rc = vusbUrbSubmitInterrupt(pUrb);
1959 break;
1960 case VUSBXFERTYPE_ISOC:
1961 rc = vusbUrbSubmitIsochronous(pUrb);
1962 break;
1963 default:
1964 AssertMsgFailed(("Unexpected pUrb type %d\n", pUrb->enmType));
1965 return vusbUrbSubmitHardError(pUrb);
1966 }
1967
1968 /*
1969 * The device was detached, so we fail everything.
1970 * (We should really detach and destroy the device, but we'll have to wait till Main reacts.)
1971 */
1972 if (rc == VERR_VUSB_DEVICE_NOT_ATTACHED)
1973 rc = vusbUrbSubmitHardError(pUrb);
1974 /*
1975 * We don't increment error count if async URBs are in flight, in
1976 * this case we just assume we need to throttle back, this also
1977 * makes sure we don't halt bulk endpoints at the wrong time.
1978 */
1979 else if ( RT_FAILURE(rc)
1980 && !ASMAtomicReadU32(&pDev->aPipes[pUrb->EndPt].async)
1981 /* && pUrb->enmType == VUSBXFERTYPE_BULK ?? */
1982 && !vusbUrbErrorRh(pUrb))
1983 {
1984 /* don't retry it anymore. */
1985 pUrb->enmState = VUSBURBSTATE_REAPED;
1986 pUrb->enmStatus = VUSBSTATUS_CRC;
1987 vusbUrbCompletionRh(pUrb);
1988 return VINF_SUCCESS;
1989 }
1990
1991 return rc;
1992}
1993
1994
1995/**
1996 * Reap in-flight URBs.
1997 *
1998 * @param pHead Pointer to the head of the URB list.
1999 * @param cMillies Number of milliseconds to block in each reap operation.
2000 * Use 0 to not block at all.
2001 */
2002void vusbUrbDoReapAsync(PVUSBURB pHead, RTMSINTERVAL cMillies)
2003{
2004 PVUSBURB pUrb = pHead;
2005 while (pUrb)
2006 {
2007 vusbUrbAssert(pUrb);
2008 PVUSBURB pUrbNext = pUrb->VUsb.pNext;
2009 PVUSBDEV pDev = pUrb->VUsb.pDev;
2010
2011 /* Don't touch resetting devices - paranoid safety precaution. */
2012 if (vusbDevGetState(pDev) != VUSB_DEVICE_STATE_RESET)
2013 {
2014 /*
2015 * Reap most URBs pending on a single device.
2016 */
2017 PVUSBURB pRipe;
2018
2019 /**
2020 * This is workaround for race(should be fixed) detach on one EMT thread and frame boundary timer on other
2021 * and leaked URBs (shouldn't be affected by leaked URBs).
2022 */
2023 Assert(pDev->pUsbIns);
2024 while ( pDev->pUsbIns
2025 && ((pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, cMillies)) != NULL))
2026 {
2027 vusbUrbAssert(pRipe);
2028 if (pRipe == pUrbNext)
2029 pUrbNext = pUrbNext->VUsb.pNext;
2030 vusbUrbRipe(pRipe);
2031 }
2032 }
2033
2034 /* next */
2035 pUrb = pUrbNext;
2036 }
2037}
2038
2039/**
2040 * Reap URBs on a per device level.
2041 *
2042 * @returns nothing.
2043 * @param pDev The device instance to reap URBs for.
2044 * @param cMillies Number of milliseconds to block in each reap operation.
2045 * Use 0 to not block at all.
2046 */
2047void vusbUrbDoReapAsyncDev(PVUSBDEV pDev, RTMSINTERVAL cMillies)
2048{
2049 Assert(pDev->enmState != VUSB_DEVICE_STATE_RESET);
2050
2051 /*
2052 * Reap most URBs pending on a single device.
2053 */
2054 PVUSBURB pRipe;
2055
2056 /**
2057 * This is workaround for race(should be fixed) detach on one EMT thread and frame boundary timer on other
2058 * and leaked URBs (shouldn't be affected by leaked URBs).
2059 */
2060
2061 if (ASMAtomicXchgBool(&pDev->fWokenUp, false))
2062 return;
2063
2064 Assert(pDev->pUsbIns);
2065 while ( pDev->pUsbIns
2066 && ((pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, cMillies)) != NULL))
2067 {
2068 vusbUrbAssert(pRipe);
2069 vusbUrbRipe(pRipe);
2070 if (ASMAtomicXchgBool(&pDev->fWokenUp, false))
2071 break;
2072 }
2073}
2074
2075/**
2076 * Completes the URB.
2077 */
2078static void vusbUrbCompletion(PVUSBURB pUrb)
2079{
2080 Assert(pUrb->VUsb.pDev->aPipes);
2081 ASMAtomicDecU32(&pUrb->VUsb.pDev->aPipes[pUrb->EndPt].async);
2082
2083 if (pUrb->enmState == VUSBURBSTATE_REAPED)
2084 vusbUrbUnlink(pUrb);
2085#ifdef VBOX_WITH_USB
2086 // Read-ahead URBs are handled differently
2087 if (pUrb->Hci.pNext != NULL)
2088 vusbUrbCompletionReadAhead(pUrb);
2089 else
2090#endif
2091 vusbUrbCompletionRh(pUrb);
2092}
2093
2094/**
2095 * The worker for vusbUrbCancel() which is executed on the I/O thread.
2096 *
2097 * @returns IPRT status code.
2098 * @param pUrb The URB to cancel.
2099 * @param enmMode The way the URB should be canceled.
2100 */
2101DECLHIDDEN(int) vusbUrbCancelWorker(PVUSBURB pUrb, CANCELMODE enmMode)
2102{
2103 vusbUrbAssert(pUrb);
2104#ifdef VBOX_WITH_STATISTICS
2105 PVUSBROOTHUB pRh = vusbDevGetRh(pUrb->VUsb.pDev);
2106#endif
2107 if (pUrb->enmState == VUSBURBSTATE_IN_FLIGHT)
2108 {
2109 LogFlow(("%s: vusbUrbCancel: Canceling in-flight\n", pUrb->pszDesc));
2110 STAM_COUNTER_INC(&pRh->Total.StatUrbsCancelled);
2111 if (pUrb->enmType != VUSBXFERTYPE_MSG)
2112 {
2113 STAM_STATS({Assert(pUrb->enmType >= 0 && pUrb->enmType < (int)RT_ELEMENTS(pRh->aTypes));});
2114 STAM_COUNTER_INC(&pRh->aTypes[pUrb->enmType].StatUrbsCancelled);
2115 }
2116
2117 pUrb->enmState = VUSBURBSTATE_CANCELLED;
2118 PPDMUSBINS pUsbIns = pUrb->pUsbIns;
2119 pUsbIns->pReg->pfnUrbCancel(pUsbIns, pUrb);
2120 Assert(pUrb->enmState == VUSBURBSTATE_CANCELLED || pUrb->enmState == VUSBURBSTATE_REAPED);
2121
2122 pUrb->enmStatus = VUSBSTATUS_CRC;
2123 vusbUrbCompletion(pUrb);
2124 }
2125 else if (pUrb->enmState == VUSBURBSTATE_REAPED)
2126 {
2127 LogFlow(("%s: vusbUrbCancel: Canceling reaped urb\n", pUrb->pszDesc));
2128 STAM_COUNTER_INC(&pRh->Total.StatUrbsCancelled);
2129 if (pUrb->enmType != VUSBXFERTYPE_MSG)
2130 {
2131 STAM_STATS({Assert(pUrb->enmType >= 0 && pUrb->enmType < (int)RT_ELEMENTS(pRh->aTypes));});
2132 STAM_COUNTER_INC(&pRh->aTypes[pUrb->enmType].StatUrbsCancelled);
2133 }
2134
2135 pUrb->enmStatus = VUSBSTATUS_CRC;
2136 vusbUrbCompletion(pUrb);
2137 }
2138 else
2139 {
2140 AssertMsg(pUrb->enmState == VUSBURBSTATE_CANCELLED, ("Invalid state %d, pUrb=%p\n", pUrb->enmState, pUrb));
2141 switch (enmMode)
2142 {
2143 default:
2144 AssertMsgFailed(("Invalid cancel mode\n"));
2145 case CANCELMODE_FAIL:
2146 pUrb->enmStatus = VUSBSTATUS_CRC;
2147 break;
2148 case CANCELMODE_UNDO:
2149 pUrb->enmStatus = VUSBSTATUS_UNDO;
2150 break;
2151
2152 }
2153 }
2154 return VINF_SUCCESS;
2155}
2156
2157/**
2158 * Cancels an URB with CRC failure.
2159 *
2160 * Cancelling an URB is a tricky thing. The USBProxy backend can not
2161 * all cancel it and we must keep the URB around until it's ripe and
2162 * can be reaped the normal way. However, we must complete the URB
2163 * now, before leaving this function. This is not nice. sigh.
2164 *
2165 * This function will cancel the URB if it's in-flight and complete
2166 * it. The device will in its pfnCancel method be given the chance to
2167 * say that the URB doesn't need reaping and should be unlinked.
2168 *
2169 * An URB which is in the cancel state after pfnCancel will remain in that
2170 * state and in the async list until its reaped. When it's finally reaped
2171 * it will be unlinked and freed without doing any completion.
2172 *
2173 * There are different modes of canceling an URB. When devices are being
2174 * disconnected etc., they will be completed with an error (CRC). However,
2175 * when the HC needs to temporarily halt communication with a device, the
2176 * URB/TD must be left alone if possible.
2177 *
2178 * @param pUrb The URB to cancel.
2179 * @param mode The way the URB should be canceled.
2180 */
2181void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode)
2182{
2183 int rc = vusbDevIoThreadExecSync(pUrb->VUsb.pDev, (PFNRT)vusbUrbCancelWorker, 2, pUrb, mode);
2184 AssertRC(rc);
2185}
2186
2187
2188/**
2189 * Async version of vusbUrbCancel() - doesn't wait for the cancelling to be complete.
2190 */
2191void vusbUrbCancelAsync(PVUSBURB pUrb, CANCELMODE mode)
2192{
2193 /* Don't try to cancel the URB when completion is in progress at the moment. */
2194 if (!ASMAtomicXchgBool(&pUrb->fCompleting, true))
2195 {
2196 int rc = vusbDevIoThreadExec(pUrb->VUsb.pDev, 0 /* fFlags */, (PFNRT)vusbUrbCancelWorker, 2, pUrb, mode);
2197 AssertRC(rc);
2198 }
2199}
2200
2201
2202/**
2203 * Deals with a ripe URB (i.e. after reaping it).
2204 *
2205 * If an URB is in the reaped or in-flight state, we'll
2206 * complete it. If it's cancelled, we'll simply free it.
2207 * Any other states should never get here.
2208 *
2209 * @param pUrb The URB.
2210 */
2211void vusbUrbRipe(PVUSBURB pUrb)
2212{
2213 if ( pUrb->enmState == VUSBURBSTATE_IN_FLIGHT
2214 || pUrb->enmState == VUSBURBSTATE_REAPED)
2215 {
2216 pUrb->enmState = VUSBURBSTATE_REAPED;
2217 if (!ASMAtomicXchgBool(&pUrb->fCompleting, true))
2218 vusbUrbCompletion(pUrb);
2219 }
2220 else if (pUrb->enmState == VUSBURBSTATE_CANCELLED)
2221 {
2222 vusbUrbUnlink(pUrb);
2223 LogFlow(("%s: vusbUrbRipe: Freeing cancelled URB\n", pUrb->pszDesc));
2224 pUrb->VUsb.pfnFree(pUrb);
2225 }
2226 else
2227 AssertMsgFailed(("Invalid URB state %d; %s\n", pUrb->enmState, pUrb->pszDesc));
2228}
2229
2230
2231/*
2232 * Local Variables:
2233 * mode: c
2234 * c-file-style: "bsd"
2235 * c-basic-offset: 4
2236 * tab-width: 4
2237 * indent-tabs-mode: s
2238 * End:
2239 */
2240
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