VirtualBox

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

Last change on this file since 54729 was 54729, checked in by vboxsync, 10 years ago

VBoxUSB: use try/catch to handle possible errors and set the last element to NULL according to the recommendations

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.4 KB
Line 
1/* $Id: VBoxUsbRt.cpp 54729 2015-03-12 05:21:24Z vboxsync $ */
2/** @file
3 * VBox USB R0 runtime
4 */
5/*
6 * Copyright (C) 2011 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 Log((__FUNCTION__": pDevExt (0x%x) Owner(0x%x) acquired\n", pFObj));
55 }
56 else
57 {
58 Log((__FUNCTION__": 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 Log((__FUNCTION__": pDevExt (0x%x) Owner(0x%x) released\n", pFObj));
69 }
70 else
71 {
72 Log((__FUNCTION__": 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 = VBoxUsbToolGetStringDescriptorA(pDevExt->pLowerDO, pDevExt->Rt.szSerial, sizeof (pDevExt->Rt.szSerial), pDr->iSerialNumber, langId, RT_INDEFINITE_WAIT);
449 }
450 else
451 {
452 Status = STATUS_SUCCESS;
453 }
454 }
455 }
456 vboxUsbMemFree(pDr);
457 }
458
459 return Status;
460}
461
462static NTSTATUS vboxUsbRtDispatchGetDevice(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
463{
464 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
465 PUSBSUP_GETDEV pDev = (PUSBSUP_GETDEV)pIrp->AssociatedIrp.SystemBuffer;
466 NTSTATUS Status = STATUS_SUCCESS;
467 ULONG cbOut = 0;
468
469 /* don't check for owner since this request is allowed for non-owners as well */
470
471 if (pDev && pSl->Parameters.DeviceIoControl.InputBufferLength == sizeof (*pDev)
472 && pSl->Parameters.DeviceIoControl.OutputBufferLength == sizeof (*pDev))
473 {
474 Status = VBoxUsbToolGetDeviceSpeed(pDevExt->pLowerDO, &pDevExt->Rt.fIsHighSpeed);
475 if (NT_SUCCESS(Status))
476 {
477 pDev->hDevice = pDevExt->Rt.hMonDev;
478 pDev->fAttached = true;
479 pDev->fHiSpeed = pDevExt->Rt.fIsHighSpeed;
480 cbOut = sizeof (*pDev);
481 }
482 }
483 else
484 {
485 Status = STATUS_INVALID_PARAMETER;
486 }
487
488 Assert(Status != STATUS_PENDING);
489 VBoxDrvToolIoComplete(pIrp, Status, cbOut);
490 vboxUsbDdiStateRelease(pDevExt);
491 return Status;
492}
493
494static NTSTATUS vboxUsbRtDispatchUsbReset(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
495{
496 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
497 PFILE_OBJECT pFObj = pSl->FileObject;
498 PUSBSUP_GETDEV pDev = (PUSBSUP_GETDEV)pIrp->AssociatedIrp.SystemBuffer;
499 NTSTATUS Status = STATUS_SUCCESS;
500
501 do
502 {
503 if (!pFObj)
504 {
505 AssertFailed();
506 Status = STATUS_INVALID_PARAMETER;
507 break;
508 }
509
510 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
511 {
512 AssertFailed();
513 Status = STATUS_ACCESS_DENIED;
514 break;
515 }
516
517 if (pIrp->AssociatedIrp.SystemBuffer
518 || pSl->Parameters.DeviceIoControl.InputBufferLength
519 || pSl->Parameters.DeviceIoControl.OutputBufferLength)
520 {
521 AssertFailed();
522 Status = STATUS_INVALID_PARAMETER;
523 break;
524 }
525
526 Status = VBoxUsbToolIoInternalCtlSendSync(pDevExt->pLowerDO, IOCTL_INTERNAL_USB_RESET_PORT, NULL, NULL);
527 Assert(NT_SUCCESS(Status));
528 } while (0);
529
530 Assert(Status != STATUS_PENDING);
531 VBoxDrvToolIoComplete(pIrp, Status, 0);
532 vboxUsbDdiStateRelease(pDevExt);
533 return Status;
534}
535
536static PUSB_CONFIGURATION_DESCRIPTOR vboxUsbRtFindConfigDesc(PVBOXUSBDEV_EXT pDevExt, uint8_t uConfiguration)
537{
538 PUSB_CONFIGURATION_DESCRIPTOR pCfgDr = NULL;
539
540 for (ULONG i = 0; i < VBOXUSBRT_MAX_CFGS; ++i)
541 {
542 if (pDevExt->Rt.cfgdescr[i])
543 {
544 if (pDevExt->Rt.cfgdescr[i]->bConfigurationValue == uConfiguration)
545 {
546 pCfgDr = pDevExt->Rt.cfgdescr[i];
547 break;
548 }
549 }
550 }
551
552 return pCfgDr;
553}
554
555static NTSTATUS vboxUsbRtSetConfig(PVBOXUSBDEV_EXT pDevExt, uint8_t uConfiguration)
556{
557 PURB pUrb = NULL;
558 NTSTATUS Status = STATUS_SUCCESS;
559 uint32_t i;
560
561 if (!uConfiguration)
562 {
563 pUrb = VBoxUsbToolUrbAllocZ(URB_FUNCTION_SELECT_CONFIGURATION, sizeof (struct _URB_SELECT_CONFIGURATION));
564 if(!pUrb)
565 {
566 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbAlloc failed\n"));
567 return STATUS_INSUFFICIENT_RESOURCES;
568 }
569
570 vboxUsbRtFreeInterfaces(pDevExt, TRUE);
571
572 pUrb->UrbSelectConfiguration.ConfigurationDescriptor = NULL;
573
574 Status = VBoxUsbToolUrbPost(pDevExt->pLowerDO, pUrb, RT_INDEFINITE_WAIT);
575 if(NT_SUCCESS(Status) && USBD_SUCCESS(pUrb->UrbHeader.Status))
576 {
577 pDevExt->Rt.hConfiguration = pUrb->UrbSelectConfiguration.ConfigurationHandle;
578 pDevExt->Rt.uConfigValue = uConfiguration;
579 }
580 else
581 {
582 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbPost failed Status (0x%x), usb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
583 }
584
585 VBoxUsbToolUrbFree(pUrb);
586
587 return Status;
588 }
589
590 PUSB_CONFIGURATION_DESCRIPTOR pCfgDr = vboxUsbRtFindConfigDesc(pDevExt, uConfiguration);
591 if (!pCfgDr)
592 {
593 AssertMsgFailed((__FUNCTION__": VBoxUSBFindConfigDesc did not find cfg (%d)\n", uConfiguration));
594 return STATUS_INVALID_PARAMETER;
595 }
596
597 PUSBD_INTERFACE_LIST_ENTRY pIfLe = (PUSBD_INTERFACE_LIST_ENTRY)vboxUsbMemAllocZ((pCfgDr->bNumInterfaces + 1) * sizeof(USBD_INTERFACE_LIST_ENTRY));
598 if (!pIfLe)
599 {
600 AssertMsgFailed((__FUNCTION__": vboxUsbMemAllocZ for pIfLe failed\n"));
601 return STATUS_INSUFFICIENT_RESOURCES;
602 }
603
604 for (i = 0; i < pCfgDr->bNumInterfaces; i++)
605 {
606 pIfLe[i].InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(pCfgDr, pCfgDr, i, 0, -1, -1, -1);
607 pIfLe[i].Interface = NULL;
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 uint32_t uTotalIfaceInfoLength = sizeof (struct _URB_SELECT_INTERFACE) + ((pIfLe[i].Interface->NumberOfPipes > 0) ? (pIfLe[i].Interface->NumberOfPipes - 1) : 0) * sizeof(USBD_PIPE_INFORMATION);
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 *pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo = *pIfLe[i].Interface;
662
663 // AM try/catch for handle citrix case with wrong data from device.
664 __try
665 {
666 for (ULONG j = 0; j < pIfLe[i].Interface->NumberOfPipes; j++)
667 {
668 pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j] = pIfLe[i].Interface->Pipes[j];
669 pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j].EndpointAddress = pIfLe[i].Interface->Pipes[j].EndpointAddress;
670 pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j].NextScheduledFrame = 0;
671 }
672 }
673 __except (EXCEPTION_EXECUTE_HANDLER)
674 {
675 Status = GetExceptionCode();
676 break;
677 }
678 }
679
680// if (NT_SUCCESS(Status))
681// {
682//
683// }
684 }
685 else
686 {
687 AssertMsgFailed((__FUNCTION__": vboxUsbMemAllocZ failed\n"));
688 Status = STATUS_NO_MEMORY;
689 }
690 }
691 else
692 {
693 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbPost failed Status (0x%x), usb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
694 }
695 ExFreePool(pUrb);
696 }
697 else
698 {
699 AssertMsgFailed((__FUNCTION__": USBD_CreateConfigurationRequestEx failed\n"));
700 Status = STATUS_INSUFFICIENT_RESOURCES;
701 }
702 }
703
704 vboxUsbMemFree(pIfLe);
705
706 return Status;
707}
708
709static NTSTATUS vboxUsbRtDispatchUsbSetConfig(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
710{
711 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
712 PFILE_OBJECT pFObj = pSl->FileObject;
713 PUSBSUP_SET_CONFIG pCfg = (PUSBSUP_SET_CONFIG)pIrp->AssociatedIrp.SystemBuffer;
714 NTSTATUS Status = STATUS_SUCCESS;
715
716 do
717 {
718 if (!pFObj)
719 {
720 AssertFailed();
721 Status = STATUS_INVALID_PARAMETER;
722 break;
723 }
724
725 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
726 {
727 AssertFailed();
728 Status = STATUS_ACCESS_DENIED;
729 break;
730 }
731
732 if ( !pCfg
733 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pCfg)
734 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
735 {
736 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
737 Status = STATUS_INVALID_PARAMETER;
738 break;
739 }
740
741 Status = vboxUsbRtSetConfig(pDevExt, pCfg->bConfigurationValue);
742 } while (0);
743
744 Assert(Status != STATUS_PENDING);
745 VBoxDrvToolIoComplete(pIrp, Status, 0);
746 vboxUsbDdiStateRelease(pDevExt);
747 return Status;
748}
749
750static NTSTATUS vboxUsbRtSetInterface(PVBOXUSBDEV_EXT pDevExt, uint32_t InterfaceNumber, int AlternateSetting)
751{
752 if (!pDevExt->Rt.uConfigValue)
753 {
754 AssertMsgFailed((__FUNCTION__": Can't select an interface without an active configuration\n"));
755 return STATUS_INVALID_PARAMETER;
756 }
757
758 if (InterfaceNumber >= pDevExt->Rt.uNumInterfaces)
759 {
760 AssertMsgFailed((__FUNCTION__": InterfaceNumber %d too high!!\n", InterfaceNumber));
761 return STATUS_INVALID_PARAMETER;
762 }
763
764 PUSB_CONFIGURATION_DESCRIPTOR pCfgDr = vboxUsbRtFindConfigDesc(pDevExt, pDevExt->Rt.uConfigValue);
765 if (!pCfgDr)
766 {
767 AssertMsgFailed((__FUNCTION__": configuration %d not found!!\n", pDevExt->Rt.uConfigValue));
768 return STATUS_INVALID_PARAMETER;
769 }
770
771 PUSB_INTERFACE_DESCRIPTOR pIfDr = USBD_ParseConfigurationDescriptorEx(pCfgDr, pCfgDr, InterfaceNumber, AlternateSetting, -1, -1, -1);
772 if (!pIfDr)
773 {
774 AssertMsgFailed((__FUNCTION__": invalid interface %d or alternate setting %d\n", InterfaceNumber, AlternateSetting));
775 return STATUS_UNSUCCESSFUL;
776 }
777
778 USHORT uUrbSize = GET_SELECT_INTERFACE_REQUEST_SIZE(pIfDr->bNumEndpoints);
779 ULONG uTotalIfaceInfoLength = GET_USBD_INTERFACE_SIZE(pIfDr->bNumEndpoints);
780 NTSTATUS Status = STATUS_SUCCESS;
781 PURB pUrb = VBoxUsbToolUrbAllocZ(0, uUrbSize);
782 if (!pUrb)
783 {
784 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbAlloc failed\n"));
785 return STATUS_NO_MEMORY;
786 }
787
788 /*
789 * Free old interface and pipe info, allocate new again
790 */
791 if (pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo)
792 {
793 /* Clear pipes associated with the interface, else Windows may hang. */
794 for(ULONG i = 0; i < pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo->NumberOfPipes; i++)
795 {
796 VBoxUsbToolPipeClear(pDevExt->pLowerDO, pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo->Pipes[i].PipeHandle, FALSE);
797 }
798 vboxUsbMemFree(pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo);
799 }
800
801 if (pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo)
802 {
803 vboxUsbMemFree(pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo);
804 }
805
806 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo = (PUSBD_INTERFACE_INFORMATION)vboxUsbMemAlloc(uTotalIfaceInfoLength);
807 if (pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo)
808 {
809 if (pIfDr->bNumEndpoints > 0)
810 {
811 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo = (VBOXUSB_PIPE_INFO*)vboxUsbMemAlloc(pIfDr->bNumEndpoints * sizeof(VBOXUSB_PIPE_INFO));
812 if (!pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo)
813 {
814 AssertMsgFailed(("VBoxUSBSetInterface: ExAllocatePool failed!\n"));
815 Status = STATUS_NO_MEMORY;
816 }
817 }
818 else
819 {
820 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo = NULL;
821 }
822
823 if (NT_SUCCESS(Status))
824 {
825 UsbBuildSelectInterfaceRequest(pUrb, uUrbSize, pDevExt->Rt.hConfiguration, InterfaceNumber, AlternateSetting);
826 pUrb->UrbSelectInterface.Interface.Length = GET_USBD_INTERFACE_SIZE(pIfDr->bNumEndpoints);
827
828 Status = VBoxUsbToolUrbPost(pDevExt->pLowerDO, pUrb, RT_INDEFINITE_WAIT);
829 if (NT_SUCCESS(Status) && USBD_SUCCESS(pUrb->UrbHeader.Status))
830 {
831 USBD_INTERFACE_INFORMATION *pIfInfo = &pUrb->UrbSelectInterface.Interface;
832 memcpy(pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo, pIfInfo, GET_USBD_INTERFACE_SIZE(pIfDr->bNumEndpoints));
833
834 Assert(pIfInfo->NumberOfPipes == pIfDr->bNumEndpoints);
835 for(ULONG i = 0; i < pIfInfo->NumberOfPipes; i++)
836 {
837 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pInterfaceInfo->Pipes[i] = pIfInfo->Pipes[i];
838 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo[i].EndpointAddress = pIfInfo->Pipes[i].EndpointAddress;
839 pDevExt->Rt.pVBIfaceInfo[InterfaceNumber].pPipeInfo[i].NextScheduledFrame = 0;
840 }
841 }
842 else
843 {
844 AssertMsgFailed((__FUNCTION__": VBoxUsbToolUrbPost failed Status (0x%x) usb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
845 }
846 }
847
848 }
849 else
850 {
851 AssertMsgFailed(("VBoxUSBSetInterface: ExAllocatePool failed!\n"));
852 Status = STATUS_NO_MEMORY;
853 }
854
855 VBoxUsbToolUrbFree(pUrb);
856
857 return Status;
858}
859
860static NTSTATUS vboxUsbRtDispatchUsbSelectInterface(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
861{
862 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
863 PFILE_OBJECT pFObj = pSl->FileObject;
864 PUSBSUP_SELECT_INTERFACE pIf = (PUSBSUP_SELECT_INTERFACE)pIrp->AssociatedIrp.SystemBuffer;
865 NTSTATUS Status;
866
867 do
868 {
869 if (!pFObj)
870 {
871 AssertFailed();
872 Status = STATUS_INVALID_PARAMETER;
873 break;
874 }
875
876 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
877 {
878 AssertFailed();
879 Status = STATUS_ACCESS_DENIED;
880 break;
881 }
882
883 if ( !pIf
884 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pIf)
885 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
886 {
887 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
888 Status = STATUS_INVALID_PARAMETER;
889 break;
890 }
891
892 Status = vboxUsbRtSetInterface(pDevExt, pIf->bInterfaceNumber, pIf->bAlternateSetting);
893 } while (0);
894
895 Assert(Status != STATUS_PENDING);
896 VBoxDrvToolIoComplete(pIrp, Status, 0);
897 vboxUsbDdiStateRelease(pDevExt);
898 return Status;
899}
900
901static HANDLE vboxUsbRtGetPipeHandle(PVBOXUSBDEV_EXT pDevExt, uint32_t EndPointAddress)
902{
903 for (ULONG i = 0; i < pDevExt->Rt.uNumInterfaces; i++)
904 {
905 for (ULONG j = 0; j < pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->NumberOfPipes; j++)
906 {
907 /* Note that bit 7 determines pipe direction, but is still significant
908 * because endpoints may be numbered like 0x01, 0x81, 0x02, 0x82 etc.
909 */
910 if (pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j].EndpointAddress == EndPointAddress)
911 return pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->Pipes[j].PipeHandle;
912 }
913 }
914 return 0;
915}
916
917static VBOXUSB_PIPE_INFO* vboxUsbRtGetPipeInfo(PVBOXUSBDEV_EXT pDevExt, uint32_t EndPointAddress)
918{
919 for (ULONG i = 0; i < pDevExt->Rt.uNumInterfaces; i++)
920 {
921 for (ULONG j = 0; j < pDevExt->Rt.pVBIfaceInfo[i].pInterfaceInfo->NumberOfPipes; j++)
922 {
923 if (pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j].EndpointAddress == EndPointAddress)
924 return &pDevExt->Rt.pVBIfaceInfo[i].pPipeInfo[j];
925 }
926 }
927 return NULL;
928}
929
930
931
932static NTSTATUS vboxUsbRtClearEndpoint(PVBOXUSBDEV_EXT pDevExt, uint32_t EndPointAddress, bool fReset)
933{
934 NTSTATUS Status = VBoxUsbToolPipeClear(pDevExt->pLowerDO, vboxUsbRtGetPipeHandle(pDevExt, EndPointAddress), fReset);
935 if (!NT_SUCCESS(Status))
936 {
937 AssertMsgFailed((__FUNCTION__": VBoxUsbToolPipeClear failed Status (0x%x)\n", Status));
938 }
939
940 return Status;
941}
942
943static NTSTATUS vboxUsbRtDispatchUsbClearEndpoint(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
944{
945 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
946 PFILE_OBJECT pFObj = pSl->FileObject;
947 PUSBSUP_CLEAR_ENDPOINT pCe = (PUSBSUP_CLEAR_ENDPOINT)pIrp->AssociatedIrp.SystemBuffer;
948 NTSTATUS Status;
949
950 do
951 {
952 if (!pFObj)
953 {
954 AssertFailed();
955 Status = STATUS_INVALID_PARAMETER;
956 break;
957 }
958
959 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
960 {
961 AssertFailed();
962 Status = STATUS_ACCESS_DENIED;
963 break;
964 }
965
966 if ( !pCe
967 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pCe)
968 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
969 {
970 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
971 Status = STATUS_INVALID_PARAMETER;
972 break;
973 }
974
975 Status = vboxUsbRtClearEndpoint(pDevExt, pCe->bEndpoint, TRUE);
976 } while (0);
977
978 Assert(Status != STATUS_PENDING);
979 VBoxDrvToolIoComplete(pIrp, Status, 0);
980 vboxUsbDdiStateRelease(pDevExt);
981 return Status;
982}
983
984static NTSTATUS vboxUsbRtDispatchUsbAbortEndpoint(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
985{
986 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
987 PFILE_OBJECT pFObj = pSl->FileObject;
988 PUSBSUP_CLEAR_ENDPOINT pCe = (PUSBSUP_CLEAR_ENDPOINT)pIrp->AssociatedIrp.SystemBuffer;
989 NTSTATUS Status;
990
991 do
992 {
993 if (!pFObj)
994 {
995 AssertFailed();
996 Status = STATUS_INVALID_PARAMETER;
997 break;
998 }
999
1000 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
1001 {
1002 AssertFailed();
1003 Status = STATUS_ACCESS_DENIED;
1004 break;
1005 }
1006
1007 if ( !pCe
1008 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pCe)
1009 || pSl->Parameters.DeviceIoControl.OutputBufferLength != 0)
1010 {
1011 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
1012 Status = STATUS_INVALID_PARAMETER;
1013 break;
1014 }
1015
1016 Status = vboxUsbRtClearEndpoint(pDevExt, pCe->bEndpoint, FALSE);
1017 } while (0);
1018
1019 Assert(Status != STATUS_PENDING);
1020 VBoxDrvToolIoComplete(pIrp, Status, 0);
1021 vboxUsbDdiStateRelease(pDevExt);
1022 return Status;
1023}
1024
1025static NTSTATUS vboxUsbRtUrbSendCompletion(PDEVICE_OBJECT pDevObj, IRP *pIrp, void *pvContext)
1026{
1027 if (!pvContext)
1028 {
1029 AssertMsgFailed((__FUNCTION__": context is NULL\n"));
1030 pIrp->IoStatus.Information = 0;
1031 return STATUS_CONTINUE_COMPLETION;
1032 }
1033
1034 PVBOXUSB_URB_CONTEXT pContext = (PVBOXUSB_URB_CONTEXT)pvContext;
1035
1036 if (pContext->ulMagic != VBOXUSB_MAGIC)
1037 {
1038 AssertMsgFailed((__FUNCTION__": Invalid context magic\n"));
1039 pIrp->IoStatus.Information = 0;
1040 return STATUS_CONTINUE_COMPLETION;
1041 }
1042
1043 PURB pUrb = pContext->pUrb;
1044 PMDL pMdlBuf = pContext->pMdlBuf;
1045 PUSBSUP_URB pUrbInfo = (PUSBSUP_URB)pContext->pOut;
1046 PVBOXUSBDEV_EXT pDevExt = pContext->pDevExt;
1047
1048 if (!pUrb || !pMdlBuf || !pUrbInfo | !pDevExt)
1049 {
1050 AssertMsgFailed((__FUNCTION__": Invalid args\n"));
1051 if (pDevExt)
1052 vboxUsbDdiStateRelease(pDevExt);
1053 pIrp->IoStatus.Information = 0;
1054 return STATUS_CONTINUE_COMPLETION;
1055 }
1056
1057 NTSTATUS Status = pIrp->IoStatus.Status;
1058 if (Status == STATUS_SUCCESS)
1059 {
1060 switch(pUrb->UrbHeader.Status)
1061 {
1062 case USBD_STATUS_CRC:
1063 pUrbInfo->error = USBSUP_XFER_CRC;
1064 break;
1065 case USBD_STATUS_SUCCESS:
1066 pUrbInfo->error = USBSUP_XFER_OK;
1067 break;
1068 case USBD_STATUS_STALL_PID:
1069 pUrbInfo->error = USBSUP_XFER_STALL;
1070 break;
1071 case USBD_STATUS_INVALID_URB_FUNCTION:
1072 case USBD_STATUS_INVALID_PARAMETER:
1073 AssertMsgFailed((__FUNCTION__": sw error, urb Status (0x%x)\n", pUrb->UrbHeader.Status));
1074 case USBD_STATUS_DEV_NOT_RESPONDING:
1075 default:
1076 pUrbInfo->error = USBSUP_XFER_DNR;
1077 break;
1078 }
1079
1080 switch(pContext->ulTransferType)
1081 {
1082 case USBSUP_TRANSFER_TYPE_CTRL:
1083 case USBSUP_TRANSFER_TYPE_MSG:
1084 pUrbInfo->len = pUrb->UrbControlTransfer.TransferBufferLength;
1085 if (pContext->ulTransferType == USBSUP_TRANSFER_TYPE_MSG)
1086 {
1087 /* QUSB_TRANSFER_TYPE_MSG is a control transfer, but it is special
1088 * the first 8 bytes of the buffer is the setup packet so the real
1089 * data length is therefore urb->len - 8
1090 */
1091 pUrbInfo->len += sizeof (pUrb->UrbControlTransfer.SetupPacket);
1092 }
1093 break;
1094 case USBSUP_TRANSFER_TYPE_ISOC:
1095 pUrbInfo->len = pUrb->UrbIsochronousTransfer.TransferBufferLength;
1096 break;
1097 case USBSUP_TRANSFER_TYPE_BULK:
1098 case USBSUP_TRANSFER_TYPE_INTR:
1099 if (pUrbInfo->dir == USBSUP_DIRECTION_IN && pUrbInfo->error == USBSUP_XFER_OK
1100 && !(pUrbInfo->flags & USBSUP_FLAG_SHORT_OK)
1101 && pUrbInfo->len > pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength
1102 )
1103 {
1104 /* If we don't use the USBD_SHORT_TRANSFER_OK flag, the returned buffer lengths are
1105 * wrong for short transfers (always a multiple of max packet size?). So we just figure
1106 * out if this was a data underrun on our own.
1107 */
1108 pUrbInfo->error = USBSUP_XFER_UNDERRUN;
1109 }
1110 pUrbInfo->len = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
1111 break;
1112 default:
1113 break;
1114 }
1115 }
1116 else
1117 {
1118 pUrbInfo->len = 0;
1119
1120 Log((__FUNCTION__": URB failed Status (0x%x) urb Status (0x%x)\n", Status, pUrb->UrbHeader.Status));
1121#ifdef DEBUG
1122 switch(pContext->ulTransferType)
1123 {
1124 case USBSUP_TRANSFER_TYPE_CTRL:
1125 case USBSUP_TRANSFER_TYPE_MSG:
1126 LogRel(("Ctrl/Msg length=%d\n", pUrb->UrbControlTransfer.TransferBufferLength));
1127 break;
1128 case USBSUP_TRANSFER_TYPE_ISOC:
1129 LogRel(("ISOC length=%d\n", pUrb->UrbIsochronousTransfer.TransferBufferLength));
1130 break;
1131 case USBSUP_TRANSFER_TYPE_BULK:
1132 case USBSUP_TRANSFER_TYPE_INTR:
1133 LogRel(("BULK/INTR length=%d\n", pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength));
1134 break;
1135 }
1136#endif
1137 switch(pUrb->UrbHeader.Status)
1138 {
1139 case USBD_STATUS_CRC:
1140 pUrbInfo->error = USBSUP_XFER_CRC;
1141 Status = STATUS_SUCCESS;
1142 break;
1143 case USBD_STATUS_STALL_PID:
1144 pUrbInfo->error = USBSUP_XFER_STALL;
1145 Status = STATUS_SUCCESS;
1146 break;
1147 case USBD_STATUS_DEV_NOT_RESPONDING:
1148 case USBD_STATUS_DEVICE_GONE:
1149 pUrbInfo->error = USBSUP_XFER_DNR;
1150 Status = STATUS_SUCCESS;
1151 break;
1152 case ((USBD_STATUS)0xC0010000L): // USBD_STATUS_CANCELED - too bad usbdi.h and usb.h aren't consistent!
1153 // TODO: What the heck are we really supposed to do here?
1154 pUrbInfo->error = USBSUP_XFER_STALL;
1155 Status = STATUS_SUCCESS;
1156 break;
1157 case USBD_STATUS_BAD_START_FRAME: // This one really shouldn't happen
1158 case USBD_STATUS_ISOCH_REQUEST_FAILED:
1159 pUrbInfo->error = USBSUP_XFER_NAC;
1160 Status = STATUS_SUCCESS;
1161 break;
1162 default:
1163 AssertMsgFailed((__FUNCTION__": err Status (0x%x) (0x%x)\n", Status, pUrb->UrbHeader.Status));
1164 pUrbInfo->error = USBSUP_XFER_DNR;
1165 Status = STATUS_SUCCESS;
1166 break;
1167 }
1168 }
1169 // For isochronous transfers, always update the individual packets
1170 if (pContext->ulTransferType == USBSUP_TRANSFER_TYPE_ISOC)
1171 {
1172 Assert(pUrbInfo->numIsoPkts == pUrb->UrbIsochronousTransfer.NumberOfPackets);
1173 for (ULONG i = 0; i < pUrbInfo->numIsoPkts; ++i)
1174 {
1175 Assert(pUrbInfo->aIsoPkts[i].off == pUrb->UrbIsochronousTransfer.IsoPacket[i].Offset);
1176 pUrbInfo->aIsoPkts[i].cb = (uint16_t)pUrb->UrbIsochronousTransfer.IsoPacket[i].Length;
1177 switch (pUrb->UrbIsochronousTransfer.IsoPacket[i].Status)
1178 {
1179 case USBD_STATUS_SUCCESS:
1180 pUrbInfo->aIsoPkts[i].stat = USBSUP_XFER_OK;
1181 break;
1182 case USBD_STATUS_NOT_ACCESSED:
1183 pUrbInfo->aIsoPkts[i].stat = USBSUP_XFER_NAC;
1184 break;
1185 default:
1186 pUrbInfo->aIsoPkts[i].stat = USBSUP_XFER_STALL;
1187 break;
1188 }
1189 }
1190 }
1191
1192 MmUnlockPages(pMdlBuf);
1193 IoFreeMdl(pMdlBuf);
1194
1195 vboxUsbMemFree(pContext);
1196
1197 vboxUsbDdiStateRelease(pDevExt);
1198
1199 Assert(pIrp->IoStatus.Status != STATUS_IO_TIMEOUT);
1200 pIrp->IoStatus.Information = sizeof(*pUrbInfo);
1201 pIrp->IoStatus.Status = Status;
1202 return STATUS_CONTINUE_COMPLETION;
1203}
1204
1205static NTSTATUS vboxUsbRtUrbSend(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp, PUSBSUP_URB pUrbInfo)
1206{
1207 NTSTATUS Status = STATUS_SUCCESS;
1208 PVBOXUSB_URB_CONTEXT pContext = NULL;
1209 PMDL pMdlBuf = NULL;
1210 ULONG cbUrb;
1211
1212 Assert(pUrbInfo);
1213 if (pUrbInfo->type == USBSUP_TRANSFER_TYPE_ISOC)
1214 {
1215 Assert(pUrbInfo->numIsoPkts <= 8);
1216 cbUrb = GET_ISO_URB_SIZE(pUrbInfo->numIsoPkts);
1217 }
1218 else
1219 cbUrb = sizeof (URB);
1220
1221 do
1222 {
1223 pContext = (PVBOXUSB_URB_CONTEXT)vboxUsbMemAllocZ(cbUrb + sizeof (VBOXUSB_URB_CONTEXT));
1224 if (!pContext)
1225 {
1226 AssertMsgFailed((__FUNCTION__": vboxUsbMemAlloc failed\n"));
1227 Status = STATUS_INSUFFICIENT_RESOURCES;
1228 break;
1229 }
1230
1231 PURB pUrb = (PURB)(pContext + 1);
1232 HANDLE hPipe = NULL;
1233 if (pUrbInfo->ep)
1234 {
1235 hPipe = vboxUsbRtGetPipeHandle(pDevExt, pUrbInfo->ep | ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? 0x80 : 0x00));
1236 if (!hPipe)
1237 {
1238 AssertMsgFailed((__FUNCTION__": vboxUsbRtGetPipeHandle failed for endpoint (0x%x)\n", pUrbInfo->ep));
1239 Status = STATUS_INVALID_PARAMETER;
1240 break;
1241 }
1242 }
1243
1244 pMdlBuf = IoAllocateMdl(pUrbInfo->buf, (ULONG)pUrbInfo->len, FALSE, FALSE, NULL);
1245 if (!pMdlBuf)
1246 {
1247 AssertMsgFailed((__FUNCTION__": IoAllocateMdl failed for buffer (0x%p) length (%d)\n", pUrbInfo->buf, pUrbInfo->len));
1248 Status = STATUS_INSUFFICIENT_RESOURCES;
1249 break;
1250 }
1251
1252 __try
1253 {
1254 MmProbeAndLockPages(pMdlBuf, KernelMode, IoModifyAccess);
1255 }
1256 __except(EXCEPTION_EXECUTE_HANDLER)
1257 {
1258 Status = GetExceptionCode();
1259 IoFreeMdl(pMdlBuf);
1260 pMdlBuf = NULL;
1261 AssertMsgFailed((__FUNCTION__": Exception Code (0x%x)\n", Status));
1262 break;
1263 }
1264
1265 /* For some reason, passing a MDL in the URB does not work reliably. Notably
1266 * the iPhone when used with iTunes fails.
1267 */
1268 PVOID pBuffer = MmGetSystemAddressForMdlSafe(pMdlBuf, NormalPagePriority);
1269 if (!pBuffer)
1270 {
1271 AssertMsgFailed((__FUNCTION__": MmGetSystemAddressForMdlSafe failed\n"));
1272 Status = STATUS_INSUFFICIENT_RESOURCES;
1273 break;
1274 }
1275
1276 switch (pUrbInfo->type)
1277 {
1278 case USBSUP_TRANSFER_TYPE_CTRL:
1279 case USBSUP_TRANSFER_TYPE_MSG:
1280 {
1281 pUrb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
1282 pUrb->UrbHeader.Length = sizeof (struct _URB_CONTROL_TRANSFER);
1283 pUrb->UrbControlTransfer.PipeHandle = hPipe;
1284 pUrb->UrbControlTransfer.TransferBufferLength = (ULONG)pUrbInfo->len;
1285 pUrb->UrbControlTransfer.TransferFlags = ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT);
1286 pUrb->UrbControlTransfer.UrbLink = 0;
1287
1288 if (!hPipe)
1289 pUrb->UrbControlTransfer.TransferFlags |= USBD_DEFAULT_PIPE_TRANSFER;
1290
1291 if (pUrbInfo->type == USBSUP_TRANSFER_TYPE_MSG)
1292 {
1293 /* QUSB_TRANSFER_TYPE_MSG is a control transfer, but it is special
1294 * the first 8 bytes of the buffer is the setup packet so the real
1295 * data length is therefore pUrb->len - 8
1296 */
1297 PVBOXUSB_SETUP pSetup = (PVBOXUSB_SETUP)pUrb->UrbControlTransfer.SetupPacket;
1298 memcpy(pUrb->UrbControlTransfer.SetupPacket, pBuffer, min(sizeof (pUrb->UrbControlTransfer.SetupPacket), pUrbInfo->len));
1299
1300 if (pUrb->UrbControlTransfer.TransferBufferLength <= sizeof (pUrb->UrbControlTransfer.SetupPacket))
1301 pUrb->UrbControlTransfer.TransferBufferLength = 0;
1302 else
1303 pUrb->UrbControlTransfer.TransferBufferLength -= sizeof (pUrb->UrbControlTransfer.SetupPacket);
1304
1305 pUrb->UrbControlTransfer.TransferBuffer = (uint8_t *)pBuffer + sizeof(pUrb->UrbControlTransfer.SetupPacket);
1306 pUrb->UrbControlTransfer.TransferBufferMDL = 0;
1307 pUrb->UrbControlTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
1308 }
1309 else
1310 {
1311 pUrb->UrbControlTransfer.TransferBuffer = 0;
1312 pUrb->UrbControlTransfer.TransferBufferMDL = pMdlBuf;
1313 }
1314 break;
1315 }
1316 case USBSUP_TRANSFER_TYPE_ISOC:
1317 {
1318 Assert(pUrbInfo->dir == USBSUP_DIRECTION_IN || pUrbInfo->type == USBSUP_TRANSFER_TYPE_BULK);
1319 Assert(hPipe);
1320 VBOXUSB_PIPE_INFO *pPipeInfo = vboxUsbRtGetPipeInfo(pDevExt, pUrbInfo->ep | ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? 0x80 : 0x00));
1321 if (pPipeInfo == NULL)
1322 {
1323 /* Can happen if the isoc request comes in too early or late. */
1324 AssertMsgFailed((__FUNCTION__": pPipeInfo not found\n"));
1325 Status = STATUS_INVALID_PARAMETER;
1326 break;
1327 }
1328
1329 pUrb->UrbHeader.Function = URB_FUNCTION_ISOCH_TRANSFER;
1330 pUrb->UrbHeader.Length = (USHORT)cbUrb;
1331 pUrb->UrbIsochronousTransfer.PipeHandle = hPipe;
1332 pUrb->UrbIsochronousTransfer.TransferBufferLength = (ULONG)pUrbInfo->len;
1333 pUrb->UrbIsochronousTransfer.TransferBufferMDL = 0;
1334 pUrb->UrbIsochronousTransfer.TransferBuffer = pBuffer;
1335 pUrb->UrbIsochronousTransfer.TransferFlags = ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT);
1336 pUrb->UrbIsochronousTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; // May be implied already
1337 pUrb->UrbIsochronousTransfer.NumberOfPackets = pUrbInfo->numIsoPkts;
1338 pUrb->UrbIsochronousTransfer.ErrorCount = 0;
1339 pUrb->UrbIsochronousTransfer.UrbLink = 0;
1340
1341 Assert(pUrbInfo->numIsoPkts == pUrb->UrbIsochronousTransfer.NumberOfPackets);
1342 for (ULONG i = 0; i < pUrbInfo->numIsoPkts; ++i)
1343 {
1344 pUrb->UrbIsochronousTransfer.IsoPacket[i].Offset = pUrbInfo->aIsoPkts[i].off;
1345 pUrb->UrbIsochronousTransfer.IsoPacket[i].Length = pUrbInfo->aIsoPkts[i].cb;
1346 }
1347
1348 /* We have to schedule the URBs ourselves. There is an ASAP flag but
1349 * that can only be reliably used after pipe creation/reset, ie. it's
1350 * almost completely useless.
1351 */
1352 ULONG iFrame, iStartFrame;
1353 VBoxUsbToolCurrentFrame(pDevExt->pLowerDO, pIrp, &iFrame);
1354 iFrame += 2;
1355 iStartFrame = pPipeInfo->NextScheduledFrame;
1356 if ((iFrame < iStartFrame) || (iStartFrame > iFrame + 512))
1357 iFrame = iStartFrame;
1358 pPipeInfo->NextScheduledFrame = iFrame + pUrbInfo->numIsoPkts;
1359 pUrb->UrbIsochronousTransfer.StartFrame = iFrame;
1360 break;
1361 }
1362 case USBSUP_TRANSFER_TYPE_BULK:
1363 case USBSUP_TRANSFER_TYPE_INTR:
1364 {
1365 Assert(pUrbInfo->dir != USBSUP_DIRECTION_SETUP);
1366 Assert(pUrbInfo->dir == USBSUP_DIRECTION_IN || pUrbInfo->type == USBSUP_TRANSFER_TYPE_BULK);
1367 Assert(hPipe);
1368
1369 pUrb->UrbHeader.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
1370 pUrb->UrbHeader.Length = sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER);
1371 pUrb->UrbBulkOrInterruptTransfer.PipeHandle = hPipe;
1372 pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (ULONG)pUrbInfo->len;
1373 pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = 0;
1374 pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pBuffer;
1375 pUrb->UrbBulkOrInterruptTransfer.TransferFlags = ((pUrbInfo->dir == USBSUP_DIRECTION_IN) ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT);
1376
1377 if (pUrb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1378 pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= (USBD_SHORT_TRANSFER_OK);
1379
1380 pUrb->UrbBulkOrInterruptTransfer.UrbLink = 0;
1381 break;
1382 }
1383 default:
1384 {
1385 AssertFailed();
1386 Status = STATUS_INVALID_PARAMETER;
1387 break;
1388 }
1389 }
1390
1391 if (!NT_SUCCESS(Status))
1392 {
1393 break;
1394 }
1395
1396 pContext->pDevExt = pDevExt;
1397 pContext->pMdlBuf = pMdlBuf;
1398 pContext->pUrb = pUrb;
1399 pContext->pOut = pUrbInfo;
1400 pContext->ulTransferType = pUrbInfo->type;
1401 pContext->ulMagic = VBOXUSB_MAGIC;
1402
1403 PIO_STACK_LOCATION pSl = IoGetNextIrpStackLocation(pIrp);
1404 pSl->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1405 pSl->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
1406 pSl->Parameters.Others.Argument1 = pUrb;
1407 pSl->Parameters.Others.Argument2 = NULL;
1408
1409 IoSetCompletionRoutine(pIrp, vboxUsbRtUrbSendCompletion, pContext, TRUE, TRUE, TRUE);
1410 IoMarkIrpPending(pIrp);
1411 Status = IoCallDriver(pDevExt->pLowerDO, pIrp);
1412 AssertMsg(NT_SUCCESS(Status), (__FUNCTION__": IoCallDriver failed Status (0x%x)\n", Status));
1413 return STATUS_PENDING;
1414 } while (0);
1415
1416 Assert(!NT_SUCCESS(Status));
1417
1418 if (pMdlBuf)
1419 {
1420 MmUnlockPages(pMdlBuf);
1421 IoFreeMdl(pMdlBuf);
1422 }
1423
1424 if (pContext)
1425 vboxUsbMemFree(pContext);
1426
1427 VBoxDrvToolIoComplete(pIrp, Status, 0);
1428 vboxUsbDdiStateRelease(pDevExt);
1429 return Status;
1430}
1431
1432static NTSTATUS vboxUsbRtDispatchSendUrb(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1433{
1434 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1435 PFILE_OBJECT pFObj = pSl->FileObject;
1436 PUSBSUP_URB pUrbInfo = (PUSBSUP_URB)pIrp->AssociatedIrp.SystemBuffer;
1437 NTSTATUS Status;
1438
1439 do
1440 {
1441 if (!pFObj)
1442 {
1443 AssertFailed();
1444 Status = STATUS_INVALID_PARAMETER;
1445 break;
1446 }
1447
1448 if (!vboxUsbRtCtxIsOwner(pDevExt, pFObj))
1449 {
1450 AssertFailed();
1451 Status = STATUS_ACCESS_DENIED;
1452 break;
1453 }
1454
1455 if ( !pUrbInfo
1456 || pSl->Parameters.DeviceIoControl.InputBufferLength != sizeof (*pUrbInfo)
1457 || pSl->Parameters.DeviceIoControl.OutputBufferLength != sizeof (*pUrbInfo))
1458 {
1459 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
1460 Status = STATUS_INVALID_PARAMETER;
1461 break;
1462 }
1463 return vboxUsbRtUrbSend(pDevExt, pIrp, pUrbInfo);
1464 } while (0);
1465
1466 Assert(Status != STATUS_PENDING);
1467 VBoxDrvToolIoComplete(pIrp, Status, 0);
1468 vboxUsbDdiStateRelease(pDevExt);
1469 return Status;
1470}
1471
1472static NTSTATUS vboxUsbRtDispatchIsOperational(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1473{
1474 VBoxDrvToolIoComplete(pIrp, STATUS_SUCCESS, 0);
1475 vboxUsbDdiStateRelease(pDevExt);
1476 return STATUS_SUCCESS;
1477}
1478
1479static NTSTATUS vboxUsbRtDispatchGetVersion(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1480{
1481 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1482 PUSBSUP_VERSION pVer= (PUSBSUP_VERSION)pIrp->AssociatedIrp.SystemBuffer;
1483 NTSTATUS Status = STATUS_SUCCESS;
1484
1485 if (pVer && pSl->Parameters.DeviceIoControl.InputBufferLength == 0
1486 && pSl->Parameters.DeviceIoControl.OutputBufferLength == sizeof (*pVer))
1487 {
1488 pVer->u32Major = USBDRV_MAJOR_VERSION;
1489 pVer->u32Minor = USBDRV_MINOR_VERSION;
1490 }
1491 else
1492 {
1493 AssertMsgFailed((__FUNCTION__": STATUS_INVALID_PARAMETER\n"));
1494 Status = STATUS_INVALID_PARAMETER;
1495 }
1496
1497 Assert(Status != STATUS_PENDING);
1498 VBoxDrvToolIoComplete(pIrp, Status, sizeof (*pVer));
1499 vboxUsbDdiStateRelease(pDevExt);
1500 return Status;
1501}
1502
1503static NTSTATUS vboxUsbRtDispatchDefault(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1504{
1505 VBoxDrvToolIoComplete(pIrp, STATUS_INVALID_DEVICE_REQUEST, 0);
1506 vboxUsbDdiStateRelease(pDevExt);
1507 return STATUS_INVALID_DEVICE_REQUEST;
1508}
1509
1510DECLHIDDEN(NTSTATUS) vboxUsbRtCreate(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1511{
1512 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1513 PFILE_OBJECT pFObj = pSl->FileObject;
1514 if (!pFObj)
1515 {
1516 AssertFailed();
1517 return STATUS_INVALID_PARAMETER;
1518 }
1519
1520 return STATUS_SUCCESS;
1521}
1522
1523DECLHIDDEN(NTSTATUS) vboxUsbRtClose(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1524{
1525 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1526 PFILE_OBJECT pFObj = pSl->FileObject;
1527 Assert(pFObj);
1528
1529 vboxUsbRtCtxReleaseOwner(pDevExt, pFObj);
1530
1531 return STATUS_SUCCESS;
1532}
1533
1534DECLHIDDEN(NTSTATUS) vboxUsbRtDispatch(PVBOXUSBDEV_EXT pDevExt, PIRP pIrp)
1535{
1536 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
1537 switch (pSl->Parameters.DeviceIoControl.IoControlCode)
1538 {
1539 case SUPUSB_IOCTL_USB_CLAIM_DEVICE:
1540 {
1541 return vboxUsbRtDispatchClaimDevice(pDevExt, pIrp);
1542 }
1543 case SUPUSB_IOCTL_USB_RELEASE_DEVICE:
1544 {
1545 return vboxUsbRtDispatchReleaseDevice(pDevExt, pIrp);
1546 }
1547 case SUPUSB_IOCTL_GET_DEVICE:
1548 {
1549 return vboxUsbRtDispatchGetDevice(pDevExt, pIrp);
1550 }
1551 case SUPUSB_IOCTL_USB_RESET:
1552 {
1553 return vboxUsbRtDispatchUsbReset(pDevExt, pIrp);
1554 }
1555 case SUPUSB_IOCTL_USB_SET_CONFIG:
1556 {
1557 return vboxUsbRtDispatchUsbSetConfig(pDevExt, pIrp);
1558 }
1559 case SUPUSB_IOCTL_USB_SELECT_INTERFACE:
1560 {
1561 return vboxUsbRtDispatchUsbSelectInterface(pDevExt, pIrp);
1562 }
1563 case SUPUSB_IOCTL_USB_CLEAR_ENDPOINT:
1564 {
1565 return vboxUsbRtDispatchUsbClearEndpoint(pDevExt, pIrp);
1566 }
1567 case SUPUSB_IOCTL_USB_ABORT_ENDPOINT:
1568 {
1569 return vboxUsbRtDispatchUsbAbortEndpoint(pDevExt, pIrp);
1570 }
1571 case SUPUSB_IOCTL_SEND_URB:
1572 {
1573 return vboxUsbRtDispatchSendUrb(pDevExt, pIrp);
1574 }
1575 case SUPUSB_IOCTL_IS_OPERATIONAL:
1576 {
1577 return vboxUsbRtDispatchIsOperational(pDevExt, pIrp);
1578 }
1579 case SUPUSB_IOCTL_GET_VERSION:
1580 {
1581 return vboxUsbRtDispatchGetVersion(pDevExt, pIrp);
1582 }
1583 default:
1584 {
1585 return vboxUsbRtDispatchDefault(pDevExt, pIrp);
1586 }
1587 }
1588}
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