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