VirtualBox

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

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

VUSB: Some structural cleanup (#3 Make the VUSB URB specific data private to the VUSB stack, some interface changes required for XHCI because it previously required access to some VUsb members)

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