1 // Copyright (c) 2004, Antony C. Roberts
2
3 // Use of this file is subject to the terms
4 // described in the LICENSE.TXT file that
5 // accompanies this file.
6 //
7 // Your use of this file indicates your
8 // acceptance of the terms described in
9 // LICENSE.TXT.
10 //
11 // http://www.freebt.net
12
13 #include "stdio.h"
14 #include "fbtusb.h"
15 #include "fbtpnp.h"
16 #include "fbtpwr.h"
17 #include "fbtdev.h"
18 #include "fbtrwr.h"
19 #include "fbtwmi.h"
20
21 #include "fbtusr.h"
22
23 // Handle PNP events
FreeBT_DispatchPnP(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)24 NTSTATUS NTAPI FreeBT_DispatchPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
25 {
26 PIO_STACK_LOCATION irpStack;
27 PDEVICE_EXTENSION deviceExtension;
28 //KEVENT startDeviceEvent;
29 NTSTATUS ntStatus;
30
31 irpStack = IoGetCurrentIrpStackLocation(Irp);
32 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
33
34 // since the device is removed, fail the Irp.
35 if (Removed == deviceExtension->DeviceState)
36 {
37 ntStatus = STATUS_DELETE_PENDING;
38 Irp->IoStatus.Status = ntStatus;
39 Irp->IoStatus.Information = 0;
40 IoCompleteRequest(Irp, IO_NO_INCREMENT);
41 return ntStatus;
42
43 }
44
45 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
46 FreeBT_IoIncrement(deviceExtension);
47 if (irpStack->MinorFunction == IRP_MN_START_DEVICE)
48 {
49 ASSERT(deviceExtension->IdleReqPend == 0);
50
51 }
52
53 else
54 {
55 if (deviceExtension->SSEnable)
56 {
57 CancelSelectSuspend(deviceExtension);
58
59 }
60
61 }
62
63 FreeBT_DbgPrint(3, ("FBTUSB: ///////////////////////////////////////////\n"));
64 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
65 FreeBT_DbgPrint(2, (PnPMinorFunctionString(irpStack->MinorFunction)));
66 switch (irpStack->MinorFunction)
67 {
68 case IRP_MN_START_DEVICE:
69 ntStatus = HandleStartDevice(DeviceObject, Irp);
70 break;
71
72 case IRP_MN_QUERY_STOP_DEVICE:
73 // if we cannot stop the device, we fail the query stop irp
74 ntStatus = CanStopDevice(DeviceObject, Irp);
75 if(NT_SUCCESS(ntStatus))
76 {
77 ntStatus = HandleQueryStopDevice(DeviceObject, Irp);
78 return ntStatus;
79
80 }
81
82 break;
83
84 case IRP_MN_CANCEL_STOP_DEVICE:
85 ntStatus = HandleCancelStopDevice(DeviceObject, Irp);
86 break;
87
88 case IRP_MN_STOP_DEVICE:
89 ntStatus = HandleStopDevice(DeviceObject, Irp);
90 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::IRP_MN_STOP_DEVICE::"));
91 FreeBT_IoDecrement(deviceExtension);
92
93 return ntStatus;
94
95 case IRP_MN_QUERY_REMOVE_DEVICE:
96 // if we cannot remove the device, we fail the query remove irp
97 ntStatus = HandleQueryRemoveDevice(DeviceObject, Irp);
98
99 return ntStatus;
100
101 case IRP_MN_CANCEL_REMOVE_DEVICE:
102 ntStatus = HandleCancelRemoveDevice(DeviceObject, Irp);
103 break;
104
105 case IRP_MN_SURPRISE_REMOVAL:
106 ntStatus = HandleSurpriseRemoval(DeviceObject, Irp);
107 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::IRP_MN_SURPRISE_REMOVAL::"));
108 FreeBT_IoDecrement(deviceExtension);
109 return ntStatus;
110
111 case IRP_MN_REMOVE_DEVICE:
112 ntStatus = HandleRemoveDevice(DeviceObject, Irp);
113 return ntStatus;
114
115 case IRP_MN_QUERY_CAPABILITIES:
116 ntStatus = HandleQueryCapabilities(DeviceObject, Irp);
117 break;
118
119 default:
120 IoSkipCurrentIrpStackLocation(Irp);
121
122 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
123
124 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::default::"));
125 FreeBT_IoDecrement(deviceExtension);
126
127 return ntStatus;
128
129 }
130
131 Irp->IoStatus.Status = ntStatus;
132 Irp->IoStatus.Information = 0;
133 IoCompleteRequest(Irp, IO_NO_INCREMENT);
134
135 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
136 FreeBT_IoDecrement(deviceExtension);
137
138 return ntStatus;
139
140 }
141
HandleStartDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)142 NTSTATUS NTAPI HandleStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
143 {
144 KIRQL oldIrql;
145 KEVENT startDeviceEvent;
146 NTSTATUS ntStatus;
147 PDEVICE_EXTENSION deviceExtension;
148 LARGE_INTEGER dueTime;
149
150 FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Entered\n"));
151
152 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
153 deviceExtension->UsbConfigurationDescriptor = NULL;
154 deviceExtension->UsbInterface = NULL;
155 deviceExtension->PipeContext = NULL;
156
157 // We cannot touch the device (send it any non pnp irps) until a
158 // start device has been passed down to the lower drivers.
159 // first pass the Irp down
160 KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
161 IoCopyCurrentIrpStackLocationToNext(Irp);
162 IoSetCompletionRoutine(Irp,
163 (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
164 (PVOID)&startDeviceEvent,
165 TRUE,
166 TRUE,
167 TRUE);
168
169 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
170 if (ntStatus == STATUS_PENDING)
171 {
172 KeWaitForSingleObject(&startDeviceEvent, Executive, KernelMode, FALSE, NULL);
173 ntStatus = Irp->IoStatus.Status;
174
175 }
176
177 if (!NT_SUCCESS(ntStatus))
178 {
179 FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: Lower drivers failed this Irp (0x%08x)\n", ntStatus));
180 return ntStatus;
181
182 }
183
184 // Read the device descriptor, configuration descriptor
185 // and select the interface descriptors
186 ntStatus = ReadandSelectDescriptors(DeviceObject);
187 if (!NT_SUCCESS(ntStatus))
188 {
189 FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: ReadandSelectDescriptors failed (0x%08x)\n", ntStatus));
190 return ntStatus;
191
192 }
193
194 // enable the symbolic links for system components to open
195 // handles to the device
196 ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, TRUE);
197 if (!NT_SUCCESS(ntStatus))
198 {
199 FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: IoSetDeviceInterfaceState failed (0x%08x)\n", ntStatus));
200 return ntStatus;
201
202 }
203
204 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
205
206 SET_NEW_PNP_STATE(deviceExtension, Working);
207 deviceExtension->QueueState = AllowRequests;
208
209 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
210
211 deviceExtension->FlagWWOutstanding = 0;
212 deviceExtension->FlagWWCancel = 0;
213 deviceExtension->WaitWakeIrp = NULL;
214
215 if (deviceExtension->WaitWakeEnable)
216 {
217 IssueWaitWake(deviceExtension);
218
219 }
220
221 ProcessQueuedRequests(deviceExtension);
222 if (WinXpOrBetter == deviceExtension->WdmVersion)
223 {
224 deviceExtension->SSEnable = deviceExtension->SSRegistryEnable;
225
226 // set timer.for selective suspend requests
227 if (deviceExtension->SSEnable)
228 {
229 dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms
230 KeSetTimerEx(&deviceExtension->Timer, dueTime, IDLE_INTERVAL, &deviceExtension->DeferredProcCall);
231 deviceExtension->FreeIdleIrpCount = 0;
232
233 }
234
235 }
236
237 FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Leaving\n"));
238
239 return ntStatus;
240
241 }
242
243
ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject)244 NTSTATUS NTAPI ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject)
245 {
246 PURB urb;
247 ULONG siz;
248 NTSTATUS ntStatus;
249 PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
250
251 urb = NULL;
252 deviceDescriptor = NULL;
253
254 // 1. Read the device descriptor
255 urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
256 if(urb)
257 {
258 siz = sizeof(USB_DEVICE_DESCRIPTOR);
259 deviceDescriptor = (PUSB_DEVICE_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
260 if (deviceDescriptor)
261 {
262 UsbBuildGetDescriptorRequest(
263 urb,
264 (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
265 USB_DEVICE_DESCRIPTOR_TYPE,
266 0,
267 0,
268 deviceDescriptor,
269 NULL,
270 siz,
271 NULL);
272
273 ntStatus = CallUSBD(DeviceObject, urb);
274 if (NT_SUCCESS(ntStatus))
275 {
276 ASSERT(deviceDescriptor->bNumConfigurations);
277 ntStatus = ConfigureDevice(DeviceObject);
278
279 }
280
281 ExFreePool(urb);
282 ExFreePool(deviceDescriptor);
283
284 }
285
286 else
287 {
288 FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for deviceDescriptor"));
289 ExFreePool(urb);
290 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
291
292 }
293
294 }
295
296 else
297 {
298 FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for urb"));
299 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
300
301 }
302
303
304 return ntStatus;
305
306 }
307
ConfigureDevice(IN PDEVICE_OBJECT DeviceObject)308 NTSTATUS NTAPI ConfigureDevice(IN PDEVICE_OBJECT DeviceObject)
309 {
310 PURB urb;
311 ULONG siz;
312 NTSTATUS ntStatus;
313 PDEVICE_EXTENSION deviceExtension;
314 PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
315
316 urb = NULL;
317 configurationDescriptor = NULL;
318 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
319
320 // Read the first configuration descriptor
321 // This requires two steps:
322 // 1. Read the fixed sized configuration desciptor (CD)
323 // 2. Read the CD with all embedded interface and endpoint descriptors
324 urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
325 if (urb)
326 {
327 siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
328 configurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
329
330 if(configurationDescriptor)
331 {
332 UsbBuildGetDescriptorRequest(
333 urb,
334 (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
335 USB_CONFIGURATION_DESCRIPTOR_TYPE,
336 0,
337 0,
338 configurationDescriptor,
339 NULL,
340 sizeof(USB_CONFIGURATION_DESCRIPTOR),
341 NULL);
342
343 ntStatus = CallUSBD(DeviceObject, urb);
344 if(!NT_SUCCESS(ntStatus))
345 {
346 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: UsbBuildGetDescriptorRequest failed\n"));
347 goto ConfigureDevice_Exit;
348
349 }
350
351 }
352
353 else
354 {
355 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate mem for config Descriptor\n"));
356 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
357 goto ConfigureDevice_Exit;
358
359 }
360
361 siz = configurationDescriptor->wTotalLength;
362 ExFreePool(configurationDescriptor);
363
364 configurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
365 if (configurationDescriptor)
366 {
367 UsbBuildGetDescriptorRequest(
368 urb,
369 (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
370 USB_CONFIGURATION_DESCRIPTOR_TYPE,
371 0,
372 0,
373 configurationDescriptor,
374 NULL,
375 siz,
376 NULL);
377
378 ntStatus = CallUSBD(DeviceObject, urb);
379 if (!NT_SUCCESS(ntStatus))
380 {
381 FreeBT_DbgPrint(1,("FBTUSB: ConfigureDevice: Failed to read configuration descriptor"));
382 goto ConfigureDevice_Exit;
383
384 }
385
386 }
387
388 else
389 {
390 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to alloc mem for config Descriptor\n"));
391 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
392 goto ConfigureDevice_Exit;
393
394 }
395
396 }
397
398 else
399 {
400 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate memory for urb\n"));
401 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
402 goto ConfigureDevice_Exit;
403
404 }
405
406 if (configurationDescriptor)
407 {
408 // save a copy of configurationDescriptor in deviceExtension
409 // remember to free it later.
410 deviceExtension->UsbConfigurationDescriptor = configurationDescriptor;
411
412 if (configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
413 {
414 // this configuration supports remote wakeup
415 deviceExtension->WaitWakeEnable = 1;
416
417 }
418
419 else
420 {
421 deviceExtension->WaitWakeEnable = 0;
422
423 }
424
425 ntStatus = SelectInterfaces(DeviceObject, configurationDescriptor);
426
427 }
428
429 else
430 {
431 deviceExtension->UsbConfigurationDescriptor = NULL;
432
433 }
434
435 ConfigureDevice_Exit:
436 if (urb)
437 {
438 ExFreePool(urb);
439
440 }
441
442 return ntStatus;
443
444 }
445
SelectInterfaces(IN PDEVICE_OBJECT DeviceObject,IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)446 NTSTATUS NTAPI SelectInterfaces(IN PDEVICE_OBJECT DeviceObject, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
447 {
448 LONG numberOfInterfaces, interfaceNumber, interfaceindex;
449 ULONG i;
450 PURB urb;
451 //PUCHAR pInf;
452 NTSTATUS ntStatus;
453 PDEVICE_EXTENSION deviceExtension;
454 PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
455 PUSBD_INTERFACE_LIST_ENTRY interfaceList,
456 tmp;
457 PUSBD_INTERFACE_INFORMATION Interface;
458
459 urb = NULL;
460 Interface = NULL;
461 interfaceDescriptor = NULL;
462 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
463 numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
464 interfaceindex = interfaceNumber = 0;
465
466 // Parse the configuration descriptor for the interface;
467 tmp = interfaceList = (PUSBD_INTERFACE_LIST_ENTRY)
468 ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1));
469
470 if (!tmp)
471 {
472
473 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to allocate mem for interfaceList\n"));
474 return STATUS_INSUFFICIENT_RESOURCES;
475
476 }
477
478
479 FreeBT_DbgPrint(3, ("FBTUSB: -------------\n"));
480 FreeBT_DbgPrint(3, ("FBTUSB: Number of interfaces %d\n", numberOfInterfaces));
481
482 while (interfaceNumber < numberOfInterfaces)
483 {
484 interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
485 ConfigurationDescriptor,
486 ConfigurationDescriptor,
487 interfaceindex,
488 0, -1, -1, -1);
489
490 if (interfaceDescriptor)
491 {
492 interfaceList->InterfaceDescriptor = interfaceDescriptor;
493 interfaceList->Interface = NULL;
494 interfaceList++;
495 interfaceNumber++;
496
497 }
498
499 interfaceindex++;
500
501 }
502
503 interfaceList->InterfaceDescriptor = NULL;
504 interfaceList->Interface = NULL;
505 urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
506
507 if (urb)
508 {
509 Interface = &urb->UrbSelectConfiguration.Interface;
510 for (i=0; i<Interface->NumberOfPipes; i++)
511 {
512 // perform pipe initialization here
513 // set the transfer size and any pipe flags we use
514 // USBD sets the rest of the Interface struct members
515 Interface->Pipes[i].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
516
517 }
518
519 ntStatus = CallUSBD(DeviceObject, urb);
520 if (NT_SUCCESS(ntStatus))
521 {
522 // save a copy of interface information in the device extension.
523 deviceExtension->UsbInterface = (PUSBD_INTERFACE_INFORMATION) ExAllocatePool(NonPagedPool, Interface->Length);
524 if (deviceExtension->UsbInterface)
525 {
526 RtlCopyMemory(deviceExtension->UsbInterface, Interface, Interface->Length);
527
528 }
529
530 else
531 {
532 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
533 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Memory alloc for UsbInterface failed\n"));
534
535 }
536
537 // Dump the interface to the debugger
538 Interface = &urb->UrbSelectConfiguration.Interface;
539
540 FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
541 FreeBT_DbgPrint(3, ("FBTUSB: NumberOfPipes 0x%x\n", Interface->NumberOfPipes));
542 FreeBT_DbgPrint(3, ("FBTUSB: Length 0x%x\n", Interface->Length));
543 FreeBT_DbgPrint(3, ("FBTUSB: Alt Setting 0x%x\n", Interface->AlternateSetting));
544 FreeBT_DbgPrint(3, ("FBTUSB: Interface Number 0x%x\n", Interface->InterfaceNumber));
545 FreeBT_DbgPrint(3, ("FBTUSB: Class, subclass, protocol 0x%x 0x%x 0x%x\n",
546 Interface->Class,
547 Interface->SubClass,
548 Interface->Protocol));
549
550 if (Interface->Class==FREEBT_USB_STDCLASS && Interface->SubClass==FREEBT_USB_STDSUBCLASS &&
551 Interface->Protocol==FREEBT_USB_STDPROTOCOL)
552 {
553 FreeBT_DbgPrint(3, ("FBTUSB: This is a standard USB Bluetooth device\n"));
554
555 }
556
557 else
558 {
559 FreeBT_DbgPrint(3, ("FBTUSB: WARNING: This device does not report itself as a standard USB Bluetooth device\n"));
560
561 }
562
563 // Initialize the PipeContext
564 // Dump the pipe info
565 deviceExtension->PipeContext = (PFREEBT_PIPE_CONTEXT) ExAllocatePool(
566 NonPagedPool,
567 Interface->NumberOfPipes *
568 sizeof(FREEBT_PIPE_CONTEXT));
569
570 if (!deviceExtension->PipeContext)
571 {
572 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
573 FreeBT_DbgPrint(1, ("FBTUSB: Memory alloc for UsbInterface failed\n"));
574
575 }
576
577 else
578 {
579 FreeBT_DbgPrint(3, ("FBTUSB: SelectInterfaces: Allocated PipeContext %p\n", deviceExtension->PipeContext));
580 for (i=0; i<Interface->NumberOfPipes; i++)
581 {
582 deviceExtension->PipeContext[i].PipeOpen = FALSE;
583
584 FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
585 FreeBT_DbgPrint(3, ("FBTUSB: PipeType 0x%x\n", Interface->Pipes[i].PipeType));
586 FreeBT_DbgPrint(3, ("FBTUSB: EndpointAddress 0x%x\n", Interface->Pipes[i].EndpointAddress));
587 FreeBT_DbgPrint(3, ("FBTUSB: MaxPacketSize 0x%x\n", Interface->Pipes[i].MaximumPacketSize));
588 FreeBT_DbgPrint(3, ("FBTUSB: Interval 0x%x\n", Interface->Pipes[i].Interval));
589 FreeBT_DbgPrint(3, ("FBTUSB: Handle 0x%x\n", Interface->Pipes[i].PipeHandle));
590 FreeBT_DbgPrint(3, ("FBTUSB: MaximumTransferSize 0x%x\n", Interface->Pipes[i].MaximumTransferSize));
591
592 // Log the pipes
593 // Note the HCI Command endpoint won't appear here, because the Default Control Pipe
594 // is used for this. The Default Control Pipe is always present at EndPointAddress 0x0
595 switch (Interface->Pipes[i].EndpointAddress)
596 {
597 case FREEBT_STDENDPOINT_HCIEVENT:
598 deviceExtension->PipeContext[i].PipeType=HciEventPipe;
599 deviceExtension->EventPipe=Interface->Pipes[i];
600 FreeBT_DbgPrint(3, ("FBTUSB: HCI Event Endpoint\n"));
601 break;
602
603 case FREEBT_STDENDPOINT_ACLIN:
604 deviceExtension->PipeContext[i].PipeType=AclDataIn;
605 deviceExtension->DataInPipe=Interface->Pipes[i];
606 FreeBT_DbgPrint(3, ("FBTUSB: ACL Data In Endpoint\n"));
607 break;
608
609 case FREEBT_STDENDPOINT_ACLOUT:
610 deviceExtension->PipeContext[i].PipeType=AclDataOut;
611 deviceExtension->DataOutPipe=Interface->Pipes[i];
612 FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
613 break;
614
615 case FREEBT_STDENDPOINT_AUDIOIN:
616 deviceExtension->PipeContext[i].PipeType=SCODataIn;
617 deviceExtension->AudioInPipe=Interface->Pipes[i];
618 FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
619 break;
620
621 case FREEBT_STDENDPOINT_AUDIOOUT:
622 deviceExtension->PipeContext[i].PipeType=SCODataOut;
623 deviceExtension->AudioOutPipe=Interface->Pipes[i];
624 FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
625 break;
626
627 }
628
629 }
630
631 }
632
633 FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
634
635 }
636
637 else
638 {
639 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to select an interface\n"));
640
641 }
642
643 }
644
645 else
646 {
647 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: USBD_CreateConfigurationRequestEx failed\n"));
648 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
649
650 }
651
652 if (tmp)
653 {
654 ExFreePool(tmp);
655
656 }
657
658 if (urb)
659 {
660 ExFreePool(urb);
661
662 }
663
664 return ntStatus;
665 }
666
667
DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject)668 NTSTATUS NTAPI DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject)
669 {
670 PURB urb;
671 ULONG siz;
672 NTSTATUS ntStatus;
673
674 siz = sizeof(struct _URB_SELECT_CONFIGURATION);
675 urb = (PURB) ExAllocatePool(NonPagedPool, siz);
676 if (urb)
677 {
678 UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
679 ntStatus = CallUSBD(DeviceObject, urb);
680 if(!NT_SUCCESS(ntStatus))
681 {
682 FreeBT_DbgPrint(3, ("FBTUSB: DeconfigureDevice: Failed to deconfigure device\n"));
683
684 }
685
686 ExFreePool(urb);
687
688 }
689
690 else
691 {
692 FreeBT_DbgPrint(1, ("FBTUSB: DeconfigureDevice: Failed to allocate urb\n"));
693 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
694
695 }
696
697 return ntStatus;
698
699 }
700
CallUSBD(IN PDEVICE_OBJECT DeviceObject,IN PURB Urb)701 NTSTATUS NTAPI CallUSBD(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb)
702 {
703 PIRP irp;
704 KEVENT event;
705 NTSTATUS ntStatus;
706 IO_STATUS_BLOCK ioStatus;
707 PIO_STACK_LOCATION nextStack;
708 PDEVICE_EXTENSION deviceExtension;
709
710 irp = NULL;
711 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
712
713 KeInitializeEvent(&event, NotificationEvent, FALSE);
714 irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
715 deviceExtension->TopOfStackDeviceObject,
716 NULL,
717 0,
718 NULL,
719 0,
720 TRUE,
721 &event,
722 &ioStatus);
723
724 if (!irp)
725 {
726 FreeBT_DbgPrint(1, ("FBTUSB: CallUSBD: IoBuildDeviceIoControlRequest failed\n"));
727 return STATUS_INSUFFICIENT_RESOURCES;
728
729 }
730
731 nextStack = IoGetNextIrpStackLocation(irp);
732 ASSERT(nextStack != NULL);
733 nextStack->Parameters.Others.Argument1 = Urb;
734
735 FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
736 FreeBT_IoIncrement(deviceExtension);
737
738 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
739 if (ntStatus == STATUS_PENDING)
740 {
741 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
742 ntStatus = ioStatus.Status;
743
744 }
745
746 FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
747 FreeBT_IoDecrement(deviceExtension);
748 return ntStatus;
749
750 }
751
HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)752 NTSTATUS NTAPI HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
753 {
754 KIRQL oldIrql;
755 NTSTATUS ntStatus;
756 PDEVICE_EXTENSION deviceExtension;
757
758 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Entered\n"));
759
760 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
761
762 // If we can stop the device, we need to set the QueueState to
763 // HoldRequests so further requests will be queued.
764 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
765
766 SET_NEW_PNP_STATE(deviceExtension, PendingStop);
767 deviceExtension->QueueState = HoldRequests;
768
769 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
770
771 // wait for the existing ones to be finished.
772 // first, decrement this operation
773 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice::"));
774 FreeBT_IoDecrement(deviceExtension);
775
776 KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
777
778 Irp->IoStatus.Status = STATUS_SUCCESS;
779 Irp->IoStatus.Information = 0;
780
781 IoSkipCurrentIrpStackLocation(Irp);
782
783 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
784
785 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Leaving\n"));
786
787 return ntStatus;
788
789 }
790
HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)791 NTSTATUS NTAPI HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
792 {
793 KIRQL oldIrql;
794 KEVENT event;
795 NTSTATUS ntStatus;
796 PDEVICE_EXTENSION deviceExtension;
797
798 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Entered\n"));
799
800 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
801
802 // Send this IRP down and wait for it to come back.
803 // Set the QueueState flag to AllowRequests,
804 // and process all the previously queued up IRPs.
805
806 // First check to see whether you have received cancel-stop
807 // without first receiving a query-stop. This could happen if someone
808 // above us fails a query-stop and passes down the subsequent
809 // cancel-stop.
810 if(PendingStop == deviceExtension->DeviceState)
811 {
812 KeInitializeEvent(&event, NotificationEvent, FALSE);
813
814 IoCopyCurrentIrpStackLocationToNext(Irp);
815 IoSetCompletionRoutine(Irp,
816 (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
817 (PVOID)&event,
818 TRUE,
819 TRUE,
820 TRUE);
821
822 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
823 if(ntStatus == STATUS_PENDING)
824 {
825 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
826 ntStatus = Irp->IoStatus.Status;
827
828 }
829
830 if(NT_SUCCESS(ntStatus))
831 {
832 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
833
834 RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
835 deviceExtension->QueueState = AllowRequests;
836 ASSERT(deviceExtension->DeviceState == Working);
837
838 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
839
840 ProcessQueuedRequests(deviceExtension);
841
842 }
843
844 }
845
846 else
847 {
848 // spurious Irp
849 ntStatus = STATUS_SUCCESS;
850
851 }
852
853 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Leaving\n"));
854
855 return ntStatus;
856
857 }
858
HandleStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)859 NTSTATUS NTAPI HandleStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
860 {
861 KIRQL oldIrql;
862 NTSTATUS ntStatus;
863 PDEVICE_EXTENSION deviceExtension;
864
865 FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Entered\n"));
866
867 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
868 if(WinXpOrBetter == deviceExtension->WdmVersion)
869 {
870 if(deviceExtension->SSEnable)
871 {
872 // Cancel the timer so that the DPCs are no longer fired.
873 // Thus, we are making judicious usage of our resources.
874 // we do not need DPCs because the device is stopping.
875 // The timers are re-initialized while handling the start
876 // device irp.
877 KeCancelTimer(&deviceExtension->Timer);
878
879 // after the device is stopped, it can be surprise removed.
880 // we set this to 0, so that we do not attempt to cancel
881 // the timer while handling surprise remove or remove irps.
882 // when we get the start device request, this flag will be
883 // reinitialized.
884 deviceExtension->SSEnable = 0;
885
886 // make sure that if a DPC was fired before we called cancel timer,
887 // then the DPC and work-time have run to their completion
888 KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
889
890 // make sure that the selective suspend request has been completed.
891 KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
892
893 }
894
895 }
896
897 // after the stop Irp is sent to the lower driver object,
898 // the driver must not send any more Irps down that touch
899 // the device until another Start has occurred.
900 if (deviceExtension->WaitWakeEnable)
901 {
902 CancelWaitWake(deviceExtension);
903
904 }
905
906 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
907
908 SET_NEW_PNP_STATE(deviceExtension, Stopped);
909
910 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
911
912 // This is the right place to actually give up all the resources used
913 // This might include calls to IoDisconnectInterrupt, MmUnmapIoSpace,
914 // etc.
915 ReleaseMemory(DeviceObject);
916
917 ntStatus = DeconfigureDevice(DeviceObject);
918
919 Irp->IoStatus.Status = ntStatus;
920 Irp->IoStatus.Information = 0;
921
922 IoSkipCurrentIrpStackLocation(Irp);
923 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
924
925 FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Leaving\n"));
926
927 return ntStatus;
928
929 }
930
HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)931 NTSTATUS NTAPI HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
932 {
933 KIRQL oldIrql;
934 NTSTATUS ntStatus;
935 PDEVICE_EXTENSION deviceExtension;
936
937 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Entered\n"));
938
939 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
940
941 // If we can allow removal of the device, we should set the QueueState
942 // to HoldRequests so further requests will be queued. This is required
943 // so that we can process queued up requests in cancel-remove just in
944 // case somebody else in the stack fails the query-remove.
945 ntStatus = CanRemoveDevice(DeviceObject, Irp);
946
947 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
948
949 deviceExtension->QueueState = HoldRequests;
950 SET_NEW_PNP_STATE(deviceExtension, PendingRemove);
951
952 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
953
954 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice::"));
955 FreeBT_IoDecrement(deviceExtension);
956
957 // Wait for all the requests to be completed
958 KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
959
960 Irp->IoStatus.Status = STATUS_SUCCESS;
961 Irp->IoStatus.Information = 0;
962
963 IoSkipCurrentIrpStackLocation(Irp);
964 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
965
966 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Leaving\n"));
967
968 return ntStatus;
969
970 }
971
HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)972 NTSTATUS NTAPI HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
973 {
974 KIRQL oldIrql;
975 KEVENT event;
976 NTSTATUS ntStatus;
977 PDEVICE_EXTENSION deviceExtension;
978
979 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Entered\n"));
980
981 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
982
983 // We need to reset the QueueState flag to ProcessRequest,
984 // since the device resume its normal activities.
985
986 // First check to see whether you have received cancel-remove
987 // without first receiving a query-remove. This could happen if
988 // someone above us fails a query-remove and passes down the
989 // subsequent cancel-remove.
990 if(PendingRemove == deviceExtension->DeviceState)
991 {
992
993 KeInitializeEvent(&event, NotificationEvent, FALSE);
994
995 IoCopyCurrentIrpStackLocationToNext(Irp);
996 IoSetCompletionRoutine(Irp,
997 (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
998 (PVOID)&event,
999 TRUE,
1000 TRUE,
1001 TRUE);
1002
1003 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
1004 if(ntStatus == STATUS_PENDING)
1005 {
1006 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
1007 ntStatus = Irp->IoStatus.Status;
1008
1009 }
1010
1011 if (NT_SUCCESS(ntStatus))
1012 {
1013 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
1014
1015 deviceExtension->QueueState = AllowRequests;
1016 RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
1017
1018 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
1019
1020 // process the queued requests that arrive between
1021 // QUERY_REMOVE and CANCEL_REMOVE
1022 ProcessQueuedRequests(deviceExtension);
1023
1024 }
1025
1026 }
1027
1028 else
1029 {
1030 // spurious cancel-remove
1031 ntStatus = STATUS_SUCCESS;
1032
1033 }
1034
1035 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Leaving\n"));
1036
1037 return ntStatus;
1038
1039 }
1040
HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1041 NTSTATUS NTAPI HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
1042 {
1043 KIRQL oldIrql;
1044 NTSTATUS ntStatus;
1045 PDEVICE_EXTENSION deviceExtension;
1046
1047 FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Entered\n"));
1048
1049 // initialize variables
1050 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1051
1052 // 1. fail pending requests
1053 // 2. return device and memory resources
1054 // 3. disable interfaces
1055 if(deviceExtension->WaitWakeEnable)
1056 {
1057 CancelWaitWake(deviceExtension);
1058
1059 }
1060
1061
1062 if (WinXpOrBetter == deviceExtension->WdmVersion)
1063 {
1064 if (deviceExtension->SSEnable)
1065 {
1066 // Cancel the timer so that the DPCs are no longer fired.
1067 // we do not need DPCs because the device has been surprise
1068 // removed
1069 KeCancelTimer(&deviceExtension->Timer);
1070
1071 deviceExtension->SSEnable = 0;
1072
1073 // make sure that if a DPC was fired before we called cancel timer,
1074 // then the DPC and work-time have run to their completion
1075 KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
1076
1077 // make sure that the selective suspend request has been completed.
1078 KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
1079
1080 }
1081
1082 }
1083
1084 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
1085 deviceExtension->QueueState = FailRequests;
1086 SET_NEW_PNP_STATE(deviceExtension, SurpriseRemoved);
1087 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
1088
1089 ProcessQueuedRequests(deviceExtension);
1090
1091 ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);
1092 if(!NT_SUCCESS(ntStatus))
1093 {
1094 FreeBT_DbgPrint(1, ("FBTUSB: HandleSurpriseRemoval: IoSetDeviceInterfaceState::disable:failed\n"));
1095
1096 }
1097
1098 FreeBT_AbortPipes(DeviceObject);
1099
1100 Irp->IoStatus.Status = STATUS_SUCCESS;
1101 Irp->IoStatus.Information = 0;
1102
1103 IoSkipCurrentIrpStackLocation(Irp);
1104 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
1105
1106 FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Leaving\n"));
1107
1108 return ntStatus;
1109
1110 }
1111
HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1112 NTSTATUS NTAPI HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
1113 {
1114 KIRQL oldIrql;
1115 //KEVENT event;
1116 ULONG requestCount;
1117 NTSTATUS ntStatus;
1118 PDEVICE_EXTENSION deviceExtension;
1119
1120 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Entered\n"));
1121
1122 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1123
1124 // The Plug & Play system has dictated the removal of this device. We
1125 // have no choice but to detach and delete the device object.
1126 // (If we wanted to express an interest in preventing this removal,
1127 // we should have failed the query remove IRP).
1128 if(SurpriseRemoved != deviceExtension->DeviceState)
1129 {
1130
1131 // we are here after QUERY_REMOVE
1132 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
1133 deviceExtension->QueueState = FailRequests;
1134 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
1135
1136 if(deviceExtension->WaitWakeEnable)
1137 {
1138 CancelWaitWake(deviceExtension);
1139
1140 }
1141
1142 if(WinXpOrBetter == deviceExtension->WdmVersion)
1143 {
1144 if (deviceExtension->SSEnable)
1145 {
1146 // Cancel the timer so that the DPCs are no longer fired.
1147 // we do not need DPCs because the device has been removed
1148 KeCancelTimer(&deviceExtension->Timer);
1149
1150 deviceExtension->SSEnable = 0;
1151
1152 // make sure that if a DPC was fired before we called cancel timer,
1153 // then the DPC and work-time have run to their completion
1154 KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
1155
1156 // make sure that the selective suspend request has been completed.
1157 KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
1158
1159 }
1160
1161 }
1162
1163 ProcessQueuedRequests(deviceExtension);
1164
1165 ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);
1166 if(!NT_SUCCESS(ntStatus))
1167 {
1168 FreeBT_DbgPrint(1, ("FBTUSB: HandleRemoveDevice: IoSetDeviceInterfaceState::disable:failed\n"));
1169
1170 }
1171
1172 FreeBT_AbortPipes(DeviceObject);
1173
1174 }
1175
1176 KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
1177 SET_NEW_PNP_STATE(deviceExtension, Removed);
1178 KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
1179 #ifdef ENABLE_WMI
1180 FreeBT_WmiDeRegistration(deviceExtension);
1181 #endif
1182
1183 // Need 2 decrements
1184 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
1185 requestCount = FreeBT_IoDecrement(deviceExtension);
1186
1187 ASSERT(requestCount > 0);
1188
1189 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
1190 requestCount = FreeBT_IoDecrement(deviceExtension);
1191
1192 KeWaitForSingleObject(&deviceExtension->RemoveEvent,
1193 Executive,
1194 KernelMode,
1195 FALSE,
1196 NULL);
1197
1198 ReleaseMemory(DeviceObject);
1199
1200 // We need to send the remove down the stack before we detach,
1201 // but we don't need to wait for the completion of this operation
1202 // (and to register a completion routine).
1203 Irp->IoStatus.Status = STATUS_SUCCESS;
1204 Irp->IoStatus.Information = 0;
1205
1206 IoSkipCurrentIrpStackLocation(Irp);
1207 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
1208
1209 IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
1210 IoDeleteDevice(DeviceObject);
1211
1212 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Leaving\n"));
1213
1214 return ntStatus;
1215
1216 }
1217
HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1218 NTSTATUS NTAPI HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
1219 {
1220 ULONG i;
1221 KEVENT event;
1222 NTSTATUS ntStatus;
1223 PDEVICE_EXTENSION deviceExtension;
1224 PDEVICE_CAPABILITIES pdc;
1225 PIO_STACK_LOCATION irpStack;
1226
1227 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Entered\n"));
1228
1229 irpStack = IoGetCurrentIrpStackLocation(Irp);
1230 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1231 pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
1232
1233 if(pdc->Version < 1 || pdc->Size < sizeof(DEVICE_CAPABILITIES))
1234 {
1235
1236 FreeBT_DbgPrint(1, ("FBTUSB: HandleQueryCapabilities::request failed\n"));
1237 ntStatus = STATUS_UNSUCCESSFUL;
1238 return ntStatus;
1239
1240 }
1241
1242 // Add in the SurpriseRemovalOK bit before passing it down.
1243 pdc->SurpriseRemovalOK = TRUE;
1244 Irp->IoStatus.Status = STATUS_SUCCESS;
1245
1246 KeInitializeEvent(&event, NotificationEvent, FALSE);
1247
1248 IoCopyCurrentIrpStackLocationToNext(Irp);
1249 IoSetCompletionRoutine(Irp,
1250 (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
1251 (PVOID)&event,
1252 TRUE,
1253 TRUE,
1254 TRUE);
1255 ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
1256 if(ntStatus == STATUS_PENDING)
1257 {
1258 KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
1259 ntStatus = Irp->IoStatus.Status;
1260
1261 }
1262
1263 // initialize PowerDownLevel to disabled
1264 deviceExtension->PowerDownLevel = PowerDeviceUnspecified;
1265 if(NT_SUCCESS(ntStatus))
1266 {
1267 deviceExtension->DeviceCapabilities = *pdc;
1268 for(i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++)
1269 {
1270 if(deviceExtension->DeviceCapabilities.DeviceState[i] < PowerDeviceD3)
1271 {
1272 deviceExtension->PowerDownLevel = deviceExtension->DeviceCapabilities.DeviceState[i];
1273
1274 }
1275
1276 }
1277
1278 // since its safe to surprise-remove this device, we shall
1279 // set the SurpriseRemoveOK flag to supress any dialog to
1280 // user.
1281 pdc->SurpriseRemovalOK = 1;
1282
1283 }
1284
1285 if(deviceExtension->PowerDownLevel == PowerDeviceUnspecified ||
1286 deviceExtension->PowerDownLevel <= PowerDeviceD0)
1287 {
1288 deviceExtension->PowerDownLevel = PowerDeviceD2;
1289
1290 }
1291
1292 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Leaving\n"));
1293
1294 return ntStatus;
1295 }
1296
1297
DpcRoutine(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)1298 VOID NTAPI DpcRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
1299 /*++
1300
1301 DPC routine triggered by the timer to check the idle state
1302 of the device and submit an idle request for the device.
1303
1304 --*/
1305 {
1306 NTSTATUS ntStatus;
1307 PDEVICE_OBJECT deviceObject;
1308 PDEVICE_EXTENSION deviceExtension;
1309 PIO_WORKITEM item;
1310
1311 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Entered\n"));
1312
1313 deviceObject = (PDEVICE_OBJECT)DeferredContext;
1314 deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
1315
1316 // Clear this event since a DPC has been fired!
1317 KeClearEvent(&deviceExtension->NoDpcWorkItemPendingEvent);
1318
1319 if(CanDeviceSuspend(deviceExtension))
1320 {
1321 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Device is Idle\n"));
1322 item = IoAllocateWorkItem(deviceObject);
1323
1324 if (item)
1325 {
1326 IoQueueWorkItem(item, IdleRequestWorkerRoutine, DelayedWorkQueue, item);
1327 ntStatus = STATUS_PENDING;
1328
1329 }
1330
1331 else
1332 {
1333 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Cannot alloc memory for work item\n"));
1334 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1335 KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
1336
1337 }
1338
1339 }
1340
1341 else
1342 {
1343 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Idle event not signaled\n"));
1344 KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
1345
1346 }
1347
1348 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Leaving\n"));
1349 }
1350
1351
IdleRequestWorkerRoutine(IN PDEVICE_OBJECT DeviceObject,IN PVOID Context)1352 VOID NTAPI IdleRequestWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
1353 {
1354 //PIRP irp;
1355 NTSTATUS ntStatus;
1356 PDEVICE_EXTENSION deviceExtension;
1357 PIO_WORKITEM workItem;
1358
1359 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Entered\n"));
1360
1361 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1362 workItem = (PIO_WORKITEM) Context;
1363
1364 if(CanDeviceSuspend(deviceExtension))
1365 {
1366 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is idle\n"));
1367 ntStatus = SubmitIdleRequestIrp(deviceExtension);
1368 if(!NT_SUCCESS(ntStatus))
1369 {
1370 FreeBT_DbgPrint(1, ("FBTUSB: IdleRequestWorkerRoutine: SubmitIdleRequestIrp failed\n"));
1371
1372 }
1373
1374 }
1375
1376 else
1377 {
1378 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is not idle\n"));
1379
1380 }
1381
1382 IoFreeWorkItem(workItem);
1383
1384 KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
1385
1386 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestsWorkerRoutine: Leaving\n"));
1387
1388 }
1389
1390
ProcessQueuedRequests(IN OUT PDEVICE_EXTENSION DeviceExtension)1391 VOID NTAPI ProcessQueuedRequests(IN OUT PDEVICE_EXTENSION DeviceExtension)
1392 /*++
1393
1394 Routine Description:
1395
1396 Remove and process the entries in the queue. If this routine is called
1397 when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
1398 or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
1399 If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
1400 are complete with STATUS_DELETE_PENDING
1401
1402 Arguments:
1403
1404 DeviceExtension - pointer to device extension
1405
1406 Return Value:
1407
1408 None
1409
1410 --*/
1411 {
1412 KIRQL oldIrql;
1413 PIRP nextIrp,
1414 cancelledIrp;
1415 PVOID cancelRoutine;
1416 LIST_ENTRY cancelledIrpList;
1417 PLIST_ENTRY listEntry;
1418
1419 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Entered\n"));
1420
1421 cancelRoutine = NULL;
1422 InitializeListHead(&cancelledIrpList);
1423
1424 // 1. dequeue the entries in the queue
1425 // 2. reset the cancel routine
1426 // 3. process them
1427 // 3a. if the device is active, send them down
1428 // 3b. else complete with STATUS_DELETE_PENDING
1429 while(1)
1430 {
1431 KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
1432 if(IsListEmpty(&DeviceExtension->NewRequestsQueue))
1433 {
1434 KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
1435 break;
1436
1437 }
1438
1439 listEntry = RemoveHeadList(&DeviceExtension->NewRequestsQueue);
1440 nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
1441
1442 cancelRoutine = IoSetCancelRoutine(nextIrp, NULL);
1443
1444 // check if its already cancelled
1445 if (nextIrp->Cancel)
1446 {
1447 if(cancelRoutine)
1448 {
1449 // the cancel routine for this IRP hasnt been called yet
1450 // so queue the IRP in the cancelledIrp list and complete
1451 // after releasing the lock
1452 InsertTailList(&cancelledIrpList, listEntry);
1453
1454 }
1455
1456 else
1457 {
1458 // the cancel routine has run
1459 // it must be waiting to hold the queue lock
1460 // so initialize the IRPs listEntry
1461 InitializeListHead(listEntry);
1462
1463 }
1464
1465 KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
1466
1467 }
1468
1469 else
1470 {
1471 KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
1472 if(FailRequests == DeviceExtension->QueueState)
1473 {
1474 nextIrp->IoStatus.Information = 0;
1475 nextIrp->IoStatus.Status = STATUS_DELETE_PENDING;
1476 IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
1477
1478 }
1479
1480 else
1481 {
1482 //PIO_STACK_LOCATION irpStack;
1483
1484 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
1485 FreeBT_IoIncrement(DeviceExtension);
1486
1487 IoSkipCurrentIrpStackLocation(nextIrp);
1488 IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
1489
1490 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
1491 FreeBT_IoDecrement(DeviceExtension);
1492
1493 }
1494
1495 }
1496
1497 }
1498
1499 while(!IsListEmpty(&cancelledIrpList))
1500 {
1501 PLIST_ENTRY cancelEntry = RemoveHeadList(&cancelledIrpList);
1502
1503 cancelledIrp = CONTAINING_RECORD(cancelEntry, IRP, Tail.Overlay.ListEntry);
1504 cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
1505 cancelledIrp->IoStatus.Information = 0;
1506
1507 IoCompleteRequest(cancelledIrp, IO_NO_INCREMENT);
1508
1509 }
1510
1511 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Leaving\n"));
1512
1513 return;
1514
1515 }
1516
FreeBT_GetRegistryDword(IN PWCHAR RegPath,IN PWCHAR ValueName,IN OUT PULONG Value)1517 NTSTATUS NTAPI FreeBT_GetRegistryDword(IN PWCHAR RegPath, IN PWCHAR ValueName, IN OUT PULONG Value)
1518 {
1519 ULONG defaultData;
1520 WCHAR buffer[MAXIMUM_FILENAME_LENGTH];
1521 NTSTATUS ntStatus;
1522 UNICODE_STRING regPath;
1523 RTL_QUERY_REGISTRY_TABLE paramTable[2];
1524
1525 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Entered\n"));
1526
1527 regPath.Length = 0;
1528 regPath.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
1529 regPath.Buffer = buffer;
1530
1531 RtlZeroMemory(regPath.Buffer, regPath.MaximumLength);
1532 RtlMoveMemory(regPath.Buffer, RegPath, wcslen(RegPath) * sizeof(WCHAR));
1533 RtlZeroMemory(paramTable, sizeof(paramTable));
1534
1535 paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1536 paramTable[0].Name = ValueName;
1537 paramTable[0].EntryContext = Value;
1538 paramTable[0].DefaultType = REG_DWORD;
1539 paramTable[0].DefaultData = &defaultData;
1540 paramTable[0].DefaultLength = sizeof(ULONG);
1541
1542 ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE |
1543 RTL_REGISTRY_OPTIONAL,
1544 regPath.Buffer,
1545 paramTable,
1546 NULL,
1547 NULL);
1548
1549 if (NT_SUCCESS(ntStatus))
1550 {
1551 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Success, Value = %X\n", *Value));
1552 return STATUS_SUCCESS;
1553 }
1554
1555 else
1556 {
1557 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Failed\n"));
1558 *Value = 0;
1559 return STATUS_UNSUCCESSFUL;
1560
1561 }
1562 }
1563
1564
FreeBT_DispatchClean(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1565 NTSTATUS NTAPI FreeBT_DispatchClean(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
1566 {
1567 PDEVICE_EXTENSION deviceExtension;
1568 KIRQL oldIrql;
1569 LIST_ENTRY cleanupList;
1570 PLIST_ENTRY thisEntry,
1571 nextEntry,
1572 listHead;
1573 PIRP pendingIrp;
1574 PIO_STACK_LOCATION pendingIrpStack,
1575 irpStack;
1576 //NTSTATUS ntStatus;
1577
1578 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1579 irpStack = IoGetCurrentIrpStackLocation(Irp);
1580 InitializeListHead(&cleanupList);
1581
1582 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
1583 FreeBT_IoIncrement(deviceExtension);
1584
1585 KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);
1586
1587 listHead = &deviceExtension->NewRequestsQueue;
1588 for(thisEntry = listHead->Flink, nextEntry = thisEntry->Flink;
1589 thisEntry != listHead;
1590 thisEntry = nextEntry, nextEntry = thisEntry->Flink)
1591 {
1592 pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
1593 pendingIrpStack = IoGetCurrentIrpStackLocation(pendingIrp);
1594 if (irpStack->FileObject == pendingIrpStack->FileObject)
1595 {
1596 RemoveEntryList(thisEntry);
1597
1598 if (NULL == IoSetCancelRoutine(pendingIrp, NULL))
1599 {
1600 InitializeListHead(thisEntry);
1601
1602 }
1603
1604 else
1605 {
1606 InsertTailList(&cleanupList, thisEntry);
1607
1608 }
1609
1610 }
1611
1612 }
1613
1614 KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
1615
1616 while(!IsListEmpty(&cleanupList))
1617 {
1618 thisEntry = RemoveHeadList(&cleanupList);
1619 pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
1620
1621 pendingIrp->IoStatus.Information = 0;
1622 pendingIrp->IoStatus.Status = STATUS_CANCELLED;
1623 IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
1624
1625 }
1626
1627 Irp->IoStatus.Information = 0;
1628 Irp->IoStatus.Status = STATUS_SUCCESS;
1629
1630 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1631
1632 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
1633 FreeBT_IoDecrement(deviceExtension);
1634
1635 return STATUS_SUCCESS;
1636
1637 }
1638
1639
CanDeviceSuspend(IN PDEVICE_EXTENSION DeviceExtension)1640 BOOLEAN NTAPI CanDeviceSuspend(IN PDEVICE_EXTENSION DeviceExtension)
1641 {
1642 FreeBT_DbgPrint(3, ("FBTUSB: CanDeviceSuspend: Entered\n"));
1643
1644 if ((DeviceExtension->OpenHandleCount == 0) && (DeviceExtension->OutStandingIO == 1))
1645 return TRUE;
1646
1647 return FALSE;
1648
1649 }
1650
FreeBT_AbortPipes(IN PDEVICE_OBJECT DeviceObject)1651 NTSTATUS NTAPI FreeBT_AbortPipes(IN PDEVICE_OBJECT DeviceObject)
1652 {
1653 PURB urb;
1654 ULONG i;
1655 NTSTATUS ntStatus;
1656 PDEVICE_EXTENSION deviceExtension;
1657 PFREEBT_PIPE_CONTEXT pipeContext;
1658 //PUSBD_PIPE_INFORMATION pipeInformation;
1659 PUSBD_INTERFACE_INFORMATION interfaceInfo;
1660
1661 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1662 pipeContext = deviceExtension->PipeContext;
1663 interfaceInfo = deviceExtension->UsbInterface;
1664
1665 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Entered\n"));
1666
1667 if(interfaceInfo == NULL || pipeContext == NULL)
1668 return STATUS_SUCCESS;
1669
1670 for(i=0; i<interfaceInfo->NumberOfPipes; i++)
1671 {
1672 if(pipeContext[i].PipeOpen)
1673 {
1674 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Aborting open pipe %d\n", i));
1675
1676 urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
1677 if (urb)
1678 {
1679 urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
1680 urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
1681 urb->UrbPipeRequest.PipeHandle = interfaceInfo->Pipes[i].PipeHandle;
1682
1683 ntStatus = CallUSBD(DeviceObject, urb);
1684
1685 ExFreePool(urb);
1686
1687 }
1688
1689 else
1690 {
1691 FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_AbortPipes: Failed to alloc memory for urb\n"));
1692 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1693 return ntStatus;
1694
1695 }
1696
1697 if(NT_SUCCESS(ntStatus))
1698 pipeContext[i].PipeOpen = FALSE;
1699
1700
1701 }
1702
1703 }
1704
1705 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Leaving\n"));
1706
1707 return STATUS_SUCCESS;
1708
1709 }
1710
1711 // Completion routine for PNP IRPs
IrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)1712 NTSTATUS NTAPI IrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
1713 {
1714 PKEVENT event = (PKEVENT) Context;
1715 KeSetEvent(event, 0, FALSE);
1716
1717 return STATUS_MORE_PROCESSING_REQUIRED;
1718
1719 }
1720
1721
FreeBT_IoIncrement(IN OUT PDEVICE_EXTENSION DeviceExtension)1722 LONG NTAPI FreeBT_IoIncrement(IN OUT PDEVICE_EXTENSION DeviceExtension)
1723 {
1724 LONG result = 0;
1725 KIRQL oldIrql;
1726
1727 KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
1728 result = InterlockedIncrement((PLONG)(&DeviceExtension->OutStandingIO));
1729
1730 // When OutStandingIO bumps from 1 to 2, clear the StopEvent
1731 if (result == 2)
1732 KeClearEvent(&DeviceExtension->StopEvent);
1733
1734 KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
1735
1736 FreeBT_DbgPrint(3, ("FreeBT_IoIncrement::%d\n", result));
1737
1738 return result;
1739
1740 }
1741
FreeBT_IoDecrement(IN OUT PDEVICE_EXTENSION DeviceExtension)1742 LONG NTAPI FreeBT_IoDecrement(IN OUT PDEVICE_EXTENSION DeviceExtension)
1743 {
1744 LONG result = 0;
1745 KIRQL oldIrql;
1746
1747 KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
1748
1749 result = InterlockedDecrement((PLONG)(&DeviceExtension->OutStandingIO));
1750
1751 if (result == 1)
1752 KeSetEvent(&DeviceExtension->StopEvent, IO_NO_INCREMENT, FALSE);
1753
1754 if(result == 0)
1755 {
1756 ASSERT(Removed == DeviceExtension->DeviceState);
1757 KeSetEvent(&DeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE);
1758
1759 }
1760
1761 KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
1762
1763 FreeBT_DbgPrint(3, ("FreeBT_IoDecrement::%d\n", result));
1764
1765 return result;
1766
1767 }
1768
CanStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1769 NTSTATUS NTAPI CanStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
1770 {
1771 // For the time being, just allow it to be stopped
1772 UNREFERENCED_PARAMETER(DeviceObject);
1773 UNREFERENCED_PARAMETER(Irp);
1774
1775 return STATUS_SUCCESS;
1776
1777 }
1778
CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1779 NTSTATUS NTAPI CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
1780
1781 {
1782 // For the time being, just allow it to be removed
1783 UNREFERENCED_PARAMETER(DeviceObject);
1784 UNREFERENCED_PARAMETER(Irp);
1785
1786 return STATUS_SUCCESS;
1787
1788 }
1789
ReleaseMemory(IN PDEVICE_OBJECT DeviceObject)1790 NTSTATUS NTAPI ReleaseMemory(IN PDEVICE_OBJECT DeviceObject)
1791 {
1792 // Disconnect from the interrupt and unmap any I/O ports
1793 PDEVICE_EXTENSION deviceExtension;
1794 UNICODE_STRING uniDeviceName;
1795 NTSTATUS ntStatus;
1796
1797 deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
1798 if (deviceExtension->UsbConfigurationDescriptor)
1799 {
1800 FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbConfigurationDescriptor\n"));
1801 ExFreePool(deviceExtension->UsbConfigurationDescriptor);
1802 deviceExtension->UsbConfigurationDescriptor = NULL;
1803
1804 }
1805
1806 if(deviceExtension->UsbInterface)
1807 {
1808 FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbInterface\n"));
1809 ExFreePool(deviceExtension->UsbInterface);
1810 deviceExtension->UsbInterface = NULL;
1811
1812 }
1813
1814 if(deviceExtension->PipeContext)
1815 {
1816 RtlInitUnicodeString(&uniDeviceName, deviceExtension->wszDosDeviceName);
1817 ntStatus = IoDeleteSymbolicLink(&uniDeviceName);
1818 if (!NT_SUCCESS(ntStatus))
1819 FreeBT_DbgPrint(3, ("FBTUSB: Failed to delete symbolic link %ws\n", deviceExtension->wszDosDeviceName));
1820
1821 FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing PipeContext %p\n", deviceExtension->PipeContext));
1822 ExFreePool(deviceExtension->PipeContext);
1823 deviceExtension->PipeContext = NULL;
1824
1825 }
1826
1827 return STATUS_SUCCESS;
1828
1829 }
1830
PnPMinorFunctionString(UCHAR MinorFunction)1831 PCHAR NTAPI PnPMinorFunctionString (UCHAR MinorFunction)
1832 {
1833 switch (MinorFunction)
1834 {
1835 case IRP_MN_START_DEVICE:
1836 return "IRP_MN_START_DEVICE\n";
1837
1838 case IRP_MN_QUERY_REMOVE_DEVICE:
1839 return "IRP_MN_QUERY_REMOVE_DEVICE\n";
1840
1841 case IRP_MN_REMOVE_DEVICE:
1842 return "IRP_MN_REMOVE_DEVICE\n";
1843
1844 case IRP_MN_CANCEL_REMOVE_DEVICE:
1845 return "IRP_MN_CANCEL_REMOVE_DEVICE\n";
1846
1847 case IRP_MN_STOP_DEVICE:
1848 return "IRP_MN_STOP_DEVICE\n";
1849
1850 case IRP_MN_QUERY_STOP_DEVICE:
1851 return "IRP_MN_QUERY_STOP_DEVICE\n";
1852
1853 case IRP_MN_CANCEL_STOP_DEVICE:
1854 return "IRP_MN_CANCEL_STOP_DEVICE\n";
1855
1856 case IRP_MN_QUERY_DEVICE_RELATIONS:
1857 return "IRP_MN_QUERY_DEVICE_RELATIONS\n";
1858
1859 case IRP_MN_QUERY_INTERFACE:
1860 return "IRP_MN_QUERY_INTERFACE\n";
1861
1862 case IRP_MN_QUERY_CAPABILITIES:
1863 return "IRP_MN_QUERY_CAPABILITIES\n";
1864
1865 case IRP_MN_QUERY_RESOURCES:
1866 return "IRP_MN_QUERY_RESOURCES\n";
1867
1868 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1869 return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n";
1870
1871 case IRP_MN_QUERY_DEVICE_TEXT:
1872 return "IRP_MN_QUERY_DEVICE_TEXT\n";
1873
1874 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1875 return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n";
1876
1877 case IRP_MN_READ_CONFIG:
1878 return "IRP_MN_READ_CONFIG\n";
1879
1880 case IRP_MN_WRITE_CONFIG:
1881 return "IRP_MN_WRITE_CONFIG\n";
1882
1883 case IRP_MN_EJECT:
1884 return "IRP_MN_EJECT\n";
1885
1886 case IRP_MN_SET_LOCK:
1887 return "IRP_MN_SET_LOCK\n";
1888
1889 case IRP_MN_QUERY_ID:
1890 return "IRP_MN_QUERY_ID\n";
1891
1892 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1893 return "IRP_MN_QUERY_PNP_DEVICE_STATE\n";
1894
1895 case IRP_MN_QUERY_BUS_INFORMATION:
1896 return "IRP_MN_QUERY_BUS_INFORMATION\n";
1897
1898 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1899 return "IRP_MN_DEVICE_USAGE_NOTIFICATION\n";
1900
1901 case IRP_MN_SURPRISE_REMOVAL:
1902 return "IRP_MN_SURPRISE_REMOVAL\n";
1903
1904 default:
1905 return "IRP_MN_?????\n";
1906
1907 }
1908
1909 }
1910
1911