VirtualBox

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

Last change on this file since 28175 was 27901, checked in by vboxsync, 15 years ago

OSE header fixes

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

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