ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fbtdev.c
Go to the documentation of this file.
00001 // Copyright (c) 2004, Antony C. Roberts
00002 
00003 // Use of this file is subject to the terms
00004 // described in the LICENSE.TXT file that
00005 // accompanies this file.
00006 //
00007 // Your use of this file indicates your
00008 // acceptance of the terms described in
00009 // LICENSE.TXT.
00010 //
00011 // http://www.freebt.net
00012 
00013 #include "fbtusb.h"
00014 #include "fbtpnp.h"
00015 #include "fbtpwr.h"
00016 #include "fbtdev.h"
00017 #include "fbtwmi.h"
00018 #include "fbtrwr.h"
00019 
00020 #include "fbtusr.h"
00021 
00022 // Dispatch routine for CreateHandle
00023 NTSTATUS FreeBT_DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00024 {
00025     //ULONG                       i;
00026     NTSTATUS                    ntStatus;
00027     PFILE_OBJECT                fileObject;
00028     PDEVICE_EXTENSION           deviceExtension;
00029     PIO_STACK_LOCATION          irpStack;
00030     //PFREEBT_PIPE_CONTEXT        pipeContext;
00031     PUSBD_INTERFACE_INFORMATION interface;
00032 
00033     PAGED_CODE();
00034 
00035     FreeBT_DbgPrint(3, ("FreeBT_DispatchCreate: Entered\n"));
00036 
00037     irpStack = IoGetCurrentIrpStackLocation(Irp);
00038     fileObject = irpStack->FileObject;
00039     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00040 
00041     if (deviceExtension->DeviceState != Working)
00042     {
00043         ntStatus = STATUS_INVALID_DEVICE_STATE;
00044         goto FreeBT_DispatchCreate_Exit;
00045 
00046     }
00047 
00048     if (deviceExtension->UsbInterface)
00049     {
00050         interface = deviceExtension->UsbInterface;
00051 
00052     }
00053 
00054     else
00055     {
00056         FreeBT_DbgPrint(1, ("UsbInterface not found\n"));
00057         ntStatus = STATUS_INVALID_DEVICE_STATE;
00058         goto FreeBT_DispatchCreate_Exit;
00059 
00060     }
00061 
00062     if (fileObject)
00063     {
00064         fileObject->FsContext = NULL;
00065     }
00066 
00067     else
00068     {
00069         ntStatus = STATUS_INVALID_PARAMETER;
00070         goto FreeBT_DispatchCreate_Exit;
00071 
00072     }
00073 
00074     if (deviceExtension->OpenHandleCount>0)
00075     {
00076         ntStatus = STATUS_ACCESS_VIOLATION;
00077         goto FreeBT_DispatchCreate_Exit;
00078 
00079     }
00080 
00081     // opening a device as opposed to pipe.
00082     ntStatus = STATUS_SUCCESS;
00083 
00084     InterlockedIncrement(&deviceExtension->OpenHandleCount);
00085 
00086     // the device is idle if it has no open handles or pending PnP Irps
00087     // since we just received an open handle request, cancel idle req.
00088     if (deviceExtension->SSEnable)
00089         CancelSelectSuspend(deviceExtension);
00090 
00091 FreeBT_DispatchCreate_Exit:
00092     Irp->IoStatus.Status = ntStatus;
00093     Irp->IoStatus.Information = 0;
00094     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00095 
00096     FreeBT_DbgPrint(3, ("FreeBT_DispatchCreate: Leaving\n"));
00097     return ntStatus;
00098 
00099 }
00100 
00101 // Dispatch routine for CloseHandle
00102 NTSTATUS FreeBT_DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00103 {
00104     NTSTATUS               ntStatus;
00105     PFILE_OBJECT           fileObject;
00106     PDEVICE_EXTENSION      deviceExtension;
00107     PIO_STACK_LOCATION     irpStack;
00108     //PFREEBT_PIPE_CONTEXT  pipeContext;
00109     //PUSBD_PIPE_INFORMATION pipeInformation;
00110 
00111     PAGED_CODE();
00112 
00113     irpStack = IoGetCurrentIrpStackLocation(Irp);
00114     fileObject = irpStack->FileObject;
00115     //pipeContext = NULL;
00116     //pipeInformation = NULL;
00117     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00118 
00119     FreeBT_DbgPrint(3, ("FreeBT_DispatchClose: Entered\n"));
00120 
00121     ntStatus = STATUS_SUCCESS;
00122     Irp->IoStatus.Status = ntStatus;
00123     Irp->IoStatus.Information = 0;
00124     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00125 
00126     InterlockedDecrement(&deviceExtension->OpenHandleCount);
00127 
00128     FreeBT_DbgPrint(3, ("FreeBT_DispatchClose: Leaving\n"));
00129 
00130     return ntStatus;
00131 
00132 }
00133 
00134 // Called when a HCI Send on the control pipe completes
00135 NTSTATUS FreeBT_HCISendCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
00136 {
00137     //ULONG               stageLength;
00138     NTSTATUS            ntStatus;
00139 
00140     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_HCISendCompletion, status=0x%08X\n", Irp->IoStatus.Status));
00141 
00142     if (Irp->PendingReturned)
00143         IoMarkIrpPending(Irp);
00144 
00145     ExFreePool(Context);
00146     FreeBT_IoDecrement(DeviceObject->DeviceExtension);
00147     ntStatus = Irp->IoStatus.Status;
00148     Irp->IoStatus.Information = 0;
00149 
00150     return ntStatus;
00151 
00152 }
00153 
00154 // Called the DeviceIOControl handler to send an HCI command received from the user
00155 // HCI Commands are sent on the (default) control pipe
00156 NTSTATUS FreeBT_SendHCICommand(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID IoBuffer, IN ULONG InputBufferLength)
00157 {
00158     PDEVICE_EXTENSION   deviceExtension;
00159     //ULONG               urbFlags;
00160     //ULONG               stageLength;
00161     //PVOID               pBuffer;
00162     PURB                urb;
00163     NTSTATUS            ntStatus;
00164     PIO_STACK_LOCATION  nextStack;
00165     //PFBT_HCI_CMD_HEADER pHCICommand;
00166     //LARGE_INTEGER       delay;
00167 
00168     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00169     if (!deviceExtension)
00170     {
00171         ntStatus=STATUS_INVALID_PARAMETER;
00172         FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Failed to get DeviceExtension\n"));
00173         Irp->IoStatus.Status = ntStatus;
00174         Irp->IoStatus.Information = 0;
00175         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00176         return ntStatus;
00177 
00178     }
00179 
00180     // The user is doing a reset, reset all the pipes as well, so that any
00181     // old events or data are removed
00182     /*pHCICommand=(PFBT_HCI_CMD_HEADER)IoBuffer;
00183     if (pHCICommand->OpCode==FBT_HCI_CMD_RESET)
00184     {
00185         FreeBT_ResetPipe(DeviceObject, deviceExtension->EventPipe.PipeHandle);
00186         FreeBT_ResetPipe(DeviceObject, deviceExtension->DataInPipe.PipeHandle);
00187         FreeBT_ResetPipe(DeviceObject, deviceExtension->DataOutPipe.PipeHandle);
00188         FreeBT_ResetPipe(DeviceObject, deviceExtension->AudioInPipe.PipeHandle);
00189         FreeBT_ResetPipe(DeviceObject, deviceExtension->AudioOutPipe.PipeHandle);
00190 
00191         // Wait a second for the device to recover
00192         FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Sleeping\n"));
00193         delay.QuadPart = -10000 * 5000; // 5s
00194         KeWaitForSingleObject(&deviceExtension->DelayEvent,
00195                               Executive,
00196                               UserMode,
00197                               FALSE,
00198                               &delay);
00199 
00200         FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Finished sleeping\n"));
00201 
00202 
00203     }*/
00204 
00205     // Create the URB
00206     urb = (PURB)ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
00207     if(urb == NULL)
00208     {
00209         FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_SendHCICommand: Failed to alloc mem for urb\n"));
00210         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00211         Irp->IoStatus.Status = ntStatus;
00212         Irp->IoStatus.Information = 0;
00213         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00214         return ntStatus;
00215 
00216     }
00217 
00218     UsbBuildVendorRequest(
00219         urb,
00220         URB_FUNCTION_CLASS_DEVICE, // This works, for CSR and Silicon Wave
00221         sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
00222         0,
00223         0,
00224         0,
00225         0,
00226         0,
00227         IoBuffer,
00228         NULL,
00229         InputBufferLength,
00230         NULL);
00231 
00232     // use the original irp as an internal device control irp
00233     nextStack = IoGetNextIrpStackLocation(Irp);
00234     nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
00235     nextStack->Parameters.Others.Argument1 = (PVOID) urb;
00236     nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
00237 
00238     IoSetCompletionRoutine(
00239         Irp,
00240         (PIO_COMPLETION_ROUTINE)FreeBT_HCISendCompletion,
00241         urb,
00242         TRUE,
00243         TRUE,
00244         TRUE);
00245 
00246     // We return STATUS_PENDING; call IoMarkIrpPending.
00247     IoMarkIrpPending(Irp);
00248 
00249     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand::"));
00250     FreeBT_IoIncrement(deviceExtension);
00251 
00252     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: Sending IRP %X to underlying driver\n", Irp));
00253     ntStatus=IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00254     if(!NT_SUCCESS(ntStatus))
00255     {
00256         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: IoCallDriver fails with status %X\n", ntStatus));
00257 
00258         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand::"));
00259         FreeBT_IoDecrement(deviceExtension);
00260 
00261         // If the device was surprise removed out, the pipeInformation field is invalid.
00262         // similarly if the request was cancelled, then we need not reset the device.
00263         if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
00264             ntStatus = FreeBT_ResetDevice(DeviceObject);
00265 
00266         else
00267             FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
00268 
00269         Irp->IoStatus.Status = ntStatus;
00270         Irp->IoStatus.Information = 0;
00271         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00272 
00273         return ntStatus;
00274 
00275     }
00276 
00277     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SendHCICommand: Completed successfully\n"));
00278 
00279     return STATUS_PENDING;
00280 
00281 }
00282 
00283 // Called when a HCI Get on the event pipe completes
00284 NTSTATUS FreeBT_HCIEventCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
00285 {
00286     //ULONG               stageLength;
00287     NTSTATUS            ntStatus;
00288     PIO_STACK_LOCATION  nextStack;
00289     PURB                urb;
00290 
00291     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_HCIEventCompletion, status=0x%08X\n", Irp->IoStatus.Status));
00292 
00293     if (Irp->PendingReturned)
00294         IoMarkIrpPending(Irp);
00295 
00296     // initialize variables
00297     urb=(PURB)Context;
00298     ntStatus = Irp->IoStatus.Status;
00299     Irp->IoStatus.Information = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
00300     nextStack = IoGetNextIrpStackLocation(Irp);
00301 
00302     ExFreePool(Context);
00303     FreeBT_IoDecrement(DeviceObject->DeviceExtension);
00304 
00305     return ntStatus;
00306 
00307 }
00308 
00309 // Called from the DeviceIOControl handler to wait for an event on the interrupt pipe
00310 NTSTATUS FreeBT_GetHCIEvent(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID IoBuffer, IN ULONG InputBufferLength)
00311 {
00312     PDEVICE_EXTENSION   deviceExtension;
00313     PURB                urb;
00314     NTSTATUS            ntStatus;
00315     PIO_STACK_LOCATION  nextStack;
00316 
00317     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: Entered\n"));
00318 
00319     urb = NULL;
00320     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00321 
00322     urb = (PURB)ExAllocatePool(NonPagedPool, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
00323     if (urb==NULL)
00324     {
00325         FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_GetHCIEvent: Failed to alloc mem for urb\n"));
00326         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00327         goto FreeBT_GetHCIEvent_Exit;
00328 
00329     }
00330 
00331     UsbBuildInterruptOrBulkTransferRequest(
00332                             urb,
00333                             sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
00334                             deviceExtension->EventPipe.PipeHandle,
00335                             IoBuffer,
00336                             NULL,
00337                             InputBufferLength,
00338                             USBD_SHORT_TRANSFER_OK|USBD_TRANSFER_DIRECTION_IN,
00339                             NULL);
00340 
00341     // use the original irp as an internal device control irp, which we send down to the
00342     // USB class driver in order to get our request out on the wire
00343     nextStack = IoGetNextIrpStackLocation(Irp);
00344     nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
00345     nextStack->Parameters.Others.Argument1 = (PVOID) urb;
00346     nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
00347 
00348     IoSetCompletionRoutine(
00349         Irp,
00350         (PIO_COMPLETION_ROUTINE)FreeBT_HCIEventCompletion,
00351         urb,
00352         TRUE,
00353         TRUE,
00354         TRUE);
00355 
00356     // We return STATUS_PENDING; call IoMarkIrpPending.
00357     IoMarkIrpPending(Irp);
00358 
00359     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent::"));
00360     FreeBT_IoIncrement(deviceExtension);
00361 
00362     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00363     if (!NT_SUCCESS(ntStatus))
00364     {
00365         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: IoCallDriver fails with status %X\n", ntStatus));
00366 
00367         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent::"));
00368         FreeBT_IoDecrement(deviceExtension);
00369 
00370         // If the device was surprise removed out, the pipeInformation field is invalid.
00371         // similarly if the request was cancelled, then we need not reset the pipe.
00372         if((ntStatus != STATUS_CANCELLED) && (ntStatus != STATUS_DEVICE_NOT_CONNECTED))
00373         {
00374             ntStatus = FreeBT_ResetPipe(DeviceObject, deviceExtension->EventPipe.PipeHandle);
00375             if(!NT_SUCCESS(ntStatus))
00376             {
00377                 FreeBT_DbgPrint(1, ("FreeBT_ResetPipe failed\n"));
00378                 ntStatus = FreeBT_ResetDevice(DeviceObject);
00379 
00380             }
00381 
00382         }
00383 
00384         else
00385         {
00386             FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: ntStatus is STATUS_CANCELLED or STATUS_DEVICE_NOT_CONNECTED\n"));
00387 
00388         }
00389 
00390         goto FreeBT_GetHCIEvent_Exit;
00391 
00392     }
00393 
00394     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: Leaving\n"));
00395 
00396     // Return STATUS_PENDING, when the lower driver completes the request,
00397     // the FreeBT_HCIEventCompletion completion routine.
00398     return STATUS_PENDING;
00399 
00400 FreeBT_GetHCIEvent_Exit:
00401     Irp->IoStatus.Status=ntStatus;
00402     Irp->IoStatus.Information=0;
00403 
00404     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetHCIEvent: Failure (0x%08x), completing IRP\n", ntStatus));
00405     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00406 
00407     return ntStatus;
00408 
00409 }
00410 
00411 // DeviceIOControl dispatch
00412 NTSTATUS FreeBT_DispatchDevCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00413 {
00414     ULONG              code;
00415     PVOID              ioBuffer;
00416     ULONG              inputBufferLength;
00417     ULONG              outputBufferLength;
00418     ULONG              info;
00419     NTSTATUS           ntStatus;
00420     PDEVICE_EXTENSION  deviceExtension;
00421     PIO_STACK_LOCATION irpStack;
00422 
00423     info = 0;
00424     irpStack = IoGetCurrentIrpStackLocation(Irp);
00425     code = irpStack->Parameters.DeviceIoControl.IoControlCode;
00426     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00427 
00428     ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
00429     inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
00430     outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
00431 
00432     if (deviceExtension->DeviceState != Working)
00433     {
00434         FreeBT_DbgPrint(1, ("FBTUSB: Invalid device state\n"));
00435         ntStatus = STATUS_INVALID_DEVICE_STATE;
00436         goto FreeBT_DispatchDevCtrlExit;
00437 
00438     }
00439 
00440     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchDevCtrl::"));
00441 
00442     // Make sure that any selective suspend request has been completed.
00443     if (deviceExtension->SSEnable)
00444     {
00445         FreeBT_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));
00446         KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
00447                               Executive,
00448                               KernelMode,
00449                               FALSE,
00450                               NULL);
00451 
00452     }
00453 
00454     switch(code)
00455     {
00456     case IOCTL_FREEBT_HCI_SEND_CMD:
00457         FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_SEND_CMD received\n"));
00458         if (inputBufferLength<FBT_HCI_CMD_MIN_SIZE)
00459         {
00460             ntStatus = STATUS_BUFFER_TOO_SMALL;
00461             FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_SEND_CMD: Buffer too small\n"));
00462             goto FreeBT_DispatchDevCtrlExit;
00463 
00464         }
00465 
00466         if (inputBufferLength>FBT_HCI_CMD_MAX_SIZE)
00467         {
00468             ntStatus = STATUS_INVALID_BUFFER_SIZE;
00469             FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_SEND_CMD: Buffer too long\n"));
00470             goto FreeBT_DispatchDevCtrlExit;
00471 
00472         }
00473 
00474         return FreeBT_SendHCICommand(DeviceObject, Irp, ioBuffer, inputBufferLength);
00475         break;
00476 
00477     case IOCTL_FREEBT_HCI_GET_EVENT:
00478         FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_GET_EVENT received\n"));
00479         if (outputBufferLength<FBT_HCI_EVENT_MAX_SIZE)
00480         {
00481             ntStatus = STATUS_BUFFER_TOO_SMALL;
00482             FreeBT_DbgPrint(3, ("FBTUSB: IOCTL_FREEBT_HCI_GET_EVENT: Buffer too small\n"));
00483             goto FreeBT_DispatchDevCtrlExit;
00484 
00485         }
00486 
00487         return FreeBT_GetHCIEvent(DeviceObject, Irp, ioBuffer, outputBufferLength);
00488         break;
00489 
00490     default:
00491         FreeBT_DbgPrint(3, ("FBTUSB: Invalid IOCTL 0x%08x received\n", code));
00492         ntStatus = STATUS_INVALID_DEVICE_REQUEST;
00493         break;
00494 
00495     }
00496 
00497 FreeBT_DispatchDevCtrlExit:
00498     Irp->IoStatus.Information = 0;
00499     Irp->IoStatus.Status = ntStatus;
00500     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00501 
00502     return ntStatus;
00503 }
00504 
00505 // Submit URB_FUNCTION_RESET_PIPE
00506 NTSTATUS FreeBT_ResetPipe(IN PDEVICE_OBJECT DeviceObject, IN USBD_PIPE_HANDLE PipeHandle)
00507 {
00508     PURB              urb;
00509     NTSTATUS          ntStatus;
00510     PDEVICE_EXTENSION deviceExtension;
00511 
00512     urb = NULL;
00513     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00514 
00515     urb = (PURB)ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
00516     if (urb)
00517     {
00518         urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
00519         urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
00520         urb->UrbPipeRequest.PipeHandle = PipeHandle;
00521 
00522         ntStatus = CallUSBD(DeviceObject, urb);
00523 
00524         ExFreePool(urb);
00525 
00526     }
00527 
00528     else
00529         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00530 
00531     if(NT_SUCCESS(ntStatus))
00532     {
00533         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_ResetPipe - success\n"));
00534         ntStatus = STATUS_SUCCESS;
00535 
00536     }
00537 
00538     else
00539         FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_ResetPipe - failed\n"));
00540 
00541     return ntStatus;
00542 
00543 }
00544 
00545 // Call FreeBT_ResetParentPort to reset the device
00546 NTSTATUS FreeBT_ResetDevice(IN PDEVICE_OBJECT DeviceObject)
00547 {
00548     NTSTATUS ntStatus;
00549     ULONG    portStatus;
00550 
00551     FreeBT_DbgPrint(3, ("FreeBT_ResetDevice: Entered\n"));
00552 
00553     ntStatus = FreeBT_GetPortStatus(DeviceObject, &portStatus);
00554 
00555     if ( (NT_SUCCESS(ntStatus)) && (!(portStatus & USBD_PORT_ENABLED)) && (portStatus & USBD_PORT_CONNECTED))
00556         ntStatus=FreeBT_ResetParentPort(DeviceObject);
00557 
00558     FreeBT_DbgPrint(3, ("FreeBT_ResetDevice: Leaving\n"));
00559 
00560     return ntStatus;
00561 
00562 }
00563 
00564 // Read port status from the lower driver (USB class driver)
00565 NTSTATUS FreeBT_GetPortStatus(IN PDEVICE_OBJECT DeviceObject, IN OUT PULONG PortStatus)
00566 {
00567     NTSTATUS           ntStatus;
00568     KEVENT             event;
00569     PIRP               irp;
00570     IO_STATUS_BLOCK    ioStatus;
00571     PIO_STACK_LOCATION nextStack;
00572     PDEVICE_EXTENSION  deviceExtension;
00573 
00574     FreeBT_DbgPrint(3, ("FreeBT_GetPortStatus: Entered\n"));
00575 
00576     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00577     *PortStatus = 0;
00578 
00579     KeInitializeEvent(&event, NotificationEvent, FALSE);
00580     irp = IoBuildDeviceIoControlRequest(
00581                     IOCTL_INTERNAL_USB_GET_PORT_STATUS,
00582                     deviceExtension->TopOfStackDeviceObject,
00583                     NULL,
00584                     0,
00585                     NULL,
00586                     0,
00587                     TRUE,
00588                     &event,
00589                     &ioStatus);
00590 
00591     if (NULL == irp)
00592     {
00593         FreeBT_DbgPrint(1, ("memory alloc for irp failed\n"));
00594         return STATUS_INSUFFICIENT_RESOURCES;
00595 
00596     }
00597 
00598     nextStack = IoGetNextIrpStackLocation(irp);
00599     ASSERT(nextStack != NULL);
00600     nextStack->Parameters.Others.Argument1 = PortStatus;
00601 
00602     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
00603     if (STATUS_PENDING==ntStatus)
00604         KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
00605 
00606     else
00607         ioStatus.Status = ntStatus;
00608 
00609     ntStatus = ioStatus.Status;
00610     FreeBT_DbgPrint(3, ("FreeBT_GetPortStatus: Leaving\n"));
00611 
00612     return ntStatus;
00613 
00614 }
00615 
00616 // Sends an IOCTL_INTERNAL_USB_RESET_PORT via the lower driver
00617 NTSTATUS FreeBT_ResetParentPort(IN PDEVICE_OBJECT DeviceObject)
00618 {
00619     NTSTATUS           ntStatus;
00620     KEVENT             event;
00621     PIRP               irp;
00622     IO_STATUS_BLOCK    ioStatus;
00623     PIO_STACK_LOCATION nextStack;
00624     PDEVICE_EXTENSION  deviceExtension;
00625 
00626     FreeBT_DbgPrint(3, ("FreeBT_ResetParentPort: Entered\n"));
00627 
00628     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00629 
00630     KeInitializeEvent(&event, NotificationEvent, FALSE);
00631     irp = IoBuildDeviceIoControlRequest(
00632                     IOCTL_INTERNAL_USB_RESET_PORT,
00633                     deviceExtension->TopOfStackDeviceObject,
00634                     NULL,
00635                     0,
00636                     NULL,
00637                     0,
00638                     TRUE,
00639                     &event,
00640                     &ioStatus);
00641 
00642     if (NULL == irp)
00643     {
00644         FreeBT_DbgPrint(1, ("memory alloc for irp failed\n"));
00645         return STATUS_INSUFFICIENT_RESOURCES;
00646 
00647     }
00648 
00649     nextStack = IoGetNextIrpStackLocation(irp);
00650     ASSERT(nextStack != NULL);
00651 
00652     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
00653     if(STATUS_PENDING == ntStatus)
00654         KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
00655 
00656     else
00657         ioStatus.Status = ntStatus;
00658 
00659 
00660     ntStatus = ioStatus.Status;
00661 
00662     FreeBT_DbgPrint(3, ("FreeBT_ResetParentPort: Leaving\n"));
00663 
00664     return ntStatus;
00665 
00666 }
00667 
00668 // Send an idle request to the lower driver
00669 NTSTATUS SubmitIdleRequestIrp(IN PDEVICE_EXTENSION DeviceExtension)
00670 {
00671     PIRP                    irp;
00672     NTSTATUS                ntStatus;
00673     KIRQL                   oldIrql;
00674     PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
00675     PIO_STACK_LOCATION      nextStack;
00676 
00677     FreeBT_DbgPrint(3, ("SubmitIdleRequest: Entered\n"));
00678 
00679     irp = NULL;
00680     idleCallbackInfo = NULL;
00681 
00682     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
00683 
00684     if(PowerDeviceD0 != DeviceExtension->DevPower) {
00685 
00686         ntStatus = STATUS_POWER_STATE_INVALID;
00687 
00688         goto SubmitIdleRequestIrp_Exit;
00689     }
00690 
00691     KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
00692 
00693     if(InterlockedExchange(&DeviceExtension->IdleReqPend, 1)) {
00694 
00695         FreeBT_DbgPrint(1, ("Idle request pending..\n"));
00696 
00697         KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
00698 
00699         ntStatus = STATUS_DEVICE_BUSY;
00700 
00701         goto SubmitIdleRequestIrp_Exit;
00702     }
00703 
00704     //
00705     // clear the NoIdleReqPendEvent because we are about
00706     // to submit an idle request. Since we are so early
00707     // to clear this event, make sure that if we fail this
00708     // request we set back the event.
00709     //
00710     KeClearEvent(&DeviceExtension->NoIdleReqPendEvent);
00711 
00712     idleCallbackInfo = (PUSB_IDLE_CALLBACK_INFO)ExAllocatePool(NonPagedPool, sizeof(struct _USB_IDLE_CALLBACK_INFO));
00713 
00714     if(idleCallbackInfo) {
00715 
00716         idleCallbackInfo->IdleCallback = (USB_IDLE_CALLBACK)IdleNotificationCallback;
00717 
00718         idleCallbackInfo->IdleContext = (PVOID)DeviceExtension;
00719 
00720         ASSERT(DeviceExtension->IdleCallbackInfo == NULL);
00721 
00722         DeviceExtension->IdleCallbackInfo = idleCallbackInfo;
00723 
00724         //
00725         // we use IoAllocateIrp to create an irp to selectively suspend the
00726         // device. This irp lies pending with the hub driver. When appropriate
00727         // the hub driver will invoked callback, where we power down. The completion
00728         // routine is invoked when we power back.
00729         //
00730         irp = IoAllocateIrp(DeviceExtension->TopOfStackDeviceObject->StackSize,
00731                             FALSE);
00732 
00733         if(irp == NULL) {
00734 
00735             FreeBT_DbgPrint(1, ("cannot build idle request irp\n"));
00736 
00737             KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
00738                        IO_NO_INCREMENT,
00739                        FALSE);
00740 
00741             InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
00742 
00743             KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
00744 
00745             ExFreePool(idleCallbackInfo);
00746 
00747             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00748 
00749             goto SubmitIdleRequestIrp_Exit;
00750         }
00751 
00752         nextStack = IoGetNextIrpStackLocation(irp);
00753 
00754         nextStack->MajorFunction =
00755                     IRP_MJ_INTERNAL_DEVICE_CONTROL;
00756 
00757         nextStack->Parameters.DeviceIoControl.IoControlCode =
00758                     IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION;
00759 
00760         nextStack->Parameters.DeviceIoControl.Type3InputBuffer =
00761                     idleCallbackInfo;
00762 
00763         nextStack->Parameters.DeviceIoControl.InputBufferLength =
00764                     sizeof(struct _USB_IDLE_CALLBACK_INFO);
00765 
00766 
00767         IoSetCompletionRoutine(irp,
00768                                (PIO_COMPLETION_ROUTINE)IdleNotificationRequestComplete,
00769                                DeviceExtension,
00770                                TRUE,
00771                                TRUE,
00772                                TRUE);
00773 
00774         DeviceExtension->PendingIdleIrp = irp;
00775 
00776         //
00777         // we initialize the count to 2.
00778         // The reason is, if the CancelSelectSuspend routine manages
00779         // to grab the irp from the device extension, then the last of the
00780         // CancelSelectSuspend routine/IdleNotificationRequestComplete routine
00781         // to execute will free this irp. We need to have this schema so that
00782         // 1. completion routine does not attempt to touch the irp freed by
00783         //    CancelSelectSuspend routine.
00784         // 2. CancelSelectSuspend routine doesnt wait for ever for the completion
00785         //    routine to complete!
00786         //
00787         DeviceExtension->FreeIdleIrpCount = 2;
00788 
00789         KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
00790 
00791         //
00792         // check if the device is idle.
00793         // A check here ensures that a race condition did not
00794         // completely reverse the call sequence of SubmitIdleRequestIrp
00795         // and CancelSelectiveSuspend
00796         //
00797 
00798         if(!CanDeviceSuspend(DeviceExtension) ||
00799            PowerDeviceD0 != DeviceExtension->DevPower) {
00800 
00801             //
00802             // IRPs created using IoBuildDeviceIoControlRequest should be
00803             // completed by calling IoCompleteRequest and not merely
00804             // deallocated.
00805             //
00806 
00807             FreeBT_DbgPrint(1, ("Device is not idle\n"));
00808 
00809             KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
00810 
00811             DeviceExtension->IdleCallbackInfo = NULL;
00812 
00813             DeviceExtension->PendingIdleIrp = NULL;
00814 
00815             KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
00816                        IO_NO_INCREMENT,
00817                        FALSE);
00818 
00819             InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
00820 
00821             KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
00822 
00823             if(idleCallbackInfo) {
00824 
00825                 ExFreePool(idleCallbackInfo);
00826             }
00827 
00828             //
00829             // it is still safe to touch the local variable "irp" here.
00830             // the irp has not been passed down the stack, the irp has
00831             // no cancellation routine. The worse position is that the
00832             // CancelSelectSuspend has run after we released the spin
00833             // lock above. It is still essential to free the irp.
00834             //
00835             if(irp) {
00836 
00837                 IoFreeIrp(irp);
00838             }
00839 
00840             ntStatus = STATUS_UNSUCCESSFUL;
00841 
00842             goto SubmitIdleRequestIrp_Exit;
00843         }
00844 
00845         FreeBT_DbgPrint(3, ("Cancel the timers\n"));
00846         //
00847         // Cancel the timer so that the DPCs are no longer fired.
00848         // Thus, we are making judicious usage of our resources.
00849         // we do not need DPCs because we already have an idle irp pending.
00850         // The timers are re-initialized in the completion routine.
00851         //
00852         KeCancelTimer(&DeviceExtension->Timer);
00853 
00854         ntStatus = IoCallDriver(DeviceExtension->TopOfStackDeviceObject, irp);
00855 
00856         if(!NT_SUCCESS(ntStatus)) {
00857 
00858             FreeBT_DbgPrint(1, ("IoCallDriver failed\n"));
00859 
00860             goto SubmitIdleRequestIrp_Exit;
00861         }
00862     }
00863     else {
00864 
00865         FreeBT_DbgPrint(1, ("Memory allocation for idleCallbackInfo failed\n"));
00866 
00867         KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
00868                    IO_NO_INCREMENT,
00869                    FALSE);
00870 
00871         InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
00872 
00873         KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
00874 
00875         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00876     }
00877 
00878 SubmitIdleRequestIrp_Exit:
00879 
00880     FreeBT_DbgPrint(3, ("SubmitIdleRequest: Leaving\n"));
00881 
00882     return ntStatus;
00883 }
00884 
00885 
00886 VOID IdleNotificationCallback(IN PDEVICE_EXTENSION DeviceExtension)
00887 {
00888     NTSTATUS                ntStatus;
00889     POWER_STATE             powerState;
00890     KEVENT                  irpCompletionEvent;
00891     PIRP_COMPLETION_CONTEXT irpContext;
00892 
00893     FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback: Entered\n"));
00894 
00895     //
00896     // Dont idle, if the device was just disconnected or being stopped
00897     // i.e. return for the following DeviceState(s)
00898     // NotStarted, Stopped, PendingStop, PendingRemove, SurpriseRemoved, Removed
00899     //
00900 
00901     if(DeviceExtension->DeviceState != Working) {
00902 
00903         return;
00904     }
00905 
00906     //
00907     // If there is not already a WW IRP pending, submit one now
00908     //
00909     if(DeviceExtension->WaitWakeEnable) {
00910 
00911         IssueWaitWake(DeviceExtension);
00912     }
00913 
00914 
00915     //
00916     // power down the device
00917     //
00918 
00919     irpContext = (PIRP_COMPLETION_CONTEXT)
00920                  ExAllocatePool(NonPagedPool,
00921                                 sizeof(IRP_COMPLETION_CONTEXT));
00922 
00923     if(!irpContext) {
00924 
00925         FreeBT_DbgPrint(1, ("FBTUSB: IdleNotificationCallback: Failed to alloc memory for irpContext\n"));
00926         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00927     }
00928     else {
00929 
00930         //
00931         // increment the count. In the HoldIoRequestWorkerRoutine, the
00932         // count is decremented twice (one for the system Irp and the
00933         // other for the device Irp. An increment here compensates for
00934         // the sytem irp..The decrement corresponding to this increment
00935         // is in the completion function
00936         //
00937 
00938         FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback::"));
00939         FreeBT_IoIncrement(DeviceExtension);
00940 
00941         powerState.DeviceState = (DEVICE_POWER_STATE) DeviceExtension->PowerDownLevel;
00942 
00943         KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE);
00944 
00945         irpContext->DeviceExtension = DeviceExtension;
00946         irpContext->Event = &irpCompletionEvent;
00947 
00948         ntStatus = PoRequestPowerIrp(
00949                           DeviceExtension->PhysicalDeviceObject,
00950                           IRP_MN_SET_POWER,
00951                           powerState,
00952                           (PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc,
00953                           irpContext,
00954                           NULL);
00955 
00956         if(STATUS_PENDING == ntStatus) {
00957 
00958             FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback::"
00959                            "waiting for the power irp to complete\n"));
00960 
00961             KeWaitForSingleObject(&irpCompletionEvent,
00962                                   Executive,
00963                                   KernelMode,
00964                                   FALSE,
00965                                   NULL);
00966         }
00967     }
00968 
00969     if(!NT_SUCCESS(ntStatus)) {
00970 
00971         if(irpContext) {
00972 
00973             ExFreePool(irpContext);
00974         }
00975     }
00976 
00977     FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationCallback: Leaving\n"));
00978 }
00979 
00980 
00981 NTSTATUS IdleNotificationRequestComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
00982 {
00983     NTSTATUS                ntStatus;
00984     POWER_STATE             powerState;
00985     KIRQL                   oldIrql;
00986     LARGE_INTEGER           dueTime;
00987     PIRP                    idleIrp;
00988     PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
00989 
00990     FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationRequestCompete: Entered\n"));
00991 
00992     idleIrp = NULL;
00993 
00994     ntStatus = Irp->IoStatus.Status;
00995     if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED)
00996     {
00997         FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationRequestCompete: Idle irp completes with error::"));
00998         switch(ntStatus)
00999         {
01000         case STATUS_INVALID_DEVICE_REQUEST:
01001             FreeBT_DbgPrint(3, ("STATUS_INVALID_DEVICE_REQUEST\n"));
01002             break;
01003 
01004         case STATUS_CANCELLED:
01005             FreeBT_DbgPrint(3, ("STATUS_CANCELLED\n"));
01006             break;
01007 
01008         case STATUS_DEVICE_BUSY:
01009             FreeBT_DbgPrint(3, ("STATUS_DEVICE_BUSY\n"));
01010             break;
01011 
01012         case STATUS_POWER_STATE_INVALID:
01013             FreeBT_DbgPrint(3, ("STATUS_POWER_STATE_INVALID\n"));
01014             goto IdleNotificationRequestComplete_Exit;
01015 
01016         default:
01017             FreeBT_DbgPrint(3, ("default: status = %X\n", ntStatus));
01018             break;
01019 
01020         }
01021 
01022         // if in error, issue a SetD0
01023         FreeBT_DbgPrint(3, ("FBTUSB: IdleNotificationRequestComplete::"));
01024         FreeBT_IoIncrement(DeviceExtension);
01025 
01026         powerState.DeviceState = PowerDeviceD0;
01027         ntStatus = PoRequestPowerIrp(
01028                           DeviceExtension->PhysicalDeviceObject,
01029                           IRP_MN_SET_POWER,
01030                           powerState,
01031                           (PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc,
01032                           DeviceExtension,
01033                           NULL);
01034 
01035         if(!NT_SUCCESS(ntStatus))
01036             FreeBT_DbgPrint(1, ("PoRequestPowerIrp failed\n"));
01037 
01038     }
01039 
01040 IdleNotificationRequestComplete_Exit:
01041     KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
01042     idleCallbackInfo = DeviceExtension->IdleCallbackInfo;
01043     DeviceExtension->IdleCallbackInfo = NULL;
01044 
01045     idleIrp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL);
01046     InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
01047 
01048     KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
01049 
01050     if(idleCallbackInfo)
01051         ExFreePool(idleCallbackInfo);
01052 
01053     // Since the irp was created using IoAllocateIrp,
01054     // the Irp needs to be freed using IoFreeIrp.
01055     // Also return STATUS_MORE_PROCESSING_REQUIRED so that
01056     // the kernel does not reference this in the near future.
01057     if(idleIrp)
01058     {
01059         FreeBT_DbgPrint(3, ("completion routine has a valid irp and frees it\n"));
01060         IoFreeIrp(Irp);
01061         KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
01062 
01063     }
01064 
01065     else
01066     {
01067         // The CancelSelectiveSuspend routine has grabbed the Irp from the device
01068         // extension. Now the last one to decrement the FreeIdleIrpCount should
01069         // free the irp.
01070         if (0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount))
01071         {
01072             FreeBT_DbgPrint(3, ("completion routine frees the irp\n"));
01073             IoFreeIrp(Irp);
01074             KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
01075 
01076         }
01077 
01078     }
01079 
01080     if(DeviceExtension->SSEnable)
01081     {
01082         FreeBT_DbgPrint(3, ("Set the timer to fire DPCs\n"));
01083         dueTime.QuadPart = -10000 * IDLE_INTERVAL;               // 5000 ms
01084         KeSetTimerEx(&DeviceExtension->Timer, dueTime, IDLE_INTERVAL, &DeviceExtension->DeferredProcCall);
01085         FreeBT_DbgPrint(3, ("IdleNotificationRequestCompete: Leaving\n"));
01086 
01087     }
01088 
01089     return STATUS_MORE_PROCESSING_REQUIRED;
01090 
01091 }
01092 
01093 VOID CancelSelectSuspend(IN PDEVICE_EXTENSION DeviceExtension)
01094 {
01095     PIRP  irp;
01096     KIRQL oldIrql;
01097 
01098     FreeBT_DbgPrint(3, ("CancelSelectSuspend: Entered\n"));
01099 
01100     irp = NULL;
01101 
01102     KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
01103 
01104     if(!CanDeviceSuspend(DeviceExtension))
01105     {
01106         FreeBT_DbgPrint(3, ("Device is not idle\n"));
01107         irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->PendingIdleIrp, NULL);
01108 
01109     }
01110 
01111     KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
01112 
01113     // since we have a valid Irp ptr,
01114     // we can call IoCancelIrp on it,
01115     // without the fear of the irp
01116     // being freed underneath us.
01117     if(irp)
01118     {
01119         // This routine has the irp pointer.
01120         // It is safe to call IoCancelIrp because we know that
01121         // the compleiton routine will not free this irp unless...
01122         //
01123         //
01124         if(IoCancelIrp(irp))
01125         {
01126             FreeBT_DbgPrint(3, ("IoCancelIrp returns TRUE\n"));
01127 
01128         }
01129 
01130         else
01131         {
01132             FreeBT_DbgPrint(3, ("IoCancelIrp returns FALSE\n"));
01133 
01134         }
01135 
01136         // ....we decrement the FreeIdleIrpCount from 2 to 1.
01137         // if completion routine runs ahead of us, then this routine
01138         // decrements the FreeIdleIrpCount from 1 to 0 and hence shall
01139         // free the irp.
01140         if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount))
01141         {
01142             FreeBT_DbgPrint(3, ("CancelSelectSuspend frees the irp\n"));
01143             IoFreeIrp(irp);
01144             KeSetEvent(&DeviceExtension->NoIdleReqPendEvent, IO_NO_INCREMENT, FALSE);
01145 
01146         }
01147 
01148     }
01149 
01150     FreeBT_DbgPrint(3, ("CancelSelectSuspend: Leaving\n"));
01151 
01152     return;
01153 
01154 }
01155 
01156 VOID PoIrpCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
01157 {
01158     PIRP_COMPLETION_CONTEXT irpContext;
01159     irpContext = NULL;
01160 
01161     FreeBT_DbgPrint(3, ("PoIrpCompletionFunc::"));
01162 
01163     if(Context)
01164         irpContext = (PIRP_COMPLETION_CONTEXT) Context;
01165 
01166     // all we do is set the event and decrement the count
01167     if(irpContext)
01168     {
01169         KeSetEvent(irpContext->Event, 0, FALSE);
01170         FreeBT_IoDecrement(irpContext->DeviceExtension);
01171         ExFreePool(irpContext);
01172 
01173     }
01174 
01175     return;
01176 
01177 }
01178 
01179 VOID PoIrpAsyncCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
01180 {
01181     PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Context;
01182     FreeBT_DbgPrint(3, ("PoIrpAsyncCompletionFunc::"));
01183     FreeBT_IoDecrement(DeviceExtension);
01184 
01185     return;
01186 
01187 }
01188 
01189 VOID WWIrpCompletionFunc(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
01190 {
01191     PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Context;
01192 
01193     FreeBT_DbgPrint(3, ("WWIrpCompletionFunc::"));
01194     FreeBT_IoDecrement(DeviceExtension);
01195 
01196     return;
01197 
01198 }

Generated on Sun May 27 2012 04:27:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.