VirtualBox

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

Last change on this file since 27867 was 26970, checked in by vboxsync, 15 years ago

Export code for handling virtual USB devices to OSE, mainly for emulating USB mouse and USB keyboard. This does NOT include support for passing through USB host devices!

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