VirtualBox

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

最後變更 在這個檔案從27653是 26970,由 vboxsync 提交於 15 年 前

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!

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 78.1 KB
 
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
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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