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

fdo.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Universal Serial Bus Hub Driver
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            drivers/usb/usbhub/fdo.c
00005  * PURPOSE:         Handle FDO
00006  * PROGRAMMERS:
00007  *                  Michael Martin (michael.martin@reactos.org)
00008  *                  Johannes Anderwald (johannes.anderwald@reactos.org)
00009  */
00010 
00011 #define INITGUID
00012 #include "usbhub.h"
00013 
00014 NTSTATUS
00015 QueryStatusChangeEndpoint(
00016     IN PDEVICE_OBJECT DeviceObject);
00017 
00018 NTSTATUS
00019 CreateUsbChildDeviceObject(
00020     IN PDEVICE_OBJECT UsbHubDeviceObject,
00021     IN LONG PortId,
00022     OUT PDEVICE_OBJECT *UsbChildDeviceObject,
00023     IN ULONG PortStatus);
00024 
00025 NTSTATUS
00026 DestroyUsbChildDeviceObject(
00027     IN PDEVICE_OBJECT UsbHubDeviceObject,
00028     IN LONG PortId);
00029 
00030 
00031 NTSTATUS
00032 GetPortStatusAndChange(
00033     IN PDEVICE_OBJECT RootHubDeviceObject,
00034     IN ULONG PortId,
00035     OUT PPORT_STATUS_CHANGE StatusChange)
00036 {
00037     NTSTATUS Status;
00038     PURB Urb;
00039 
00040     //
00041     // Allocate URB
00042     //
00043     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
00044     if (!Urb)
00045     {
00046         DPRINT1("Failed to allocate memory for URB!\n");
00047         return STATUS_INSUFFICIENT_RESOURCES;
00048     }
00049 
00050     //
00051     // Zero it
00052     //
00053     RtlZeroMemory(Urb, sizeof(URB));
00054 
00055     //
00056     // Initialize URB for getting Port Status
00057     //
00058     UsbBuildVendorRequest(Urb,
00059                           URB_FUNCTION_CLASS_OTHER,
00060                           sizeof(Urb->UrbControlVendorClassRequest),
00061                           USBD_TRANSFER_DIRECTION_OUT,
00062                           0,
00063                           USB_REQUEST_GET_STATUS,
00064                           0,
00065                           PortId,
00066                           StatusChange,
00067                           0,
00068                           sizeof(PORT_STATUS_CHANGE),
00069                           0);
00070 
00071     // FIXME: support usb hubs
00072     Urb->UrbHeader.UsbdDeviceHandle = NULL;
00073 
00074 
00075     //
00076     // Query the Root Hub
00077     //
00078     Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
00079 
00080     //
00081     // Free URB
00082     //
00083     ExFreePool(Urb);
00084 
00085     return Status;
00086 }
00087 
00088 NTSTATUS
00089 SetPortFeature(
00090     IN PDEVICE_OBJECT RootHubDeviceObject,
00091     IN ULONG PortId,
00092     IN ULONG Feature)
00093 {
00094     NTSTATUS Status;
00095     PURB Urb;
00096 
00097     //
00098     // Allocate URB
00099     //
00100     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
00101     if (!Urb)
00102     {
00103         DPRINT1("Failed to allocate memory for URB!\n");
00104         return STATUS_INSUFFICIENT_RESOURCES;
00105     }
00106 
00107     //
00108     // Zero it
00109     //
00110     RtlZeroMemory(Urb, sizeof(URB));
00111 
00112     //
00113     // Initialize URB for Clearing Port Reset
00114     //
00115     UsbBuildVendorRequest(Urb,
00116                           URB_FUNCTION_CLASS_OTHER,
00117                           sizeof(Urb->UrbControlVendorClassRequest),
00118                           USBD_TRANSFER_DIRECTION_IN,
00119                           0,
00120                           USB_REQUEST_SET_FEATURE,
00121                           Feature,
00122                           PortId,
00123                           NULL,
00124                           0,
00125                           0,
00126                           0);
00127 
00128     // FIXME support usbhubs
00129     Urb->UrbHeader.UsbdDeviceHandle = NULL;
00130 
00131     //
00132     // Query the Root Hub
00133     //
00134     Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
00135 
00136     //
00137     // Free URB
00138     //
00139     ExFreePool(Urb);
00140 
00141     return Status;
00142 }
00143 
00144 NTSTATUS
00145 ClearPortFeature(
00146     IN PDEVICE_OBJECT RootHubDeviceObject,
00147     IN ULONG PortId,
00148     IN ULONG Feature)
00149 {
00150     NTSTATUS Status;
00151     PURB Urb;
00152 
00153     //
00154     // Allocate a URB
00155     //
00156     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
00157     if (!Urb)
00158     {
00159         DPRINT1("Failed to allocate memory for URB!\n");
00160         return STATUS_INSUFFICIENT_RESOURCES;
00161     }
00162 
00163     //
00164     // Zero it
00165     //
00166     RtlZeroMemory(Urb, sizeof(URB));
00167 
00168     //
00169     // Initialize URB for Clearing Port Reset
00170     //
00171     UsbBuildVendorRequest(Urb,
00172                           URB_FUNCTION_CLASS_OTHER,
00173                           sizeof(Urb->UrbControlVendorClassRequest),
00174                           USBD_TRANSFER_DIRECTION_IN,
00175                           0,
00176                           USB_REQUEST_CLEAR_FEATURE,
00177                           Feature,
00178                           PortId,
00179                           NULL,
00180                           0,
00181                           0,
00182                           0);
00183 
00184     // FIXME: support usb hubs
00185     Urb->UrbHeader.UsbdDeviceHandle = NULL;
00186 
00187     //
00188     // Query the Root Hub
00189     //
00190     Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
00191 
00192     //
00193     // Free URB
00194     //
00195     ExFreePool(Urb);
00196 
00197     return Status;
00198 }
00199 
00200 VOID NTAPI
00201 DeviceStatusChangeThread(
00202     IN PVOID Context)
00203 {
00204     NTSTATUS Status;
00205     PDEVICE_OBJECT DeviceObject, RootHubDeviceObject;
00206     PHUB_DEVICE_EXTENSION HubDeviceExtension;
00207     PWORK_ITEM_DATA WorkItemData;
00208     PORT_STATUS_CHANGE PortStatus;
00209     LONG PortId;
00210     BOOLEAN SignalResetComplete = FALSE;
00211 
00212     DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context);
00213 
00214     WorkItemData = (PWORK_ITEM_DATA)Context;
00215     DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context;
00216     HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00217     RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
00218     //
00219     // Loop all ports
00220     //
00221     for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
00222     {
00223         //
00224         // Get Port Status
00225         //
00226         Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
00227         if (!NT_SUCCESS(Status))
00228         {
00229             DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
00230             // FIXME: Do we really want to halt further SCE requests?
00231             return;
00232         }
00233 
00234         DPRINT1("Port %d Status %x\n", PortId, PortStatus.Status);
00235         DPRINT1("Port %d Change %x\n", PortId, PortStatus.Change);
00236 
00237 
00238         //
00239         // Check for new device connection
00240         //
00241         if (PortStatus.Change & USB_PORT_STATUS_CONNECT)
00242         {
00243             //
00244             // Clear Port Connect 
00245             //
00246             Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION);
00247             if (!NT_SUCCESS(Status))
00248             {
00249                 DPRINT1("Failed to clear connection change for port %d\n", PortId);
00250                 continue;
00251             }
00252 
00253             //
00254             // Is this a connect or disconnect?
00255             //
00256             if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT))
00257             {
00258                 DPRINT1("Device disconnected from port %d\n", PortId);
00259 
00260                 Status = DestroyUsbChildDeviceObject(DeviceObject, PortId);
00261                 if (!NT_SUCCESS(Status))
00262                 {
00263                     DPRINT1("Failed to delete child device object after disconnect\n");
00264                     continue;
00265                 }
00266             }
00267             else
00268             {
00269                 DPRINT1("Device connected from port %d\n", PortId);
00270 
00271                 // No SCE completion done for clearing C_PORT_CONNECT
00272 
00273                 //
00274                 // Reset Port
00275                 //
00276                 Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET);
00277                 if (!NT_SUCCESS(Status))
00278                 {
00279                     DPRINT1("Failed to reset port %d\n", PortId);
00280                     SignalResetComplete = TRUE;
00281                     continue;
00282                 }
00283             }
00284         }
00285         else if (PortStatus.Change & USB_PORT_STATUS_ENABLE)
00286         {
00287             //
00288             // Clear Enable
00289             //
00290             Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_ENABLE);
00291             if (!NT_SUCCESS(Status))
00292             {
00293                 DPRINT1("Failed to clear enable change on port %d\n", PortId);
00294                 continue;
00295             }
00296         }
00297         else if (PortStatus.Change & USB_PORT_STATUS_RESET)
00298         {
00299             //
00300             // Request event signalling later
00301             //
00302             SignalResetComplete = TRUE;
00303 
00304             //
00305             // Clear Reset
00306             //
00307             Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_RESET);
00308             if (!NT_SUCCESS(Status))
00309             {
00310                 DPRINT1("Failed to clear reset change on port %d\n", PortId);
00311                 continue;
00312             }
00313 
00314             //
00315             // Get Port Status
00316             //
00317             Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
00318             if (!NT_SUCCESS(Status))
00319             {
00320                 DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status);
00321                 // FIXME: Do we really want to halt further SCE requests?
00322                 return;
00323             }
00324 
00325             DPRINT1("Port %d Status %x\n", PortId, PortStatus.Status);
00326             DPRINT1("Port %d Change %x\n", PortId, PortStatus.Change);
00327 
00328             //
00329             // Check that reset was cleared
00330             //
00331             if(PortStatus.Change & USB_PORT_STATUS_RESET)
00332             {
00333                 DPRINT1("Port did not clear reset! Possible Hardware problem!\n");
00334                 continue;
00335             }
00336 
00337             //
00338             // Check if the device is still connected
00339             //
00340             if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT))
00341             {
00342                 DPRINT1("Device has been disconnected\n");
00343                 continue;
00344             }
00345 
00346             //
00347             // Make sure its Connected and Enabled
00348             //
00349             if (!(PortStatus.Status & (USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE)))
00350             {
00351                 DPRINT1("Usb Device is not connected and enabled!\n");
00352                 //
00353                 // Attempt another reset
00354                 //
00355                 Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET);
00356                 if (!NT_SUCCESS(Status))
00357                 {
00358                     DPRINT1("Failed to reset port %d\n", PortId);
00359                 }
00360                 continue;
00361             }
00362 
00363             //
00364             // This is a new device
00365             //
00366             Status = CreateUsbChildDeviceObject(DeviceObject, PortId, NULL, PortStatus.Status);
00367         }
00368     }
00369 
00370     ExFreePool(WorkItemData);
00371 
00372     //
00373     // Send another SCE Request
00374     //
00375     DPRINT("Sending another SCE!\n");
00376     QueryStatusChangeEndpoint(DeviceObject);
00377 
00378     //
00379     // Check if a reset event was satisfied
00380     //
00381     if (SignalResetComplete)
00382     {
00383         //
00384         // Signal anyone waiting on it
00385         //
00386         KeSetEvent(&HubDeviceExtension->ResetComplete, IO_NO_INCREMENT, FALSE);
00387     }
00388 }
00389 
00390 NTSTATUS
00391 NTAPI
00392 StatusChangeEndpointCompletion(
00393     IN PDEVICE_OBJECT DeviceObject,
00394     IN PIRP Irp,
00395     IN PVOID Context)
00396 {
00397     PDEVICE_OBJECT RealDeviceObject;
00398     PHUB_DEVICE_EXTENSION HubDeviceExtension;
00399     PWORK_ITEM_DATA WorkItemData;
00400 
00401     RealDeviceObject = (PDEVICE_OBJECT)Context;
00402     HubDeviceExtension = (PHUB_DEVICE_EXTENSION)RealDeviceObject->DeviceExtension;
00403 
00404     //
00405     // NOTE: USBPORT frees this IRP
00406     //
00407     DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp, HubDeviceExtension->PendingSCEIrp);
00408     //IoFreeIrp(Irp);
00409 
00410     //
00411     // Create and initialize work item data
00412     //
00413     WorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_ITEM_DATA), USB_HUB_TAG);
00414     if (!WorkItemData)
00415     {
00416         DPRINT1("Failed to allocate memory!n");
00417         return STATUS_INSUFFICIENT_RESOURCES;
00418     }
00419     WorkItemData->Context = RealDeviceObject;
00420 
00421     DPRINT("Queuing work item\n");
00422 
00423     //
00424     // Queue the work item to handle initializing the device
00425     //
00426     ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
00427     ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
00428 
00429     //
00430     // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed
00431     //
00432     return STATUS_MORE_PROCESSING_REQUIRED;
00433 }
00434 
00435 NTSTATUS
00436 QueryStatusChangeEndpoint(
00437     IN PDEVICE_OBJECT DeviceObject)
00438 {
00439     NTSTATUS Status;
00440     PDEVICE_OBJECT RootHubDeviceObject;
00441     PIO_STACK_LOCATION Stack;
00442     PHUB_DEVICE_EXTENSION HubDeviceExtension;
00443     PURB PendingSCEUrb;
00444 
00445     HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00446     RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
00447 
00448     //
00449     // Allocate a URB
00450     //
00451     PendingSCEUrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
00452 
00453     //
00454     // Initialize URB for Status Change Endpoint request
00455     //
00456     UsbBuildInterruptOrBulkTransferRequest(PendingSCEUrb,
00457                                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
00458                                            HubDeviceExtension->PipeHandle,
00459                                            HubDeviceExtension->PortStatusChange,
00460                                            NULL,
00461                                            sizeof(USHORT) * 2 * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
00462                                            USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
00463                                            NULL);
00464 
00465     // Set the device handle
00466     PendingSCEUrb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
00467 
00468     //
00469     // Allocate an Irp
00470     //
00471     HubDeviceExtension->PendingSCEIrp = ExAllocatePoolWithTag(NonPagedPool,
00472                                                               IoSizeOfIrp(RootHubDeviceObject->StackSize),
00473                                                               USB_HUB_TAG);
00474 /*
00475     HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize,
00476                                   FALSE);
00477 */
00478     DPRINT("Allocated IRP %x\n", HubDeviceExtension->PendingSCEIrp);
00479 
00480     if (!HubDeviceExtension->PendingSCEIrp)
00481     {
00482         DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n");
00483         return STATUS_INSUFFICIENT_RESOURCES;
00484     }
00485 
00486     //
00487     // Initialize the IRP
00488     //
00489     IoInitializeIrp(HubDeviceExtension->PendingSCEIrp,
00490                     IoSizeOfIrp(RootHubDeviceObject->StackSize),
00491                     RootHubDeviceObject->StackSize);
00492 
00493     HubDeviceExtension->PendingSCEIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
00494     HubDeviceExtension->PendingSCEIrp->IoStatus.Information = 0;
00495     HubDeviceExtension->PendingSCEIrp->Flags = 0;
00496     HubDeviceExtension->PendingSCEIrp->UserBuffer = NULL;
00497 
00498     //
00499     // Get the Next Stack Location and Initialize it
00500     //
00501     Stack = IoGetNextIrpStackLocation(HubDeviceExtension->PendingSCEIrp);
00502     Stack->DeviceObject = DeviceObject;
00503     Stack->Parameters.Others.Argument1 = PendingSCEUrb;
00504     Stack->Parameters.Others.Argument2 = NULL;
00505     Stack->MajorFunction =  IRP_MJ_INTERNAL_DEVICE_CONTROL;
00506     Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
00507 
00508     //
00509     // Set the completion routine for when device is connected to root hub
00510     //
00511     IoSetCompletionRoutine(HubDeviceExtension->PendingSCEIrp,
00512                            StatusChangeEndpointCompletion,
00513                            DeviceObject,
00514                            TRUE,
00515                            TRUE,
00516                            TRUE);
00517 
00518     //
00519     // Send to RootHub
00520     //
00521     DPRINT("DeviceObject is %x\n", DeviceObject);
00522     DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp);
00523     Status = IoCallDriver(RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp);
00524 
00525     return STATUS_PENDING;
00526 }
00527 
00528 NTSTATUS
00529 QueryInterface(
00530     IN PDEVICE_OBJECT DeviceObject,
00531     IN CONST GUID InterfaceType,
00532     IN LONG Size,
00533     IN LONG Version,
00534     OUT PVOID Interface)
00535 {
00536     KEVENT Event;
00537     PIRP Irp;
00538     IO_STATUS_BLOCK IoStatus;
00539     NTSTATUS Status;
00540     PIO_STACK_LOCATION Stack = NULL;
00541 
00542     //
00543     // Initialize the Event used to wait for Irp completion
00544     //
00545     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00546 
00547     //
00548     // Build Control Request
00549     //
00550     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
00551                                        DeviceObject,
00552                                        NULL,
00553                                        0,
00554                                        NULL,
00555                                        &Event,
00556                                        &IoStatus);
00557 
00558     //
00559     // Get Next Stack Location and Initialize it.
00560     //
00561     Stack = IoGetNextIrpStackLocation(Irp);
00562     Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
00563     Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID;
00564     Stack->Parameters.QueryInterface.Size = Size;
00565     Stack->Parameters.QueryInterface.Version = Version;
00566     Stack->Parameters.QueryInterface.Interface = Interface;
00567     Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
00568 
00569     Status = IoCallDriver(DeviceObject, Irp);
00570 
00571     if (Status == STATUS_PENDING)
00572     {
00573         DPRINT("Operation pending\n");
00574         KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
00575         Status = IoStatus.Status;
00576     }
00577 
00578     return Status;
00579 }
00580 
00581 NTSTATUS
00582 GetUsbDeviceDescriptor(
00583     IN PDEVICE_OBJECT ChildDeviceObject,
00584     IN UCHAR DescriptorType,
00585     IN UCHAR Index,
00586     IN USHORT LangId,
00587     OUT PVOID TransferBuffer,
00588     IN ULONG TransferBufferLength)
00589 {
00590     NTSTATUS Status;
00591     PDEVICE_OBJECT RootHubDeviceObject;
00592     PURB Urb;
00593     PHUB_DEVICE_EXTENSION HubDeviceExtension;
00594     PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
00595 
00596     //
00597     // Get the Hubs Device Extension
00598     //
00599     ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension;
00600     HubDeviceExtension = (PHUB_DEVICE_EXTENSION) ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
00601     RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
00602 
00603     //
00604     // Allocate a URB
00605     //
00606     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
00607     if (!Urb)
00608     {
00609         DPRINT1("Failed to allocate memory for URB!\n");
00610         return STATUS_INSUFFICIENT_RESOURCES;
00611     }
00612 
00613     //
00614     // Zero it
00615     //
00616     RtlZeroMemory(Urb, sizeof(URB));
00617 
00618     //
00619     // Initialize URB for getting device descriptor
00620     //
00621     UsbBuildGetDescriptorRequest(Urb,
00622                                  sizeof(Urb->UrbControlDescriptorRequest),
00623                                  DescriptorType,
00624                                  Index,
00625                                  LangId,
00626                                  TransferBuffer,
00627                                  NULL,
00628                                  TransferBufferLength,
00629                                  NULL);
00630 
00631     //
00632     // Set the device handle
00633     //
00634     Urb->UrbHeader.UsbdDeviceHandle = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
00635 
00636     //
00637     // Query the Root Hub
00638     //
00639     Status = SubmitRequestToRootHub(RootHubDeviceObject,
00640                                     IOCTL_INTERNAL_USB_SUBMIT_URB,
00641                                     Urb,
00642                                     NULL);
00643 
00644     return Status;
00645 }
00646 
00647 NTSTATUS
00648 GetUsbStringDescriptor(
00649     IN PDEVICE_OBJECT ChildDeviceObject,
00650     IN UCHAR Index,
00651     IN USHORT LangId,
00652     OUT PVOID *TransferBuffer,
00653     OUT USHORT *Size)
00654 {
00655     NTSTATUS Status;
00656     PUSB_STRING_DESCRIPTOR StringDesc = NULL;
00657     ULONG SizeNeeded;
00658     LPWSTR Buffer;
00659 
00660     StringDesc = ExAllocatePoolWithTag(NonPagedPool,
00661                                        sizeof(USB_STRING_DESCRIPTOR),
00662                                        USB_HUB_TAG);
00663     if (!StringDesc)
00664     {
00665         DPRINT1("Failed to allocate buffer for string!\n");
00666         return STATUS_INSUFFICIENT_RESOURCES;
00667     }
00668 
00669     //
00670     // Get the index string descriptor length
00671     // FIXME: Implement LangIds
00672     //
00673     Status = GetUsbDeviceDescriptor(ChildDeviceObject,
00674                                     USB_STRING_DESCRIPTOR_TYPE,
00675                                     Index,
00676                                     0x0409,
00677                                     StringDesc,
00678                                     sizeof(USB_STRING_DESCRIPTOR));
00679     if (!NT_SUCCESS(Status))
00680     {
00681         DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status);
00682         ExFreePool(StringDesc);
00683         return Status;
00684     }
00685     DPRINT1("StringDesc->bLength %d\n", StringDesc->bLength);
00686 
00687     //
00688     // Did we get something more than the length of the first two fields of structure?
00689     //
00690     if (StringDesc->bLength == 2)
00691     {
00692         DPRINT1("USB Device Error!\n");
00693         ExFreePool(StringDesc);
00694         return STATUS_DEVICE_DATA_ERROR;
00695     }
00696     SizeNeeded = StringDesc->bLength + sizeof(WCHAR);
00697 
00698     //
00699     // Free String
00700     //
00701     ExFreePool(StringDesc);
00702 
00703     //
00704     // Recreate with appropriate size
00705     //
00706     StringDesc = ExAllocatePoolWithTag(NonPagedPool,
00707                                        SizeNeeded,
00708                                        USB_HUB_TAG);
00709     if (!StringDesc)
00710     {
00711         DPRINT1("Failed to allocate buffer for string!\n");
00712         return STATUS_INSUFFICIENT_RESOURCES;
00713     }
00714 
00715     RtlZeroMemory(StringDesc, SizeNeeded);
00716 
00717     //
00718     // Get the string
00719     //
00720     Status = GetUsbDeviceDescriptor(ChildDeviceObject,
00721                                     USB_STRING_DESCRIPTOR_TYPE,
00722                                     Index,
00723                                     0x0409,
00724                                     StringDesc,
00725                                     SizeNeeded);
00726     if (!NT_SUCCESS(Status))
00727     {
00728         DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status);
00729         ExFreePool(StringDesc);
00730         return Status;
00731     }
00732 
00733     //
00734     // Allocate Buffer to return
00735     //
00736     Buffer = ExAllocatePoolWithTag(NonPagedPool,
00737                                    SizeNeeded,
00738                                    USB_HUB_TAG);
00739     if (!Buffer)
00740     {
00741         DPRINT1("Failed to allocate buffer for string!\n");
00742         ExFreePool(StringDesc);
00743         return STATUS_INSUFFICIENT_RESOURCES;
00744     }
00745 
00746     RtlZeroMemory(Buffer, SizeNeeded);
00747 
00748     //
00749     // Copy the string to destination
00750     //
00751     RtlCopyMemory(Buffer, StringDesc->bString, SizeNeeded - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString));
00752     *Size = SizeNeeded;
00753     *TransferBuffer = Buffer;
00754 
00755     ExFreePool(StringDesc);
00756 
00757     return STATUS_SUCCESS;
00758 }
00759 
00760 ULONG
00761 IsCompositeDevice(
00762     IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor,
00763     IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
00764 {
00765     if (DeviceDescriptor->bNumConfigurations != 1)
00766     {
00767          //
00768          // composite device must have only one configuration
00769          //
00770          DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
00771          return FALSE;
00772     }
00773 
00774     if (ConfigurationDescriptor->bNumInterfaces < 2)
00775     {
00776         //
00777         // composite device must have multiple interfaces
00778         //
00779         DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
00780         return FALSE;
00781     }
00782 
00783     if (DeviceDescriptor->bDeviceClass == 0)
00784     {
00785         //
00786         // composite device
00787         //
00788         ASSERT(DeviceDescriptor->bDeviceSubClass == 0);
00789         ASSERT(DeviceDescriptor->bDeviceProtocol == 0);
00790         DPRINT1("IsCompositeDevice: TRUE\n");
00791         return TRUE;
00792     }
00793 
00794     if (DeviceDescriptor->bDeviceClass == 0xEF && 
00795         DeviceDescriptor->bDeviceSubClass == 0x02 &&
00796         DeviceDescriptor->bDeviceProtocol == 0x01)
00797     {
00798         //
00799         // USB-IF association descriptor
00800         //
00801         DPRINT1("IsCompositeDevice: TRUE\n");
00802         return TRUE;
00803     }
00804 
00805     DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol);
00806 
00807     //
00808     // not a composite device
00809     //
00810     return FALSE;
00811 }
00812 
00813 NTSTATUS
00814 CreateDeviceIds(
00815     PDEVICE_OBJECT UsbChildDeviceObject)
00816 {
00817     NTSTATUS Status = STATUS_SUCCESS;
00818     ULONG Index = 0;
00819     LPWSTR DeviceString;
00820     WCHAR Buffer[200];
00821     PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
00822     PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
00823     PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
00824     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
00825 
00826     //
00827     // get child device extension
00828     //
00829     UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
00830 
00831     //
00832     // get device descriptor
00833     //
00834     DeviceDescriptor = &UsbChildExtension->DeviceDesc;
00835 
00836     //
00837     // get configuration descriptor
00838     //
00839     ConfigurationDescriptor = UsbChildExtension->FullConfigDesc;
00840 
00841     //
00842     // use first interface descriptor available
00843     //
00844     InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, 0, -1, -1, -1, -1);
00845     ASSERT(InterfaceDescriptor);
00846 
00847     //
00848     // Construct the CompatibleIds
00849     //
00850     if (IsCompositeDevice(DeviceDescriptor, ConfigurationDescriptor))
00851     {
00852         //
00853         // sanity checks
00854         //
00855         ASSERT(DeviceDescriptor->bNumConfigurations == 1);
00856         ASSERT(ConfigurationDescriptor->bNumInterfaces > 1);
00857         Index += swprintf(&Buffer[Index],
00858                           L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
00859                           DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
00860         Index += swprintf(&Buffer[Index],
00861                           L"USB\\DevClass_%02x&SubClass_%02x",
00862                           DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
00863         Index += swprintf(&Buffer[Index],
00864                           L"USB\\DevClass_%02x",
00865                           DeviceDescriptor->bDeviceClass) + 1;
00866         Index += swprintf(&Buffer[Index],
00867                           L"USB\\COMPOSITE") + 1;
00868     }
00869     else
00870     {
00871         //
00872         // FIXME: support multiple configurations
00873         //
00874         ASSERT(DeviceDescriptor->bNumConfigurations == 1);
00875 
00876         if (DeviceDescriptor->bDeviceClass == 0)
00877         {
00878             Index += swprintf(&Buffer[Index], 
00879                           L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
00880                           InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass, InterfaceDescriptor->bInterfaceProtocol) + 1;
00881             Index += swprintf(&Buffer[Index],
00882                           L"USB\\Class_%02x&SubClass_%02x",
00883                           InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass) + 1;
00884             Index += swprintf(&Buffer[Index],
00885                           L"USB\\Class_%02x",
00886                           InterfaceDescriptor->bInterfaceClass) + 1;
00887         }
00888         else
00889         {
00890             Index += swprintf(&Buffer[Index], 
00891                           L"USB\\Class_%02x&SubClass_%02x&Prot_%02x",
00892                           DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1;
00893             Index += swprintf(&Buffer[Index],
00894                           L"USB\\Class_%02x&SubClass_%02x",
00895                           DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1;
00896             Index += swprintf(&Buffer[Index],
00897                           L"USB\\Class_%02x",
00898                           DeviceDescriptor->bDeviceClass) + 1;
00899         }
00900     }
00901 
00902     //
00903     // now allocate the buffer
00904     //
00905     DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR));
00906     if (!DeviceString)
00907     {
00908         //
00909         // no memory
00910         //
00911         return STATUS_INSUFFICIENT_RESOURCES;
00912     }
00913 
00914     //
00915     // copy buffer
00916     //
00917     RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
00918     DeviceString[Index] = UNICODE_NULL;
00919     UsbChildExtension->usCompatibleIds.Buffer = DeviceString;
00920     UsbChildExtension->usCompatibleIds.Length = Index * sizeof(WCHAR);
00921     UsbChildExtension->usCompatibleIds.MaximumLength = (Index + 1) * sizeof(WCHAR);
00922     DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds);
00923 
00924     //
00925     // Construct DeviceId string
00926     //
00927     Index = swprintf(Buffer, L"USB\\Vid_%04x&Pid_%04x", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1;
00928 
00929     //
00930     // now allocate the buffer
00931     //
00932     DeviceString = ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
00933     if (!DeviceString)
00934     {
00935         //
00936         // no memory
00937         //
00938         return STATUS_INSUFFICIENT_RESOURCES;
00939     }
00940 
00941     //
00942     // copy buffer
00943     //
00944     RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
00945     UsbChildExtension->usDeviceId.Buffer = DeviceString;
00946     UsbChildExtension->usDeviceId.Length = (Index-1) * sizeof(WCHAR);
00947     UsbChildExtension->usDeviceId.MaximumLength = Index * sizeof(WCHAR);
00948     DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usDeviceId);
00949 
00950     //
00951     // Construct HardwareIds
00952     //
00953     Index = 0;
00954     Index += swprintf(&Buffer[Index], 
00955                       L"USB\\Vid_%04x&Pid_%04x&Rev_%04x",
00956                       UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct, UsbChildExtension->DeviceDesc.bcdDevice) + 1;
00957     Index += swprintf(&Buffer[Index],
00958                       L"USB\\Vid_%04x&Pid_%04x",
00959                       UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1;
00960 
00961     //
00962     // now allocate the buffer
00963     //
00964     DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR));
00965     if (!DeviceString)
00966     {
00967         //
00968         // no memory
00969         //
00970         return STATUS_INSUFFICIENT_RESOURCES;
00971     }
00972 
00973     //
00974     // copy buffer
00975     //
00976     RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR));
00977     DeviceString[Index] = UNICODE_NULL;
00978     UsbChildExtension->usHardwareIds.Buffer = DeviceString;
00979     UsbChildExtension->usHardwareIds.Length = (Index + 1) * sizeof(WCHAR);
00980     UsbChildExtension->usHardwareIds.MaximumLength = (Index + 1) * sizeof(WCHAR);
00981     DPRINT("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds);
00982 
00983     //
00984     // FIXME: Handle Lang ids
00985     //
00986 
00987     //
00988     // Get the product string if obe provided
00989     //
00990     if (UsbChildExtension->DeviceDesc.iProduct)
00991     {
00992         Status = GetUsbStringDescriptor(UsbChildDeviceObject,
00993                                         UsbChildExtension->DeviceDesc.iProduct,
00994                                         0,
00995                                         (PVOID*)&UsbChildExtension->usTextDescription.Buffer,
00996                                         &UsbChildExtension->usTextDescription.Length);
00997         if (!NT_SUCCESS(Status))
00998         {
00999             DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status);
01000             RtlInitUnicodeString(&UsbChildExtension->usTextDescription, L"USB Device"); // FIXME NON-NLS
01001         }
01002         else
01003         {
01004             UsbChildExtension->usTextDescription.MaximumLength = UsbChildExtension->usTextDescription.Length;
01005             DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension->usTextDescription);
01006         }
01007     }
01008 
01009     //
01010     // Get the Serial Number string if obe provided
01011     //
01012     if (UsbChildExtension->DeviceDesc.iSerialNumber)
01013     {
01014         Status = GetUsbStringDescriptor(UsbChildDeviceObject,
01015                                         UsbChildExtension->DeviceDesc.iSerialNumber,
01016                                         0,
01017                                         (PVOID*)&UsbChildExtension->usInstanceId.Buffer,
01018                                         &UsbChildExtension->usInstanceId.Length);
01019         if (!NT_SUCCESS(Status))
01020         {
01021             DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status);
01022             return Status;
01023         }
01024 
01025         UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length;
01026         DPRINT("Usb InstanceId %wZ\n", &UsbChildExtension->usInstanceId);
01027     }
01028     else
01029     {
01030        //
01031        // the device did not provide a serial number, lets create a pseudo instance id
01032        //
01033        Index = swprintf(Buffer, L"0&%04d", UsbChildExtension->PortNumber) + 1;
01034        UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
01035        if (UsbChildExtension->usInstanceId.Buffer == NULL)
01036        {
01037            DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
01038            Status = STATUS_INSUFFICIENT_RESOURCES;
01039            return Status;
01040        }
01041 
01042        //
01043        // copy instance id
01044        //
01045        RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
01046        UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR);
01047 
01048        DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usInstanceId);
01049     }
01050 
01051     return STATUS_SUCCESS;
01052 }
01053 
01054 NTSTATUS
01055 DestroyUsbChildDeviceObject(
01056     IN PDEVICE_OBJECT UsbHubDeviceObject,
01057     IN LONG PortId)
01058 {
01059     PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension;
01060     PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL;
01061     PDEVICE_OBJECT ChildDeviceObject = NULL;
01062     ULONG Index = 0;
01063 
01064     DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index);
01065 
01066     for (Index = 0; Index < USB_MAXCHILDREN; Index++)
01067     {
01068         if (HubDeviceExtension->ChildDeviceObject[Index])
01069         {
01070             UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension;
01071 
01072             /* Check if it matches the port ID */
01073             if (UsbChildExtension->PortNumber == PortId)
01074             {
01075                 /* We found it */
01076                 ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index];
01077                 break;
01078             }
01079         }
01080     }
01081 
01082     /* Fail the request if the device doesn't exist */
01083     if (!ChildDeviceObject)
01084     {
01085         DPRINT1("Removal request for non-existant device!\n");
01086         return STATUS_UNSUCCESSFUL;
01087     }
01088 
01089     /* Remove the device from the table */
01090     HubDeviceExtension->ChildDeviceObject[Index] = NULL;
01091 
01092     /* Invalidate device relations for the root hub */
01093     IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations);
01094 
01095     /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */
01096     return STATUS_SUCCESS;
01097 }
01098 
01099 NTSTATUS
01100 CreateUsbChildDeviceObject(
01101     IN PDEVICE_OBJECT UsbHubDeviceObject,
01102     IN LONG PortId,
01103     OUT PDEVICE_OBJECT *UsbChildDeviceObject,
01104     IN ULONG PortStatus)
01105 {
01106     NTSTATUS Status;
01107     PDEVICE_OBJECT RootHubDeviceObject, NewChildDeviceObject;
01108     PHUB_DEVICE_EXTENSION HubDeviceExtension;
01109     PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
01110     PUSB_BUS_INTERFACE_HUB_V5 HubInterface;
01111     ULONG ChildDeviceCount, UsbDeviceNumber = 0;
01112     WCHAR CharDeviceName[64];
01113     UNICODE_STRING DeviceName;
01114     ULONG ConfigDescSize, DeviceDescSize;
01115     PVOID HubInterfaceBusContext;
01116     USB_CONFIGURATION_DESCRIPTOR ConfigDesc;
01117 
01118     HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbHubDeviceObject->DeviceExtension;
01119     HubInterface = &HubDeviceExtension->HubInterface;
01120     RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
01121     HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
01122     //
01123     // Find an empty slot in the child device array 
01124     //
01125     for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++)
01126     {
01127         if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL)
01128         {
01129         DPRINT("Found unused entry at %d\n", ChildDeviceCount);
01130             break;
01131         }
01132     }
01133 
01134     //
01135     // Check if the limit has been reached for maximum usb devices
01136     //
01137     if (ChildDeviceCount == USB_MAXCHILDREN)
01138     {
01139         DPRINT1("USBHUB: Too many child devices!\n");
01140         return STATUS_UNSUCCESSFUL;
01141     }
01142 
01143     while (TRUE)
01144     {
01145         //
01146         // Create a Device Name
01147         //
01148         swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber);
01149 
01150         //
01151         // Initialize UnicodeString
01152         //
01153         RtlInitUnicodeString(&DeviceName, CharDeviceName);
01154 
01155         //
01156         // Create a DeviceObject
01157         //
01158         Status = IoCreateDevice(UsbHubDeviceObject->DriverObject,
01159                                 sizeof(HUB_CHILDDEVICE_EXTENSION),
01160                                 NULL,
01161                                 FILE_DEVICE_CONTROLLER,
01162                                 FILE_AUTOGENERATED_DEVICE_NAME,
01163                                 FALSE,
01164                                 &NewChildDeviceObject);
01165 
01166         //
01167         // Check if the name is already in use
01168         //
01169         if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION))
01170         {
01171             //
01172             // Try next name
01173             //
01174             UsbDeviceNumber++;
01175             continue;
01176         }
01177 
01178         //
01179         // Check for other errors
01180         //
01181         if (!NT_SUCCESS(Status))
01182         {
01183             DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status);
01184             return Status;
01185         }
01186 
01187         DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject);
01188         break;
01189     }
01190 
01191     NewChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
01192 
01193     //
01194     // Assign the device extensions
01195     //
01196     UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)NewChildDeviceObject->DeviceExtension;
01197     RtlZeroMemory(UsbChildExtension, sizeof(HUB_CHILDDEVICE_EXTENSION));
01198     UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject;
01199     UsbChildExtension->PortNumber = PortId;
01200 
01201     // copy device interface
01202     RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
01203 
01204 
01205     //
01206     // Create the UsbDeviceObject
01207     //
01208     Status = HubInterface->CreateUsbDevice(HubInterfaceBusContext,
01209                                            (PVOID)&UsbChildExtension->UsbDeviceHandle,
01210                                            HubDeviceExtension->RootHubHandle,
01211                                            PortStatus,
01212                                            PortId);
01213     if (!NT_SUCCESS(Status))
01214     {
01215         DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status);
01216         goto Cleanup;
01217     }
01218 
01219     // copy device interface
01220     RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
01221 
01222     // FIXME replace buscontext
01223     UsbChildExtension->DeviceInterface.BusContext = UsbChildExtension->UsbDeviceHandle;
01224 
01225     //
01226     // Initialize UsbDevice
01227     //
01228     Status = HubInterface->InitializeUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle);
01229     if (!NT_SUCCESS(Status))
01230     {
01231         DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status);
01232         goto Cleanup;
01233     }
01234 
01235     DPRINT("Usb Device Handle %x\n", UsbChildExtension->UsbDeviceHandle);
01236 
01237     ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
01238     DeviceDescSize = sizeof(USB_DEVICE_DESCRIPTOR);
01239 
01240     //
01241     // Get the descriptors
01242     //
01243     Status = HubInterface->GetUsbDescriptors(HubInterfaceBusContext,
01244                                              UsbChildExtension->UsbDeviceHandle,
01245                                              (PUCHAR)&UsbChildExtension->DeviceDesc,
01246                                              &DeviceDescSize,
01247                                              (PUCHAR)&ConfigDesc,
01248                                              &ConfigDescSize);
01249     if (!NT_SUCCESS(Status))
01250     {
01251         DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status);
01252         goto Cleanup;
01253     }
01254 
01255     DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc);
01256     DumpConfigurationDescriptor(&ConfigDesc);
01257 
01258     //
01259     // FIXME: Support more than one configuration and one interface?
01260     //
01261     if (UsbChildExtension->DeviceDesc.bNumConfigurations > 1)
01262     {
01263         DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n");
01264     }
01265 
01266     if (ConfigDesc.bNumInterfaces > 1)
01267     {
01268         DPRINT1("Warning: Device has more that one interface. Only one interface (the first) is currently supported\n");
01269     }
01270 
01271     ConfigDescSize = ConfigDesc.wTotalLength;
01272 
01273     //
01274     // Allocate memory for the first full descriptor, including interfaces and endpoints.
01275     //
01276     UsbChildExtension->FullConfigDesc = ExAllocatePoolWithTag(PagedPool, ConfigDescSize, USB_HUB_TAG);
01277 
01278     //
01279     // Retrieve the full configuration descriptor
01280     //
01281     Status = GetUsbDeviceDescriptor(NewChildDeviceObject,
01282                                     USB_CONFIGURATION_DESCRIPTOR_TYPE,
01283                                     0,
01284                                     0,
01285                                     UsbChildExtension->FullConfigDesc,
01286                                     ConfigDescSize);
01287 
01288     if (!NT_SUCCESS(Status))
01289     {
01290         DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status);
01291         goto Cleanup;
01292     }
01293 
01294     //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc);
01295 
01296     //
01297     // Construct all the strings that will described the device to PNP
01298     //
01299     Status = CreateDeviceIds(NewChildDeviceObject);
01300     if (!NT_SUCCESS(Status))
01301     {
01302         DPRINT1("Failed to create strings needed to describe device to PNP.\n");
01303         goto Cleanup;
01304     }
01305 
01306     HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
01307 
01308     IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
01309     return STATUS_SUCCESS;
01310 
01311 Cleanup:
01312 
01313     //
01314     // Remove the usb device if it was created
01315     //
01316     if (UsbChildExtension->UsbDeviceHandle)
01317         HubInterface->RemoveUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle, 0);
01318 
01319     //
01320     // Free full configuration descriptor if one was allocated
01321     //
01322     if (UsbChildExtension->FullConfigDesc)
01323         ExFreePool(UsbChildExtension->FullConfigDesc);
01324 
01325     //
01326     // Delete the device object
01327     //
01328     IoDeleteDevice(NewChildDeviceObject);
01329     return Status;
01330 }
01331 
01332 NTSTATUS
01333 USBHUB_FdoQueryBusRelations(
01334     IN PDEVICE_OBJECT DeviceObject,
01335     OUT PDEVICE_RELATIONS* pDeviceRelations)
01336 {
01337     PHUB_DEVICE_EXTENSION HubDeviceExtension;
01338     PDEVICE_RELATIONS DeviceRelations;
01339     ULONG i;
01340     ULONG Children = 0;
01341     ULONG NeededSize;
01342 
01343     HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
01344 
01345     //
01346     // Count the number of children
01347     //
01348     for (i = 0; i < USB_MAXCHILDREN; i++)
01349     {
01350 
01351         if (HubDeviceExtension->ChildDeviceObject[i] == NULL)
01352         {
01353             continue;
01354         }
01355         Children++;
01356     }
01357 
01358     NeededSize = sizeof(DEVICE_RELATIONS);
01359     if (Children > 1)
01360         NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT);
01361 
01362     //
01363     // Allocate DeviceRelations
01364     //
01365     DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool,
01366                                                         NeededSize);
01367 
01368     if (!DeviceRelations)
01369         return STATUS_INSUFFICIENT_RESOURCES;
01370     DeviceRelations->Count = Children;
01371     Children = 0;
01372 
01373     //
01374     // Fill in return structure
01375     //
01376     for (i = 0; i < USB_MAXCHILDREN; i++)
01377     {
01378         if (HubDeviceExtension->ChildDeviceObject[i])
01379         {
01380             ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]);
01381             HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING;
01382             DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i];
01383         }
01384     }
01385 
01386     ASSERT(Children == DeviceRelations->Count);
01387     *pDeviceRelations = DeviceRelations;
01388 
01389     return STATUS_SUCCESS;
01390 }
01391 
01392 VOID
01393 NTAPI
01394 RootHubInitCallbackFunction(
01395     PVOID Context)
01396 {
01397     PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
01398     NTSTATUS Status;
01399     ULONG PortId;
01400     PHUB_DEVICE_EXTENSION HubDeviceExtension;
01401     PORT_STATUS_CHANGE StatusChange;
01402 
01403     HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
01404 
01405     DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject);
01406 
01407     //
01408     // Send the first SCE Request
01409     //
01410     QueryStatusChangeEndpoint(DeviceObject);
01411 
01412     for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
01413     {
01414         //
01415         // get port status
01416         //
01417         Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange);
01418         if (NT_SUCCESS(Status))
01419         {
01420             //
01421             // is there a device connected
01422             //
01423             if (StatusChange.Status & USB_PORT_STATUS_CONNECT)
01424             {
01425                 //
01426                 // reset port
01427                 //
01428                 Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
01429                 if (!NT_SUCCESS(Status))
01430                 {
01431                     DPRINT1("Failed to reset on port %d\n", PortId);
01432                 }
01433                 else
01434                 {
01435                     //
01436                     // wait for the reset to be handled since we want to enumerate synchronously
01437                     //
01438                     KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
01439                                           Executive,
01440                                           KernelMode,
01441                                           FALSE,
01442                                           NULL);
01443                     KeClearEvent(&HubDeviceExtension->ResetComplete);
01444                 }
01445             }
01446         }
01447     }
01448 }
01449 
01450 BOOLEAN
01451 USBHUB_IsRootHubFDO(
01452    IN PDEVICE_OBJECT DeviceObject)
01453 {
01454     NTSTATUS Status;
01455     PDEVICE_OBJECT RootHubPhysicalDeviceObject = NULL;
01456     PHUB_DEVICE_EXTENSION HubDeviceExtension;
01457 
01458     // get hub device extension
01459     HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
01460 
01461     // Get the Root Hub Pdo
01462     Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
01463                                     IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
01464                                     &RootHubPhysicalDeviceObject,
01465                                     NULL);
01466 
01467     // FIXME handle error
01468     ASSERT(NT_SUCCESS(Status));
01469 
01470     // physical device object is only obtained for root hubs
01471     return (RootHubPhysicalDeviceObject != NULL);
01472 }
01473 
01474 
01475 NTSTATUS
01476 USBHUB_FdoStartDevice(
01477    IN PDEVICE_OBJECT DeviceObject,
01478    IN PIRP Irp)
01479 {
01480     PURB Urb;
01481     PUSB_INTERFACE_DESCRIPTOR Pid;
01482     ULONG Result = 0, PortId;
01483     USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
01484     PURB ConfigUrb = NULL;
01485     ULONG HubStatus;
01486     PIO_STACK_LOCATION Stack;
01487     NTSTATUS Status = STATUS_SUCCESS;
01488     PHUB_DEVICE_EXTENSION HubDeviceExtension;
01489     PDEVICE_OBJECT RootHubDeviceObject;
01490     PVOID HubInterfaceBusContext , UsbDInterfaceBusContext;
01491     PORT_STATUS_CHANGE StatusChange;
01492 
01493     // get current stack location
01494     Stack = IoGetCurrentIrpStackLocation(Irp);
01495 
01496     // get hub device extension
01497     HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
01498 
01499     DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
01500 
01501     // Allocated size including the sizeof USBD_INTERFACE_LIST_ENTRY
01502     Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG);
01503     if (!Urb)
01504     {
01505          // no memory
01506          return STATUS_INSUFFICIENT_RESOURCES;
01507     }
01508 
01509     // zero urb
01510     RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY));
01511 
01512     // Get the Root Hub Pdo
01513     Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
01514                                     IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
01515                                     &HubDeviceExtension->RootHubPhysicalDeviceObject,
01516                                     &HubDeviceExtension->RootHubFunctionalDeviceObject);
01517     if (!NT_SUCCESS(Status))
01518     {
01519         // failed to obtain hub pdo
01520         DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status);
01521         ExFreePool(Urb);
01522         return Status;
01523     }
01524 
01525     // sanity checks
01526     ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject);
01527     ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject);
01528 
01529     // get roothub
01530     RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
01531 
01532     // Send the StartDevice to RootHub
01533     Status = ForwardIrpAndWait(RootHubDeviceObject, Irp);
01534 
01535     if (!NT_SUCCESS(Status))
01536     {
01537         // failed to start pdo
01538         DPRINT1("Failed to start the RootHub PDO\n");
01539         ExFreePool(Urb);
01540         return Status;
01541     }
01542 
01543     // Get the current number of hubs
01544     Status = SubmitRequestToRootHub(RootHubDeviceObject,
01545                                     IOCTL_INTERNAL_USB_GET_HUB_COUNT,
01546                                     &HubDeviceExtension->NumberOfHubs, NULL);
01547     if (!NT_SUCCESS(Status))
01548     {
01549         // failed to get number of hubs
01550         DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status);
01551         ExFreePool(Urb);
01552         return Status;
01553     }
01554 
01555     // Get the Hub Interface
01556     Status = QueryInterface(RootHubDeviceObject,
01557                             USB_BUS_INTERFACE_HUB_GUID,
01558                             sizeof(USB_BUS_INTERFACE_HUB_V5),
01559                             USB_BUSIF_HUB_VERSION_5,
01560                             (PVOID)&HubDeviceExtension->HubInterface);
01561 
01562     if (!NT_SUCCESS(Status))
01563     {
01564         // failed to get root hub interface
01565         DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
01566         ExFreePool(Urb);
01567         return Status;
01568     }
01569 
01570     HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext;
01571 
01572     // Get the USBDI Interface
01573     Status = QueryInterface(RootHubDeviceObject,
01574                             USB_BUS_INTERFACE_USBDI_GUID,
01575                             sizeof(USB_BUS_INTERFACE_USBDI_V2),
01576                             USB_BUSIF_USBDI_VERSION_2,
01577                             (PVOID)&HubDeviceExtension->UsbDInterface);
01578 
01579     if (!NT_SUCCESS(Status))
01580     {
01581         // failed to get usbdi interface
01582         DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
01583         ExFreePool(Urb);
01584         return Status;
01585     }
01586 
01587     UsbDInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
01588 
01589     // Get Root Hub Device Handle
01590     Status = SubmitRequestToRootHub(RootHubDeviceObject,
01591                                     IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE,
01592                                     &HubDeviceExtension->RootHubHandle,
01593                                     NULL);
01594 
01595     if (!NT_SUCCESS(Status))
01596     {
01597         // failed
01598         DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status);
01599         ExFreePool(Urb);
01600         return Status;
01601     }
01602 
01603     //
01604     // Get Hub Device Information
01605     //
01606     Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubInterfaceBusContext,
01607                                                                         HubDeviceExtension->RootHubHandle,
01608                                                                         &HubDeviceExtension->DeviceInformation,
01609                                                                         sizeof(USB_DEVICE_INFORMATION_0),
01610                                                                         &Result);
01611 
01612     DPRINT1("Status %x, Result 0x%08lx\n", Status, Result);
01613     DPRINT1("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel);
01614     DPRINT1("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength);
01615     DPRINT1("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber);
01616     DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor);
01617     DPRINT1("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress);
01618     DPRINT1("NumberofPipes %x\n", HubDeviceExtension->DeviceInformation.NumberOfOpenPipes);
01619 
01620     // Get Root Hubs Device Descriptor
01621     UsbBuildGetDescriptorRequest(Urb,
01622                                     sizeof(Urb->UrbControlDescriptorRequest),
01623                                     USB_DEVICE_DESCRIPTOR_TYPE,
01624                                     0,
01625                                     0,
01626                                     &HubDeviceExtension->HubDeviceDescriptor,
01627                                     NULL,
01628                                     sizeof(USB_DEVICE_DESCRIPTOR),
01629                                     NULL);
01630 
01631     // set device handle
01632     Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
01633 
01634     // get hub device descriptor
01635     Status = SubmitRequestToRootHub(RootHubDeviceObject,
01636                                     IOCTL_INTERNAL_USB_SUBMIT_URB,
01637                                     Urb,
01638                                     NULL);
01639 
01640     if (!NT_SUCCESS(Status))
01641     {
01642         // failed to get device descriptor of hub
01643         DPRINT1("Failed to get HubDeviceDescriptor!\n");
01644         ExFreePool(Urb);
01645         return Status;
01646     }
01647 
01648     // build configuration request
01649     UsbBuildGetDescriptorRequest(Urb,
01650                                     sizeof(Urb->UrbControlDescriptorRequest),
01651                                     USB_CONFIGURATION_DESCRIPTOR_TYPE,
01652                                     0,
01653                                     0,
01654                                     &HubDeviceExtension->HubConfigDescriptor,
01655                                     NULL,
01656                                     sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
01657                                     NULL);
01658 
01659     // set device handle
01660     Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
01661 
01662     // request configuration descriptor
01663     Status = SubmitRequestToRootHub(RootHubDeviceObject,
01664                                     IOCTL_INTERNAL_USB_SUBMIT_URB,
01665                                     Urb,
01666                                     NULL);
01667 
01668     if (!NT_SUCCESS(Status))
01669     {
01670         // failed to get configuration descriptor
01671         DPRINT1("Failed to get RootHub Configuration with status %x\n", Status);
01672         ExFreePool(Urb);
01673         return Status;
01674     }
01675 
01676     // sanity checks
01677     ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR));
01678     ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE);
01679     ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
01680     ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1);
01681     ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
01682     ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
01683     ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1);
01684     ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);
01685     ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR));
01686     ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT);
01687     ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in
01688 
01689     // get hub information
01690     Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubInterfaceBusContext,
01691                                                                         RootHubDeviceObject,
01692                                                                         &HubDeviceExtension->UsbExtHubInfo,
01693                                                                         sizeof(USB_EXTHUB_INFORMATION_0),
01694                                                                         &Result);
01695     if (!NT_SUCCESS(Status))
01696     {
01697         // failed to get hub information
01698         DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
01699         ExFreePool(Urb);
01700         return Status;
01701     }
01702 
01703     if (!HubDeviceExtension->UsbExtHubInfo.NumberOfPorts)
01704     {
01705         // bogus port driver
01706         DPRINT1("Failed to retrieve the number of ports\n");
01707         ExFreePool(Urb);
01708         return STATUS_UNSUCCESSFUL;
01709     }
01710 
01711     DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
01712 
01713     // Build hub descriptor request
01714     UsbBuildVendorRequest(Urb,
01715                             URB_FUNCTION_CLASS_DEVICE,
01716                             sizeof(Urb->UrbControlVendorClassRequest),
01717                             USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
01718                             0,
01719                             USB_REQUEST_GET_DESCRIPTOR,
01720                             USB_DEVICE_CLASS_RESERVED,
01721                             0,
01722                             &HubDeviceExtension->HubDescriptor,
01723                             NULL,
01724                             sizeof(USB_HUB_DESCRIPTOR),
01725                             NULL);
01726 
01727     // set device handle
01728     Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
01729 
01730     // send request
01731     Status = SubmitRequestToRootHub(RootHubDeviceObject,
01732                                     IOCTL_INTERNAL_USB_SUBMIT_URB,
01733                                     Urb,
01734                                     NULL);
01735 
01736     if (!NT_SUCCESS(Status))
01737     {
01738         DPRINT1("Failed to get Hub Descriptor!\n");
01739         ExFreePool(Urb);
01740         return STATUS_UNSUCCESSFUL;
01741     }
01742 
01743     // sanity checks
01744     ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR));
01745     ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts == HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
01746     ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29);
01747 
01748     // build get status request
01749     HubStatus = 0;
01750     UsbBuildGetStatusRequest(Urb,
01751                                 URB_FUNCTION_GET_STATUS_FROM_DEVICE,
01752                                 0,
01753                                 &HubStatus,
01754                                 0,
01755                                 NULL);
01756     // set device handle
01757     Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle;
01758 
01759     // send request
01760     Status = SubmitRequestToRootHub(RootHubDeviceObject,
01761                                     IOCTL_INTERNAL_USB_SUBMIT_URB,
01762                                     Urb,
01763                                     NULL);
01764     if (!NT_SUCCESS(Status))
01765     {
01766         // failed to get hub status
01767         DPRINT1("Failed to get Hub Status!\n");
01768         ExFreePool(Urb);
01769         return STATUS_UNSUCCESSFUL;
01770     }
01771 
01772     // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
01773     HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool,
01774                                                                     sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
01775                                                                     USB_HUB_TAG);
01776 
01777     // Get the first Configuration Descriptor
01778     Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
01779                                                 &HubDeviceExtension->HubConfigDescriptor,
01780                                                 -1, -1, -1, -1, -1);
01781     if (Pid == NULL)
01782     {
01783         // failed parse hub descriptor
01784         DPRINT1("Failed to parse configuration descriptor\n");
01785         ExFreePool(Urb);
01786         return STATUS_UNSUCCESSFUL;
01787     }
01788 
01789     // create configuration request
01790     InterfaceList[0].InterfaceDescriptor = Pid;
01791     ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor,
01792                                                     (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
01793     if (ConfigUrb == NULL)
01794     {
01795         // failed to build urb
01796         DPRINT1("Failed to allocate urb\n");
01797         ExFreePool(Urb);
01798         return STATUS_INSUFFICIENT_RESOURCES;
01799     }
01800 
01801     // send request
01802     Status = SubmitRequestToRootHub(RootHubDeviceObject,
01803                                     IOCTL_INTERNAL_USB_SUBMIT_URB,
01804                                     ConfigUrb,
01805                                     NULL);
01806     if (!NT_SUCCESS(Status))
01807     {
01808         // failed to select configuration
01809         DPRINT1("Failed to select configuration with %x\n", Status);
01810         ExFreePool(Urb);
01811         ExFreePool(ConfigUrb);
01812         return Status;
01813     }
01814 
01815     // store configuration & pipe handle
01816     HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle;
01817     HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
01818     DPRINT("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
01819 
01820     FDO_QueryInterface(DeviceObject, &HubDeviceExtension->DeviceInterface);
01821 
01822 
01823     // free urb
01824     ExFreePool(ConfigUrb);
01825 
01826     // check if function is available
01827     if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed)
01828     {
01829         // is it high speed bus
01830         if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed(HubInterfaceBusContext))
01831         {
01832             // initialize usb 2.0 hub
01833             Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubInterfaceBusContext,
01834                                                                         HubDeviceExtension->RootHubHandle, 1);
01835             DPRINT("Status %x\n", Status);
01836 
01837             // FIXME handle error
01838             ASSERT(Status == STATUS_SUCCESS);
01839         }
01840     }
01841 
01842 
01843     // Enable power on all ports
01844     DPRINT("Enabling PortPower on all ports!\n");
01845     for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
01846     {
01847         Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_POWER);
01848         if (!NT_SUCCESS(Status))
01849             DPRINT1("Failed to power on port %d\n", PortId);
01850 
01851         Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION);
01852         if (!NT_SUCCESS(Status))
01853             DPRINT1("Failed to power on port %d\n", PortId);
01854     }
01855 
01856     // init root hub notification
01857     if (HubDeviceExtension->HubInterface.RootHubInitNotification)
01858     {
01859         Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext,
01860                                                                             DeviceObject,
01861                                                                             RootHubInitCallbackFunction);
01862         if (!NT_SUCCESS(Status))
01863         {
01864             DPRINT1("Failed to set callback\n");
01865             ExFreePool(Urb);
01866             return Status;
01867         }
01868     }
01869     else
01870     {
01871         // Send the first SCE Request
01872         QueryStatusChangeEndpoint(DeviceObject);
01873 
01874         //
01875         // reset ports
01876         //
01877         for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++)
01878         {
01879             //
01880             // get port status
01881             //
01882             Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange);
01883             if (NT_SUCCESS(Status))
01884             {
01885                 //
01886                 // is there a device connected
01887                 //
01888                 if (StatusChange.Status & USB_PORT_STATUS_CONNECT)
01889                 {
01890                     //
01891                     // reset port
01892                     //
01893                     Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
01894                     if (!NT_SUCCESS(Status))
01895                     {
01896                         DPRINT1("Failed to reset on port %d\n", PortId);
01897                     }
01898                     else
01899                     {
01900                         //
01901                         // wait for the reset to be handled since we want to enumerate synchronously
01902                         //
01903                         KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
01904                                                 Executive,
01905                                                 KernelMode,
01906                                                 FALSE,
01907                                                 NULL);
01908                         KeClearEvent(&HubDeviceExtension->ResetComplete);
01909                     }
01910                 }
01911             }
01912         }
01913     }
01914 
01915     // free urb
01916     ExFreePool(Urb);
01917 
01918     // done
01919     return Status;
01920 }
01921 
01922 NTSTATUS
01923 USBHUB_FdoHandlePnp(
01924     IN PDEVICE_OBJECT DeviceObject,
01925     IN PIRP Irp)
01926 {
01927     PIO_STACK_LOCATION Stack;
01928     NTSTATUS Status = STATUS_SUCCESS;
01929     ULONG_PTR Information = 0;
01930     PHUB_DEVICE_EXTENSION HubDeviceExtension;
01931 
01932     HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
01933 
01934     Stack = IoGetCurrentIrpStackLocation(Irp);
01935 
01936     switch (Stack->MinorFunction)
01937     {
01938         case IRP_MN_START_DEVICE:
01939         {
01940             if (USBHUB_IsRootHubFDO(DeviceObject))
01941             {
01942                 // start root hub fdo
01943                 Status = USBHUB_FdoStartDevice(DeviceObject, Irp);
01944             }
01945             else
01946             {
01947                 Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp);
01948             }
01949             break;
01950         }
01951 
01952         case IRP_MN_QUERY_DEVICE_RELATIONS:
01953         {
01954             switch (Stack->Parameters.QueryDeviceRelations.Type)
01955             {
01956                 case BusRelations:
01957                 {
01958                     PDEVICE_RELATIONS DeviceRelations = NULL;
01959                     DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
01960 
01961                     Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations);
01962 
01963                     Information = (ULONG_PTR)DeviceRelations;
01964                     break;
01965                 }
01966                 case RemovalRelations:
01967                 {
01968                     DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
01969                     return ForwardIrpAndForget(DeviceObject, Irp);
01970                 }
01971                 default:
01972                     DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
01973                             Stack->Parameters.QueryDeviceRelations.Type);
01974                     return ForwardIrpAndForget(DeviceObject, Irp);
01975             }
01976             break;
01977         }
01978         case IRP_MN_QUERY_REMOVE_DEVICE:
01979         case IRP_MN_QUERY_STOP_DEVICE:
01980         {
01981             Irp->IoStatus.Status = STATUS_SUCCESS;
01982             return ForwardIrpAndForget(DeviceObject, Irp);
01983         }
01984         case IRP_MN_REMOVE_DEVICE:
01985         {
01986             Irp->IoStatus.Status = STATUS_SUCCESS;
01987             IoCompleteRequest(Irp, IO_NO_INCREMENT);
01988 
01989             IoDetachDevice(HubDeviceExtension->LowerDeviceObject);
01990             IoDeleteDevice(DeviceObject);
01991 
01992             return STATUS_SUCCESS;
01993         }
01994         case IRP_MN_QUERY_BUS_INFORMATION:
01995         {
01996             DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
01997             break;
01998         }
01999         case IRP_MN_QUERY_ID:
02000         {
02001             DPRINT("IRP_MN_QUERY_ID\n");
02002             break;
02003         }
02004         case IRP_MN_QUERY_CAPABILITIES:
02005         {
02006             DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
02007             break;
02008         }
02009         default:
02010         {
02011             DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction);
02012             return ForwardIrpAndForget(DeviceObject, Irp);
02013         }
02014     }
02015 
02016     Irp->IoStatus.Information = Information;
02017     Irp->IoStatus.Status = Status;
02018     IoCompleteRequest(Irp, IO_NO_INCREMENT);
02019     return Status;
02020 }
02021 
02022 NTSTATUS
02023 USBHUB_FdoHandleDeviceControl(
02024     IN PDEVICE_OBJECT DeviceObject,
02025     IN PIRP Irp)
02026 {
02027     DPRINT1("FdoHandleDeviceControl\n");
02028     UNIMPLEMENTED
02029     return STATUS_NOT_IMPLEMENTED;
02030 }
02031 

Generated on Sun May 27 2012 04:27:27 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.