Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfbtdev.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
1.7.6.1
|