VirtualBox

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

Last change on this file since 58466 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

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

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