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

fbtpnp.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 "stdio.h"
00014 #include "fbtusb.h"
00015 #include "fbtpnp.h"
00016 #include "fbtpwr.h"
00017 #include "fbtdev.h"
00018 #include "fbtrwr.h"
00019 #include "fbtwmi.h"
00020 
00021 #include "fbtusr.h"
00022 
00023 // Handle PNP events
00024 NTSTATUS FreeBT_DispatchPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00025 {
00026     PIO_STACK_LOCATION irpStack;
00027     PDEVICE_EXTENSION  deviceExtension;
00028     //KEVENT             startDeviceEvent;
00029     NTSTATUS           ntStatus;
00030 
00031     irpStack = IoGetCurrentIrpStackLocation(Irp);
00032     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00033 
00034     // since the device is removed, fail the Irp.
00035     if (Removed == deviceExtension->DeviceState)
00036     {
00037         ntStatus = STATUS_DELETE_PENDING;
00038         Irp->IoStatus.Status = ntStatus;
00039         Irp->IoStatus.Information = 0;
00040         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00041         return ntStatus;
00042 
00043     }
00044 
00045     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
00046     FreeBT_IoIncrement(deviceExtension);
00047     if (irpStack->MinorFunction == IRP_MN_START_DEVICE)
00048     {
00049         ASSERT(deviceExtension->IdleReqPend == 0);
00050 
00051     }
00052 
00053     else
00054     {
00055         if (deviceExtension->SSEnable)
00056         {
00057             CancelSelectSuspend(deviceExtension);
00058 
00059         }
00060 
00061     }
00062 
00063     FreeBT_DbgPrint(3, ("FBTUSB: ///////////////////////////////////////////\n"));
00064     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
00065     FreeBT_DbgPrint(2, (PnPMinorFunctionString(irpStack->MinorFunction)));
00066     switch (irpStack->MinorFunction)
00067     {
00068     case IRP_MN_START_DEVICE:
00069         ntStatus = HandleStartDevice(DeviceObject, Irp);
00070         break;
00071 
00072     case IRP_MN_QUERY_STOP_DEVICE:
00073         // if we cannot stop the device, we fail the query stop irp
00074         ntStatus = CanStopDevice(DeviceObject, Irp);
00075         if(NT_SUCCESS(ntStatus))
00076         {
00077             ntStatus = HandleQueryStopDevice(DeviceObject, Irp);
00078             return ntStatus;
00079 
00080         }
00081 
00082         break;
00083 
00084     case IRP_MN_CANCEL_STOP_DEVICE:
00085         ntStatus = HandleCancelStopDevice(DeviceObject, Irp);
00086         break;
00087 
00088     case IRP_MN_STOP_DEVICE:
00089         ntStatus = HandleStopDevice(DeviceObject, Irp);
00090         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::IRP_MN_STOP_DEVICE::"));
00091         FreeBT_IoDecrement(deviceExtension);
00092 
00093         return ntStatus;
00094 
00095     case IRP_MN_QUERY_REMOVE_DEVICE:
00096         // if we cannot remove the device, we fail the query remove irp
00097         ntStatus = HandleQueryRemoveDevice(DeviceObject, Irp);
00098 
00099         return ntStatus;
00100 
00101     case IRP_MN_CANCEL_REMOVE_DEVICE:
00102         ntStatus = HandleCancelRemoveDevice(DeviceObject, Irp);
00103         break;
00104 
00105     case IRP_MN_SURPRISE_REMOVAL:
00106         ntStatus = HandleSurpriseRemoval(DeviceObject, Irp);
00107         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::IRP_MN_SURPRISE_REMOVAL::"));
00108         FreeBT_IoDecrement(deviceExtension);
00109         return ntStatus;
00110 
00111     case IRP_MN_REMOVE_DEVICE:
00112         ntStatus = HandleRemoveDevice(DeviceObject, Irp);
00113         return ntStatus;
00114 
00115     case IRP_MN_QUERY_CAPABILITIES:
00116         ntStatus = HandleQueryCapabilities(DeviceObject, Irp);
00117         break;
00118 
00119     default:
00120         IoSkipCurrentIrpStackLocation(Irp);
00121 
00122         ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00123 
00124         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::default::"));
00125         FreeBT_IoDecrement(deviceExtension);
00126 
00127         return ntStatus;
00128 
00129     }
00130 
00131     Irp->IoStatus.Status = ntStatus;
00132     Irp->IoStatus.Information = 0;
00133     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00134 
00135     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPnP::"));
00136     FreeBT_IoDecrement(deviceExtension);
00137 
00138     return ntStatus;
00139 
00140 }
00141 
00142 NTSTATUS HandleStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00143 {
00144     KIRQL             oldIrql;
00145     KEVENT            startDeviceEvent;
00146     NTSTATUS          ntStatus;
00147     PDEVICE_EXTENSION deviceExtension;
00148     LARGE_INTEGER     dueTime;
00149 
00150     FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Entered\n"));
00151 
00152     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00153     deviceExtension->UsbConfigurationDescriptor = NULL;
00154     deviceExtension->UsbInterface = NULL;
00155     deviceExtension->PipeContext = NULL;
00156 
00157     // We cannot touch the device (send it any non pnp irps) until a
00158     // start device has been passed down to the lower drivers.
00159     // first pass the Irp down
00160     KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
00161     IoCopyCurrentIrpStackLocationToNext(Irp);
00162     IoSetCompletionRoutine(Irp,
00163                            (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
00164                            (PVOID)&startDeviceEvent,
00165                            TRUE,
00166                            TRUE,
00167                            TRUE);
00168 
00169     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00170     if (ntStatus == STATUS_PENDING)
00171     {
00172         KeWaitForSingleObject(&startDeviceEvent, Executive, KernelMode, FALSE, NULL);
00173         ntStatus = Irp->IoStatus.Status;
00174 
00175     }
00176 
00177     if (!NT_SUCCESS(ntStatus))
00178     {
00179         FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: Lower drivers failed this Irp (0x%08x)\n", ntStatus));
00180         return ntStatus;
00181 
00182     }
00183 
00184     // Read the device descriptor, configuration descriptor
00185     // and select the interface descriptors
00186     ntStatus = ReadandSelectDescriptors(DeviceObject);
00187     if (!NT_SUCCESS(ntStatus))
00188     {
00189         FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: ReadandSelectDescriptors failed (0x%08x)\n", ntStatus));
00190         return ntStatus;
00191 
00192     }
00193 
00194     // enable the symbolic links for system components to open
00195     // handles to the device
00196     ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, TRUE);
00197     if (!NT_SUCCESS(ntStatus))
00198     {
00199         FreeBT_DbgPrint(1, ("FBTUSB: HandleStartDevice: IoSetDeviceInterfaceState failed (0x%08x)\n", ntStatus));
00200         return ntStatus;
00201 
00202     }
00203 
00204     KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
00205 
00206     SET_NEW_PNP_STATE(deviceExtension, Working);
00207     deviceExtension->QueueState = AllowRequests;
00208 
00209     KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
00210 
00211     deviceExtension->FlagWWOutstanding = 0;
00212     deviceExtension->FlagWWCancel = 0;
00213     deviceExtension->WaitWakeIrp = NULL;
00214 
00215     if (deviceExtension->WaitWakeEnable)
00216     {
00217         IssueWaitWake(deviceExtension);
00218 
00219     }
00220 
00221     ProcessQueuedRequests(deviceExtension);
00222     if (WinXpOrBetter == deviceExtension->WdmVersion)
00223     {
00224         deviceExtension->SSEnable = deviceExtension->SSRegistryEnable;
00225 
00226         // set timer.for selective suspend requests
00227         if (deviceExtension->SSEnable)
00228         {
00229             dueTime.QuadPart = -10000 * IDLE_INTERVAL;               // 5000 ms
00230             KeSetTimerEx(&deviceExtension->Timer, dueTime, IDLE_INTERVAL, &deviceExtension->DeferredProcCall);
00231             deviceExtension->FreeIdleIrpCount = 0;
00232 
00233         }
00234 
00235     }
00236 
00237     FreeBT_DbgPrint(3, ("FBTUSB: HandleStartDevice: Leaving\n"));
00238 
00239     return ntStatus;
00240 
00241 }
00242 
00243 
00244 NTSTATUS ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject)
00245 {
00246     PURB                   urb;
00247     ULONG                  siz;
00248     NTSTATUS               ntStatus;
00249     PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
00250 
00251     urb = NULL;
00252     deviceDescriptor = NULL;
00253 
00254     // 1. Read the device descriptor
00255     urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
00256     if(urb)
00257     {
00258         siz = sizeof(USB_DEVICE_DESCRIPTOR);
00259         deviceDescriptor = (PUSB_DEVICE_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
00260         if (deviceDescriptor)
00261         {
00262             UsbBuildGetDescriptorRequest(
00263                     urb,
00264                     (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
00265                     USB_DEVICE_DESCRIPTOR_TYPE,
00266                     0,
00267                     0,
00268                     deviceDescriptor,
00269                     NULL,
00270                     siz,
00271                     NULL);
00272 
00273             ntStatus = CallUSBD(DeviceObject, urb);
00274             if (NT_SUCCESS(ntStatus))
00275             {
00276                 ASSERT(deviceDescriptor->bNumConfigurations);
00277                 ntStatus = ConfigureDevice(DeviceObject);
00278 
00279             }
00280 
00281             ExFreePool(urb);
00282             ExFreePool(deviceDescriptor);
00283 
00284         }
00285 
00286         else
00287         {
00288             FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for deviceDescriptor"));
00289             ExFreePool(urb);
00290             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00291 
00292         }
00293 
00294     }
00295 
00296     else
00297     {
00298         FreeBT_DbgPrint(1, ("FBTUSB: ReadandSelectDescriptors: Failed to allocate memory for urb"));
00299         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00300 
00301     }
00302 
00303 
00304     return ntStatus;
00305 
00306 }
00307 
00308 NTSTATUS ConfigureDevice(IN PDEVICE_OBJECT DeviceObject)
00309 {
00310     PURB                          urb;
00311     ULONG                         siz;
00312     NTSTATUS                      ntStatus;
00313     PDEVICE_EXTENSION             deviceExtension;
00314     PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
00315 
00316     urb = NULL;
00317     configurationDescriptor = NULL;
00318     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00319 
00320     // Read the first configuration descriptor
00321     // This requires two steps:
00322     // 1. Read the fixed sized configuration desciptor (CD)
00323     // 2. Read the CD with all embedded interface and endpoint descriptors
00324     urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
00325     if (urb)
00326     {
00327         siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
00328         configurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
00329 
00330         if(configurationDescriptor)
00331         {
00332             UsbBuildGetDescriptorRequest(
00333                     urb,
00334                     (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
00335                     USB_CONFIGURATION_DESCRIPTOR_TYPE,
00336                     0,
00337                     0,
00338                     configurationDescriptor,
00339                     NULL,
00340                     sizeof(USB_CONFIGURATION_DESCRIPTOR),
00341                     NULL);
00342 
00343             ntStatus = CallUSBD(DeviceObject, urb);
00344             if(!NT_SUCCESS(ntStatus))
00345             {
00346                 FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: UsbBuildGetDescriptorRequest failed\n"));
00347                 goto ConfigureDevice_Exit;
00348 
00349             }
00350 
00351         }
00352 
00353         else
00354         {
00355             FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate mem for config Descriptor\n"));
00356             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00357             goto ConfigureDevice_Exit;
00358 
00359         }
00360 
00361         siz = configurationDescriptor->wTotalLength;
00362         ExFreePool(configurationDescriptor);
00363 
00364         configurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePool(NonPagedPool, siz);
00365         if (configurationDescriptor)
00366         {
00367             UsbBuildGetDescriptorRequest(
00368                     urb,
00369                     (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
00370                     USB_CONFIGURATION_DESCRIPTOR_TYPE,
00371                     0,
00372                     0,
00373                     configurationDescriptor,
00374                     NULL,
00375                     siz,
00376                     NULL);
00377 
00378             ntStatus = CallUSBD(DeviceObject, urb);
00379             if (!NT_SUCCESS(ntStatus))
00380             {
00381                 FreeBT_DbgPrint(1,("FBTUSB: ConfigureDevice: Failed to read configuration descriptor"));
00382                 goto ConfigureDevice_Exit;
00383 
00384             }
00385 
00386         }
00387 
00388         else
00389         {
00390             FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to alloc mem for config Descriptor\n"));
00391             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00392             goto ConfigureDevice_Exit;
00393 
00394         }
00395 
00396     }
00397 
00398     else
00399     {
00400         FreeBT_DbgPrint(1, ("FBTUSB: ConfigureDevice: Failed to allocate memory for urb\n"));
00401         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00402         goto ConfigureDevice_Exit;
00403 
00404     }
00405 
00406     if (configurationDescriptor)
00407     {
00408         // save a copy of configurationDescriptor in deviceExtension
00409         // remember to free it later.
00410         deviceExtension->UsbConfigurationDescriptor = configurationDescriptor;
00411 
00412         if (configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
00413         {
00414             // this configuration supports remote wakeup
00415             deviceExtension->WaitWakeEnable = 1;
00416 
00417         }
00418 
00419         else
00420         {
00421             deviceExtension->WaitWakeEnable = 0;
00422 
00423         }
00424 
00425         ntStatus = SelectInterfaces(DeviceObject, configurationDescriptor);
00426 
00427     }
00428 
00429     else
00430     {
00431         deviceExtension->UsbConfigurationDescriptor = NULL;
00432 
00433     }
00434 
00435 ConfigureDevice_Exit:
00436     if (urb)
00437     {
00438         ExFreePool(urb);
00439 
00440     }
00441 
00442     return ntStatus;
00443 
00444 }
00445 
00446 NTSTATUS SelectInterfaces(IN PDEVICE_OBJECT DeviceObject, IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
00447 {
00448     LONG                        numberOfInterfaces, interfaceNumber, interfaceindex;
00449     ULONG                       i;
00450     PURB                        urb;
00451     //PUCHAR                      pInf;
00452     NTSTATUS                    ntStatus;
00453     PDEVICE_EXTENSION           deviceExtension;
00454     PUSB_INTERFACE_DESCRIPTOR   interfaceDescriptor;
00455     PUSBD_INTERFACE_LIST_ENTRY  interfaceList,
00456                                 tmp;
00457     PUSBD_INTERFACE_INFORMATION Interface;
00458 
00459     urb = NULL;
00460     Interface = NULL;
00461     interfaceDescriptor = NULL;
00462     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00463     numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
00464     interfaceindex = interfaceNumber = 0;
00465 
00466     // Parse the configuration descriptor for the interface;
00467     tmp = interfaceList = (PUSBD_INTERFACE_LIST_ENTRY)
00468         ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1));
00469 
00470     if (!tmp)
00471     {
00472 
00473         FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to allocate mem for interfaceList\n"));
00474         return STATUS_INSUFFICIENT_RESOURCES;
00475 
00476     }
00477 
00478 
00479     FreeBT_DbgPrint(3, ("FBTUSB: -------------\n"));
00480     FreeBT_DbgPrint(3, ("FBTUSB: Number of interfaces %d\n", numberOfInterfaces));
00481 
00482     while (interfaceNumber < numberOfInterfaces)
00483     {
00484         interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
00485                                             ConfigurationDescriptor,
00486                                             ConfigurationDescriptor,
00487                                             interfaceindex,
00488                                             0, -1, -1, -1);
00489 
00490         if (interfaceDescriptor)
00491         {
00492             interfaceList->InterfaceDescriptor = interfaceDescriptor;
00493             interfaceList->Interface = NULL;
00494             interfaceList++;
00495             interfaceNumber++;
00496 
00497         }
00498 
00499         interfaceindex++;
00500 
00501     }
00502 
00503     interfaceList->InterfaceDescriptor = NULL;
00504     interfaceList->Interface = NULL;
00505     urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
00506 
00507     if (urb)
00508     {
00509         Interface = &urb->UrbSelectConfiguration.Interface;
00510         for (i=0; i<Interface->NumberOfPipes; i++)
00511         {
00512             // perform pipe initialization here
00513             // set the transfer size and any pipe flags we use
00514             // USBD sets the rest of the Interface struct members
00515             Interface->Pipes[i].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
00516 
00517         }
00518 
00519         ntStatus = CallUSBD(DeviceObject, urb);
00520         if (NT_SUCCESS(ntStatus))
00521         {
00522             // save a copy of interface information in the device extension.
00523             deviceExtension->UsbInterface = (PUSBD_INTERFACE_INFORMATION) ExAllocatePool(NonPagedPool, Interface->Length);
00524             if (deviceExtension->UsbInterface)
00525             {
00526                 RtlCopyMemory(deviceExtension->UsbInterface, Interface, Interface->Length);
00527 
00528             }
00529 
00530             else
00531             {
00532                 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00533                 FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Memory alloc for UsbInterface failed\n"));
00534 
00535             }
00536 
00537             // Dump the interface to the debugger
00538             Interface = &urb->UrbSelectConfiguration.Interface;
00539 
00540             FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
00541             FreeBT_DbgPrint(3, ("FBTUSB: NumberOfPipes 0x%x\n", Interface->NumberOfPipes));
00542             FreeBT_DbgPrint(3, ("FBTUSB: Length 0x%x\n", Interface->Length));
00543             FreeBT_DbgPrint(3, ("FBTUSB: Alt Setting 0x%x\n", Interface->AlternateSetting));
00544             FreeBT_DbgPrint(3, ("FBTUSB: Interface Number 0x%x\n", Interface->InterfaceNumber));
00545             FreeBT_DbgPrint(3, ("FBTUSB: Class, subclass, protocol 0x%x 0x%x 0x%x\n",
00546                                  Interface->Class,
00547                                  Interface->SubClass,
00548                                  Interface->Protocol));
00549 
00550             if (Interface->Class==FREEBT_USB_STDCLASS && Interface->SubClass==FREEBT_USB_STDSUBCLASS &&
00551                 Interface->Protocol==FREEBT_USB_STDPROTOCOL)
00552             {
00553                 FreeBT_DbgPrint(3, ("FBTUSB: This is a standard USB Bluetooth device\n"));
00554 
00555             }
00556 
00557             else
00558             {
00559                 FreeBT_DbgPrint(3, ("FBTUSB: WARNING: This device does not report itself as a standard USB Bluetooth device\n"));
00560 
00561             }
00562 
00563             // Initialize the PipeContext
00564             // Dump the pipe info
00565             deviceExtension->PipeContext = (PFREEBT_PIPE_CONTEXT) ExAllocatePool(
00566                                                 NonPagedPool,
00567                                                 Interface->NumberOfPipes *
00568                                                 sizeof(FREEBT_PIPE_CONTEXT));
00569 
00570             if (!deviceExtension->PipeContext)
00571             {
00572                 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00573                 FreeBT_DbgPrint(1, ("FBTUSB: Memory alloc for UsbInterface failed\n"));
00574 
00575             }
00576 
00577             else
00578             {
00579                 FreeBT_DbgPrint(3, ("FBTUSB: SelectInterfaces: Allocated PipeContext %p\n", deviceExtension->PipeContext));
00580                 for (i=0; i<Interface->NumberOfPipes; i++)
00581                 {
00582                     deviceExtension->PipeContext[i].PipeOpen = FALSE;
00583 
00584                     FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
00585                     FreeBT_DbgPrint(3, ("FBTUSB: PipeType 0x%x\n", Interface->Pipes[i].PipeType));
00586                     FreeBT_DbgPrint(3, ("FBTUSB: EndpointAddress 0x%x\n", Interface->Pipes[i].EndpointAddress));
00587                     FreeBT_DbgPrint(3, ("FBTUSB: MaxPacketSize 0x%x\n", Interface->Pipes[i].MaximumPacketSize));
00588                     FreeBT_DbgPrint(3, ("FBTUSB: Interval 0x%x\n", Interface->Pipes[i].Interval));
00589                     FreeBT_DbgPrint(3, ("FBTUSB: Handle 0x%x\n", Interface->Pipes[i].PipeHandle));
00590                     FreeBT_DbgPrint(3, ("FBTUSB: MaximumTransferSize 0x%x\n", Interface->Pipes[i].MaximumTransferSize));
00591 
00592                     // Log the pipes
00593                     // Note the HCI Command endpoint won't appear here, because the Default Control Pipe
00594                     // is used for this. The Default Control Pipe is always present at EndPointAddress 0x0
00595                     switch (Interface->Pipes[i].EndpointAddress)
00596                     {
00597                         case FREEBT_STDENDPOINT_HCIEVENT:
00598                             deviceExtension->PipeContext[i].PipeType=HciEventPipe;
00599                             deviceExtension->EventPipe=Interface->Pipes[i];
00600                             FreeBT_DbgPrint(3, ("FBTUSB: HCI Event Endpoint\n"));
00601                             break;
00602 
00603                         case FREEBT_STDENDPOINT_ACLIN:
00604                             deviceExtension->PipeContext[i].PipeType=AclDataIn;
00605                             deviceExtension->DataInPipe=Interface->Pipes[i];
00606                             FreeBT_DbgPrint(3, ("FBTUSB: ACL Data In Endpoint\n"));
00607                             break;
00608 
00609                         case FREEBT_STDENDPOINT_ACLOUT:
00610                             deviceExtension->PipeContext[i].PipeType=AclDataOut;
00611                             deviceExtension->DataOutPipe=Interface->Pipes[i];
00612                             FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
00613                             break;
00614 
00615                         case FREEBT_STDENDPOINT_AUDIOIN:
00616                             deviceExtension->PipeContext[i].PipeType=SCODataIn;
00617                             deviceExtension->AudioInPipe=Interface->Pipes[i];
00618                             FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
00619                             break;
00620 
00621                         case FREEBT_STDENDPOINT_AUDIOOUT:
00622                             deviceExtension->PipeContext[i].PipeType=SCODataOut;
00623                             deviceExtension->AudioOutPipe=Interface->Pipes[i];
00624                             FreeBT_DbgPrint(3, ("FBTUSB: ACL Data Out Endpoint\n"));
00625                             break;
00626 
00627                     }
00628 
00629                 }
00630 
00631             }
00632 
00633             FreeBT_DbgPrint(3, ("FBTUSB: ---------\n"));
00634 
00635         }
00636 
00637         else
00638         {
00639             FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: Failed to select an interface\n"));
00640 
00641         }
00642 
00643     }
00644 
00645     else
00646     {
00647         FreeBT_DbgPrint(1, ("FBTUSB: SelectInterfaces: USBD_CreateConfigurationRequestEx failed\n"));
00648         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00649 
00650     }
00651 
00652     if (tmp)
00653     {
00654         ExFreePool(tmp);
00655 
00656     }
00657 
00658     if (urb)
00659     {
00660         ExFreePool(urb);
00661 
00662     }
00663 
00664     return ntStatus;
00665 }
00666 
00667 
00668 NTSTATUS DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject)
00669 {
00670     PURB     urb;
00671     ULONG    siz;
00672     NTSTATUS ntStatus;
00673 
00674     siz = sizeof(struct _URB_SELECT_CONFIGURATION);
00675     urb = (PURB) ExAllocatePool(NonPagedPool, siz);
00676     if (urb)
00677     {
00678         UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
00679         ntStatus = CallUSBD(DeviceObject, urb);
00680         if(!NT_SUCCESS(ntStatus))
00681         {
00682             FreeBT_DbgPrint(3, ("FBTUSB: DeconfigureDevice: Failed to deconfigure device\n"));
00683 
00684         }
00685 
00686         ExFreePool(urb);
00687 
00688     }
00689 
00690     else
00691     {
00692         FreeBT_DbgPrint(1, ("FBTUSB: DeconfigureDevice: Failed to allocate urb\n"));
00693         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00694 
00695     }
00696 
00697     return ntStatus;
00698 
00699 }
00700 
00701 NTSTATUS CallUSBD(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb)
00702 {
00703     PIRP               irp;
00704     KEVENT             event;
00705     NTSTATUS           ntStatus;
00706     IO_STATUS_BLOCK    ioStatus;
00707     PIO_STACK_LOCATION nextStack;
00708     PDEVICE_EXTENSION  deviceExtension;
00709 
00710     irp = NULL;
00711     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00712 
00713     KeInitializeEvent(&event, NotificationEvent, FALSE);
00714     irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
00715                                         deviceExtension->TopOfStackDeviceObject,
00716                                         NULL,
00717                                         0,
00718                                         NULL,
00719                                         0,
00720                                         TRUE,
00721                                         &event,
00722                                         &ioStatus);
00723 
00724     if (!irp)
00725     {
00726         FreeBT_DbgPrint(1, ("FBTUSB: CallUSBD: IoBuildDeviceIoControlRequest failed\n"));
00727         return STATUS_INSUFFICIENT_RESOURCES;
00728 
00729     }
00730 
00731     nextStack = IoGetNextIrpStackLocation(irp);
00732     ASSERT(nextStack != NULL);
00733     nextStack->Parameters.Others.Argument1 = Urb;
00734 
00735     FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
00736     FreeBT_IoIncrement(deviceExtension);
00737 
00738     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
00739     if (ntStatus == STATUS_PENDING)
00740     {
00741         KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
00742         ntStatus = ioStatus.Status;
00743 
00744     }
00745 
00746     FreeBT_DbgPrint(3, ("FBTUSB: CallUSBD::"));
00747     FreeBT_IoDecrement(deviceExtension);
00748     return ntStatus;
00749 
00750 }
00751 
00752 NTSTATUS HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00753 {
00754     KIRQL             oldIrql;
00755     NTSTATUS          ntStatus;
00756     PDEVICE_EXTENSION deviceExtension;
00757 
00758     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Entered\n"));
00759 
00760     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00761 
00762     // If we can stop the device, we need to set the QueueState to
00763     // HoldRequests so further requests will be queued.
00764     KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
00765 
00766     SET_NEW_PNP_STATE(deviceExtension, PendingStop);
00767     deviceExtension->QueueState = HoldRequests;
00768 
00769     KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
00770 
00771     // wait for the existing ones to be finished.
00772     // first, decrement this operation
00773     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice::"));
00774     FreeBT_IoDecrement(deviceExtension);
00775 
00776     KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
00777 
00778     Irp->IoStatus.Status = STATUS_SUCCESS;
00779     Irp->IoStatus.Information = 0;
00780 
00781     IoSkipCurrentIrpStackLocation(Irp);
00782 
00783     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00784 
00785     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryStopDevice: Leaving\n"));
00786 
00787     return ntStatus;
00788 
00789 }
00790 
00791 NTSTATUS HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00792 {
00793     KIRQL             oldIrql;
00794     KEVENT            event;
00795     NTSTATUS          ntStatus;
00796     PDEVICE_EXTENSION deviceExtension;
00797 
00798     FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Entered\n"));
00799 
00800     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00801 
00802     // Send this IRP down and wait for it to come back.
00803     // Set the QueueState flag to AllowRequests,
00804     // and process all the previously queued up IRPs.
00805 
00806     // First check to see whether you have received cancel-stop
00807     // without first receiving a query-stop. This could happen if someone
00808     // above us fails a query-stop and passes down the subsequent
00809     // cancel-stop.
00810     if(PendingStop == deviceExtension->DeviceState)
00811     {
00812         KeInitializeEvent(&event, NotificationEvent, FALSE);
00813 
00814         IoCopyCurrentIrpStackLocationToNext(Irp);
00815         IoSetCompletionRoutine(Irp,
00816                                (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
00817                                (PVOID)&event,
00818                                TRUE,
00819                                TRUE,
00820                                TRUE);
00821 
00822         ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00823         if(ntStatus == STATUS_PENDING)
00824         {
00825             KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
00826             ntStatus = Irp->IoStatus.Status;
00827 
00828         }
00829 
00830         if(NT_SUCCESS(ntStatus))
00831         {
00832             KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
00833 
00834             RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
00835             deviceExtension->QueueState = AllowRequests;
00836             ASSERT(deviceExtension->DeviceState == Working);
00837 
00838             KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
00839 
00840             ProcessQueuedRequests(deviceExtension);
00841 
00842         }
00843 
00844     }
00845 
00846     else
00847     {
00848         // spurious Irp
00849         ntStatus = STATUS_SUCCESS;
00850 
00851     }
00852 
00853     FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelStopDevice: Leaving\n"));
00854 
00855     return ntStatus;
00856 
00857 }
00858 
00859 NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00860 {
00861     KIRQL             oldIrql;
00862     NTSTATUS          ntStatus;
00863     PDEVICE_EXTENSION deviceExtension;
00864 
00865     FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Entered\n"));
00866 
00867     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00868     if(WinXpOrBetter == deviceExtension->WdmVersion)
00869     {
00870         if(deviceExtension->SSEnable)
00871         {
00872             // Cancel the timer so that the DPCs are no longer fired.
00873             // Thus, we are making judicious usage of our resources.
00874             // we do not need DPCs because the device is stopping.
00875             // The timers are re-initialized while handling the start
00876             // device irp.
00877             KeCancelTimer(&deviceExtension->Timer);
00878 
00879             // after the device is stopped, it can be surprise removed.
00880             // we set this to 0, so that we do not attempt to cancel
00881             // the timer while handling surprise remove or remove irps.
00882             // when we get the start device request, this flag will be
00883             // reinitialized.
00884             deviceExtension->SSEnable = 0;
00885 
00886             // make sure that if a DPC was fired before we called cancel timer,
00887             // then the DPC and work-time have run to their completion
00888             KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
00889 
00890             // make sure that the selective suspend request has been completed.
00891             KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
00892 
00893         }
00894 
00895     }
00896 
00897     // after the stop Irp is sent to the lower driver object,
00898     // the driver must not send any more Irps down that touch
00899     // the device until another Start has occurred.
00900     if (deviceExtension->WaitWakeEnable)
00901     {
00902         CancelWaitWake(deviceExtension);
00903 
00904     }
00905 
00906     KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
00907 
00908     SET_NEW_PNP_STATE(deviceExtension, Stopped);
00909 
00910     KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
00911 
00912     // This is the right place to actually give up all the resources used
00913     // This might include calls to IoDisconnectInterrupt, MmUnmapIoSpace,
00914     // etc.
00915     ReleaseMemory(DeviceObject);
00916 
00917     ntStatus = DeconfigureDevice(DeviceObject);
00918 
00919     Irp->IoStatus.Status = ntStatus;
00920     Irp->IoStatus.Information = 0;
00921 
00922     IoSkipCurrentIrpStackLocation(Irp);
00923     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00924 
00925     FreeBT_DbgPrint(3, ("FBTUSB: HandleStopDevice: Leaving\n"));
00926 
00927     return ntStatus;
00928 
00929 }
00930 
00931 NTSTATUS HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00932 {
00933     KIRQL             oldIrql;
00934     NTSTATUS          ntStatus;
00935     PDEVICE_EXTENSION deviceExtension;
00936 
00937     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Entered\n"));
00938 
00939     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00940 
00941     // If we can allow removal of the device, we should set the QueueState
00942     // to HoldRequests so further requests will be queued. This is required
00943     // so that we can process queued up requests in cancel-remove just in
00944     // case somebody else in the stack fails the query-remove.
00945     ntStatus = CanRemoveDevice(DeviceObject, Irp);
00946 
00947     KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
00948 
00949     deviceExtension->QueueState = HoldRequests;
00950     SET_NEW_PNP_STATE(deviceExtension, PendingRemove);
00951 
00952     KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
00953 
00954     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice::"));
00955     FreeBT_IoDecrement(deviceExtension);
00956 
00957     // Wait for all the requests to be completed
00958     KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
00959 
00960     Irp->IoStatus.Status = STATUS_SUCCESS;
00961     Irp->IoStatus.Information = 0;
00962 
00963     IoSkipCurrentIrpStackLocation(Irp);
00964     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00965 
00966     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryRemoveDevice: Leaving\n"));
00967 
00968     return ntStatus;
00969 
00970 }
00971 
00972 NTSTATUS HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00973 {
00974     KIRQL             oldIrql;
00975     KEVENT            event;
00976     NTSTATUS          ntStatus;
00977     PDEVICE_EXTENSION deviceExtension;
00978 
00979     FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Entered\n"));
00980 
00981     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00982 
00983     // We need to reset the QueueState flag to ProcessRequest,
00984     // since the device resume its normal activities.
00985 
00986     // First check to see whether you have received cancel-remove
00987     // without first receiving a query-remove. This could happen if
00988     // someone above us fails a query-remove and passes down the
00989     // subsequent cancel-remove.
00990     if(PendingRemove == deviceExtension->DeviceState)
00991     {
00992 
00993         KeInitializeEvent(&event, NotificationEvent, FALSE);
00994 
00995         IoCopyCurrentIrpStackLocationToNext(Irp);
00996         IoSetCompletionRoutine(Irp,
00997                                (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
00998                                (PVOID)&event,
00999                                TRUE,
01000                                TRUE,
01001                                TRUE);
01002 
01003         ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
01004         if(ntStatus == STATUS_PENDING)
01005         {
01006             KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
01007             ntStatus = Irp->IoStatus.Status;
01008 
01009         }
01010 
01011         if (NT_SUCCESS(ntStatus))
01012         {
01013             KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
01014 
01015             deviceExtension->QueueState = AllowRequests;
01016             RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
01017 
01018             KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
01019 
01020             // process the queued requests that arrive between
01021             // QUERY_REMOVE and CANCEL_REMOVE
01022             ProcessQueuedRequests(deviceExtension);
01023 
01024         }
01025 
01026     }
01027 
01028     else
01029     {
01030         // spurious cancel-remove
01031         ntStatus = STATUS_SUCCESS;
01032 
01033     }
01034 
01035     FreeBT_DbgPrint(3, ("FBTUSB: HandleCancelRemoveDevice: Leaving\n"));
01036 
01037     return ntStatus;
01038 
01039 }
01040 
01041 NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
01042 {
01043     KIRQL             oldIrql;
01044     NTSTATUS          ntStatus;
01045     PDEVICE_EXTENSION deviceExtension;
01046 
01047     FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Entered\n"));
01048 
01049     // initialize variables
01050     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
01051 
01052     // 1. fail pending requests
01053     // 2. return device and memory resources
01054     // 3. disable interfaces
01055     if(deviceExtension->WaitWakeEnable)
01056     {
01057         CancelWaitWake(deviceExtension);
01058 
01059     }
01060 
01061 
01062     if (WinXpOrBetter == deviceExtension->WdmVersion)
01063     {
01064         if (deviceExtension->SSEnable)
01065         {
01066             // Cancel the timer so that the DPCs are no longer fired.
01067             // we do not need DPCs because the device has been surprise
01068             // removed
01069             KeCancelTimer(&deviceExtension->Timer);
01070 
01071             deviceExtension->SSEnable = 0;
01072 
01073             // make sure that if a DPC was fired before we called cancel timer,
01074             // then the DPC and work-time have run to their completion
01075             KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
01076 
01077             // make sure that the selective suspend request has been completed.
01078             KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
01079 
01080         }
01081 
01082     }
01083 
01084     KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
01085     deviceExtension->QueueState = FailRequests;
01086     SET_NEW_PNP_STATE(deviceExtension, SurpriseRemoved);
01087     KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
01088 
01089     ProcessQueuedRequests(deviceExtension);
01090 
01091     ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);
01092     if(!NT_SUCCESS(ntStatus))
01093     {
01094         FreeBT_DbgPrint(1, ("FBTUSB: HandleSurpriseRemoval: IoSetDeviceInterfaceState::disable:failed\n"));
01095 
01096     }
01097 
01098     FreeBT_AbortPipes(DeviceObject);
01099 
01100     Irp->IoStatus.Status = STATUS_SUCCESS;
01101     Irp->IoStatus.Information = 0;
01102 
01103     IoSkipCurrentIrpStackLocation(Irp);
01104     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
01105 
01106     FreeBT_DbgPrint(3, ("FBTUSB: HandleSurpriseRemoval: Leaving\n"));
01107 
01108     return ntStatus;
01109 
01110 }
01111 
01112 NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
01113 {
01114     KIRQL             oldIrql;
01115     //KEVENT            event;
01116     ULONG             requestCount;
01117     NTSTATUS          ntStatus;
01118     PDEVICE_EXTENSION deviceExtension;
01119 
01120     FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Entered\n"));
01121 
01122     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
01123 
01124     // The Plug & Play system has dictated the removal of this device.  We
01125     // have no choice but to detach and delete the device object.
01126     // (If we wanted to express an interest in preventing this removal,
01127     // we should have failed the query remove IRP).
01128     if(SurpriseRemoved != deviceExtension->DeviceState)
01129     {
01130 
01131         // we are here after QUERY_REMOVE
01132         KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
01133         deviceExtension->QueueState = FailRequests;
01134         KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
01135 
01136         if(deviceExtension->WaitWakeEnable)
01137         {
01138             CancelWaitWake(deviceExtension);
01139 
01140         }
01141 
01142         if(WinXpOrBetter == deviceExtension->WdmVersion)
01143         {
01144             if (deviceExtension->SSEnable)
01145             {
01146                 // Cancel the timer so that the DPCs are no longer fired.
01147                 // we do not need DPCs because the device has been removed
01148                 KeCancelTimer(&deviceExtension->Timer);
01149 
01150                 deviceExtension->SSEnable = 0;
01151 
01152                 // make sure that if a DPC was fired before we called cancel timer,
01153                 // then the DPC and work-time have run to their completion
01154                 KeWaitForSingleObject(&deviceExtension->NoDpcWorkItemPendingEvent, Executive, KernelMode, FALSE, NULL);
01155 
01156                 // make sure that the selective suspend request has been completed.
01157                 KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, Executive, KernelMode, FALSE, NULL);
01158 
01159             }
01160 
01161         }
01162 
01163         ProcessQueuedRequests(deviceExtension);
01164 
01165         ntStatus = IoSetDeviceInterfaceState(&deviceExtension->InterfaceName, FALSE);
01166         if(!NT_SUCCESS(ntStatus))
01167         {
01168             FreeBT_DbgPrint(1, ("FBTUSB: HandleRemoveDevice: IoSetDeviceInterfaceState::disable:failed\n"));
01169 
01170         }
01171 
01172         FreeBT_AbortPipes(DeviceObject);
01173 
01174     }
01175 
01176     KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
01177     SET_NEW_PNP_STATE(deviceExtension, Removed);
01178     KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
01179 #ifdef ENABLE_WMI
01180     FreeBT_WmiDeRegistration(deviceExtension);
01181 #endif
01182 
01183     // Need 2 decrements
01184     FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
01185     requestCount = FreeBT_IoDecrement(deviceExtension);
01186 
01187     ASSERT(requestCount > 0);
01188 
01189     FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice::"));
01190     requestCount = FreeBT_IoDecrement(deviceExtension);
01191 
01192     KeWaitForSingleObject(&deviceExtension->RemoveEvent,
01193                           Executive,
01194                           KernelMode,
01195                           FALSE,
01196                           NULL);
01197 
01198     ReleaseMemory(DeviceObject);
01199 
01200     // We need to send the remove down the stack before we detach,
01201     // but we don't need to wait for the completion of this operation
01202     // (and to register a completion routine).
01203     Irp->IoStatus.Status = STATUS_SUCCESS;
01204     Irp->IoStatus.Information = 0;
01205 
01206     IoSkipCurrentIrpStackLocation(Irp);
01207     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
01208 
01209     IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
01210     IoDeleteDevice(DeviceObject);
01211 
01212     FreeBT_DbgPrint(3, ("FBTUSB: HandleRemoveDevice: Leaving\n"));
01213 
01214     return ntStatus;
01215 
01216 }
01217 
01218 NTSTATUS HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
01219 {
01220     ULONG                i;
01221     KEVENT               event;
01222     NTSTATUS             ntStatus;
01223     PDEVICE_EXTENSION    deviceExtension;
01224     PDEVICE_CAPABILITIES pdc;
01225     PIO_STACK_LOCATION   irpStack;
01226 
01227     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Entered\n"));
01228 
01229     irpStack = IoGetCurrentIrpStackLocation(Irp);
01230     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
01231     pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
01232 
01233     if(pdc->Version < 1 || pdc->Size < sizeof(DEVICE_CAPABILITIES))
01234     {
01235 
01236         FreeBT_DbgPrint(1, ("FBTUSB: HandleQueryCapabilities::request failed\n"));
01237         ntStatus = STATUS_UNSUCCESSFUL;
01238         return ntStatus;
01239 
01240     }
01241 
01242     // Add in the SurpriseRemovalOK bit before passing it down.
01243     pdc->SurpriseRemovalOK = TRUE;
01244     Irp->IoStatus.Status = STATUS_SUCCESS;
01245 
01246     KeInitializeEvent(&event, NotificationEvent, FALSE);
01247 
01248     IoCopyCurrentIrpStackLocationToNext(Irp);
01249     IoSetCompletionRoutine(Irp,
01250                            (PIO_COMPLETION_ROUTINE)IrpCompletionRoutine,
01251                            (PVOID)&event,
01252                            TRUE,
01253                            TRUE,
01254                            TRUE);
01255     ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
01256     if(ntStatus == STATUS_PENDING)
01257     {
01258         KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
01259         ntStatus = Irp->IoStatus.Status;
01260 
01261     }
01262 
01263     // initialize PowerDownLevel to disabled
01264     deviceExtension->PowerDownLevel = PowerDeviceUnspecified;
01265     if(NT_SUCCESS(ntStatus))
01266     {
01267         deviceExtension->DeviceCapabilities = *pdc;
01268         for(i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++)
01269         {
01270             if(deviceExtension->DeviceCapabilities.DeviceState[i] < PowerDeviceD3)
01271             {
01272                 deviceExtension->PowerDownLevel = deviceExtension->DeviceCapabilities.DeviceState[i];
01273 
01274             }
01275 
01276         }
01277 
01278         // since its safe to surprise-remove this device, we shall
01279         // set the SurpriseRemoveOK flag to supress any dialog to
01280         // user.
01281         pdc->SurpriseRemovalOK = 1;
01282 
01283     }
01284 
01285     if(deviceExtension->PowerDownLevel == PowerDeviceUnspecified ||
01286         deviceExtension->PowerDownLevel <= PowerDeviceD0)
01287     {
01288         deviceExtension->PowerDownLevel = PowerDeviceD2;
01289 
01290     }
01291 
01292     FreeBT_DbgPrint(3, ("FBTUSB: HandleQueryCapabilities: Leaving\n"));
01293 
01294     return ntStatus;
01295 }
01296 
01297 
01298 VOID DpcRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
01299 /*++
01300 
01301     DPC routine triggered by the timer to check the idle state
01302     of the device and submit an idle request for the device.
01303 
01304  --*/
01305 {
01306     NTSTATUS          ntStatus;
01307     PDEVICE_OBJECT    deviceObject;
01308     PDEVICE_EXTENSION deviceExtension;
01309     PIO_WORKITEM      item;
01310 
01311     FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Entered\n"));
01312 
01313     deviceObject = (PDEVICE_OBJECT)DeferredContext;
01314     deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
01315 
01316     // Clear this event since a DPC has been fired!
01317     KeClearEvent(&deviceExtension->NoDpcWorkItemPendingEvent);
01318 
01319     if(CanDeviceSuspend(deviceExtension))
01320     {
01321         FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Device is Idle\n"));
01322         item = IoAllocateWorkItem(deviceObject);
01323 
01324         if (item)
01325         {
01326             IoQueueWorkItem(item, IdleRequestWorkerRoutine, DelayedWorkQueue, item);
01327             ntStatus = STATUS_PENDING;
01328 
01329         }
01330 
01331         else
01332         {
01333             FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Cannot alloc memory for work item\n"));
01334             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
01335             KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
01336 
01337         }
01338 
01339     }
01340 
01341     else
01342     {
01343         FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Idle event not signaled\n"));
01344         KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
01345 
01346     }
01347 
01348     FreeBT_DbgPrint(3, ("FBTUSB: DpcRoutine: Leaving\n"));
01349 }
01350 
01351 
01352 VOID IdleRequestWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
01353 {
01354     //PIRP                   irp;
01355     NTSTATUS               ntStatus;
01356     PDEVICE_EXTENSION      deviceExtension;
01357     PIO_WORKITEM           workItem;
01358 
01359     FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Entered\n"));
01360 
01361     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
01362     workItem = (PIO_WORKITEM) Context;
01363 
01364     if(CanDeviceSuspend(deviceExtension))
01365     {
01366         FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is idle\n"));
01367         ntStatus = SubmitIdleRequestIrp(deviceExtension);
01368         if(!NT_SUCCESS(ntStatus))
01369         {
01370             FreeBT_DbgPrint(1, ("FBTUSB: IdleRequestWorkerRoutine: SubmitIdleRequestIrp failed\n"));
01371 
01372         }
01373 
01374     }
01375 
01376     else
01377     {
01378         FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestWorkerRoutine: Device is not idle\n"));
01379 
01380     }
01381 
01382     IoFreeWorkItem(workItem);
01383 
01384     KeSetEvent(&deviceExtension->NoDpcWorkItemPendingEvent, IO_NO_INCREMENT, FALSE);
01385 
01386     FreeBT_DbgPrint(3, ("FBTUSB: IdleRequestsWorkerRoutine: Leaving\n"));
01387 
01388 }
01389 
01390 
01391 VOID ProcessQueuedRequests(IN OUT PDEVICE_EXTENSION DeviceExtension)
01392 /*++
01393 
01394 Routine Description:
01395 
01396     Remove and process the entries in the queue. If this routine is called
01397     when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
01398     or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
01399     If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
01400     are complete with STATUS_DELETE_PENDING
01401 
01402 Arguments:
01403 
01404     DeviceExtension - pointer to device extension
01405 
01406 Return Value:
01407 
01408     None
01409 
01410 --*/
01411 {
01412     KIRQL       oldIrql;
01413     PIRP        nextIrp,
01414                 cancelledIrp;
01415     PVOID       cancelRoutine;
01416     LIST_ENTRY  cancelledIrpList;
01417     PLIST_ENTRY listEntry;
01418 
01419     FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Entered\n"));
01420 
01421     cancelRoutine = NULL;
01422     InitializeListHead(&cancelledIrpList);
01423 
01424     // 1.  dequeue the entries in the queue
01425     // 2.  reset the cancel routine
01426     // 3.  process them
01427     // 3a. if the device is active, send them down
01428     // 3b. else complete with STATUS_DELETE_PENDING
01429     while(1)
01430     {
01431         KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
01432         if(IsListEmpty(&DeviceExtension->NewRequestsQueue))
01433         {
01434             KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
01435             break;
01436 
01437         }
01438 
01439         listEntry = RemoveHeadList(&DeviceExtension->NewRequestsQueue);
01440         nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
01441 
01442         cancelRoutine = IoSetCancelRoutine(nextIrp, NULL);
01443 
01444         // check if its already cancelled
01445         if (nextIrp->Cancel)
01446         {
01447             if(cancelRoutine)
01448             {
01449                 // the cancel routine for this IRP hasnt been called yet
01450                 // so queue the IRP in the cancelledIrp list and complete
01451                 // after releasing the lock
01452                 InsertTailList(&cancelledIrpList, listEntry);
01453 
01454             }
01455 
01456             else
01457             {
01458                 // the cancel routine has run
01459                 // it must be waiting to hold the queue lock
01460                 // so initialize the IRPs listEntry
01461                 InitializeListHead(listEntry);
01462 
01463             }
01464 
01465             KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
01466 
01467         }
01468 
01469         else
01470         {
01471             KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
01472             if(FailRequests == DeviceExtension->QueueState)
01473             {
01474                 nextIrp->IoStatus.Information = 0;
01475                 nextIrp->IoStatus.Status = STATUS_DELETE_PENDING;
01476                 IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
01477 
01478             }
01479 
01480             else
01481             {
01482                 //PIO_STACK_LOCATION irpStack;
01483 
01484                 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
01485                 FreeBT_IoIncrement(DeviceExtension);
01486 
01487                 IoSkipCurrentIrpStackLocation(nextIrp);
01488                 IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
01489 
01490                 FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests::"));
01491                 FreeBT_IoDecrement(DeviceExtension);
01492 
01493             }
01494 
01495         }
01496 
01497     }
01498 
01499     while(!IsListEmpty(&cancelledIrpList))
01500     {
01501         PLIST_ENTRY cancelEntry = RemoveHeadList(&cancelledIrpList);
01502 
01503         cancelledIrp = CONTAINING_RECORD(cancelEntry, IRP, Tail.Overlay.ListEntry);
01504         cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
01505         cancelledIrp->IoStatus.Information = 0;
01506 
01507         IoCompleteRequest(cancelledIrp, IO_NO_INCREMENT);
01508 
01509     }
01510 
01511     FreeBT_DbgPrint(3, ("FBTUSB: ProcessQueuedRequests: Leaving\n"));
01512 
01513     return;
01514 
01515 }
01516 
01517 NTSTATUS FreeBT_GetRegistryDword(IN PWCHAR RegPath, IN PWCHAR ValueName, IN OUT PULONG Value)
01518 {
01519     ULONG                    defaultData;
01520     WCHAR                    buffer[MAXIMUM_FILENAME_LENGTH];
01521     NTSTATUS                 ntStatus;
01522     UNICODE_STRING           regPath;
01523     RTL_QUERY_REGISTRY_TABLE paramTable[2];
01524 
01525     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Entered\n"));
01526 
01527     regPath.Length = 0;
01528     regPath.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
01529     regPath.Buffer = buffer;
01530 
01531     RtlZeroMemory(regPath.Buffer, regPath.MaximumLength);
01532     RtlMoveMemory(regPath.Buffer, RegPath, wcslen(RegPath) * sizeof(WCHAR));
01533     RtlZeroMemory(paramTable, sizeof(paramTable));
01534 
01535     paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
01536     paramTable[0].Name = ValueName;
01537     paramTable[0].EntryContext = Value;
01538     paramTable[0].DefaultType = REG_DWORD;
01539     paramTable[0].DefaultData = &defaultData;
01540     paramTable[0].DefaultLength = sizeof(ULONG);
01541 
01542     ntStatus = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE |
01543                                       RTL_REGISTRY_OPTIONAL,
01544                                       regPath.Buffer,
01545                                       paramTable,
01546                                       NULL,
01547                                       NULL);
01548 
01549     if (NT_SUCCESS(ntStatus))
01550     {
01551         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Success, Value = %X\n", *Value));
01552         return STATUS_SUCCESS;
01553     }
01554 
01555     else
01556     {
01557         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_GetRegistryDword: Failed\n"));
01558         *Value = 0;
01559         return STATUS_UNSUCCESSFUL;
01560 
01561     }
01562 }
01563 
01564 
01565 NTSTATUS FreeBT_DispatchClean(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
01566 {
01567     PDEVICE_EXTENSION  deviceExtension;
01568     KIRQL              oldIrql;
01569     LIST_ENTRY         cleanupList;
01570     PLIST_ENTRY        thisEntry,
01571                        nextEntry,
01572                        listHead;
01573     PIRP               pendingIrp;
01574     PIO_STACK_LOCATION pendingIrpStack,
01575                        irpStack;
01576     //NTSTATUS           ntStatus;
01577 
01578     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
01579     irpStack = IoGetCurrentIrpStackLocation(Irp);
01580     InitializeListHead(&cleanupList);
01581 
01582     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
01583     FreeBT_IoIncrement(deviceExtension);
01584 
01585     KeAcquireSpinLock(&deviceExtension->QueueLock, &oldIrql);
01586 
01587     listHead = &deviceExtension->NewRequestsQueue;
01588     for(thisEntry = listHead->Flink, nextEntry = thisEntry->Flink;
01589        thisEntry != listHead;
01590        thisEntry = nextEntry, nextEntry = thisEntry->Flink)
01591     {
01592         pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
01593         pendingIrpStack = IoGetCurrentIrpStackLocation(pendingIrp);
01594         if (irpStack->FileObject == pendingIrpStack->FileObject)
01595         {
01596             RemoveEntryList(thisEntry);
01597 
01598             if (NULL == IoSetCancelRoutine(pendingIrp, NULL))
01599             {
01600                 InitializeListHead(thisEntry);
01601 
01602             }
01603 
01604             else
01605             {
01606                 InsertTailList(&cleanupList, thisEntry);
01607 
01608             }
01609 
01610         }
01611 
01612     }
01613 
01614     KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
01615 
01616     while(!IsListEmpty(&cleanupList))
01617     {
01618         thisEntry = RemoveHeadList(&cleanupList);
01619         pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
01620 
01621         pendingIrp->IoStatus.Information = 0;
01622         pendingIrp->IoStatus.Status = STATUS_CANCELLED;
01623         IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
01624 
01625     }
01626 
01627     Irp->IoStatus.Information = 0;
01628     Irp->IoStatus.Status = STATUS_SUCCESS;
01629 
01630     IoCompleteRequest(Irp, IO_NO_INCREMENT);
01631 
01632     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchClean::"));
01633     FreeBT_IoDecrement(deviceExtension);
01634 
01635     return STATUS_SUCCESS;
01636 
01637 }
01638 
01639 
01640 BOOLEAN CanDeviceSuspend(IN PDEVICE_EXTENSION DeviceExtension)
01641 {
01642     FreeBT_DbgPrint(3, ("FBTUSB: CanDeviceSuspend: Entered\n"));
01643 
01644     if ((DeviceExtension->OpenHandleCount == 0) && (DeviceExtension->OutStandingIO == 1))
01645         return TRUE;
01646 
01647     return FALSE;
01648 
01649 }
01650 
01651 NTSTATUS FreeBT_AbortPipes(IN PDEVICE_OBJECT DeviceObject)
01652 {
01653     PURB                        urb;
01654     ULONG                       i;
01655     NTSTATUS                    ntStatus;
01656     PDEVICE_EXTENSION           deviceExtension;
01657     PFREEBT_PIPE_CONTEXT        pipeContext;
01658     //PUSBD_PIPE_INFORMATION      pipeInformation;
01659     PUSBD_INTERFACE_INFORMATION interfaceInfo;
01660 
01661     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
01662     pipeContext = deviceExtension->PipeContext;
01663     interfaceInfo = deviceExtension->UsbInterface;
01664 
01665     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Entered\n"));
01666 
01667     if(interfaceInfo == NULL || pipeContext == NULL)
01668         return STATUS_SUCCESS;
01669 
01670     for(i=0; i<interfaceInfo->NumberOfPipes; i++)
01671     {
01672         if(pipeContext[i].PipeOpen)
01673         {
01674             FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Aborting open pipe %d\n", i));
01675 
01676             urb = (PURB) ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
01677             if (urb)
01678             {
01679                 urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
01680                 urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
01681                 urb->UrbPipeRequest.PipeHandle = interfaceInfo->Pipes[i].PipeHandle;
01682 
01683                 ntStatus = CallUSBD(DeviceObject, urb);
01684 
01685                 ExFreePool(urb);
01686 
01687             }
01688 
01689             else
01690             {
01691                 FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_AbortPipes: Failed to alloc memory for urb\n"));
01692                 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
01693                 return ntStatus;
01694 
01695             }
01696 
01697             if(NT_SUCCESS(ntStatus))
01698                 pipeContext[i].PipeOpen = FALSE;
01699 
01700 
01701         }
01702 
01703     }
01704 
01705     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_AbortPipes: Leaving\n"));
01706 
01707     return STATUS_SUCCESS;
01708 
01709 }
01710 
01711 // Completion routine for PNP IRPs
01712 NTSTATUS IrpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
01713 {
01714     PKEVENT event = (PKEVENT) Context;
01715     KeSetEvent(event, 0, FALSE);
01716 
01717     return STATUS_MORE_PROCESSING_REQUIRED;
01718 
01719 }
01720 
01721 
01722 LONG FreeBT_IoIncrement(IN OUT PDEVICE_EXTENSION DeviceExtension)
01723 {
01724     LONG  result = 0;
01725     KIRQL oldIrql;
01726 
01727     KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
01728     result = InterlockedIncrement((PLONG)(&DeviceExtension->OutStandingIO));
01729 
01730     // When OutStandingIO bumps from 1 to 2, clear the StopEvent
01731     if (result == 2)
01732         KeClearEvent(&DeviceExtension->StopEvent);
01733 
01734     KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
01735 
01736     FreeBT_DbgPrint(3, ("FreeBT_IoIncrement::%d\n", result));
01737 
01738     return result;
01739 
01740 }
01741 
01742 LONG FreeBT_IoDecrement(IN OUT PDEVICE_EXTENSION DeviceExtension)
01743 {
01744     LONG  result = 0;
01745     KIRQL oldIrql;
01746 
01747     KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
01748 
01749     result = InterlockedDecrement((PLONG)(&DeviceExtension->OutStandingIO));
01750 
01751     if (result == 1)
01752         KeSetEvent(&DeviceExtension->StopEvent, IO_NO_INCREMENT, FALSE);
01753 
01754     if(result == 0)
01755     {
01756         ASSERT(Removed == DeviceExtension->DeviceState);
01757         KeSetEvent(&DeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE);
01758 
01759     }
01760 
01761     KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
01762 
01763     FreeBT_DbgPrint(3, ("FreeBT_IoDecrement::%d\n", result));
01764 
01765     return result;
01766 
01767 }
01768 
01769 NTSTATUS CanStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
01770 {
01771    // For the time being, just allow it to be stopped
01772    UNREFERENCED_PARAMETER(DeviceObject);
01773    UNREFERENCED_PARAMETER(Irp);
01774 
01775    return STATUS_SUCCESS;
01776 
01777 }
01778 
01779 NTSTATUS CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
01780 
01781 {
01782    // For the time being, just allow it to be removed
01783    UNREFERENCED_PARAMETER(DeviceObject);
01784    UNREFERENCED_PARAMETER(Irp);
01785 
01786    return STATUS_SUCCESS;
01787 
01788 }
01789 
01790 NTSTATUS ReleaseMemory(IN PDEVICE_OBJECT DeviceObject)
01791 {
01792     // Disconnect from the interrupt and unmap any I/O ports
01793     PDEVICE_EXTENSION   deviceExtension;
01794     UNICODE_STRING      uniDeviceName;
01795     NTSTATUS            ntStatus;
01796 
01797     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
01798     if (deviceExtension->UsbConfigurationDescriptor)
01799     {
01800         FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbConfigurationDescriptor\n"));
01801         ExFreePool(deviceExtension->UsbConfigurationDescriptor);
01802         deviceExtension->UsbConfigurationDescriptor = NULL;
01803 
01804     }
01805 
01806     if(deviceExtension->UsbInterface)
01807     {
01808         FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing UsbInterface\n"));
01809         ExFreePool(deviceExtension->UsbInterface);
01810         deviceExtension->UsbInterface = NULL;
01811 
01812     }
01813 
01814     if(deviceExtension->PipeContext)
01815     {
01816         RtlInitUnicodeString(&uniDeviceName, deviceExtension->wszDosDeviceName);
01817         ntStatus = IoDeleteSymbolicLink(&uniDeviceName);
01818         if (!NT_SUCCESS(ntStatus))
01819             FreeBT_DbgPrint(3, ("FBTUSB: Failed to delete symbolic link %ws\n", deviceExtension->wszDosDeviceName));
01820 
01821         FreeBT_DbgPrint(3, ("FBTUSB: ReleaseMemory: Freeing PipeContext %p\n", deviceExtension->PipeContext));
01822         ExFreePool(deviceExtension->PipeContext);
01823         deviceExtension->PipeContext = NULL;
01824 
01825     }
01826 
01827     return STATUS_SUCCESS;
01828 
01829 }
01830 
01831 PCHAR PnPMinorFunctionString (UCHAR MinorFunction)
01832 {
01833     switch (MinorFunction)
01834     {
01835         case IRP_MN_START_DEVICE:
01836             return "IRP_MN_START_DEVICE\n";
01837 
01838         case IRP_MN_QUERY_REMOVE_DEVICE:
01839             return "IRP_MN_QUERY_REMOVE_DEVICE\n";
01840 
01841         case IRP_MN_REMOVE_DEVICE:
01842             return "IRP_MN_REMOVE_DEVICE\n";
01843 
01844         case IRP_MN_CANCEL_REMOVE_DEVICE:
01845             return "IRP_MN_CANCEL_REMOVE_DEVICE\n";
01846 
01847         case IRP_MN_STOP_DEVICE:
01848             return "IRP_MN_STOP_DEVICE\n";
01849 
01850         case IRP_MN_QUERY_STOP_DEVICE:
01851             return "IRP_MN_QUERY_STOP_DEVICE\n";
01852 
01853         case IRP_MN_CANCEL_STOP_DEVICE:
01854             return "IRP_MN_CANCEL_STOP_DEVICE\n";
01855 
01856         case IRP_MN_QUERY_DEVICE_RELATIONS:
01857             return "IRP_MN_QUERY_DEVICE_RELATIONS\n";
01858 
01859         case IRP_MN_QUERY_INTERFACE:
01860             return "IRP_MN_QUERY_INTERFACE\n";
01861 
01862         case IRP_MN_QUERY_CAPABILITIES:
01863             return "IRP_MN_QUERY_CAPABILITIES\n";
01864 
01865         case IRP_MN_QUERY_RESOURCES:
01866             return "IRP_MN_QUERY_RESOURCES\n";
01867 
01868         case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
01869             return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n";
01870 
01871         case IRP_MN_QUERY_DEVICE_TEXT:
01872             return "IRP_MN_QUERY_DEVICE_TEXT\n";
01873 
01874         case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
01875             return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n";
01876 
01877         case IRP_MN_READ_CONFIG:
01878             return "IRP_MN_READ_CONFIG\n";
01879 
01880         case IRP_MN_WRITE_CONFIG:
01881             return "IRP_MN_WRITE_CONFIG\n";
01882 
01883         case IRP_MN_EJECT:
01884             return "IRP_MN_EJECT\n";
01885 
01886         case IRP_MN_SET_LOCK:
01887             return "IRP_MN_SET_LOCK\n";
01888 
01889         case IRP_MN_QUERY_ID:
01890             return "IRP_MN_QUERY_ID\n";
01891 
01892         case IRP_MN_QUERY_PNP_DEVICE_STATE:
01893             return "IRP_MN_QUERY_PNP_DEVICE_STATE\n";
01894 
01895         case IRP_MN_QUERY_BUS_INFORMATION:
01896             return "IRP_MN_QUERY_BUS_INFORMATION\n";
01897 
01898         case IRP_MN_DEVICE_USAGE_NOTIFICATION:
01899             return "IRP_MN_DEVICE_USAGE_NOTIFICATION\n";
01900 
01901         case IRP_MN_SURPRISE_REMOVAL:
01902             return "IRP_MN_SURPRISE_REMOVAL\n";
01903 
01904         default:
01905             return "IRP_MN_?????\n";
01906 
01907     }
01908 
01909 }
01910 

Generated on Sat May 26 2012 04:25:43 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.