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