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 "fbtusb.h"
14*c2c66affSColin Finck #include "fbtpnp.h"
15*c2c66affSColin Finck #include "fbtpwr.h"
16*c2c66affSColin Finck #include "fbtdev.h"
17*c2c66affSColin Finck #include "fbtrwr.h"
18*c2c66affSColin Finck #include "fbtwmi.h"
19*c2c66affSColin Finck
20*c2c66affSColin Finck #include "fbtusr.h"
21*c2c66affSColin Finck
22*c2c66affSColin Finck // Read/Write handler
FreeBT_DispatchRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)23*c2c66affSColin Finck NTSTATUS NTAPI FreeBT_DispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
24*c2c66affSColin Finck {
25*c2c66affSColin Finck PMDL mdl;
26*c2c66affSColin Finck PURB urb;
27*c2c66affSColin Finck ULONG totalLength;
28*c2c66affSColin Finck ULONG stageLength;
29*c2c66affSColin Finck NTSTATUS ntStatus;
30*c2c66affSColin Finck ULONG_PTR virtualAddress;
31*c2c66affSColin Finck PFILE_OBJECT fileObject;
32*c2c66affSColin Finck PDEVICE_EXTENSION deviceExtension;
33*c2c66affSColin Finck PIO_STACK_LOCATION irpStack;
34*c2c66affSColin Finck PIO_STACK_LOCATION nextStack;
35*c2c66affSColin Finck PFREEBT_RW_CONTEXT rwContext;
36*c2c66affSColin Finck //ULONG maxLength=0;
37*c2c66affSColin Finck
38*c2c66affSColin Finck urb = NULL;
39*c2c66affSColin Finck mdl = NULL;
40*c2c66affSColin Finck rwContext = NULL;
41*c2c66affSColin Finck totalLength = 0;
42*c2c66affSColin Finck irpStack = IoGetCurrentIrpStackLocation(Irp);
43*c2c66affSColin Finck fileObject = irpStack->FileObject;
44*c2c66affSColin Finck deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
45*c2c66affSColin Finck
46*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: Entered\n"));
47*c2c66affSColin Finck
48*c2c66affSColin Finck if (deviceExtension->DeviceState != Working)
49*c2c66affSColin Finck {
50*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Invalid device state\n"));
51*c2c66affSColin Finck ntStatus = STATUS_INVALID_DEVICE_STATE;
52*c2c66affSColin Finck goto FreeBT_DispatchRead_Exit;
53*c2c66affSColin Finck
54*c2c66affSColin Finck }
55*c2c66affSColin Finck
56*c2c66affSColin Finck // Make sure that any selective suspend request has been completed.
57*c2c66affSColin Finck if (deviceExtension->SSEnable)
58*c2c66affSColin Finck {
59*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: Waiting on the IdleReqPendEvent\n"));
60*c2c66affSColin Finck KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
61*c2c66affSColin Finck Executive,
62*c2c66affSColin Finck KernelMode,
63*c2c66affSColin Finck FALSE,
64*c2c66affSColin Finck NULL);
65*c2c66affSColin Finck
66*c2c66affSColin Finck }
67*c2c66affSColin Finck
68*c2c66affSColin Finck rwContext = (PFREEBT_RW_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(FREEBT_RW_CONTEXT));
69*c2c66affSColin Finck if (rwContext == NULL)
70*c2c66affSColin Finck {
71*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Failed to alloc mem for rwContext\n"));
72*c2c66affSColin Finck ntStatus = STATUS_INSUFFICIENT_RESOURCES;
73*c2c66affSColin Finck goto FreeBT_DispatchRead_Exit;
74*c2c66affSColin Finck
75*c2c66affSColin Finck }
76*c2c66affSColin Finck
77*c2c66affSColin Finck if (Irp->MdlAddress)
78*c2c66affSColin Finck {
79*c2c66affSColin Finck totalLength = MmGetMdlByteCount(Irp->MdlAddress);
80*c2c66affSColin Finck
81*c2c66affSColin Finck }
82*c2c66affSColin Finck
83*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Transfer data length = %d\n", totalLength));
84*c2c66affSColin Finck if (totalLength == 0)
85*c2c66affSColin Finck {
86*c2c66affSColin Finck ntStatus = STATUS_SUCCESS;
87*c2c66affSColin Finck ExFreePool(rwContext);
88*c2c66affSColin Finck goto FreeBT_DispatchRead_Exit;
89*c2c66affSColin Finck
90*c2c66affSColin Finck }
91*c2c66affSColin Finck
92*c2c66affSColin Finck virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);
93*c2c66affSColin Finck if (totalLength > deviceExtension->DataInPipe.MaximumPacketSize)
94*c2c66affSColin Finck {
95*c2c66affSColin Finck stageLength = deviceExtension->DataInPipe.MaximumPacketSize;
96*c2c66affSColin Finck
97*c2c66affSColin Finck }
98*c2c66affSColin Finck
99*c2c66affSColin Finck else
100*c2c66affSColin Finck {
101*c2c66affSColin Finck stageLength = totalLength;
102*c2c66affSColin Finck
103*c2c66affSColin Finck }
104*c2c66affSColin Finck
105*c2c66affSColin Finck mdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL);
106*c2c66affSColin Finck if (mdl == NULL)
107*c2c66affSColin Finck {
108*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Failed to alloc mem for mdl\n"));
109*c2c66affSColin Finck ntStatus = STATUS_INSUFFICIENT_RESOURCES;
110*c2c66affSColin Finck ExFreePool(rwContext);
111*c2c66affSColin Finck goto FreeBT_DispatchRead_Exit;
112*c2c66affSColin Finck
113*c2c66affSColin Finck }
114*c2c66affSColin Finck
115*c2c66affSColin Finck // map the portion of user-buffer described by an mdl to another mdl
116*c2c66affSColin Finck IoBuildPartialMdl(Irp->MdlAddress, mdl, (PVOID) virtualAddress, stageLength);
117*c2c66affSColin Finck urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
118*c2c66affSColin Finck if (urb == NULL)
119*c2c66affSColin Finck {
120*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: Failed to alloc mem for urb\n"));
121*c2c66affSColin Finck ntStatus = STATUS_INSUFFICIENT_RESOURCES;
122*c2c66affSColin Finck ExFreePool(rwContext);
123*c2c66affSColin Finck IoFreeMdl(mdl);
124*c2c66affSColin Finck goto FreeBT_DispatchRead_Exit;
125*c2c66affSColin Finck
126*c2c66affSColin Finck }
127*c2c66affSColin Finck
128*c2c66affSColin Finck UsbBuildInterruptOrBulkTransferRequest(
129*c2c66affSColin Finck urb,
130*c2c66affSColin Finck sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
131*c2c66affSColin Finck deviceExtension->DataInPipe.PipeHandle,
132*c2c66affSColin Finck NULL,
133*c2c66affSColin Finck mdl,
134*c2c66affSColin Finck stageLength,
135*c2c66affSColin Finck USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN,
136*c2c66affSColin Finck NULL);
137*c2c66affSColin Finck
138*c2c66affSColin Finck // set FREEBT_RW_CONTEXT parameters.
139*c2c66affSColin Finck rwContext->Urb = urb;
140*c2c66affSColin Finck rwContext->Mdl = mdl;
141*c2c66affSColin Finck rwContext->Length = totalLength - stageLength;
142*c2c66affSColin Finck rwContext->Numxfer = 0;
143*c2c66affSColin Finck rwContext->VirtualAddress = virtualAddress + stageLength;
144*c2c66affSColin Finck
145*c2c66affSColin Finck // use the original read/write irp as an internal device control irp
146*c2c66affSColin Finck nextStack = IoGetNextIrpStackLocation(Irp);
147*c2c66affSColin Finck nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
148*c2c66affSColin Finck nextStack->Parameters.Others.Argument1 = (PVOID) urb;
149*c2c66affSColin Finck nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
150*c2c66affSColin Finck IoSetCompletionRoutine(Irp,
151*c2c66affSColin Finck (PIO_COMPLETION_ROUTINE)FreeBT_ReadCompletion,
152*c2c66affSColin Finck rwContext,
153*c2c66affSColin Finck TRUE,
154*c2c66affSColin Finck TRUE,
155*c2c66affSColin Finck TRUE);
156*c2c66affSColin Finck
157*c2c66affSColin Finck // We return STATUS_PENDING; call IoMarkIrpPending.
158*c2c66affSColin Finck IoMarkIrpPending(Irp);
159*c2c66affSColin Finck
160*c2c66affSColin Finck ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
161*c2c66affSColin Finck if (!NT_SUCCESS(ntStatus))
162*c2c66affSColin Finck {
163*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: IoCallDriver fails with status %X\n", ntStatus));
164*c2c66affSColin Finck
165*c2c66affSColin Finck // if the device was yanked out, then the pipeInformation
166*c2c66affSColin Finck // field is invalid.
167*c2c66affSColin Finck // similarly if the request was cancelled, then we need not
168*c2c66affSColin Finck // invoked reset pipe/device.
169*c2c66affSColin Finck if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
170*c2c66affSColin Finck {
171*c2c66affSColin Finck ntStatus = FreeBT_ResetPipe(DeviceObject, deviceExtension->DataInPipe.PipeHandle);
172*c2c66affSColin Finck if(!NT_SUCCESS(ntStatus))
173*c2c66affSColin Finck {
174*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchRead: FreeBT_ResetPipe failed\n"));
175*c2c66affSColin Finck ntStatus = FreeBT_ResetDevice(DeviceObject);
176*c2c66affSColin Finck
177*c2c66affSColin Finck }
178*c2c66affSColin Finck
179*c2c66affSColin Finck }
180*c2c66affSColin Finck
181*c2c66affSColin Finck else
182*c2c66affSColin Finck {
183*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
184*c2c66affSColin Finck
185*c2c66affSColin Finck }
186*c2c66affSColin Finck
187*c2c66affSColin Finck }
188*c2c66affSColin Finck
189*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead::"));
190*c2c66affSColin Finck FreeBT_IoIncrement(deviceExtension);
191*c2c66affSColin Finck
192*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: URB sent to lower driver, IRP is pending\n"));
193*c2c66affSColin Finck
194*c2c66affSColin Finck // we return STATUS_PENDING and not the status returned by the lower layer.
195*c2c66affSColin Finck return STATUS_PENDING;
196*c2c66affSColin Finck
197*c2c66affSColin Finck FreeBT_DispatchRead_Exit:
198*c2c66affSColin Finck Irp->IoStatus.Status = ntStatus;
199*c2c66affSColin Finck Irp->IoStatus.Information = 0;
200*c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
201*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchRead: Leaving\n"));
202*c2c66affSColin Finck
203*c2c66affSColin Finck return ntStatus;
204*c2c66affSColin Finck
205*c2c66affSColin Finck }
206*c2c66affSColin Finck
FreeBT_ReadCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)207*c2c66affSColin Finck NTSTATUS NTAPI FreeBT_ReadCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
208*c2c66affSColin Finck {
209*c2c66affSColin Finck //ULONG stageLength;
210*c2c66affSColin Finck NTSTATUS ntStatus;
211*c2c66affSColin Finck //PIO_STACK_LOCATION nextStack;
212*c2c66affSColin Finck PFREEBT_RW_CONTEXT rwContext;
213*c2c66affSColin Finck PDEVICE_EXTENSION deviceExtension;
214*c2c66affSColin Finck
215*c2c66affSColin Finck deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
216*c2c66affSColin Finck rwContext = (PFREEBT_RW_CONTEXT) Context;
217*c2c66affSColin Finck ntStatus = Irp->IoStatus.Status;
218*c2c66affSColin Finck
219*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceObject);
220*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ReadCompletion: Entered\n"));
221*c2c66affSColin Finck
222*c2c66affSColin Finck if (NT_SUCCESS(ntStatus))
223*c2c66affSColin Finck {
224*c2c66affSColin Finck Irp->IoStatus.Information = rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
225*c2c66affSColin Finck
226*c2c66affSColin Finck }
227*c2c66affSColin Finck
228*c2c66affSColin Finck else
229*c2c66affSColin Finck {
230*c2c66affSColin Finck Irp->IoStatus.Information = 0;
231*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_ReadCompletion: - failed with status = %X\n", ntStatus));
232*c2c66affSColin Finck
233*c2c66affSColin Finck }
234*c2c66affSColin Finck
235*c2c66affSColin Finck if (rwContext)
236*c2c66affSColin Finck {
237*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ReadCompletion: ::"));
238*c2c66affSColin Finck FreeBT_IoDecrement(deviceExtension);
239*c2c66affSColin Finck
240*c2c66affSColin Finck ExFreePool(rwContext->Urb);
241*c2c66affSColin Finck IoFreeMdl(rwContext->Mdl);
242*c2c66affSColin Finck ExFreePool(rwContext);
243*c2c66affSColin Finck
244*c2c66affSColin Finck }
245*c2c66affSColin Finck
246*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ReadCompletion: Leaving\n"));
247*c2c66affSColin Finck
248*c2c66affSColin Finck return ntStatus;
249*c2c66affSColin Finck
250*c2c66affSColin Finck }
251*c2c66affSColin Finck
252*c2c66affSColin Finck // Read/Write handler
FreeBT_DispatchWrite(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)253*c2c66affSColin Finck NTSTATUS NTAPI FreeBT_DispatchWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
254*c2c66affSColin Finck {
255*c2c66affSColin Finck PMDL mdl;
256*c2c66affSColin Finck PURB urb;
257*c2c66affSColin Finck ULONG totalLength;
258*c2c66affSColin Finck ULONG stageLength;
259*c2c66affSColin Finck NTSTATUS ntStatus;
260*c2c66affSColin Finck ULONG_PTR virtualAddress;
261*c2c66affSColin Finck PFILE_OBJECT fileObject;
262*c2c66affSColin Finck PDEVICE_EXTENSION deviceExtension;
263*c2c66affSColin Finck PIO_STACK_LOCATION irpStack;
264*c2c66affSColin Finck PIO_STACK_LOCATION nextStack;
265*c2c66affSColin Finck PFREEBT_RW_CONTEXT rwContext;
266*c2c66affSColin Finck //ULONG maxLength=0;
267*c2c66affSColin Finck
268*c2c66affSColin Finck urb = NULL;
269*c2c66affSColin Finck mdl = NULL;
270*c2c66affSColin Finck rwContext = NULL;
271*c2c66affSColin Finck totalLength = 0;
272*c2c66affSColin Finck irpStack = IoGetCurrentIrpStackLocation(Irp);
273*c2c66affSColin Finck fileObject = irpStack->FileObject;
274*c2c66affSColin Finck deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
275*c2c66affSColin Finck
276*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite: Entered\n"));
277*c2c66affSColin Finck
278*c2c66affSColin Finck if (deviceExtension->DeviceState != Working)
279*c2c66affSColin Finck {
280*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Invalid device state\n"));
281*c2c66affSColin Finck ntStatus = STATUS_INVALID_DEVICE_STATE;
282*c2c66affSColin Finck goto FreeBT_DispatchWrite_Exit;
283*c2c66affSColin Finck
284*c2c66affSColin Finck }
285*c2c66affSColin Finck
286*c2c66affSColin Finck // Make sure that any selective suspend request has been completed.
287*c2c66affSColin Finck if (deviceExtension->SSEnable)
288*c2c66affSColin Finck {
289*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteDispatch: Waiting on the IdleReqPendEvent\n"));
290*c2c66affSColin Finck KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
291*c2c66affSColin Finck Executive,
292*c2c66affSColin Finck KernelMode,
293*c2c66affSColin Finck FALSE,
294*c2c66affSColin Finck NULL);
295*c2c66affSColin Finck
296*c2c66affSColin Finck }
297*c2c66affSColin Finck
298*c2c66affSColin Finck rwContext = (PFREEBT_RW_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(FREEBT_RW_CONTEXT));
299*c2c66affSColin Finck if (rwContext == NULL)
300*c2c66affSColin Finck {
301*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: Failed to alloc mem for rwContext\n"));
302*c2c66affSColin Finck ntStatus = STATUS_INSUFFICIENT_RESOURCES;
303*c2c66affSColin Finck goto FreeBT_DispatchWrite_Exit;
304*c2c66affSColin Finck
305*c2c66affSColin Finck }
306*c2c66affSColin Finck
307*c2c66affSColin Finck if (Irp->MdlAddress)
308*c2c66affSColin Finck {
309*c2c66affSColin Finck totalLength = MmGetMdlByteCount(Irp->MdlAddress);
310*c2c66affSColin Finck
311*c2c66affSColin Finck }
312*c2c66affSColin Finck
313*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Transfer data length = %d\n", totalLength));
314*c2c66affSColin Finck if (totalLength>FBT_HCI_DATA_MAX_SIZE)
315*c2c66affSColin Finck {
316*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Buffer exceeds maximum packet length (%d), failing IRP\n", FBT_HCI_DATA_MAX_SIZE));
317*c2c66affSColin Finck ntStatus = STATUS_INVALID_BUFFER_SIZE;
318*c2c66affSColin Finck ExFreePool(rwContext);
319*c2c66affSColin Finck goto FreeBT_DispatchWrite_Exit;
320*c2c66affSColin Finck
321*c2c66affSColin Finck }
322*c2c66affSColin Finck
323*c2c66affSColin Finck if (totalLength<FBT_HCI_DATA_MIN_SIZE)
324*c2c66affSColin Finck {
325*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Zero length buffer, completing IRP\n"));
326*c2c66affSColin Finck ntStatus = STATUS_BUFFER_TOO_SMALL;
327*c2c66affSColin Finck ExFreePool(rwContext);
328*c2c66affSColin Finck goto FreeBT_DispatchWrite_Exit;
329*c2c66affSColin Finck
330*c2c66affSColin Finck }
331*c2c66affSColin Finck
332*c2c66affSColin Finck virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);
333*c2c66affSColin Finck if (totalLength > deviceExtension->DataOutPipe.MaximumPacketSize)
334*c2c66affSColin Finck {
335*c2c66affSColin Finck stageLength = deviceExtension->DataOutPipe.MaximumPacketSize;
336*c2c66affSColin Finck
337*c2c66affSColin Finck }
338*c2c66affSColin Finck
339*c2c66affSColin Finck else
340*c2c66affSColin Finck {
341*c2c66affSColin Finck stageLength = totalLength;
342*c2c66affSColin Finck
343*c2c66affSColin Finck }
344*c2c66affSColin Finck
345*c2c66affSColin Finck mdl = IoAllocateMdl((PVOID) virtualAddress, totalLength, FALSE, FALSE, NULL);
346*c2c66affSColin Finck if (mdl == NULL)
347*c2c66affSColin Finck {
348*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Failed to alloc mem for mdl\n"));
349*c2c66affSColin Finck ntStatus = STATUS_INSUFFICIENT_RESOURCES;
350*c2c66affSColin Finck ExFreePool(rwContext);
351*c2c66affSColin Finck goto FreeBT_DispatchWrite_Exit;
352*c2c66affSColin Finck
353*c2c66affSColin Finck }
354*c2c66affSColin Finck
355*c2c66affSColin Finck // map the portion of user-buffer described by an mdl to another mdl
356*c2c66affSColin Finck IoBuildPartialMdl(Irp->MdlAddress, mdl, (PVOID) virtualAddress, stageLength);
357*c2c66affSColin Finck urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
358*c2c66affSColin Finck if (urb == NULL)
359*c2c66affSColin Finck {
360*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: Failed to alloc mem for urb\n"));
361*c2c66affSColin Finck ntStatus = STATUS_INSUFFICIENT_RESOURCES;
362*c2c66affSColin Finck ExFreePool(rwContext);
363*c2c66affSColin Finck IoFreeMdl(mdl);
364*c2c66affSColin Finck goto FreeBT_DispatchWrite_Exit;
365*c2c66affSColin Finck
366*c2c66affSColin Finck }
367*c2c66affSColin Finck
368*c2c66affSColin Finck UsbBuildInterruptOrBulkTransferRequest(
369*c2c66affSColin Finck urb,
370*c2c66affSColin Finck sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
371*c2c66affSColin Finck deviceExtension->DataOutPipe.PipeHandle,
372*c2c66affSColin Finck NULL,
373*c2c66affSColin Finck mdl,
374*c2c66affSColin Finck stageLength,
375*c2c66affSColin Finck USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_OUT,
376*c2c66affSColin Finck NULL);
377*c2c66affSColin Finck
378*c2c66affSColin Finck // set FREEBT_RW_CONTEXT parameters.
379*c2c66affSColin Finck rwContext->Urb = urb;
380*c2c66affSColin Finck rwContext->Mdl = mdl;
381*c2c66affSColin Finck rwContext->Length = totalLength - stageLength;
382*c2c66affSColin Finck rwContext->Numxfer = 0;
383*c2c66affSColin Finck rwContext->VirtualAddress = virtualAddress + stageLength;
384*c2c66affSColin Finck
385*c2c66affSColin Finck // use the original read/write irp as an internal device control irp
386*c2c66affSColin Finck nextStack = IoGetNextIrpStackLocation(Irp);
387*c2c66affSColin Finck nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
388*c2c66affSColin Finck nextStack->Parameters.Others.Argument1 = (PVOID) urb;
389*c2c66affSColin Finck nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
390*c2c66affSColin Finck IoSetCompletionRoutine(Irp,
391*c2c66affSColin Finck (PIO_COMPLETION_ROUTINE)FreeBT_WriteCompletion,
392*c2c66affSColin Finck rwContext,
393*c2c66affSColin Finck TRUE,
394*c2c66affSColin Finck TRUE,
395*c2c66affSColin Finck TRUE);
396*c2c66affSColin Finck
397*c2c66affSColin Finck // We return STATUS_PENDING; call IoMarkIrpPending.
398*c2c66affSColin Finck IoMarkIrpPending(Irp);
399*c2c66affSColin Finck
400*c2c66affSColin Finck ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
401*c2c66affSColin Finck if (!NT_SUCCESS(ntStatus))
402*c2c66affSColin Finck {
403*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_WriteDispatch: IoCallDriver fails with status %X\n", ntStatus));
404*c2c66affSColin Finck
405*c2c66affSColin Finck // if the device was yanked out, then the pipeInformation
406*c2c66affSColin Finck // field is invalid.
407*c2c66affSColin Finck // similarly if the request was cancelled, then we need not
408*c2c66affSColin Finck // invoked reset pipe/device.
409*c2c66affSColin Finck if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
410*c2c66affSColin Finck {
411*c2c66affSColin Finck ntStatus = FreeBT_ResetPipe(DeviceObject, deviceExtension->DataOutPipe.PipeHandle);
412*c2c66affSColin Finck if(!NT_SUCCESS(ntStatus))
413*c2c66affSColin Finck {
414*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_ResetPipe failed\n"));
415*c2c66affSColin Finck ntStatus = FreeBT_ResetDevice(DeviceObject);
416*c2c66affSColin Finck
417*c2c66affSColin Finck }
418*c2c66affSColin Finck
419*c2c66affSColin Finck }
420*c2c66affSColin Finck
421*c2c66affSColin Finck else
422*c2c66affSColin Finck {
423*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
424*c2c66affSColin Finck
425*c2c66affSColin Finck }
426*c2c66affSColin Finck
427*c2c66affSColin Finck }
428*c2c66affSColin Finck
429*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite::"));
430*c2c66affSColin Finck FreeBT_IoIncrement(deviceExtension);
431*c2c66affSColin Finck
432*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite: URB sent to lower driver, IRP is pending\n"));
433*c2c66affSColin Finck
434*c2c66affSColin Finck // we return STATUS_PENDING and not the status returned by the lower layer.
435*c2c66affSColin Finck return STATUS_PENDING;
436*c2c66affSColin Finck
437*c2c66affSColin Finck FreeBT_DispatchWrite_Exit:
438*c2c66affSColin Finck Irp->IoStatus.Status = ntStatus;
439*c2c66affSColin Finck Irp->IoStatus.Information = 0;
440*c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
441*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchWrite: Leaving\n"));
442*c2c66affSColin Finck
443*c2c66affSColin Finck return ntStatus;
444*c2c66affSColin Finck
445*c2c66affSColin Finck }
446*c2c66affSColin Finck
FreeBT_WriteCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)447*c2c66affSColin Finck NTSTATUS NTAPI FreeBT_WriteCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
448*c2c66affSColin Finck {
449*c2c66affSColin Finck ULONG stageLength;
450*c2c66affSColin Finck NTSTATUS ntStatus;
451*c2c66affSColin Finck PIO_STACK_LOCATION nextStack;
452*c2c66affSColin Finck PFREEBT_RW_CONTEXT rwContext;
453*c2c66affSColin Finck PDEVICE_EXTENSION deviceExtension;
454*c2c66affSColin Finck
455*c2c66affSColin Finck deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
456*c2c66affSColin Finck rwContext = (PFREEBT_RW_CONTEXT) Context;
457*c2c66affSColin Finck ntStatus = Irp->IoStatus.Status;
458*c2c66affSColin Finck
459*c2c66affSColin Finck UNREFERENCED_PARAMETER(DeviceObject);
460*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: Entered\n"));
461*c2c66affSColin Finck
462*c2c66affSColin Finck if (NT_SUCCESS(ntStatus))
463*c2c66affSColin Finck {
464*c2c66affSColin Finck if (rwContext)
465*c2c66affSColin Finck {
466*c2c66affSColin Finck rwContext->Numxfer += rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
467*c2c66affSColin Finck if (rwContext->Length)
468*c2c66affSColin Finck {
469*c2c66affSColin Finck // More data to transfer
470*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: Initiating next transfer\n"));
471*c2c66affSColin Finck if (rwContext->Length > deviceExtension->DataOutPipe.MaximumPacketSize)
472*c2c66affSColin Finck {
473*c2c66affSColin Finck stageLength = deviceExtension->DataOutPipe.MaximumPacketSize;
474*c2c66affSColin Finck
475*c2c66affSColin Finck }
476*c2c66affSColin Finck
477*c2c66affSColin Finck else
478*c2c66affSColin Finck {
479*c2c66affSColin Finck stageLength = rwContext->Length;
480*c2c66affSColin Finck
481*c2c66affSColin Finck }
482*c2c66affSColin Finck
483*c2c66affSColin Finck IoBuildPartialMdl(Irp->MdlAddress, rwContext->Mdl, (PVOID) rwContext->VirtualAddress, stageLength);
484*c2c66affSColin Finck
485*c2c66affSColin Finck // reinitialize the urb
486*c2c66affSColin Finck rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength;
487*c2c66affSColin Finck rwContext->VirtualAddress += stageLength;
488*c2c66affSColin Finck rwContext->Length -= stageLength;
489*c2c66affSColin Finck
490*c2c66affSColin Finck nextStack = IoGetNextIrpStackLocation(Irp);
491*c2c66affSColin Finck nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
492*c2c66affSColin Finck nextStack->Parameters.Others.Argument1 = rwContext->Urb;
493*c2c66affSColin Finck nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
494*c2c66affSColin Finck
495*c2c66affSColin Finck IoSetCompletionRoutine(Irp,
496*c2c66affSColin Finck FreeBT_ReadCompletion,
497*c2c66affSColin Finck rwContext,
498*c2c66affSColin Finck TRUE,
499*c2c66affSColin Finck TRUE,
500*c2c66affSColin Finck TRUE);
501*c2c66affSColin Finck
502*c2c66affSColin Finck IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
503*c2c66affSColin Finck
504*c2c66affSColin Finck return STATUS_MORE_PROCESSING_REQUIRED;
505*c2c66affSColin Finck
506*c2c66affSColin Finck }
507*c2c66affSColin Finck
508*c2c66affSColin Finck else
509*c2c66affSColin Finck {
510*c2c66affSColin Finck // No more data to transfer
511*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeNT_WriteCompletion: Write completed, %d bytes written\n", Irp->IoStatus.Information));
512*c2c66affSColin Finck Irp->IoStatus.Information = rwContext->Numxfer;
513*c2c66affSColin Finck
514*c2c66affSColin Finck }
515*c2c66affSColin Finck
516*c2c66affSColin Finck }
517*c2c66affSColin Finck
518*c2c66affSColin Finck }
519*c2c66affSColin Finck
520*c2c66affSColin Finck else
521*c2c66affSColin Finck {
522*c2c66affSColin Finck FreeBT_DbgPrint(1, ("FBTUSB: FreeNT_WriteCompletion - failed with status = %X\n", ntStatus));
523*c2c66affSColin Finck
524*c2c66affSColin Finck }
525*c2c66affSColin Finck
526*c2c66affSColin Finck if (rwContext)
527*c2c66affSColin Finck {
528*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: ::"));
529*c2c66affSColin Finck FreeBT_IoDecrement(deviceExtension);
530*c2c66affSColin Finck
531*c2c66affSColin Finck ExFreePool(rwContext->Urb);
532*c2c66affSColin Finck IoFreeMdl(rwContext->Mdl);
533*c2c66affSColin Finck ExFreePool(rwContext);
534*c2c66affSColin Finck
535*c2c66affSColin Finck }
536*c2c66affSColin Finck
537*c2c66affSColin Finck
538*c2c66affSColin Finck FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_WriteCompletion: Leaving\n"));
539*c2c66affSColin Finck
540*c2c66affSColin Finck return ntStatus;
541*c2c66affSColin Finck
542*c2c66affSColin Finck }
543*c2c66affSColin Finck
544