VirtualBox

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

Last change on this file since 62702 was 62702, checked in by vboxsync, 8 years ago

VBoxUsbRt.cpp: Fixed two uninitialized variables caused by slightly complicated while-break loop. Messing up the state of these is dead easy, so they should be shunned along with gotos. Fixed unused warnings.

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