1 // Copyright (c) 2004, Antony C. Roberts
3 // Use of this file is subject to the terms
4 // described in the LICENSE.TXT file that
5 // accompanies this file.
7 // Your use of this file indicates your
8 // acceptance of the terms described in
11 // http://www.freebt.net
24 NTSTATUS
FreeBT_DispatchPnP(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
26 PIO_STACK_LOCATION irpStack
;
27 PDEVICE_EXTENSION deviceExtension
;
28 KEVENT startDeviceEvent
;
31 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
32 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
34 // since the device is removed, fail the Irp.
35 if (Removed
== deviceExtension
->DeviceState
)
37 ntStatus
= STATUS_DELETE_PENDING
;
38 Irp
->IoStatus
.Status
= ntStatus
;
39 Irp
->IoStatus
.Information
= 0;
40 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
45 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
46 FreeBT_IoIncrement(deviceExtension
);
47 if (irpStack
->MinorFunction
== IRP_MN_START_DEVICE
)
49 ASSERT(deviceExtension
->IdleReqPend
== 0);
55 if (deviceExtension
->SSEnable
)
57 CancelSelectSuspend(deviceExtension
);
63 FreeBT_DbgPrint(3, ("FBTUSB: ///////////////////////////////////////////\n"));
64 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
65 FreeBT_DbgPrint(2, (PnPMinorFunctionString(irpStack
->MinorFunction
)));
66 switch (irpStack
->MinorFunction
)
68 case IRP_MN_START_DEVICE
:
69 ntStatus
= HandleStartDevice(DeviceObject
, Irp
);
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
))
77 ntStatus
= HandleQueryStopDevice(DeviceObject
, Irp
);
84 case IRP_MN_CANCEL_STOP_DEVICE
:
85 ntStatus
= HandleCancelStopDevice(DeviceObject
, Irp
);
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
);
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
);
101 case IRP_MN_CANCEL_REMOVE_DEVICE
:
102 ntStatus
= HandleCancelRemoveDevice(DeviceObject
, Irp
);
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
);
111 case IRP_MN_REMOVE_DEVICE
:
112 ntStatus
= HandleRemoveDevice(DeviceObject
, Irp
);
115 case IRP_MN_QUERY_CAPABILITIES
:
116 ntStatus
= HandleQueryCapabilities(DeviceObject
, Irp
);
120 IoSkipCurrentIrpStackLocation(Irp
);
122 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
124 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::default::"));
125 FreeBT_IoDecrement(deviceExtension
);
131 Irp
->IoStatus
.Status
= ntStatus
;
132 Irp
->IoStatus
.Information
= 0;
133 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
135 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
136 FreeBT_IoDecrement(deviceExtension
);
142 NTSTATUS
HandleStartDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
145 KEVENT startDeviceEvent
;
147 PDEVICE_EXTENSION deviceExtension
;
148 LARGE_INTEGER dueTime
;
150 FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Entered\n"));
152 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
153 deviceExtension
->UsbConfigurationDescriptor
= NULL
;
154 deviceExtension
->UsbInterface
= NULL
;
155 deviceExtension
->PipeContext
= NULL
;
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
,
169 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
170 if (ntStatus
== STATUS_PENDING
)
172 KeWaitForSingleObject(&startDeviceEvent
, Executive
, KernelMode
, FALSE
, NULL
);
173 ntStatus
= Irp
->IoStatus
.Status
;
177 if (!NT_SUCCESS(ntStatus
))
179 FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: Lower drivers failed this Irp (0x%08x)\n", ntStatus
));
184 // Read the device descriptor, configuration descriptor
185 // and select the interface descriptors
186 ntStatus
= ReadandSelectDescriptors(DeviceObject
);
187 if (!NT_SUCCESS(ntStatus
))
189 FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: ReadandSelectDescriptors failed (0x%08x)\n", ntStatus
));
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
))
199 FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: IoSetDeviceInterfaceState failed (0x%08x)\n", ntStatus
));
204 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
206 SET_NEW_PNP_STATE(deviceExtension
, Working
);
207 deviceExtension
->QueueState
= AllowRequests
;
209 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
211 deviceExtension
->FlagWWOutstanding
= 0;
212 deviceExtension
->FlagWWCancel
= 0;
213 deviceExtension
->WaitWakeIrp
= NULL
;
215 if (deviceExtension
->WaitWakeEnable
)
217 IssueWaitWake(deviceExtension
);
221 ProcessQueuedRequests(deviceExtension
);
222 if (WinXpOrBetter
== deviceExtension
->WdmVersion
)
224 deviceExtension
->SSEnable
= deviceExtension
->SSRegistryEnable
;
226 // set timer.for selective suspend requests
227 if (deviceExtension
->SSEnable
)
229 dueTime
.QuadPart
= -10000 * IDLE_INTERVAL
; // 5000 ms
230 KeSetTimerEx(&deviceExtension
->Timer
, dueTime
, IDLE_INTERVAL
, &deviceExtension
->DeferredProcCall
);
231 deviceExtension
->FreeIdleIrpCount
= 0;
237 FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Leaving\n"));
244 NTSTATUS
ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject
)
249 PUSB_DEVICE_DESCRIPTOR deviceDescriptor
;
252 deviceDescriptor
= NULL
;
254 // 1. Read the device descriptor
255 urb
= (PURB
) ExAllocatePool(NonPagedPool
, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
));
258 siz
= sizeof(USB_DEVICE_DESCRIPTOR
);
259 deviceDescriptor
= (PUSB_DEVICE_DESCRIPTOR
) ExAllocatePool(NonPagedPool
, siz
);
260 if (deviceDescriptor
)
262 UsbBuildGetDescriptorRequest(
264 (USHORT
) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
),
265 USB_DEVICE_DESCRIPTOR_TYPE
,
273 ntStatus
= CallUSBD(DeviceObject
, urb
);
274 if (NT_SUCCESS(ntStatus
))
276 ASSERT(deviceDescriptor
->bNumConfigurations
);
277 ntStatus
= ConfigureDevice(DeviceObject
);
282 ExFreePool(deviceDescriptor
);
288 FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for deviceDescriptor"));
290 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
298 FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for urb"));
299 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
308 NTSTATUS
ConfigureDevice(IN PDEVICE_OBJECT DeviceObject
)
313 PDEVICE_EXTENSION deviceExtension
;
314 PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor
;
317 configurationDescriptor
= NULL
;
318 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
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
));
327 siz
= sizeof(USB_CONFIGURATION_DESCRIPTOR
);
328 configurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
) ExAllocatePool(NonPagedPool
, siz
);
330 if(configurationDescriptor
)
332 UsbBuildGetDescriptorRequest(
334 (USHORT
) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
),
335 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
338 configurationDescriptor
,
340 sizeof(USB_CONFIGURATION_DESCRIPTOR
),
343 ntStatus
= CallUSBD(DeviceObject
, urb
);
344 if(!NT_SUCCESS(ntStatus
))
346 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: UsbBuildGetDescriptorRequest failed\n"));
347 goto ConfigureDevice_Exit
;
355 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate mem for config Descriptor\n"));
356 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
357 goto ConfigureDevice_Exit
;
361 siz
= configurationDescriptor
->wTotalLength
;
362 ExFreePool(configurationDescriptor
);
364 configurationDescriptor
= (PUSB_CONFIGURATION_DESCRIPTOR
) ExAllocatePool(NonPagedPool
, siz
);
365 if (configurationDescriptor
)
367 UsbBuildGetDescriptorRequest(
369 (USHORT
)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST
),
370 USB_CONFIGURATION_DESCRIPTOR_TYPE
,
373 configurationDescriptor
,
378 ntStatus
= CallUSBD(DeviceObject
, urb
);
379 if (!NT_SUCCESS(ntStatus
))
381 FreeBT_DbgPrint(1,("FBTUSB: ConfigureDevice: Failed to read configuration descriptor"));
382 goto ConfigureDevice_Exit
;
390 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to alloc mem for config Descriptor\n"));
391 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
392 goto ConfigureDevice_Exit
;
400 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate memory for urb\n"));
401 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
402 goto ConfigureDevice_Exit
;
406 if (configurationDescriptor
)
408 // save a copy of configurationDescriptor in deviceExtension
409 // remember to free it later.
410 deviceExtension
->UsbConfigurationDescriptor
= configurationDescriptor
;
412 if (configurationDescriptor
->bmAttributes
& REMOTE_WAKEUP_MASK
)
414 // this configuration supports remote wakeup
415 deviceExtension
->WaitWakeEnable
= 1;
421 deviceExtension
->WaitWakeEnable
= 0;
425 ntStatus
= SelectInterfaces(DeviceObject
, configurationDescriptor
);
431 deviceExtension
->UsbConfigurationDescriptor
= NULL
;
435 ConfigureDevice_Exit
:
446 NTSTATUS
SelectInterfaces(IN PDEVICE_OBJECT DeviceObject
, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
448 LONG numberOfInterfaces
, interfaceNumber
, interfaceindex
;
453 PDEVICE_EXTENSION deviceExtension
;
454 PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor
;
455 PUSBD_INTERFACE_LIST_ENTRY interfaceList
,
457 PUSBD_INTERFACE_INFORMATION Interface
;
461 interfaceDescriptor
= NULL
;
462 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
463 numberOfInterfaces
= ConfigurationDescriptor
->bNumInterfaces
;
464 interfaceindex
= interfaceNumber
= 0;
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));
473 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to allocate mem for interfaceList\n"));
474 return STATUS_INSUFFICIENT_RESOURCES
;
479 FreeBT_DbgPrint(3, ("FBTUSB: -------------\n"));
480 FreeBT_DbgPrint(3, ("FBTUSB: Number of interfaces %d\n", numberOfInterfaces
));
482 while (interfaceNumber
< numberOfInterfaces
)
484 interfaceDescriptor
= USBD_ParseConfigurationDescriptorEx(
485 ConfigurationDescriptor
,
486 ConfigurationDescriptor
,
490 if (interfaceDescriptor
)
492 interfaceList
->InterfaceDescriptor
= interfaceDescriptor
;
493 interfaceList
->Interface
= NULL
;
503 interfaceList
->InterfaceDescriptor
= NULL
;
504 interfaceList
->Interface
= NULL
;
505 urb
= USBD_CreateConfigurationRequestEx(ConfigurationDescriptor
, tmp
);
509 Interface
= &urb
->UrbSelectConfiguration
.Interface
;
510 for (i
=0; i
<Interface
->NumberOfPipes
; i
++)
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
;
519 ntStatus
= CallUSBD(DeviceObject
, urb
);
520 if (NT_SUCCESS(ntStatus
))
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
)
526 RtlCopyMemory(deviceExtension
->UsbInterface
, Interface
, Interface
->Length
);
532 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
533 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Memory alloc for UsbInterface failed\n"));
537 // Dump the interface to the debugger
538 Interface
= &urb
->UrbSelectConfiguration
.Interface
;
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",
548 Interface
->Protocol
));
550 if (Interface
->Class
==FREEBT_USB_STDCLASS
&& Interface
->SubClass
==FREEBT_USB_STDSUBCLASS
&&
551 Interface
->Protocol
==FREEBT_USB_STDPROTOCOL
)
553 FreeBT_DbgPrint(3, ("FBTUSB: This is a standard USB Bluetooth device\n"));
559 FreeBT_DbgPrint(3, ("FBTUSB: WARNING: This device does not report itself as a standard USB Bluetooth device\n"));
563 // Initialize the PipeContext
564 // Dump the pipe info
565 deviceExtension
->PipeContext
= (PFREEBT_PIPE_CONTEXT
) ExAllocatePool(
567 Interface
->NumberOfPipes
*
568 sizeof(FREEBT_PIPE_CONTEXT
));
570 if (!deviceExtension
->PipeContext
)
572 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
573 FreeBT_DbgPrint(1, ("FBTUSB: Memory alloc for UsbInterface failed\n"));
579 FreeBT_DbgPrint(3, ("FBTUSB: SelectInterfaces: Allocated PipeContext %p\n", deviceExtension
->PipeContext
));
580 for (i
=0; i
<Interface
->NumberOfPipes
; i
++)
582 deviceExtension
->PipeContext
[i
].PipeOpen
= FALSE
;
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
));
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
)
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"));
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"));
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"));
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"));
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"));
633 FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
639 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to select an interface\n"));
647 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: USBD_CreateConfigurationRequestEx failed\n"));
648 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
668 NTSTATUS
DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject
)
674 siz
= sizeof(struct _URB_SELECT_CONFIGURATION
);
675 urb
= (PURB
) ExAllocatePool(NonPagedPool
, siz
);
678 UsbBuildSelectConfigurationRequest(urb
, (USHORT
)siz
, NULL
);
679 ntStatus
= CallUSBD(DeviceObject
, urb
);
680 if(!NT_SUCCESS(ntStatus
))
682 FreeBT_DbgPrint(3, ("FBTUSB: DeconfigureDevice: Failed to deconfigure device\n"));
692 FreeBT_DbgPrint(1, ("FBTUSB: DeconfigureDevice: Failed to allocate urb\n"));
693 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
701 NTSTATUS
CallUSBD(IN PDEVICE_OBJECT DeviceObject
, IN PURB Urb
)
706 IO_STATUS_BLOCK ioStatus
;
707 PIO_STACK_LOCATION nextStack
;
708 PDEVICE_EXTENSION deviceExtension
;
711 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
713 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
714 irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB
,
715 deviceExtension
->TopOfStackDeviceObject
,
726 FreeBT_DbgPrint(1, ("FBTUSB: CallUSBD: IoBuildDeviceIoControlRequest failed\n"));
727 return STATUS_INSUFFICIENT_RESOURCES
;
731 nextStack
= IoGetNextIrpStackLocation(irp
);
732 ASSERT(nextStack
!= NULL
);
733 nextStack
->Parameters
.Others
.Argument1
= Urb
;
735 FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
736 FreeBT_IoIncrement(deviceExtension
);
738 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, irp
);
739 if (ntStatus
== STATUS_PENDING
)
741 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
742 ntStatus
= ioStatus
.Status
;
746 FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
747 FreeBT_IoDecrement(deviceExtension
);
752 NTSTATUS
HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
756 PDEVICE_EXTENSION deviceExtension
;
758 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Entered\n"));
760 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
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
);
766 SET_NEW_PNP_STATE(deviceExtension
, PendingStop
);
767 deviceExtension
->QueueState
= HoldRequests
;
769 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
771 // wait for the existing ones to be finished.
772 // first, decrement this operation
773 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice::"));
774 FreeBT_IoDecrement(deviceExtension
);
776 KeWaitForSingleObject(&deviceExtension
->StopEvent
, Executive
, KernelMode
, FALSE
, NULL
);
778 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
779 Irp
->IoStatus
.Information
= 0;
781 IoSkipCurrentIrpStackLocation(Irp
);
783 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
785 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Leaving\n"));
791 NTSTATUS
HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
796 PDEVICE_EXTENSION deviceExtension
;
798 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Entered\n"));
800 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
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.
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
810 if(PendingStop
== deviceExtension
->DeviceState
)
812 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
814 IoCopyCurrentIrpStackLocationToNext(Irp
);
815 IoSetCompletionRoutine(Irp
,
816 (PIO_COMPLETION_ROUTINE
)IrpCompletionRoutine
,
822 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
823 if(ntStatus
== STATUS_PENDING
)
825 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
826 ntStatus
= Irp
->IoStatus
.Status
;
830 if(NT_SUCCESS(ntStatus
))
832 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
834 RESTORE_PREVIOUS_PNP_STATE(deviceExtension
);
835 deviceExtension
->QueueState
= AllowRequests
;
836 ASSERT(deviceExtension
->DeviceState
== Working
);
838 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
840 ProcessQueuedRequests(deviceExtension
);
849 ntStatus
= STATUS_SUCCESS
;
853 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Leaving\n"));
859 NTSTATUS
HandleStopDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
863 PDEVICE_EXTENSION deviceExtension
;
865 FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Entered\n"));
867 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
868 if(WinXpOrBetter
== deviceExtension
->WdmVersion
)
870 if(deviceExtension
->SSEnable
)
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
877 KeCancelTimer(&deviceExtension
->Timer
);
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
884 deviceExtension
->SSEnable
= 0;
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
);
890 // make sure that the selective suspend request has been completed.
891 KeWaitForSingleObject(&deviceExtension
->NoIdleReqPendEvent
, Executive
, KernelMode
, FALSE
, NULL
);
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
)
902 CancelWaitWake(deviceExtension
);
906 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
908 SET_NEW_PNP_STATE(deviceExtension
, Stopped
);
910 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
912 // This is the right place to actually give up all the resources used
913 // This might include calls to IoDisconnectInterrupt, MmUnmapIoSpace,
915 ReleaseMemory(DeviceObject
);
917 ntStatus
= DeconfigureDevice(DeviceObject
);
919 Irp
->IoStatus
.Status
= ntStatus
;
920 Irp
->IoStatus
.Information
= 0;
922 IoSkipCurrentIrpStackLocation(Irp
);
923 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
925 FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Leaving\n"));
931 NTSTATUS
HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
935 PDEVICE_EXTENSION deviceExtension
;
937 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Entered\n"));
939 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
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
);
947 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
949 deviceExtension
->QueueState
= HoldRequests
;
950 SET_NEW_PNP_STATE(deviceExtension
, PendingRemove
);
952 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
954 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice::"));
955 FreeBT_IoDecrement(deviceExtension
);
957 // Wait for all the requests to be completed
958 KeWaitForSingleObject(&deviceExtension
->StopEvent
, Executive
, KernelMode
, FALSE
, NULL
);
960 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
961 Irp
->IoStatus
.Information
= 0;
963 IoSkipCurrentIrpStackLocation(Irp
);
964 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
966 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Leaving\n"));
972 NTSTATUS
HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
977 PDEVICE_EXTENSION deviceExtension
;
979 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Entered\n"));
981 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
983 // We need to reset the QueueState flag to ProcessRequest,
984 // since the device resume its normal activities.
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
)
993 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
995 IoCopyCurrentIrpStackLocationToNext(Irp
);
996 IoSetCompletionRoutine(Irp
,
997 (PIO_COMPLETION_ROUTINE
)IrpCompletionRoutine
,
1003 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
1004 if(ntStatus
== STATUS_PENDING
)
1006 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
1007 ntStatus
= Irp
->IoStatus
.Status
;
1011 if (NT_SUCCESS(ntStatus
))
1013 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
1015 deviceExtension
->QueueState
= AllowRequests
;
1016 RESTORE_PREVIOUS_PNP_STATE(deviceExtension
);
1018 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
1020 // process the queued requests that arrive between
1021 // QUERY_REMOVE and CANCEL_REMOVE
1022 ProcessQueuedRequests(deviceExtension
);
1030 // spurious cancel-remove
1031 ntStatus
= STATUS_SUCCESS
;
1035 FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Leaving\n"));
1041 NTSTATUS
HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
1045 PDEVICE_EXTENSION deviceExtension
;
1047 FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Entered\n"));
1049 // initialize variables
1050 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1052 // 1. fail pending requests
1053 // 2. return device and memory resources
1054 // 3. disable interfaces
1055 if(deviceExtension
->WaitWakeEnable
)
1057 CancelWaitWake(deviceExtension
);
1062 if (WinXpOrBetter
== deviceExtension
->WdmVersion
)
1064 if (deviceExtension
->SSEnable
)
1066 // Cancel the timer so that the DPCs are no longer fired.
1067 // we do not need DPCs because the device has been surprise
1069 KeCancelTimer(&deviceExtension
->Timer
);
1071 deviceExtension
->SSEnable
= 0;
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
);
1077 // make sure that the selective suspend request has been completed.
1078 KeWaitForSingleObject(&deviceExtension
->NoIdleReqPendEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1084 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
1085 deviceExtension
->QueueState
= FailRequests
;
1086 SET_NEW_PNP_STATE(deviceExtension
, SurpriseRemoved
);
1087 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
1089 ProcessQueuedRequests(deviceExtension
);
1091 ntStatus
= IoSetDeviceInterfaceState(&deviceExtension
->InterfaceName
, FALSE
);
1092 if(!NT_SUCCESS(ntStatus
))
1094 FreeBT_DbgPrint(1, ("FBTUSB: HandleSurpriseRemoval: IoSetDeviceInterfaceState::disable:failed\n"));
1098 FreeBT_AbortPipes(DeviceObject
);
1100 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1101 Irp
->IoStatus
.Information
= 0;
1103 IoSkipCurrentIrpStackLocation(Irp
);
1104 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
1106 FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Leaving\n"));
1112 NTSTATUS
HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
1118 PDEVICE_EXTENSION deviceExtension
;
1120 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Entered\n"));
1122 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
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
)
1131 // we are here after QUERY_REMOVE
1132 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
1133 deviceExtension
->QueueState
= FailRequests
;
1134 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
1136 if(deviceExtension
->WaitWakeEnable
)
1138 CancelWaitWake(deviceExtension
);
1142 if(WinXpOrBetter
== deviceExtension
->WdmVersion
)
1144 if (deviceExtension
->SSEnable
)
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
);
1150 deviceExtension
->SSEnable
= 0;
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
);
1156 // make sure that the selective suspend request has been completed.
1157 KeWaitForSingleObject(&deviceExtension
->NoIdleReqPendEvent
, Executive
, KernelMode
, FALSE
, NULL
);
1163 ProcessQueuedRequests(deviceExtension
);
1165 ntStatus
= IoSetDeviceInterfaceState(&deviceExtension
->InterfaceName
, FALSE
);
1166 if(!NT_SUCCESS(ntStatus
))
1168 FreeBT_DbgPrint(1, ("FBTUSB: HandleRemoveDevice: IoSetDeviceInterfaceState::disable:failed\n"));
1172 FreeBT_AbortPipes(DeviceObject
);
1176 KeAcquireSpinLock(&deviceExtension
->DevStateLock
, &oldIrql
);
1177 SET_NEW_PNP_STATE(deviceExtension
, Removed
);
1178 KeReleaseSpinLock(&deviceExtension
->DevStateLock
, oldIrql
);
1180 FreeBT_WmiDeRegistration(deviceExtension
);
1183 // Need 2 decrements
1184 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
1185 requestCount
= FreeBT_IoDecrement(deviceExtension
);
1187 ASSERT(requestCount
> 0);
1189 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
1190 requestCount
= FreeBT_IoDecrement(deviceExtension
);
1192 KeWaitForSingleObject(&deviceExtension
->RemoveEvent
,
1198 ReleaseMemory(DeviceObject
);
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;
1206 IoSkipCurrentIrpStackLocation(Irp
);
1207 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
1209 IoDetachDevice(deviceExtension
->TopOfStackDeviceObject
);
1210 IoDeleteDevice(DeviceObject
);
1212 FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Leaving\n"));
1218 NTSTATUS
HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
1223 PDEVICE_EXTENSION deviceExtension
;
1224 PDEVICE_CAPABILITIES pdc
;
1225 PIO_STACK_LOCATION irpStack
;
1227 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Entered\n"));
1229 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
1230 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1231 pdc
= irpStack
->Parameters
.DeviceCapabilities
.Capabilities
;
1233 if(pdc
->Version
< 1 || pdc
->Size
< sizeof(DEVICE_CAPABILITIES
))
1236 FreeBT_DbgPrint(1, ("FBTUSB: HandleQueryCapabilities::request failed\n"));
1237 ntStatus
= STATUS_UNSUCCESSFUL
;
1242 // Add in the SurpriseRemovalOK bit before passing it down.
1243 pdc
->SurpriseRemovalOK
= TRUE
;
1244 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1246 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
1248 IoCopyCurrentIrpStackLocationToNext(Irp
);
1249 IoSetCompletionRoutine(Irp
,
1250 (PIO_COMPLETION_ROUTINE
)IrpCompletionRoutine
,
1255 ntStatus
= IoCallDriver(deviceExtension
->TopOfStackDeviceObject
, Irp
);
1256 if(ntStatus
== STATUS_PENDING
)
1258 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
1259 ntStatus
= Irp
->IoStatus
.Status
;
1263 // initialize PowerDownLevel to disabled
1264 deviceExtension
->PowerDownLevel
= PowerDeviceUnspecified
;
1265 if(NT_SUCCESS(ntStatus
))
1267 deviceExtension
->DeviceCapabilities
= *pdc
;
1268 for(i
= PowerSystemSleeping1
; i
<= PowerSystemSleeping3
; i
++)
1270 if(deviceExtension
->DeviceCapabilities
.DeviceState
[i
] < PowerDeviceD3
)
1272 deviceExtension
->PowerDownLevel
= deviceExtension
->DeviceCapabilities
.DeviceState
[i
];
1278 // since its safe to surprise-remove this device, we shall
1279 // set the SurpriseRemoveOK flag to supress any dialog to
1281 pdc
->SurpriseRemovalOK
= 1;
1285 if(deviceExtension
->PowerDownLevel
== PowerDeviceUnspecified
||
1286 deviceExtension
->PowerDownLevel
<= PowerDeviceD0
)
1288 deviceExtension
->PowerDownLevel
= PowerDeviceD2
;
1292 FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Leaving\n"));
1298 VOID
DpcRoutine(IN PKDPC Dpc
, IN PVOID DeferredContext
, IN PVOID SystemArgument1
, IN PVOID SystemArgument2
)
1301 DPC routine triggered by the timer to check the idle state
1302 of the device and submit an idle request for the device.
1307 PDEVICE_OBJECT deviceObject
;
1308 PDEVICE_EXTENSION deviceExtension
;
1311 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Entered\n"));
1313 deviceObject
= (PDEVICE_OBJECT
)DeferredContext
;
1314 deviceExtension
= (PDEVICE_EXTENSION
)deviceObject
->DeviceExtension
;
1316 // Clear this event since a DPC has been fired!
1317 KeClearEvent(&deviceExtension
->NoDpcWorkItemPendingEvent
);
1319 if(CanDeviceSuspend(deviceExtension
))
1321 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Device is Idle\n"));
1322 item
= IoAllocateWorkItem(deviceObject
);
1326 IoQueueWorkItem(item
, IdleRequestWorkerRoutine
, DelayedWorkQueue
, item
);
1327 ntStatus
= STATUS_PENDING
;
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
);
1343 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Idle event not signaled\n"));
1344 KeSetEvent(&deviceExtension
->NoDpcWorkItemPendingEvent
, IO_NO_INCREMENT
, FALSE
);
1348 FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Leaving\n"));
1352 VOID
IdleRequestWorkerRoutine(IN PDEVICE_OBJECT DeviceObject
, IN PVOID Context
)
1356 PDEVICE_EXTENSION deviceExtension
;
1357 PIO_WORKITEM workItem
;
1359 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Entered\n"));
1361 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1362 workItem
= (PIO_WORKITEM
) Context
;
1364 if(CanDeviceSuspend(deviceExtension
))
1366 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is idle\n"));
1367 ntStatus
= SubmitIdleRequestIrp(deviceExtension
);
1368 if(!NT_SUCCESS(ntStatus
))
1370 FreeBT_DbgPrint(1, ("FBTUSB: IdleRequestWorkerRoutine: SubmitIdleRequestIrp failed\n"));
1378 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is not idle\n"));
1382 IoFreeWorkItem(workItem
);
1384 KeSetEvent(&deviceExtension
->NoDpcWorkItemPendingEvent
, IO_NO_INCREMENT
, FALSE
);
1386 FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestsWorkerRoutine: Leaving\n"));
1391 VOID
ProcessQueuedRequests(IN OUT PDEVICE_EXTENSION DeviceExtension
)
1394 Routine Description:
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
1404 DeviceExtension - pointer to device extension
1415 PVOID cancelRoutine
;
1416 LIST_ENTRY cancelledIrpList
;
1417 PLIST_ENTRY listEntry
;
1419 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Entered\n"));
1421 cancelRoutine
= NULL
;
1422 InitializeListHead(&cancelledIrpList
);
1424 // 1. dequeue the entries in the queue
1425 // 2. reset the cancel routine
1427 // 3a. if the device is active, send them down
1428 // 3b. else complete with STATUS_DELETE_PENDING
1431 KeAcquireSpinLock(&DeviceExtension
->QueueLock
, &oldIrql
);
1432 if(IsListEmpty(&DeviceExtension
->NewRequestsQueue
))
1434 KeReleaseSpinLock(&DeviceExtension
->QueueLock
, oldIrql
);
1439 listEntry
= RemoveHeadList(&DeviceExtension
->NewRequestsQueue
);
1440 nextIrp
= CONTAINING_RECORD(listEntry
, IRP
, Tail
.Overlay
.ListEntry
);
1442 cancelRoutine
= IoSetCancelRoutine(nextIrp
, NULL
);
1444 // check if its already cancelled
1445 if (nextIrp
->Cancel
)
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
);
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
);
1465 KeReleaseSpinLock(&DeviceExtension
->QueueLock
, oldIrql
);
1471 KeReleaseSpinLock(&DeviceExtension
->QueueLock
, oldIrql
);
1472 if(FailRequests
== DeviceExtension
->QueueState
)
1474 nextIrp
->IoStatus
.Information
= 0;
1475 nextIrp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
1476 IoCompleteRequest(nextIrp
, IO_NO_INCREMENT
);
1482 PIO_STACK_LOCATION irpStack
;
1484 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
1485 FreeBT_IoIncrement(DeviceExtension
);
1487 IoSkipCurrentIrpStackLocation(nextIrp
);
1488 IoCallDriver(DeviceExtension
->TopOfStackDeviceObject
, nextIrp
);
1490 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
1491 FreeBT_IoDecrement(DeviceExtension
);
1499 while(!IsListEmpty(&cancelledIrpList
))
1501 PLIST_ENTRY cancelEntry
= RemoveHeadList(&cancelledIrpList
);
1503 cancelledIrp
= CONTAINING_RECORD(cancelEntry
, IRP
, Tail
.Overlay
.ListEntry
);
1504 cancelledIrp
->IoStatus
.Status
= STATUS_CANCELLED
;
1505 cancelledIrp
->IoStatus
.Information
= 0;
1507 IoCompleteRequest(cancelledIrp
, IO_NO_INCREMENT
);
1511 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Leaving\n"));
1517 NTSTATUS
FreeBT_GetRegistryDword(IN PWCHAR RegPath
, IN PWCHAR ValueName
, IN OUT PULONG Value
)
1520 WCHAR buffer
[MAXIMUM_FILENAME_LENGTH
];
1522 UNICODE_STRING regPath
;
1523 RTL_QUERY_REGISTRY_TABLE paramTable
[2];
1525 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Entered\n"));
1528 regPath
.MaximumLength
= MAXIMUM_FILENAME_LENGTH
* sizeof(WCHAR
);
1529 regPath
.Buffer
= buffer
;
1531 RtlZeroMemory(regPath
.Buffer
, regPath
.MaximumLength
);
1532 RtlMoveMemory(regPath
.Buffer
, RegPath
, wcslen(RegPath
) * sizeof(WCHAR
));
1533 RtlZeroMemory(paramTable
, sizeof(paramTable
));
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
);
1542 ntStatus
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
|
1543 RTL_REGISTRY_OPTIONAL
,
1549 if (NT_SUCCESS(ntStatus
))
1551 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Success, Value = %X\n", *Value
));
1552 return STATUS_SUCCESS
;
1557 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Failed\n"));
1559 return STATUS_UNSUCCESSFUL
;
1565 NTSTATUS
FreeBT_DispatchClean(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
1567 PDEVICE_EXTENSION deviceExtension
;
1569 LIST_ENTRY cleanupList
;
1570 PLIST_ENTRY thisEntry
,
1574 PIO_STACK_LOCATION pendingIrpStack
,
1578 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1579 irpStack
= IoGetCurrentIrpStackLocation(Irp
);
1580 InitializeListHead(&cleanupList
);
1582 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
1583 FreeBT_IoIncrement(deviceExtension
);
1585 KeAcquireSpinLock(&deviceExtension
->QueueLock
, &oldIrql
);
1587 listHead
= &deviceExtension
->NewRequestsQueue
;
1588 for(thisEntry
= listHead
->Flink
, nextEntry
= thisEntry
->Flink
;
1589 thisEntry
!= listHead
;
1590 thisEntry
= nextEntry
, nextEntry
= thisEntry
->Flink
)
1592 pendingIrp
= CONTAINING_RECORD(thisEntry
, IRP
, Tail
.Overlay
.ListEntry
);
1593 pendingIrpStack
= IoGetCurrentIrpStackLocation(pendingIrp
);
1594 if (irpStack
->FileObject
== pendingIrpStack
->FileObject
)
1596 RemoveEntryList(thisEntry
);
1598 if (NULL
== IoSetCancelRoutine(pendingIrp
, NULL
))
1600 InitializeListHead(thisEntry
);
1606 InsertTailList(&cleanupList
, thisEntry
);
1614 KeReleaseSpinLock(&deviceExtension
->QueueLock
, oldIrql
);
1616 while(!IsListEmpty(&cleanupList
))
1618 thisEntry
= RemoveHeadList(&cleanupList
);
1619 pendingIrp
= CONTAINING_RECORD(thisEntry
, IRP
, Tail
.Overlay
.ListEntry
);
1621 pendingIrp
->IoStatus
.Information
= 0;
1622 pendingIrp
->IoStatus
.Status
= STATUS_CANCELLED
;
1623 IoCompleteRequest(pendingIrp
, IO_NO_INCREMENT
);
1627 Irp
->IoStatus
.Information
= 0;
1628 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1630 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1632 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
1633 FreeBT_IoDecrement(deviceExtension
);
1635 return STATUS_SUCCESS
;
1640 BOOLEAN
CanDeviceSuspend(IN PDEVICE_EXTENSION DeviceExtension
)
1642 FreeBT_DbgPrint(3, ("FBTUSB: CanDeviceSuspend: Entered\n"));
1644 if ((DeviceExtension
->OpenHandleCount
== 0) && (DeviceExtension
->OutStandingIO
== 1))
1651 NTSTATUS
FreeBT_AbortPipes(IN PDEVICE_OBJECT DeviceObject
)
1656 PDEVICE_EXTENSION deviceExtension
;
1657 PFREEBT_PIPE_CONTEXT pipeContext
;
1658 PUSBD_PIPE_INFORMATION pipeInformation
;
1659 PUSBD_INTERFACE_INFORMATION interfaceInfo
;
1661 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1662 pipeContext
= deviceExtension
->PipeContext
;
1663 interfaceInfo
= deviceExtension
->UsbInterface
;
1665 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Entered\n"));
1667 if(interfaceInfo
== NULL
|| pipeContext
== NULL
)
1668 return STATUS_SUCCESS
;
1670 for(i
=0; i
<interfaceInfo
->NumberOfPipes
; i
++)
1672 if(pipeContext
[i
].PipeOpen
)
1674 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Aborting open pipe %d\n", i
));
1676 urb
= (PURB
) ExAllocatePool(NonPagedPool
, sizeof(struct _URB_PIPE_REQUEST
));
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
;
1683 ntStatus
= CallUSBD(DeviceObject
, urb
);
1691 FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_AbortPipes: Failed to alloc memory for urb\n"));
1692 ntStatus
= STATUS_INSUFFICIENT_RESOURCES
;
1697 if(NT_SUCCESS(ntStatus
))
1698 pipeContext
[i
].PipeOpen
= FALSE
;
1705 FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Leaving\n"));
1707 return STATUS_SUCCESS
;
1711 // Completion routine for PNP IRPs
1712 NTSTATUS
IrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
, IN PVOID Context
)
1714 PKEVENT event
= (PKEVENT
) Context
;
1715 KeSetEvent(event
, 0, FALSE
);
1717 return STATUS_MORE_PROCESSING_REQUIRED
;
1722 LONG
FreeBT_IoIncrement(IN OUT PDEVICE_EXTENSION DeviceExtension
)
1727 KeAcquireSpinLock(&DeviceExtension
->IOCountLock
, &oldIrql
);
1728 result
= InterlockedIncrement((PLONG
)(&DeviceExtension
->OutStandingIO
));
1730 // When OutStandingIO bumps from 1 to 2, clear the StopEvent
1732 KeClearEvent(&DeviceExtension
->StopEvent
);
1734 KeReleaseSpinLock(&DeviceExtension
->IOCountLock
, oldIrql
);
1736 FreeBT_DbgPrint(3, ("FreeBT_IoIncrement::%d\n", result
));
1742 LONG
FreeBT_IoDecrement(IN OUT PDEVICE_EXTENSION DeviceExtension
)
1747 KeAcquireSpinLock(&DeviceExtension
->IOCountLock
, &oldIrql
);
1749 result
= InterlockedDecrement((PLONG
)(&DeviceExtension
->OutStandingIO
));
1752 KeSetEvent(&DeviceExtension
->StopEvent
, IO_NO_INCREMENT
, FALSE
);
1756 ASSERT(Removed
== DeviceExtension
->DeviceState
);
1757 KeSetEvent(&DeviceExtension
->RemoveEvent
, IO_NO_INCREMENT
, FALSE
);
1761 KeReleaseSpinLock(&DeviceExtension
->IOCountLock
, oldIrql
);
1763 FreeBT_DbgPrint(3, ("FreeBT_IoDecrement::%d\n", result
));
1769 NTSTATUS
CanStopDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
1771 // For the time being, just allow it to be stopped
1772 UNREFERENCED_PARAMETER(DeviceObject
);
1773 UNREFERENCED_PARAMETER(Irp
);
1775 return STATUS_SUCCESS
;
1779 NTSTATUS
CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject
, IN PIRP Irp
)
1782 // For the time being, just allow it to be removed
1783 UNREFERENCED_PARAMETER(DeviceObject
);
1784 UNREFERENCED_PARAMETER(Irp
);
1786 return STATUS_SUCCESS
;
1790 NTSTATUS
ReleaseMemory(IN PDEVICE_OBJECT DeviceObject
)
1792 // Disconnect from the interrupt and unmap any I/O ports
1793 PDEVICE_EXTENSION deviceExtension
;
1794 UNICODE_STRING uniDeviceName
;
1797 deviceExtension
= (PDEVICE_EXTENSION
) DeviceObject
->DeviceExtension
;
1798 if (deviceExtension
->UsbConfigurationDescriptor
)
1800 FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbConfigurationDescriptor\n"));
1801 ExFreePool(deviceExtension
->UsbConfigurationDescriptor
);
1802 deviceExtension
->UsbConfigurationDescriptor
= NULL
;
1806 if(deviceExtension
->UsbInterface
)
1808 FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbInterface\n"));
1809 ExFreePool(deviceExtension
->UsbInterface
);
1810 deviceExtension
->UsbInterface
= NULL
;
1814 if(deviceExtension
->PipeContext
)
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
));
1821 FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing PipeContext %p\n", deviceExtension
->PipeContext
));
1822 ExFreePool(deviceExtension
->PipeContext
);
1823 deviceExtension
->PipeContext
= NULL
;
1827 return STATUS_SUCCESS
;
1831 PCHAR
PnPMinorFunctionString (UCHAR MinorFunction
)
1833 switch (MinorFunction
)
1835 case IRP_MN_START_DEVICE
:
1836 return "IRP_MN_START_DEVICE\n";
1838 case IRP_MN_QUERY_REMOVE_DEVICE
:
1839 return "IRP_MN_QUERY_REMOVE_DEVICE\n";
1841 case IRP_MN_REMOVE_DEVICE
:
1842 return "IRP_MN_REMOVE_DEVICE\n";
1844 case IRP_MN_CANCEL_REMOVE_DEVICE
:
1845 return "IRP_MN_CANCEL_REMOVE_DEVICE\n";
1847 case IRP_MN_STOP_DEVICE
:
1848 return "IRP_MN_STOP_DEVICE\n";
1850 case IRP_MN_QUERY_STOP_DEVICE
:
1851 return "IRP_MN_QUERY_STOP_DEVICE\n";
1853 case IRP_MN_CANCEL_STOP_DEVICE
:
1854 return "IRP_MN_CANCEL_STOP_DEVICE\n";
1856 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1857 return "IRP_MN_QUERY_DEVICE_RELATIONS\n";
1859 case IRP_MN_QUERY_INTERFACE
:
1860 return "IRP_MN_QUERY_INTERFACE\n";
1862 case IRP_MN_QUERY_CAPABILITIES
:
1863 return "IRP_MN_QUERY_CAPABILITIES\n";
1865 case IRP_MN_QUERY_RESOURCES
:
1866 return "IRP_MN_QUERY_RESOURCES\n";
1868 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
1869 return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n";
1871 case IRP_MN_QUERY_DEVICE_TEXT
:
1872 return "IRP_MN_QUERY_DEVICE_TEXT\n";
1874 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
:
1875 return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n";
1877 case IRP_MN_READ_CONFIG
:
1878 return "IRP_MN_READ_CONFIG\n";
1880 case IRP_MN_WRITE_CONFIG
:
1881 return "IRP_MN_WRITE_CONFIG\n";
1884 return "IRP_MN_EJECT\n";
1886 case IRP_MN_SET_LOCK
:
1887 return "IRP_MN_SET_LOCK\n";
1889 case IRP_MN_QUERY_ID
:
1890 return "IRP_MN_QUERY_ID\n";
1892 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
1893 return "IRP_MN_QUERY_PNP_DEVICE_STATE\n";
1895 case IRP_MN_QUERY_BUS_INFORMATION
:
1896 return "IRP_MN_QUERY_BUS_INFORMATION\n";
1898 case IRP_MN_DEVICE_USAGE_NOTIFICATION
:
1899 return "IRP_MN_DEVICE_USAGE_NOTIFICATION\n";
1901 case IRP_MN_SURPRISE_REMOVAL
:
1902 return "IRP_MN_SURPRISE_REMOVAL\n";
1905 return "IRP_MN_?????\n";