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