xref: /reactos/drivers/bluetooth/fbtusb/fbtrwr.c (revision c2c66aff)
1*c2c66affSColin Finck // Copyright (c) 2004, Antony C. Roberts
2*c2c66affSColin Finck 
3*c2c66affSColin Finck // Use of this file is subject to the terms
4*c2c66affSColin Finck // described in the LICENSE.TXT file that
5*c2c66affSColin Finck // accompanies this file.
6*c2c66affSColin Finck //
7*c2c66affSColin Finck // Your use of this file indicates your
8*c2c66affSColin Finck // acceptance of the terms described in
9*c2c66affSColin Finck // LICENSE.TXT.
10*c2c66affSColin Finck //
11*c2c66affSColin Finck // http://www.freebt.net
12*c2c66affSColin Finck 
13*c2c66affSColin Finck #include "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