VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/dev/VBoxUsbRt.cpp@ 61556

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

HostDrivers/win: coding style

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.8 KB
Line 
1/* $Id: VBoxUsbRt.cpp 60639 2016-04-22 07:37:54Z vboxsync $ */
2/** @file
3 * VBox USB R0 runtime
4 */
5/*
6 * Copyright (C) 2011-2015 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include "VBoxUsbCmn.h"
18#include "../cmn/VBoxUsbIdc.h"
19#include "../cmn/VBoxUsbTool.h"
20
21#include <VBox/usblib-win.h>
22#include <iprt/assert.h>
23#include <VBox/log.h>
24#define _USBD_
25
26#define USBD_DEFAULT_PIPE_TRANSFER 0x00000008
27
28#define VBOXUSB_MAGIC 0xABCF1423
29
30typedef struct VBOXUSB_URB_CONTEXT
31{
32 PURB pUrb;
33 PMDL pMdlBuf;
34 PVBOXUSBDEV_EXT pDevExt;
35 PVOID pOut;
36 ULONG ulTransferType;
37 ULONG ulMagic;
38} VBOXUSB_URB_CONTEXT, * PVBOXUSB_URB_CONTEXT;
39
40typedef struct VBOXUSB_SETUP
41{
42 uint8_t bmRequestType;
43 uint8_t bRequest;
44 uint16_t wValue;
45 uint16_t wIndex;
46 uint16_t wLength;
47} VBOXUSB_SETUP, *PVBOXUSB_SETUP;
48
49static bool vboxUsbRtCtxSetOwner(PVBOXUSBDEV_EXT pDevExt, PFILE_OBJECT pFObj)
50{
51 bool bRc = ASMAtomicCmpXchgPtr(&pDevExt->Rt.pOwner, pFObj, NULL);
52 if (bRc)
53 {
54 LogFunc(("pDevExt (0x%x) Owner(0x%x) acquired\n", pFObj));
55 }
56 else
57 {
58 LogFunc(("pDevExt (0x%x) Owner(0x%x) FAILED!!\n", pFObj));
59 }
60 return bRc;
61}
62
63static bool vboxUsbRtCtxReleaseOwner(PVBOXUSBDEV_EXT pDevExt, PFILE_OBJECT pFObj)
64{
65 bool bRc = ASMAtomicCmpXchgPtr(&pDevExt->Rt.pOwner, NULL, pFObj);
66 if (bRc)
67 {
68 LogFunc(("pDevExt (0x%x) Owner(0x%x) released\n", pFObj));
69 }
70 else
71 {
72 LogFunc(("pDevExt (0x%x) Owner(0x%x) release: is NOT an owner\n", pFObj));
73 }
74 return bRc;
75}
76
77static bool vboxUsbRtCtxIsOwner(PVBOXUSBDEV_EXT pDevExt, PFILE_OBJECT pFObj)
78{
79 PFILE_OBJECT pOwner = (PFILE_OBJECT)ASMAtomicReadPtr((void *volatile *)(&pDevExt->Rt.pOwner));
80 return pOwner == pFObj;
81}
82
83static NTSTATUS vboxUsbRtIdcSubmit(ULONG uCtl, void *pvBuffer)
84{
85 /* we just reuse the standard usb tooling for simplicity here */
86 NTSTATUS Status = VBoxUsbToolIoInternalCtlSendSync(g_VBoxUsbGlobals.RtIdc.pDevice, uCtl, pvBuffer, NULL);
87 Assert(Status == STATUS_SUCCESS);
88 return Status;
89}
90
91static NTSTATUS vboxUsbRtIdcInit()
92{
93 UNICODE_STRING UniName;
94 RtlInitUnicodeString(&UniName, USBMON_DEVICE_NAME_NT);
95 NTSTATUS Status = IoGetDeviceObjectPointer(&UniName, FILE_ALL_ACCESS, &g_VBoxUsbGlobals.RtIdc.pFile, &g_VBoxUsbGlobals.RtIdc.pDevice);
96 if (NT_SUCCESS(Status))
97 {
98 VBOXUSBIDC_VERSION Version;
99 vboxUsbRtIdcSubmit(VBOXUSBIDC_INTERNAL_IOCTL_GET_VERSION, &Version);
100 if (NT_SUCCESS(Status))
101 {
102 if (Version.u32Major == VBOXUSBIDC_VERSION_MAJOR
103 && Version.u32Minor >= VBOXUSBIDC_VERSION_MINOR)
104 return STATUS_SUCCESS;
105 AssertFailed();
106 }
107 else
108 {
109 AssertFailed();
110 }
111
112 /* this will as well dereference the dev obj */
113 ObDereferenceObject(g_VBoxUsbGlobals.RtIdc.pFile);
114 }
115 else
116 {
117 AssertFailed();
118 }
119
120 memset(&g_VBoxUsbGlobals.RtIdc, 0, sizeof (g_VBoxUsbGlobals.RtIdc));
121 return Status;
122}
123
124static VOID vboxUsbRtIdcTerm()
125{
126 Assert(g_VBoxUsbGlobals.RtIdc.pFile);
127 Assert(g_VBoxUsbGlobals.RtIdc.pDevice);
128 ObDereferenceObject(g_VBoxUsbGlobals.RtIdc.pFile);
129 memset(&g_VBoxUsbGlobals.RtIdc, 0, sizeof (g_VBoxUsbGlobals.RtIdc));
130}
131
132static NTSTATUS vboxUsbRtIdcReportDevStart(PDEVICE_OBJECT pPDO, HVBOXUSBIDCDEV *phDev)
133{
134 VBOXUSBIDC_PROXY_STARTUP Start;
135 Start.u.pPDO = pPDO;
136
137 *phDev = NULL;
138
139 NTSTATUS Status = vboxUsbRtIdcSubmit(VBOXUSBIDC_INTERNAL_IOCTL_PROXY_STARTUP, &Start);
140 Assert(Status == STATUS_SUCCESS);
141 if (!NT_SUCCESS(Status))
142 return Status;
143
144 *phDev = Start.u.hDev;
145 return STATUS_SUCCESS;
146}
147
148static NTSTATUS vboxUsbRtIdcReportDevStop(HVBOXUSBIDCDEV hDev)
149{
150 VBOXUSBIDC_PROXY_TEARDOWN Stop;
151 Stop.hDev = hDev;
152
153 NTSTATUS Status = vboxUsbRtIdcSubmit(VBOXUSBIDC_INTERNAL_IOCTL_PROXY_TEARDOWN, &Stop);
154 Assert(Status == STATUS_SUCCESS);
155 return Status;
156}
157
158
159DECLHIDDEN(NTSTATUS) vboxUsbRtGlobalsInit()
160{
161 return vboxUsbRtIdcInit();
162}
163
164DECLHIDDEN(VOID) vboxUsbRtGlobalsTerm()
165{
166 vboxUsbRtIdcTerm();
167}
168
169
170DECLHIDDEN(NTSTATUS) vboxUsbRtInit(PVBOXUSBDEV_EXT pDevExt)
171{
172 RtlZeroMemory(&pDevExt->Rt, sizeof (pDevExt->Rt));
173 NTSTATUS Status = IoRegisterDeviceInterface(pDevExt->pPDO, &GUID_CLASS_VBOXUSB,
174 NULL, /* IN PUNICODE_STRING ReferenceString OPTIONAL */
175 &pDevExt->Rt.IfName);
176 Assert(Status == STATUS_SUCCESS);
177 if (NT_SUCCESS(Status))
178 {
179 Status = vboxUsbRtIdcReportDevStart(pDevExt->pPDO, &pDevExt->Rt.hMonDev);
180 Assert(Status == STATUS_SUCCESS);
181 if (NT_SUCCESS(Status))
182 {
183 Assert(pDevExt->Rt.hMonDev);
184 return STATUS_SUCCESS;
185 }
186
187 NTSTATUS tmpStatus = IoSetDeviceInterfaceState(&pDevExt->Rt.IfName, FALSE);
188 Assert(tmpStatus == STATUS_SUCCESS);
189 if (NT_SUCCESS(tmpStatus))
190 {
191 RtlFreeUnicodeString(&pDevExt->Rt.IfName);
192 }
193 }
194 return Status;
195}
196
197/**
198 * Free cached USB device/configuration descriptors
199 *
200 * @param pDevExt USB DevExt pointer
201 */
202static void vboxUsbRtFreeCachedDescriptors(PVBOXUSBDEV_EXT pDevExt)
203{
204 if (pDevExt->Rt.devdescr)
205 {
206 vboxUsbMemFree(pDevExt->Rt.devdescr);
207 pDevExt->Rt.devdescr = NULL;
208 }
209 for (ULONG i = 0; i < VBOXUSBRT_MAX_CFGS; ++i)
210 {
211 if (pDevExt->Rt.cfgdescr[i])
212 {
213 vboxUsbMemFree(pDevExt->Rt.cfgdescr[i]);
214 pDevExt->Rt.cfgdescr[i] = NULL;
215 }
216 }
217}
218
219/**
220 * Free per-device interface info
221 *
222 * @param pDevExt USB DevExt pointer
223 * @param fAbortPipes If true, also abort any open pipes
224 */
225static void vboxUsbRtFreeInterfaces(PVBOXUSBDEV_EXT pDevExt, BOOLEAN fAbortPipes)
226{
227 unsigned i;
228 unsigned j;
229
230 /*
231 * Free old interface info
232 */
233 if (pDevExt->Rt.pVBIfaceInfo)
234 {
235 for (i=0;i<pDevExt->Rt.uNumInterfaces;i++)
236 {
237 if (pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo)
238 {
239 if (fAbortPipes)
240 {
241 for (j=0; j<pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->NumberOfPipes; j++)
242 {
243 Log(("Aborting Pipe %d handle %x address %x\n", j,
244 pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j].PipeHandle,
245 pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j].EndpointAddress));
246 VBoxUsbToolPipeClear(pDevExt->pLowerDO, pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j].PipeHandle, FALSE);
247 }
248 }
249 vboxUsbMemFree(pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo);
250 }
251 pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo = NULL;
252 if (pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo)
253 vboxUsbMemFree(pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo);
254 pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo = NULL;
255 }
256 vboxUsbMemFree(pDevExt->Rt.pVBIfaceInfo);
257 pDevExt->Rt.pVBIfaceInfo = NULL;
258 }
259}
260
261DECLHIDDEN(VOID) vboxUsbRtClear(PVBOXUSBDEV_EXT pDevExt)
262{
263 vboxUsbRtFreeCachedDescriptors(pDevExt);
264 vboxUsbRtFreeInterfaces(pDevExt, FALSE);
265}
266
267DECLHIDDEN(NTSTATUS) vboxUsbRtRm(PVBOXUSBDEV_EXT pDevExt)
268{
269 if (!pDevExt->Rt.IfName.Buffer)
270 return STATUS_SUCCESS;
271
272 NTSTATUS Status = vboxUsbRtIdcReportDevStop(pDevExt->Rt.hMonDev);
273 Assert(Status == STATUS_SUCCESS);
274 Status = IoSetDeviceInterfaceState(&pDevExt->Rt.IfName, FALSE);
275 Assert(Status == STATUS_SUCCESS);
276 if (NT_SUCCESS(Status))
277 {
278 RtlFreeUnicodeString(&pDevExt->Rt.IfName);
279 pDevExt->Rt.IfName.Buffer = NULL;
280 }
281 return Status;
282}
283
284DECLHIDDEN(NTSTATUS) vboxUsbRtStart(PVBOXUSBDEV_EXT pDevExt)
285{
286 NTSTATUS Status = IoSetDeviceInterfaceState(&pDevExt->Rt.IfName, TRUE);
287 Assert(Status == STATUS_SUCCESS);
288 return Status;
289}
290
291static NTSTATUS vboxUsbRtCacheDescriptors(PVBOXUSBDEV_EXT pDevExt)
292{
293 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
294// uint32_t uTotalLength;
295// unsigned i;
296
297 /* Read device descriptor */
298 Assert(!pDevExt->Rt.devdescr);
299 pDevExt->Rt.devdescr = (PUSB_DEVICE_DESCRIPTOR)vboxUsbMemAlloc(sizeof (USB_DEVICE_DESCRIPTOR));
300 if (pDevExt->Rt.devdescr)
301 {
302 memset(pDevExt->Rt.devdescr, 0, sizeof (USB_DEVICE_DESCRIPTOR));
303 Status = VBoxUsbToolGetDescriptor(pDevExt->pLowerDO, pDevExt->Rt.devdescr, sizeof (USB_DEVICE_DESCRIPTOR), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, RT_INDEFINITE_WAIT);
304 if (NT_SUCCESS(Status))
305 {
306 Assert(pDevExt->Rt.devdescr->bNumConfigurations > 0);
307 PUSB_CONFIGURATION_DESCRIPTOR pDr = (PUSB_CONFIGURATION_DESCRIPTOR)vboxUsbMemAlloc(sizeof (USB_CONFIGURATION_DESCRIPTOR));
308 Assert(pDr);
309 if (pDr)
310 {
311 UCHAR i = 0;
312 for (; i < pDevExt->Rt.devdescr->bNumConfigurations; ++i)
313 {
314 Status = VBoxUsbToolGetDescriptor(pDevExt->pLowerDO, pDr, sizeof (USB_CONFIGURATION_DESCRIPTOR), USB_CONFIGURATION_DESCRIPTOR_TYPE, i, 0, RT_INDEFINITE_WAIT);
315 if (!NT_SUCCESS(Status))
316 {
317 break;
318 }
319
320 USHORT uTotalLength = pDr->wTotalLength;
321 pDevExt->Rt.cfgdescr[i] = (PUSB_CONFIGURATION_DESCRIPTOR)vboxUsbMemAlloc(uTotalLength);
322 if (!pDevExt->Rt.cfgdescr[i])
323 {
324 Status = STATUS_INSUFFICIENT_RESOURCES;
325 break;
326 }
327
328 Status = VBoxUsbToolGetDescriptor(pDevExt->pLowerDO, pDevExt->Rt.cfgdescr[i], uTotalLength, USB_CONFIGURATION_DESCRIPTOR_TYPE, i, 0, RT_INDEFINITE_WAIT);
329 if (!NT_SUCCESS(Status))
330 {
331 break;
332 }
333 }
334
335 vboxUsbMemFree(pDr);
336
337 if (NT_SUCCESS(Status))
338 return Status;
339
340 /* recources will be freed in vboxUsbRtFreeCachedDescriptors below */
341 }
342 }
343
344 vboxUsbRtFreeCachedDescriptors(pDevExt);
345 }
346
347 /* shoud be only on fail here */
348 Assert(!NT_SUCCESS(Status));
349 return Status;
350}
351
352static NTSTATUS vboxUsbRtDispatchClaimDevice(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
353{
354 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
355 PFILE_OBJECT pFObj = pSl->FileObject;
356 PUSBSUP_CLAIMDEV pDev = (PUSBSUP_CLAIMDEV)pIrp->AssociatedIrp.SystemBuffer;
357 ULONG cbOut = 0;
358 NTSTATUS Status = STATUS_SUCCESS;
359
360 do
361 {
362 if (!pFObj)
363 {
364 AssertFailed();
365 Status = STATUS_INVALID_PARAMETER;
366 break;
367 }
368
369 if ( !pDev
370 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pDev)
371 || pSl->Parameters.DeviceIoControl.OutputBufferLength != sizeof (*pDev))
372 {
373 AssertFailed();
374 Status = STATUS_INVALID_PARAMETER;
375 break;
376 }
377
378 if (!vboxUsbRtCtxSetOwner(pDevExt, pFObj))
379 {
380 AssertFailed();
381 pDev->fClaimed = false;
382 cbOut = sizeof (*pDev);
383 break;
384 }
385
386 vboxUsbRtFreeCachedDescriptors(pDevExt);
387 Status = vboxUsbRtCacheDescriptors(pDevExt);
388 if (NT_SUCCESS(Status))
389 {
390 pDev->fClaimed = true;
391 cbOut = sizeof (*pDev);
392 }
393 } while (0);
394
395 Assert(Status != STATUS_PENDING);
396 VBoxDrvToolIoComplete(pIrp, Status, cbOut);
397 vboxUsbDdiStateRelease(pDevExt);
398 return Status;
399}
400
401static NTSTATUS vboxUsbRtDispatchReleaseDevice(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
402{
403 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
404 PFILE_OBJECT pFObj = pSl->FileObject;
405 NTSTATUS Status= STATUS_SUCCESS;
406
407 if (vboxUsbRtCtxIsOwner(pDevExt, pFObj))
408 {
409 vboxUsbRtFreeCachedDescriptors(pDevExt);
410 bool bRc = vboxUsbRtCtxReleaseOwner(pDevExt, pFObj);
411 Assert(bRc);
412 }
413 else
414 {
415 AssertFailed();
416 Status = STATUS_ACCESS_DENIED;
417 }
418
419 VBoxDrvToolIoComplete(pIrp, STATUS_SUCCESS, 0);
420 vboxUsbDdiStateRelease(pDevExt);
421 return STATUS_SUCCESS;
422}
423
424static NTSTATUS vboxUsbRtGetDeviceDescription(PVBOXUSBDEV_EXT pDevExt)
425{
426 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
427 PUSB_DEVICE_DESCRIPTOR pDr = (PUSB_DEVICE_DESCRIPTOR)vboxUsbMemAllocZ(sizeof (USB_DEVICE_DESCRIPTOR));
428 if (pDr)
429 {
430 Status = VBoxUsbToolGetDescriptor(pDevExt->pLowerDO, pDr, sizeof(*pDr), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, RT_INDEFINITE_WAIT);
431 if (NT_SUCCESS(Status))
432 {
433 pDevExt->Rt.idVendor = pDr->idVendor;
434 pDevExt->Rt.idProduct = pDr->idProduct;
435 pDevExt->Rt.bcdDevice = pDr->bcdDevice;
436 pDevExt->Rt.szSerial[0] = 0;
437
438 if (pDr->iSerialNumber
439#ifdef DEBUG
440 || pDr->iProduct || pDr->iManufacturer
441#endif
442 )
443 {
444 int langId;
445 Status = VBoxUsbToolGetLangID(pDevExt->pLowerDO, &langId, RT_INDEFINITE_WAIT);
446 if (NT_SUCCESS(Status))
447 {
448 Status = VBoxUsbToolGetStringDescriptor(pDevExt->pLowerDO, pDevExt->Rt.szSerial, sizeof (pDevExt->Rt.szSerial),
449 pDr->iSerialNumber, langId, RT_INDEFINITE_WAIT);
450 }
451 else
452 {
453 Status = STATUS_SUCCESS;
454 }
455 }
456 }
457 vboxUsbMemFree(pDr);
458 }
459
460 return Status;
461}
462
463static NTSTATUS vboxUsbRtDispatchGetDevice(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
464{
465 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
466 PUSBSUP_GETDEV pDev = (PUSBSUP_GETDEV)pIrp->AssociatedIrp.SystemBuffer;
467 NTSTATUS Status = STATUS_SUCCESS;
468 ULONG cbOut = 0;
469
470 /* don't check for owner since this request is allowed for non-owners as well */
471
472 if (pDev && pSl->Parameters.DeviceIoControl.InputBufferLength == sizeof (*pDev)
473 && pSl->Parameters.DeviceIoControl.OutputBufferLength == sizeof (*pDev))
474 {
475 Status = VBoxUsbToolGetDeviceSpeed(pDevExt->pLowerDO, &pDevExt->Rt.fIsHighSpeed);
476 if (NT_SUCCESS(Status))
477 {
478 pDev->hDevice = pDevExt->Rt.hMonDev;
479 pDev->fAttached = true;
480 pDev->fHiSpeed = pDevExt->Rt.fIsHighSpeed;
481 cbOut = sizeof (*pDev);
482 }
483 }
484 else
485 {
486 Status = STATUS_INVALID_PARAMETER;
487 }
488
489 Assert(Status != STATUS_PENDING);
490 VBoxDrvToolIoComplete(pIrp, Status, cbOut);
491 vboxUsbDdiStateRelease(pDevExt);
492 return Status;
493}
494
495static NTSTATUS vboxUsbRtDispatchUsbReset(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
496{
497 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
498 PFILE_OBJECT pFObj = pSl->FileObject;
499 PUSBSUP_GETDEV pDev = (PUSBSUP_GETDEV)pIrp->AssociatedIrp.SystemBuffer;
500 NTSTATUS Status = STATUS_SUCCESS;
501
502 do
503 {
504 if (!pFObj)
505 {
506 AssertFailed();
507 Status = STATUS_INVALID_PARAMETER;
508 break;
509 }
510
511 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
512 {
513 AssertFailed();
514 Status = STATUS_ACCESS_DENIED;
515 break;
516 }
517
518 if (pIrp->AssociatedIrp.SystemBuffer
519 || pSl->Parameters.DeviceIoControl.InputBufferLength
520 || pSl->Parameters.DeviceIoControl.OutputBufferLength)
521 {
522 AssertFailed();
523 Status = STATUS_INVALID_PARAMETER;
524 break;
525 }
526
527 Status = VBoxUsbToolIoInternalCtlSendSync(pDevExt->pLowerDO, IOCTL_INTERNAL_USB_RESET_PORT, NULL, NULL);
528 Assert(NT_SUCCESS(Status));
529 } while (0);
530
531 Assert(Status != STATUS_PENDING);
532 VBoxDrvToolIoComplete(pIrp, Status, 0);
533 vboxUsbDdiStateRelease(pDevExt);
534 return Status;
535}
536
537static PUSB_CONFIGURATION_DESCRIPTOR vboxUsbRtFindConfigDesc(PVBOXUSBDEV_EXT pDevExt, uint8_t uConfiguration)
538{
539 PUSB_CONFIGURATION_DESCRIPTOR pCfgDr = NULL;
540
541 for (ULONG i = 0; i < VBOXUSBRT_MAX_CFGS; ++i)
542 {
543 if (pDevExt->Rt.cfgdescr[i])
544 {
545 if (pDevExt->Rt.cfgdescr[i]->bConfigurationValue == uConfiguration)
546 {
547 pCfgDr = pDevExt->Rt.cfgdescr[i];
548 break;
549 }
550 }
551 }
552
553 return pCfgDr;
554}
555
556static NTSTATUS vboxUsbRtSetConfig(PVBOXUSBDEV_EXT pDevExt, uint8_t uConfiguration)
557{
558 PURB pUrb = NULL;
559 NTSTATUS Status = STATUS_SUCCESS;
560 uint32_t i;
561
562 if (!uConfiguration)
563 {
564 pUrb = VBoxUsbToolUrbAllocZ(URB_FUNCTION_SELECT_CONFIGURATION, sizeof (struct _URB_SELECT_CONFIGURATION));
565 if (!pUrb)
566 {
567 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbAlloc failed\n"));
568 return STATUS_INSUFFICIENT_RESOURCES;
569 }
570
571 vboxUsbRtFreeInterfaces(pDevExt, TRUE);
572
573 pUrb->UrbSelectConfiguration.ConfigurationDescriptor = NULL;
574
575 Status = VBoxUsbToolUrbPost(pDevExt->pLowerDO, pUrb, RT_INDEFINITE_WAIT);
576 if (NT_SUCCESS(Status) && USBD_SUCCESS(pUrb->UrbHeader.Status))
577 {
578 pDevExt->Rt.hConfiguration = pUrb->UrbSelectConfiguration.ConfigurationHandle;
579 pDevExt->Rt.uConfigValue = uConfiguration;
580 }
581 else
582 {
583 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbPost failed Status (0x%x), usb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
584 }
585
586 VBoxUsbToolUrbFree(pUrb);
587
588 return Status;
589 }
590
591 PUSB_CONFIGURATION_DESCRIPTOR pCfgDr = vboxUsbRtFindConfigDesc(pDevExt, uConfiguration);
592 if (!pCfgDr)
593 {
594 AssertMsgFailed((__FUNCTION__": VBoxUSBFindConfigDesc did not find cfg (%d)\n", uConfiguration));
595 return STATUS_INVALID_PARAMETER;
596 }
597
598 PUSBD_INTERFACE_LIST_ENTRY pIfLe = (PUSBD_INTERFACE_LIST_ENTRY)vboxUsbMemAllocZ((pCfgDr->bNumInterfaces + 1) * sizeof(USBD_INTERFACE_LIST_ENTRY));
599 if (!pIfLe)
600 {
601 AssertMsgFailed((__FUNCTION__": vboxUsbMemAllocZ for pIfLe failed\n"));
602 return STATUS_INSUFFICIENT_RESOURCES;
603 }
604
605 for (i = 0; i < pCfgDr->bNumInterfaces; i++)
606 {
607 pIfLe[i].InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(pCfgDr, pCfgDr, i, 0, -1, -1, -1);
608 if (!pIfLe[i].InterfaceDescriptor)
609 {
610 AssertMsgFailed((__FUNCTION__": interface %d not found\n", i));
611 Status = STATUS_INVALID_PARAMETER;
612 break;
613 }
614 }
615 pIfLe[pCfgDr->bNumInterfaces].InterfaceDescriptor = NULL;
616
617 if (NT_SUCCESS(Status))
618 {
619 pUrb = USBD_CreateConfigurationRequestEx(pCfgDr, pIfLe);
620 if (pUrb)
621 {
622 Status = VBoxUsbToolUrbPost(pDevExt->pLowerDO, pUrb, RT_INDEFINITE_WAIT);
623 if (NT_SUCCESS(Status) && USBD_SUCCESS(pUrb->UrbHeader.Status))
624 {
625 vboxUsbRtFreeInterfaces(pDevExt, FALSE);
626
627 pDevExt->Rt.hConfiguration = pUrb->UrbSelectConfiguration.ConfigurationHandle;
628 pDevExt->Rt.uConfigValue = uConfiguration;
629 pDevExt->Rt.uNumInterfaces = pCfgDr->bNumInterfaces;
630
631 pDevExt->Rt.pVBIfaceInfo = (VBOXUSB_IFACE_INFO*)vboxUsbMemAllocZ(pDevExt->Rt.uNumInterfaces * sizeof (VBOXUSB_IFACE_INFO));
632 if (pDevExt->Rt.pVBIfaceInfo)
633 {
634 Assert(NT_SUCCESS(Status));
635 for (i = 0; i < pDevExt->Rt.uNumInterfaces; i++)
636 {
637 size_t uTotalIfaceInfoLength = GET_USBD_INTERFACE_SIZE(pIfLe[i].Interface->NumberOfPipes);
638 pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo = (PUSBD_INTERFACE_INFORMATION)vboxUsbMemAlloc(uTotalIfaceInfoLength);
639 if (!pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo)
640 {
641 AssertMsgFailed((__FUNCTION__": vboxUsbMemAlloc failed\n"));
642 Status = STATUS_INSUFFICIENT_RESOURCES;
643 break;
644 }
645
646 if (pIfLe[i].Interface->NumberOfPipes > 0)
647 {
648 pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo = (VBOXUSB_PIPE_INFO *)vboxUsbMemAlloc(pIfLe[i].Interface->NumberOfPipes * sizeof(VBOXUSB_PIPE_INFO));
649 if (!pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo)
650 {
651 AssertMsgFailed((__FUNCTION__": vboxUsbMemAlloc failed\n"));
652 Status = STATUS_NO_MEMORY;
653 break;
654 }
655 }
656 else
657 {
658 pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo = NULL;
659 }
660
661 RtlCopyMemory(pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo, pIfLe[i].Interface, uTotalIfaceInfoLength);
662
663 for (ULONG j = 0; j < pIfLe[i].Interface->NumberOfPipes; j++)
664 {
665 pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j].EndpointAddress = pIfLe[i].Interface->Pipes[j].EndpointAddress;
666 pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j].NextScheduledFrame = 0;
667 }
668 }
669
670// if (NT_SUCCESS(Status))
671// {
672//
673// }
674 }
675 else
676 {
677 AssertMsgFailed((__FUNCTION__": vboxUsbMemAllocZ failed\n"));
678 Status = STATUS_NO_MEMORY;
679 }
680 }
681 else
682 {
683 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbPost failed Status (0x%x), usb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
684 }
685 ExFreePool(pUrb);
686 }
687 else
688 {
689 AssertMsgFailed((__FUNCTION__": USBD_CreateConfigurationRequestEx failed\n"));
690 Status = STATUS_INSUFFICIENT_RESOURCES;
691 }
692 }
693
694 vboxUsbMemFree(pIfLe);
695
696 return Status;
697}
698
699static NTSTATUS vboxUsbRtDispatchUsbSetConfig(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
700{
701 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
702 PFILE_OBJECT pFObj = pSl->FileObject;
703 PUSBSUP_SET_CONFIG pCfg = (PUSBSUP_SET_CONFIG)pIrp->AssociatedIrp.SystemBuffer;
704 NTSTATUS Status = STATUS_SUCCESS;
705
706 do
707 {
708 if (!pFObj)
709 {
710 AssertFailed();
711 Status = STATUS_INVALID_PARAMETER;
712 break;
713 }
714
715 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
716 {
717 AssertFailed();
718 Status = STATUS_ACCESS_DENIED;
719 break;
720 }
721
722 if ( !pCfg
723 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pCfg)
724 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
725 {
726 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
727 Status = STATUS_INVALID_PARAMETER;
728 break;
729 }
730
731 Status = vboxUsbRtSetConfig(pDevExt, pCfg->bConfigurationValue);
732 } while (0);
733
734 Assert(Status != STATUS_PENDING);
735 VBoxDrvToolIoComplete(pIrp, Status, 0);
736 vboxUsbDdiStateRelease(pDevExt);
737 return Status;
738}
739
740static NTSTATUS vboxUsbRtSetInterface(PVBOXUSBDEV_EXT pDevExt, uint32_t InterfaceNumber, int AlternateSetting)
741{
742 if (!pDevExt->Rt.uConfigValue)
743 {
744 AssertMsgFailed((__FUNCTION__": Can't select an interface without an active configuration\n"));
745 return STATUS_INVALID_PARAMETER;
746 }
747
748 if (InterfaceNumber >= pDevExt->Rt.uNumInterfaces)
749 {
750 AssertMsgFailed((__FUNCTION__": InterfaceNumber %d too high!!\n", InterfaceNumber));
751 return STATUS_INVALID_PARAMETER;
752 }
753
754 PUSB_CONFIGURATION_DESCRIPTOR pCfgDr = vboxUsbRtFindConfigDesc(pDevExt, pDevExt->Rt.uConfigValue);
755 if (!pCfgDr)
756 {
757 AssertMsgFailed((__FUNCTION__": configuration %d not found!!\n", pDevExt->Rt.uConfigValue));
758 return STATUS_INVALID_PARAMETER;
759 }
760
761 PUSB_INTERFACE_DESCRIPTOR pIfDr = USBD_ParseConfigurationDescriptorEx(pCfgDr, pCfgDr, InterfaceNumber, AlternateSetting, -1, -1, -1);
762 if (!pIfDr)
763 {
764 AssertMsgFailed((__FUNCTION__": invalid interface %d or alternate setting %d\n", InterfaceNumber, AlternateSetting));
765 return STATUS_UNSUCCESSFUL;
766 }
767
768 USHORT uUrbSize = GET_SELECT_INTERFACE_REQUEST_SIZE(pIfDr->bNumEndpoints);
769 ULONG uTotalIfaceInfoLength = GET_USBD_INTERFACE_SIZE(pIfDr->bNumEndpoints);
770 NTSTATUS Status = STATUS_SUCCESS;
771 PURB pUrb;
772 PUSBD_INTERFACE_INFORMATION pNewIFInfo;
773 VBOXUSB_PIPE_INFO *pNewPipeInfo;
774
775 if (pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo)
776 {
777 /* Clear pipes associated with the interface, else Windows may hang. */
778 for (ULONG i = 0; i < pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo->NumberOfPipes; i++)
779 VBoxUsbToolPipeClear(pDevExt->pLowerDO, pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo->Pipes[i].PipeHandle, FALSE);
780 }
781
782 do {
783 /* First allocate all the structures we'll need. */
784 pUrb = VBoxUsbToolUrbAllocZ(0, uUrbSize);
785 if (!pUrb)
786 {
787 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbAllocZ failed\n"));
788 Status = STATUS_NO_MEMORY;
789 break;
790 }
791
792 pNewIFInfo = (PUSBD_INTERFACE_INFORMATION)vboxUsbMemAlloc(uTotalIfaceInfoLength);
793 if (!pNewIFInfo)
794 {
795 AssertMsgFailed((__FUNCTION__": Failed allocating interface storage\n"));
796 Status = STATUS_NO_MEMORY;
797 break;
798 }
799
800 if (pIfDr->bNumEndpoints > 0)
801 {
802 pNewPipeInfo = (VBOXUSB_PIPE_INFO *)vboxUsbMemAlloc(pIfDr->bNumEndpoints * sizeof(VBOXUSB_PIPE_INFO));
803 if (!pNewPipeInfo)
804 {
805 AssertMsgFailed((__FUNCTION__": Failed allocating pipe info storage\n"));
806 Status = STATUS_NO_MEMORY;
807 break;
808 }
809 }
810 else
811 pNewPipeInfo = NULL;
812
813 /* Now that we have all the bits, select the interface. */
814 UsbBuildSelectInterfaceRequest(pUrb, uUrbSize, pDevExt->Rt.hConfiguration, InterfaceNumber, AlternateSetting);
815 pUrb->UrbSelectInterface.Interface.Length = GET_USBD_INTERFACE_SIZE(pIfDr->bNumEndpoints);
816
817 Status = VBoxUsbToolUrbPost(pDevExt->pLowerDO, pUrb, RT_INDEFINITE_WAIT);
818 if (NT_SUCCESS(Status) && USBD_SUCCESS(pUrb->UrbHeader.Status))
819 {
820 /* Free the old memory and put new in. */
821 if (pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo)
822 vboxUsbMemFree(pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo);
823 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo = pNewIFInfo;
824 if (pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo)
825 vboxUsbMemFree(pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo);
826 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo = pNewPipeInfo;
827 pNewPipeInfo = NULL; pNewIFInfo = NULL; /* Don't try to free it again. */
828
829 USBD_INTERFACE_INFORMATION *pIfInfo = &pUrb->UrbSelectInterface.Interface;
830 memcpy(pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo, pIfInfo, GET_USBD_INTERFACE_SIZE(pIfDr->bNumEndpoints));
831
832 Assert(pIfInfo->NumberOfPipes == pIfDr->bNumEndpoints);
833 for (ULONG i = 0; i < pIfInfo->NumberOfPipes; i++)
834 {
835 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo[i].EndpointAddress = pIfInfo->Pipes[i].EndpointAddress;
836 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo[i].NextScheduledFrame = 0;
837 }
838 }
839 else
840 {
841 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbPost failed Status (0x%x) usb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
842 }
843 } while (0);
844
845 /* Clean up. */
846 if (pUrb)
847 VBoxUsbToolUrbFree(pUrb);
848 if (pNewIFInfo)
849 vboxUsbMemFree(pNewIFInfo);
850 if (pNewPipeInfo)
851 vboxUsbMemFree(pNewPipeInfo);
852
853 return Status;
854}
855
856static NTSTATUS vboxUsbRtDispatchUsbSelectInterface(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
857{
858 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
859 PFILE_OBJECT pFObj = pSl->FileObject;
860 PUSBSUP_SELECT_INTERFACE pIf = (PUSBSUP_SELECT_INTERFACE)pIrp->AssociatedIrp.SystemBuffer;
861 NTSTATUS Status;
862
863 do
864 {
865 if (!pFObj)
866 {
867 AssertFailed();
868 Status = STATUS_INVALID_PARAMETER;
869 break;
870 }
871
872 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
873 {
874 AssertFailed();
875 Status = STATUS_ACCESS_DENIED;
876 break;
877 }
878
879 if ( !pIf
880 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pIf)
881 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
882 {
883 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
884 Status = STATUS_INVALID_PARAMETER;
885 break;
886 }
887
888 Status = vboxUsbRtSetInterface(pDevExt, pIf->bInterfaceNumber, pIf->bAlternateSetting);
889 } while (0);
890
891 Assert(Status != STATUS_PENDING);
892 VBoxDrvToolIoComplete(pIrp, Status, 0);
893 vboxUsbDdiStateRelease(pDevExt);
894 return Status;
895}
896
897static HANDLE vboxUsbRtGetPipeHandle(PVBOXUSBDEV_EXT pDevExt, uint32_t EndPointAddress)
898{
899 if (EndPointAddress == 0)
900 {
901 return pDevExt->Rt.hPipe0;
902 }
903
904 for (ULONG i = 0; i < pDevExt->Rt.uNumInterfaces; i++)
905 {
906 for (ULONG j = 0; j < pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->NumberOfPipes; j++)
907 {
908 /* Note that bit 7 determines pipe direction, but is still significant
909 * because endpoints may be numbered like 0x01, 0x81, 0x02, 0x82 etc.
910 */
911 if (pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j].EndpointAddress == EndPointAddress)
912 return pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j].PipeHandle;
913 }
914 }
915 return 0;
916}
917
918static VBOXUSB_PIPE_INFO* vboxUsbRtGetPipeInfo(PVBOXUSBDEV_EXT pDevExt, uint32_t EndPointAddress)
919{
920 for (ULONG i = 0; i < pDevExt->Rt.uNumInterfaces; i++)
921 {
922 for (ULONG j = 0; j < pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->NumberOfPipes; j++)
923 {
924 if (pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j].EndpointAddress == EndPointAddress)
925 return &pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j];
926 }
927 }
928 return NULL;
929}
930
931
932
933static NTSTATUS vboxUsbRtClearEndpoint(PVBOXUSBDEV_EXT pDevExt, uint32_t EndPointAddress, bool fReset)
934{
935 NTSTATUS Status = VBoxUsbToolPipeClear(pDevExt->pLowerDO, vboxUsbRtGetPipeHandle(pDevExt, EndPointAddress), fReset);
936 if (!NT_SUCCESS(Status))
937 {
938 AssertMsgFailed((__FUNCTION__": VBoxUsbToolPipeClear failed Status (0x%x)\n", Status));
939 }
940
941 return Status;
942}
943
944static NTSTATUS vboxUsbRtDispatchUsbClearEndpoint(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
945{
946 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
947 PFILE_OBJECT pFObj = pSl->FileObject;
948 PUSBSUP_CLEAR_ENDPOINT pCe = (PUSBSUP_CLEAR_ENDPOINT)pIrp->AssociatedIrp.SystemBuffer;
949 NTSTATUS Status;
950
951 do
952 {
953 if (!pFObj)
954 {
955 AssertFailed();
956 Status = STATUS_INVALID_PARAMETER;
957 break;
958 }
959
960 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
961 {
962 AssertFailed();
963 Status = STATUS_ACCESS_DENIED;
964 break;
965 }
966
967 if ( !pCe
968 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pCe)
969 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
970 {
971 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
972 Status = STATUS_INVALID_PARAMETER;
973 break;
974 }
975
976 Status = vboxUsbRtClearEndpoint(pDevExt, pCe->bEndpoint, TRUE);
977 } while (0);
978
979 Assert(Status != STATUS_PENDING);
980 VBoxDrvToolIoComplete(pIrp, Status, 0);
981 vboxUsbDdiStateRelease(pDevExt);
982 return Status;
983}
984
985static NTSTATUS vboxUsbRtDispatchUsbAbortEndpoint(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
986{
987 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
988 PFILE_OBJECT pFObj = pSl->FileObject;
989 PUSBSUP_CLEAR_ENDPOINT pCe = (PUSBSUP_CLEAR_ENDPOINT)pIrp->AssociatedIrp.SystemBuffer;
990 NTSTATUS Status;
991
992 do
993 {
994 if (!pFObj)
995 {
996 AssertFailed();
997 Status = STATUS_INVALID_PARAMETER;
998 break;
999 }
1000
1001 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
1002 {
1003 AssertFailed();
1004 Status = STATUS_ACCESS_DENIED;
1005 break;
1006 }
1007
1008 if ( !pCe
1009 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pCe)
1010 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
1011 {
1012 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
1013 Status = STATUS_INVALID_PARAMETER;
1014 break;
1015 }
1016
1017 Status = vboxUsbRtClearEndpoint(pDevExt, pCe->bEndpoint, FALSE);
1018 } while (0);
1019
1020 Assert(Status != STATUS_PENDING);
1021 VBoxDrvToolIoComplete(pIrp, Status, 0);
1022 vboxUsbDdiStateRelease(pDevExt);
1023 return Status;
1024}
1025
1026static NTSTATUS vboxUsbRtUrbSendCompletion(PDEVICE_OBJECT pDevObj, IRP *pIrp, void *pvContext)
1027{
1028 if (!pvContext)
1029 {
1030 AssertMsgFailed((__FUNCTION__": context is NULL\n"));
1031 pIrp->IoStatus.Information = 0;
1032 return STATUS_CONTINUE_COMPLETION;
1033 }
1034
1035 PVBOXUSB_URB_CONTEXT pContext = (PVBOXUSB_URB_CONTEXT)pvContext;
1036
1037 if (pContext->ulMagic != VBOXUSB_MAGIC)
1038 {
1039 AssertMsgFailed((__FUNCTION__": Invalid context magic\n"));
1040 pIrp->IoStatus.Information = 0;
1041 return STATUS_CONTINUE_COMPLETION;
1042 }
1043
1044 PURB pUrb = pContext->pUrb;
1045 PMDL pMdlBuf = pContext->pMdlBuf;
1046 PUSBSUP_URB pUrbInfo = (PUSBSUP_URB)pContext->pOut;
1047 PVBOXUSBDEV_EXT pDevExt = pContext->pDevExt;
1048
1049 if (!pUrb || !pMdlBuf || !pUrbInfo || !pDevExt)
1050 {
1051 AssertMsgFailed((__FUNCTION__": Invalid args\n"));
1052 if (pDevExt)
1053 vboxUsbDdiStateRelease(pDevExt);
1054 pIrp->IoStatus.Information = 0;
1055 return STATUS_CONTINUE_COMPLETION;
1056 }
1057
1058 NTSTATUS Status = pIrp->IoStatus.Status;
1059 if (Status == STATUS_SUCCESS)
1060 {
1061 switch(pUrb->UrbHeader.Status)
1062 {
1063 case USBD_STATUS_CRC:
1064 pUrbInfo->error = USBSUP_XFER_CRC;
1065 break;
1066 case USBD_STATUS_SUCCESS:
1067 pUrbInfo->error = USBSUP_XFER_OK;
1068 break;
1069 case USBD_STATUS_STALL_PID:
1070 pUrbInfo->error = USBSUP_XFER_STALL;
1071 break;
1072 case USBD_STATUS_INVALID_URB_FUNCTION:
1073 case USBD_STATUS_INVALID_PARAMETER:
1074 AssertMsgFailed((__FUNCTION__": sw error, urb Status (0x%x)\n", pUrb->UrbHeader.Status));
1075 case USBD_STATUS_DEV_NOT_RESPONDING:
1076 default:
1077 pUrbInfo->error = USBSUP_XFER_DNR;
1078 break;
1079 }
1080
1081 switch(pContext->ulTransferType)
1082 {
1083 case USBSUP_TRANSFER_TYPE_MSG:
1084 pUrbInfo->len = pUrb->UrbControlTransfer.TransferBufferLength;
1085 /* QUSB_TRANSFER_TYPE_MSG is a control transfer, but it is special
1086 * the first 8 bytes of the buffer is the setup packet so the real
1087 * data length is therefore urb->len - 8
1088 */
1089 pUrbInfo->len += sizeof (pUrb->UrbControlTransfer.SetupPacket);
1090
1091 /* If a control URB was successfully completed on the default control
1092 * pipe, stash away the handle. When submitting the URB, we don't need
1093 * to know (and initially don't have) the handle. If we want to abort
1094 * the default control pipe, we *have* to have a handle. This is how we
1095 * find out what the handle is.
1096 */
1097 if (!pUrbInfo->ep && (pDevExt->Rt.hPipe0 == NULL))
1098 {
1099 pDevExt->Rt.hPipe0 = pUrb->UrbControlTransfer.PipeHandle;
1100 }
1101
1102 break;
1103 case USBSUP_TRANSFER_TYPE_ISOC:
1104 pUrbInfo->len = pUrb->UrbIsochronousTransfer.TransferBufferLength;
1105 break;
1106 case USBSUP_TRANSFER_TYPE_BULK:
1107 case USBSUP_TRANSFER_TYPE_INTR:
1108 if (pUrbInfo->dir == USBSUP_DIRECTION_IN && pUrbInfo->error == USBSUP_XFER_OK
1109 && !(pUrbInfo->flags & USBSUP_FLAG_SHORT_OK)
1110 && pUrbInfo->len > pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength
1111 )
1112 {
1113 /* If we don't use the USBD_SHORT_TRANSFER_OK flag, the returned buffer lengths are
1114 * wrong for short transfers (always a multiple of max packet size?). So we just figure
1115 * out if this was a data underrun on our own.
1116 */
1117 pUrbInfo->error = USBSUP_XFER_UNDERRUN;
1118 }
1119 pUrbInfo->len = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
1120 break;
1121 default:
1122 break;
1123 }
1124 }
1125 else
1126 {
1127 pUrbInfo->len = 0;
1128
1129 LogFunc(("URB failed Status (0x%x) urb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
1130#ifdef DEBUG
1131 switch(pContext->ulTransferType)
1132 {
1133 case USBSUP_TRANSFER_TYPE_MSG:
1134 LogRel(("Msg (CTRL) length=%d\n", pUrb->UrbControlTransfer.TransferBufferLength));
1135 break;
1136 case USBSUP_TRANSFER_TYPE_ISOC:
1137 LogRel(("ISOC length=%d\n", pUrb->UrbIsochronousTransfer.TransferBufferLength));
1138 break;
1139 case USBSUP_TRANSFER_TYPE_BULK:
1140 case USBSUP_TRANSFER_TYPE_INTR:
1141 LogRel(("BULK/INTR length=%d\n", pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength));
1142 break;
1143 }
1144#endif
1145 switch(pUrb->UrbHeader.Status)
1146 {
1147 case USBD_STATUS_CRC:
1148 pUrbInfo->error = USBSUP_XFER_CRC;
1149 Status = STATUS_SUCCESS;
1150 break;
1151 case USBD_STATUS_STALL_PID:
1152 pUrbInfo->error = USBSUP_XFER_STALL;
1153 Status = STATUS_SUCCESS;
1154 break;
1155 case USBD_STATUS_DEV_NOT_RESPONDING:
1156 case USBD_STATUS_DEVICE_GONE:
1157 pUrbInfo->error = USBSUP_XFER_DNR;
1158 Status = STATUS_SUCCESS;
1159 break;
1160 case ((USBD_STATUS)0xC0010000L): // USBD_STATUS_CANCELED - too bad usbdi.h and usb.h aren't consistent!
1161 // TODO: What the heck are we really supposed to do here?
1162 pUrbInfo->error = USBSUP_XFER_STALL;
1163 Status = STATUS_SUCCESS;
1164 break;
1165 case USBD_STATUS_BAD_START_FRAME: // This one really shouldn't happen
1166 case USBD_STATUS_ISOCH_REQUEST_FAILED:
1167 pUrbInfo->error = USBSUP_XFER_NAC;
1168 Status = STATUS_SUCCESS;
1169 break;
1170 default:
1171 AssertMsgFailed((__FUNCTION__": err Status (0x%x) (0x%x)\n", Status, pUrb->UrbHeader.Status));
1172 pUrbInfo->error = USBSUP_XFER_DNR;
1173 Status = STATUS_SUCCESS;
1174 break;
1175 }
1176 }
1177 // For isochronous transfers, always update the individual packets
1178 if (pContext->ulTransferType == USBSUP_TRANSFER_TYPE_ISOC)
1179 {
1180 Assert(pUrbInfo->numIsoPkts == pUrb->UrbIsochronousTransfer.NumberOfPackets);
1181 for (ULONG i = 0; i < pUrbInfo->numIsoPkts; ++i)
1182 {
1183 Assert(pUrbInfo->aIsoPkts[i].off == pUrb->UrbIsochronousTransfer.IsoPacket[i].Offset);
1184 pUrbInfo->aIsoPkts[i].cb = (uint16_t)pUrb->UrbIsochronousTransfer.IsoPacket[i].Length;
1185 switch (pUrb->UrbIsochronousTransfer.IsoPacket[i].Status)
1186 {
1187 case USBD_STATUS_SUCCESS:
1188 pUrbInfo->aIsoPkts[i].stat = USBSUP_XFER_OK;
1189 break;
1190 case USBD_STATUS_NOT_ACCESSED:
1191 pUrbInfo->aIsoPkts[i].stat = USBSUP_XFER_NAC;
1192 break;
1193 default:
1194 pUrbInfo->aIsoPkts[i].stat = USBSUP_XFER_STALL;
1195 break;
1196 }
1197 }
1198 }
1199
1200 MmUnlockPages(pMdlBuf);
1201 IoFreeMdl(pMdlBuf);
1202
1203 vboxUsbMemFree(pContext);
1204
1205 vboxUsbDdiStateRelease(pDevExt);
1206
1207 Assert(pIrp->IoStatus.Status != STATUS_IO_TIMEOUT);
1208 pIrp->IoStatus.Information = sizeof(*pUrbInfo);
1209 pIrp->IoStatus.Status = Status;
1210 return STATUS_CONTINUE_COMPLETION;
1211}
1212
1213static NTSTATUS vboxUsbRtUrbSend(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp, PUSBSUP_URB pUrbInfo)
1214{
1215 NTSTATUS Status = STATUS_SUCCESS;
1216 PVBOXUSB_URB_CONTEXT pContext = NULL;
1217 PMDL pMdlBuf = NULL;
1218 ULONG cbUrb;
1219
1220 Assert(pUrbInfo);
1221 if (pUrbInfo->type == USBSUP_TRANSFER_TYPE_ISOC)
1222 {
1223 Assert(pUrbInfo->numIsoPkts <= 8);
1224 cbUrb = GET_ISO_URB_SIZE(pUrbInfo->numIsoPkts);
1225 }
1226 else
1227 cbUrb = sizeof (URB);
1228
1229 do
1230 {
1231 pContext = (PVBOXUSB_URB_CONTEXT)vboxUsbMemAllocZ(cbUrb + sizeof (VBOXUSB_URB_CONTEXT));
1232 if (!pContext)
1233 {
1234 AssertMsgFailed((__FUNCTION__": vboxUsbMemAlloc failed\n"));
1235 Status = STATUS_INSUFFICIENT_RESOURCES;
1236 break;
1237 }
1238
1239 PURB pUrb = (PURB)(pContext + 1);
1240 HANDLE hPipe = NULL;
1241 if (pUrbInfo->ep)
1242 {
1243 hPipe = vboxUsbRtGetPipeHandle(pDevExt, pUrbInfo->ep | ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? 0x80 : 0x00));
1244 if (!hPipe)
1245 {
1246 AssertMsgFailed((__FUNCTION__": vboxUsbRtGetPipeHandle failed for endpoint (0x%x)\n", pUrbInfo->ep));
1247 Status = STATUS_INVALID_PARAMETER;
1248 break;
1249 }
1250 }
1251
1252 pMdlBuf = IoAllocateMdl(pUrbInfo->buf, (ULONG)pUrbInfo->len, FALSE, FALSE, NULL);
1253 if (!pMdlBuf)
1254 {
1255 AssertMsgFailed((__FUNCTION__": IoAllocateMdl failed for buffer (0x%p) length (%d)\n", pUrbInfo->buf, pUrbInfo->len));
1256 Status = STATUS_INSUFFICIENT_RESOURCES;
1257 break;
1258 }
1259
1260 __try
1261 {
1262 MmProbeAndLockPages(pMdlBuf, KernelMode, IoModifyAccess);
1263 }
1264 __except(EXCEPTION_EXECUTE_HANDLER)
1265 {
1266 Status = GetExceptionCode();
1267 IoFreeMdl(pMdlBuf);
1268 pMdlBuf = NULL;
1269 AssertMsgFailed((__FUNCTION__": Exception Code (0x%x)\n", Status));
1270 break;
1271 }
1272
1273 /* For some reason, passing a MDL in the URB does not work reliably. Notably
1274 * the iPhone when used with iTunes fails.
1275 */
1276 PVOID pBuffer = MmGetSystemAddressForMdlSafe(pMdlBuf, NormalPagePriority);
1277 if (!pBuffer)
1278 {
1279 AssertMsgFailed((__FUNCTION__": MmGetSystemAddressForMdlSafe failed\n"));
1280 Status = STATUS_INSUFFICIENT_RESOURCES;
1281 break;
1282 }
1283
1284 switch (pUrbInfo->type)
1285 {
1286 case USBSUP_TRANSFER_TYPE_MSG:
1287 {
1288 pUrb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
1289 pUrb->UrbHeader.Length = sizeof (struct _URB_CONTROL_TRANSFER);
1290 pUrb->UrbControlTransfer.PipeHandle = hPipe;
1291 pUrb->UrbControlTransfer.TransferBufferLength = (ULONG)pUrbInfo->len;
1292 pUrb->UrbControlTransfer.TransferFlags = ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT);
1293 pUrb->UrbControlTransfer.UrbLink = 0;
1294
1295 if (!hPipe)
1296 pUrb->UrbControlTransfer.TransferFlags |= USBD_DEFAULT_PIPE_TRANSFER;
1297
1298 /* QUSB_TRANSFER_TYPE_MSG is a control transfer, but it is special
1299 * the first 8 bytes of the buffer is the setup packet so the real
1300 * data length is therefore pUrb->len - 8
1301 */
1302 PVBOXUSB_SETUP pSetup = (PVBOXUSB_SETUP)pUrb->UrbControlTransfer.SetupPacket;
1303 memcpy(pUrb->UrbControlTransfer.SetupPacket, pBuffer, min(sizeof (pUrb->UrbControlTransfer.SetupPacket), pUrbInfo->len));
1304
1305 if (pUrb->UrbControlTransfer.TransferBufferLength <= sizeof (pUrb->UrbControlTransfer.SetupPacket))
1306 pUrb->UrbControlTransfer.TransferBufferLength = 0;
1307 else
1308 pUrb->UrbControlTransfer.TransferBufferLength -= sizeof (pUrb->UrbControlTransfer.SetupPacket);
1309
1310 pUrb->UrbControlTransfer.TransferBuffer = (uint8_t *)pBuffer + sizeof(pUrb->UrbControlTransfer.SetupPacket);
1311 pUrb->UrbControlTransfer.TransferBufferMDL = 0;
1312 pUrb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
1313 break;
1314 }
1315 case USBSUP_TRANSFER_TYPE_ISOC:
1316 {
1317 Assert(hPipe);
1318 VBOXUSB_PIPE_INFO *pPipeInfo = vboxUsbRtGetPipeInfo(pDevExt, pUrbInfo->ep | ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? 0x80 : 0x00));
1319 if (pPipeInfo == NULL)
1320 {
1321 /* Can happen if the isoc request comes in too early or late. */
1322 AssertMsgFailed((__FUNCTION__": pPipeInfo not found\n"));
1323 Status = STATUS_INVALID_PARAMETER;
1324 break;
1325 }
1326
1327 pUrb->UrbHeader.Function = URB_FUNCTION_ISOCH_TRANSFER;
1328 pUrb->UrbHeader.Length = (USHORT)cbUrb;
1329 pUrb->UrbIsochronousTransfer.PipeHandle = hPipe;
1330 pUrb->UrbIsochronousTransfer.TransferBufferLength = (ULONG)pUrbInfo->len;
1331 pUrb->UrbIsochronousTransfer.TransferBufferMDL = 0;
1332 pUrb->UrbIsochronousTransfer.TransferBuffer = pBuffer;
1333 pUrb->UrbIsochronousTransfer.TransferFlags = ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT);
1334 pUrb->UrbIsochronousTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; // May be implied already
1335 pUrb->UrbIsochronousTransfer.NumberOfPackets = pUrbInfo->numIsoPkts;
1336 pUrb->UrbIsochronousTransfer.ErrorCount = 0;
1337 pUrb->UrbIsochronousTransfer.UrbLink = 0;
1338
1339 Assert(pUrbInfo->numIsoPkts == pUrb->UrbIsochronousTransfer.NumberOfPackets);
1340 for (ULONG i = 0; i < pUrbInfo->numIsoPkts; ++i)
1341 {
1342 pUrb->UrbIsochronousTransfer.IsoPacket[i].Offset = pUrbInfo->aIsoPkts[i].off;
1343 pUrb->UrbIsochronousTransfer.IsoPacket[i].Length = pUrbInfo->aIsoPkts[i].cb;
1344 }
1345
1346 /* We have to schedule the URBs ourselves. There is an ASAP flag but
1347 * that can only be reliably used after pipe creation/reset, ie. it's
1348 * almost completely useless.
1349 */
1350 ULONG iFrame, iStartFrame;
1351 VBoxUsbToolCurrentFrame(pDevExt->pLowerDO, pIrp, &iFrame);
1352 iFrame += 2;
1353 iStartFrame = pPipeInfo->NextScheduledFrame;
1354 if ((iFrame < iStartFrame) || (iStartFrame > iFrame + 512))
1355 iFrame = iStartFrame;
1356 /* For full-speed devices, there must be one transfer per frame (Windows USB
1357 * stack requirement), but URBs can contain multiple packets. For high-speed or
1358 * faster transfers, we expect one URB per frame, regardless of the interval.
1359 */
1360 if (pDevExt->Rt.devdescr->bcdUSB < 0x300 && !pDevExt->Rt.fIsHighSpeed)
1361 pPipeInfo->NextScheduledFrame = iFrame + pUrbInfo->numIsoPkts;
1362 else
1363 pPipeInfo->NextScheduledFrame = iFrame + 1;
1364 pUrb->UrbIsochronousTransfer.StartFrame = iFrame;
1365 break;
1366 }
1367 case USBSUP_TRANSFER_TYPE_BULK:
1368 case USBSUP_TRANSFER_TYPE_INTR:
1369 {
1370 Assert(pUrbInfo->dir != USBSUP_DIRECTION_SETUP);
1371 Assert(pUrbInfo->dir == USBSUP_DIRECTION_IN || pUrbInfo->type == USBSUP_TRANSFER_TYPE_BULK);
1372 Assert(hPipe);
1373
1374 pUrb->UrbHeader.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
1375 pUrb->UrbHeader.Length = sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER);
1376 pUrb->UrbBulkOrInterruptTransfer.PipeHandle = hPipe;
1377 pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (ULONG)pUrbInfo->len;
1378 pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = 0;
1379 pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pBuffer;
1380 pUrb->UrbBulkOrInterruptTransfer.TransferFlags = ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT);
1381
1382 if (pUrb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1383 pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= (USBD_SHORT_TRANSFER_OK);
1384
1385 pUrb->UrbBulkOrInterruptTransfer.UrbLink = 0;
1386 break;
1387 }
1388 default:
1389 {
1390 AssertFailed();
1391 Status = STATUS_INVALID_PARAMETER;
1392 break;
1393 }
1394 }
1395
1396 if (!NT_SUCCESS(Status))
1397 {
1398 break;
1399 }
1400
1401 pContext->pDevExt = pDevExt;
1402 pContext->pMdlBuf = pMdlBuf;
1403 pContext->pUrb = pUrb;
1404 pContext->pOut = pUrbInfo;
1405 pContext->ulTransferType = pUrbInfo->type;
1406 pContext->ulMagic = VBOXUSB_MAGIC;
1407
1408 PIO_STACK_LOCATION pSl = IoGetNextIrpStackLocation(pIrp);
1409 pSl->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1410 pSl->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1411 pSl->Parameters.Others.Argument1 = pUrb;
1412 pSl->Parameters.Others.Argument2 = NULL;
1413
1414 IoSetCompletionRoutine(pIrp, vboxUsbRtUrbSendCompletion, pContext, TRUE, TRUE, TRUE);
1415 IoMarkIrpPending(pIrp);
1416 Status = IoCallDriver(pDevExt->pLowerDO, pIrp);
1417 AssertMsg(NT_SUCCESS(Status), (__FUNCTION__": IoCallDriver failed Status (0x%x)\n", Status));
1418 return STATUS_PENDING;
1419 } while (0);
1420
1421 Assert(!NT_SUCCESS(Status));
1422
1423 if (pMdlBuf)
1424 {
1425 MmUnlockPages(pMdlBuf);
1426 IoFreeMdl(pMdlBuf);
1427 }
1428
1429 if (pContext)
1430 vboxUsbMemFree(pContext);
1431
1432 VBoxDrvToolIoComplete(pIrp, Status, 0);
1433 vboxUsbDdiStateRelease(pDevExt);
1434 return Status;
1435}
1436
1437static NTSTATUS vboxUsbRtDispatchSendUrb(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1438{
1439 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1440 PFILE_OBJECT pFObj = pSl->FileObject;
1441 PUSBSUP_URB pUrbInfo = (PUSBSUP_URB)pIrp->AssociatedIrp.SystemBuffer;
1442 NTSTATUS Status;
1443
1444 do
1445 {
1446 if (!pFObj)
1447 {
1448 AssertFailed();
1449 Status = STATUS_INVALID_PARAMETER;
1450 break;
1451 }
1452
1453 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
1454 {
1455 AssertFailed();
1456 Status = STATUS_ACCESS_DENIED;
1457 break;
1458 }
1459
1460 if ( !pUrbInfo
1461 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pUrbInfo)
1462 || pSl->Parameters.DeviceIoControl.OutputBufferLength != sizeof (*pUrbInfo))
1463 {
1464 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
1465 Status = STATUS_INVALID_PARAMETER;
1466 break;
1467 }
1468 return vboxUsbRtUrbSend(pDevExt, pIrp, pUrbInfo);
1469 } while (0);
1470
1471 Assert(Status != STATUS_PENDING);
1472 VBoxDrvToolIoComplete(pIrp, Status, 0);
1473 vboxUsbDdiStateRelease(pDevExt);
1474 return Status;
1475}
1476
1477static NTSTATUS vboxUsbRtDispatchIsOperational(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1478{
1479 VBoxDrvToolIoComplete(pIrp, STATUS_SUCCESS, 0);
1480 vboxUsbDdiStateRelease(pDevExt);
1481 return STATUS_SUCCESS;
1482}
1483
1484static NTSTATUS vboxUsbRtDispatchGetVersion(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1485{
1486 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1487 PUSBSUP_VERSION pVer= (PUSBSUP_VERSION)pIrp->AssociatedIrp.SystemBuffer;
1488 NTSTATUS Status = STATUS_SUCCESS;
1489
1490 if (pVer && pSl->Parameters.DeviceIoControl.InputBufferLength == 0
1491 && pSl->Parameters.DeviceIoControl.OutputBufferLength == sizeof (*pVer))
1492 {
1493 pVer->u32Major = USBDRV_MAJOR_VERSION;
1494 pVer->u32Minor = USBDRV_MINOR_VERSION;
1495 }
1496 else
1497 {
1498 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
1499 Status = STATUS_INVALID_PARAMETER;
1500 }
1501
1502 Assert(Status != STATUS_PENDING);
1503 VBoxDrvToolIoComplete(pIrp, Status, sizeof (*pVer));
1504 vboxUsbDdiStateRelease(pDevExt);
1505 return Status;
1506}
1507
1508static NTSTATUS vboxUsbRtDispatchDefault(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1509{
1510 VBoxDrvToolIoComplete(pIrp, STATUS_INVALID_DEVICE_REQUEST, 0);
1511 vboxUsbDdiStateRelease(pDevExt);
1512 return STATUS_INVALID_DEVICE_REQUEST;
1513}
1514
1515DECLHIDDEN(NTSTATUS) vboxUsbRtCreate(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1516{
1517 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1518 PFILE_OBJECT pFObj = pSl->FileObject;
1519 if (!pFObj)
1520 {
1521 AssertFailed();
1522 return STATUS_INVALID_PARAMETER;
1523 }
1524
1525 return STATUS_SUCCESS;
1526}
1527
1528DECLHIDDEN(NTSTATUS) vboxUsbRtClose(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1529{
1530 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1531 PFILE_OBJECT pFObj = pSl->FileObject;
1532 Assert(pFObj);
1533
1534 vboxUsbRtCtxReleaseOwner(pDevExt, pFObj);
1535
1536 return STATUS_SUCCESS;
1537}
1538
1539DECLHIDDEN(NTSTATUS) vboxUsbRtDispatch(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1540{
1541 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1542 switch (pSl->Parameters.DeviceIoControl.IoControlCode)
1543 {
1544 case SUPUSB_IOCTL_USB_CLAIM_DEVICE:
1545 {
1546 return vboxUsbRtDispatchClaimDevice(pDevExt, pIrp);
1547 }
1548 case SUPUSB_IOCTL_USB_RELEASE_DEVICE:
1549 {
1550 return vboxUsbRtDispatchReleaseDevice(pDevExt, pIrp);
1551 }
1552 case SUPUSB_IOCTL_GET_DEVICE:
1553 {
1554 return vboxUsbRtDispatchGetDevice(pDevExt, pIrp);
1555 }
1556 case SUPUSB_IOCTL_USB_RESET:
1557 {
1558 return vboxUsbRtDispatchUsbReset(pDevExt, pIrp);
1559 }
1560 case SUPUSB_IOCTL_USB_SET_CONFIG:
1561 {
1562 return vboxUsbRtDispatchUsbSetConfig(pDevExt, pIrp);
1563 }
1564 case SUPUSB_IOCTL_USB_SELECT_INTERFACE:
1565 {
1566 return vboxUsbRtDispatchUsbSelectInterface(pDevExt, pIrp);
1567 }
1568 case SUPUSB_IOCTL_USB_CLEAR_ENDPOINT:
1569 {
1570 return vboxUsbRtDispatchUsbClearEndpoint(pDevExt, pIrp);
1571 }
1572 case SUPUSB_IOCTL_USB_ABORT_ENDPOINT:
1573 {
1574 return vboxUsbRtDispatchUsbAbortEndpoint(pDevExt, pIrp);
1575 }
1576 case SUPUSB_IOCTL_SEND_URB:
1577 {
1578 return vboxUsbRtDispatchSendUrb(pDevExt, pIrp);
1579 }
1580 case SUPUSB_IOCTL_IS_OPERATIONAL:
1581 {
1582 return vboxUsbRtDispatchIsOperational(pDevExt, pIrp);
1583 }
1584 case SUPUSB_IOCTL_GET_VERSION:
1585 {
1586 return vboxUsbRtDispatchGetVersion(pDevExt, pIrp);
1587 }
1588 default:
1589 {
1590 return vboxUsbRtDispatchDefault(pDevExt, pIrp);
1591 }
1592 }
1593}
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