// Send vendor specific command to usb device by control pipe. NTSTATUS UsbDev::UsbControlVendorTransfer( USHORT Functions, BOOL Rw, UCHAR Request, USHORT Value, USHORT Index, PVOID TransferBuffer, ULONG TransferBufferLength ) { NTSTATUS ntStatus = STATUS_SUCCESS; PURB Urb; Urb = (PURB) ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), USBDEV_POOLTAG); if (Urb) {// if Urb != NULL RtlZeroMemory((void *) Urb, sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST)); UsbBuildVendorRequest( Urb, // Urb Functions, // Functions (USHORT)sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST), // Length (Rw ? USBD_TRANSFER_DIRECTION_IN : USBD_TRANSFER_DIRECTION_OUT), // TransferFlags 0, // ReservedBits Request, // Request Value, // Value Index, // Index TransferBuffer, // TransferBuffer NULL, // TransferBufferMDL TransferBufferLength, // TransferBufferLength NULL); // Link ntStatus = SendAwaitUrb(Urb); ExFreePoolWithTag(Urb,USBDEV_POOLTAG); // if (!NT_SUCCESS(ntStatus)) // { // DBGU_TRACE("Cannot WriteCommandToASIC %X!!\n",ntStatus); // } }// if Urb != NULL else {// if Urb == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }// if Urb == NULL return ntStatus; }
NTSTATUS UsbclassTypeRequestCall ( IN PMP_ADAPTER Adapter, UCHAR bmRequestType, UCHAR bmRequest, USHORT wValue, USHORT wIndex, USHORT wLength, PVOID pData, ULONG* pRetSize ) { NTSTATUS ntStatus; USHORT FlagsWord; USHORT wRecipient, wType; USHORT UrbFunction; ULONG size; PURB pUrb; // //init var // pUrb =NULL; ntStatus =STATUS_SUCCESS; FlagsWord = USBD_SHORT_TRANSFER_OK; wType = bmRequestType &USB_TYPE_MASK; wRecipient= bmRequestType&USB_RECIP_MASK; if(NULL!=pRetSize) (*pRetSize)= 0; if (bmRequestType & USB_DIR_IN) { FlagsWord |= USBD_TRANSFER_DIRECTION_IN; } ASSERT(wType==USB_TYPE_CLASS); switch( wRecipient ) { case USB_RECIP_DEVICE: { UrbFunction = URB_FUNCTION_CLASS_DEVICE; break; } case USB_RECIP_INTERFACE: { UrbFunction = URB_FUNCTION_CLASS_INTERFACE; break; } case USB_RECIP_ENDPOINT: { UrbFunction = URB_FUNCTION_CLASS_ENDPOINT; break; } default: { ntStatus = STATUS_INVALID_PARAMETER; goto func_return; } } size = sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ); pUrb = ExAllocatePoolWithTag( NonPagedPool, size ,NIC_TAG); if ( !pUrb ) { ntStatus = STATUS_NO_MEMORY; goto func_return; } RtlZeroMemory( pUrb, size ); UsbBuildVendorRequest ( pUrb, UrbFunction, (USHORT)size, //size of this URB FlagsWord, 0, //reserved bits bmRequest, //request (USHORT)wValue, //value (USHORT)wIndex, //index (zero interface?) pData, //transfer buffer NULL, wLength, //size of transfer buffer (PURB)NULL //URB link ); ntStatus = CallUSBD( Adapter, pUrb ); if (NT_SUCCESS( ntStatus )&&NULL!=pRetSize) { *pRetSize = pUrb -> UrbControlVendorClassRequest.TransferBufferLength; } func_return: USB_EXFreePool(pUrb); return ntStatus; }
NTSTATUS USBHUB_ParentFDOStartDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PHUB_DEVICE_EXTENSION HubDeviceExtension; PURB Urb, ConfigurationUrb; PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; PUSBD_INTERFACE_LIST_ENTRY InterfaceList; ULONG Index; NTSTATUS Status; // get hub device extension HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; // Send the StartDevice to lower device object Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp); if (!NT_SUCCESS(Status)) { // failed to start pdo DPRINT1("Failed to start the RootHub PDO\n"); return Status; } // FIXME get capabilities Urb = ExAllocatePool(NonPagedPool, sizeof(URB)); if (!Urb) { // no memory DPRINT1("No memory\n"); return STATUS_INSUFFICIENT_RESOURCES; } // lets get device descriptor UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &HubDeviceExtension->HubDeviceDescriptor, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL); // get hub device descriptor Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { // failed to get device descriptor of hub DPRINT1("Failed to get hub device descriptor with Status %x!\n", Status); ExFreePool(Urb); return Status; } // now get configuration descriptor UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, &HubDeviceExtension->HubConfigDescriptor, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), NULL); // request configuration descriptor Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { // failed to get configuration descriptor DPRINT1("Failed to get hub configuration descriptor with status %x\n", Status); ExFreePool(Urb); return Status; } // sanity checks ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE); ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1); ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE); ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT); ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in // Build hub descriptor request UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_DEVICE, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, 0, USB_REQUEST_GET_DESCRIPTOR, USB_DEVICE_CLASS_RESERVED, 0, &HubDeviceExtension->HubDescriptor, NULL, sizeof(USB_HUB_DESCRIPTOR), NULL); // send request Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status); ExFreePool(Urb); return STATUS_UNSUCCESSFUL; } // sanity checks ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR)); ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts); ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29); // store number of ports DPRINT1("NumberOfPorts %lu\n", HubDeviceExtension->HubDescriptor.bNumberOfPorts); HubDeviceExtension->UsbExtHubInfo.NumberOfPorts = HubDeviceExtension->HubDescriptor.bNumberOfPorts; // allocate interface list InterfaceList = ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1)); if (!InterfaceList) { // no memory DPRINT1("No memory\n"); return STATUS_INSUFFICIENT_RESOURCES; } // zero list RtlZeroMemory(InterfaceList, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1)); // grab all interface descriptors for(Index = 0; Index < HubDeviceExtension->HubConfigDescriptor.bNumInterfaces; Index++) { // Get the first Configuration Descriptor InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor, &HubDeviceExtension->HubConfigDescriptor, Index, 0, -1, -1, -1); // store in list InterfaceList[Index].InterfaceDescriptor = InterfaceDescriptor; } // now create configuration request ConfigurationUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); if (ConfigurationUrb == NULL) { // failed to build urb DPRINT1("Failed to build configuration urb\n"); ExFreePool(Urb); return STATUS_INSUFFICIENT_RESOURCES; } // send request Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigurationUrb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status); ExFreePool(Urb); ExFreePool(ConfigurationUrb); return STATUS_UNSUCCESSFUL; } // store configuration & pipe handle HubDeviceExtension->ConfigurationHandle = ConfigurationUrb->UrbSelectConfiguration.ConfigurationHandle; HubDeviceExtension->PipeHandle = ConfigurationUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; DPRINT("Hub Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle); // free urb ExFreePool(ConfigurationUrb); ExFreePool(Urb); // FIXME build SCE interrupt request // FIXME create pdos return Status; }
NTSTATUS NTAPI UsbhubPnpFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IrpSp; NTSTATUS Status = STATUS_SUCCESS; ULONG MinorFunction; ULONG_PTR Information = 0; PHUB_DEVICE_EXTENSION DeviceExtension; IrpSp = IoGetCurrentIrpStackLocation(Irp); MinorFunction = IrpSp->MinorFunction; DeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; switch (MinorFunction) { case IRP_MN_START_DEVICE: /* 0x0 */ { PURB Urb; ULONG Result = 0; PUSB_INTERFACE_DESCRIPTOR Pid; /* Theres only one descriptor on hub */ USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}}; PURB ConfigUrb = NULL; /* We differ from windows on hubpdo because we dont have usbport.sys which manages all usb device objects */ DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); /* Allocating size including the sizeof USBD_INTERFACE_LIST_ENTRY */ Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG); RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY)); /* Get the hubs PDO */ QueryRootHub(DeviceExtension->LowerDevice, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, &DeviceExtension->RootHubPdo, &DeviceExtension->RootHubFdo); ASSERT(DeviceExtension->RootHubPdo); ASSERT(DeviceExtension->RootHubFdo); DPRINT1("RootPdo %x, RootFdo %x\n", DeviceExtension->RootHubPdo, DeviceExtension->RootHubFdo); /* Send the START_DEVICE irp down to the PDO of RootHub */ Status = ForwardIrpAndWait(DeviceExtension->RootHubPdo, Irp); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to start the RootHub PDO\n"); ASSERT(FALSE); } /* Get the current number of hubs */ QueryRootHub(DeviceExtension->RootHubPdo,IOCTL_INTERNAL_USB_GET_HUB_COUNT, &DeviceExtension->HubCount, NULL); /* Get the Direct Call Interfaces */ Status = QueryInterface(DeviceExtension->RootHubPdo, USB_BUS_INTERFACE_HUB_GUID, sizeof(USB_BUS_INTERFACE_HUB_V5), 5, (PVOID)&DeviceExtension->HubInterface); if (!NT_SUCCESS(Status)) { DPRINT1("UsbhubM Failed to get HUB_GUID interface with status 0x%08lx\n", Status); return STATUS_UNSUCCESSFUL; } Status = QueryInterface(DeviceExtension->RootHubPdo, USB_BUS_INTERFACE_USBDI_GUID, sizeof(USB_BUS_INTERFACE_USBDI_V2), 2, (PVOID)&DeviceExtension->UsbDInterface); if (!NT_SUCCESS(Status)) { DPRINT1("UsbhubM Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); return STATUS_UNSUCCESSFUL; } /* Get roothub device handle */ Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, &DeviceExtension->RootHubUsbDevice, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: GetRootHubDeviceHandle failed with status 0x%08lx\n", Status); return Status; } Status = DeviceExtension->HubInterface.QueryDeviceInformation(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, &DeviceExtension->DeviceInformation, sizeof(USB_DEVICE_INFORMATION_0), &Result); DPRINT("Status %x, Result %x\n", Status, Result); DPRINT("InformationLevel %x\n", DeviceExtension->DeviceInformation.InformationLevel); DPRINT("ActualLength %x\n", DeviceExtension->DeviceInformation.ActualLength); DPRINT("PortNumber %x\n", DeviceExtension->DeviceInformation.PortNumber); DPRINT("DeviceDescriptor %x\n", DeviceExtension->DeviceInformation.DeviceDescriptor); DPRINT("HubAddress %x\n", DeviceExtension->DeviceInformation.HubAddress); DPRINT("NumberofPipes %x\n", DeviceExtension->DeviceInformation.NumberOfOpenPipes); /* Get roothubs device descriptor */ UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &DeviceExtension->HubDeviceDescriptor, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to get HubDeviceDescriptor!\n"); } DumpDeviceDescriptor(&DeviceExtension->HubDeviceDescriptor); /* Get roothubs configuration descriptor */ UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, &DeviceExtension->HubConfigDescriptor, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to get RootHub Configuration with status %x\n", Status); ASSERT(FALSE); } ASSERT(DeviceExtension->HubConfigDescriptor.wTotalLength); DumpFullConfigurationDescriptor(&DeviceExtension->HubConfigDescriptor); //DPRINT1("DeviceExtension->HubConfigDescriptor.wTotalLength %x\n", DeviceExtension->HubConfigDescriptor.wTotalLength); Status = DeviceExtension->HubInterface.GetExtendedHubInformation(DeviceExtension->RootHubPdo, DeviceExtension->RootHubPdo, &DeviceExtension->UsbExtHubInfo, sizeof(USB_EXTHUB_INFORMATION_0), &Result); if (!NT_SUCCESS(Status)) { DPRINT1("Usbhub: Failed to extended hub information. Unable to determine the number of ports!\n"); ASSERT(FALSE); } DPRINT1("DeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", DeviceExtension->UsbExtHubInfo.NumberOfPorts); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_DEVICE, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_DEVICE_CLASS_RESERVED, 0, 0, &DeviceExtension->HubDescriptor, NULL, sizeof(USB_HUB_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("bDescriptorType %x\n", DeviceExtension->HubDescriptor.bDescriptorType); /* Select the configuration */ /* Get the first one */ Pid = USBD_ParseConfigurationDescriptorEx(&DeviceExtension->HubConfigDescriptor, &DeviceExtension->HubConfigDescriptor, -1, -1, -1, -1, -1); ASSERT(Pid != NULL); InterfaceList[0].InterfaceDescriptor = Pid; ConfigUrb = USBD_CreateConfigurationRequestEx(&DeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); ASSERT(ConfigUrb != NULL); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigUrb, NULL); DeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle; DeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; DPRINT1("Configuration Handle %x\n", DeviceExtension->ConfigurationHandle); ExFreePool(ConfigUrb); Status = DeviceExtension->HubInterface.Initialize20Hub(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, 1); DPRINT1("Status %x\n", Status); { int PortLoop; USHORT PortStatusAndChange[2]; for (PortLoop=0; PortLoop< DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) { DPRINT1("Port %x\n", PortLoop); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_SET_FEATURE, PORT_POWER, 1, 0, 0, 0, 0); Urb->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = PortLoop + 1; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("Status %x\n", Status); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_OUT, 0, USB_REQUEST_GET_STATUS, 0, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PortStatusAndChange), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT1("Status %x\n", Status); DPRINT1("PortStatus = %x\n", PortStatusAndChange[0]); DPRINT1("PortChange = %x\n", PortStatusAndChange[1]); } } ExFreePool(Urb); break; } case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */ { switch (IrpSp->Parameters.QueryDeviceRelations.Type) { case BusRelations: { PDEVICE_RELATIONS DeviceRelations = NULL; DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); Status = UsbhubFdoQueryBusRelations(DeviceObject, &DeviceRelations); Information = (ULONG_PTR)DeviceRelations; break; } case RemovalRelations: { DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); return ForwardIrpAndForget(DeviceObject, Irp); } default: DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", IrpSp->Parameters.QueryDeviceRelations.Type); return ForwardIrpAndForget(DeviceObject, Irp); } break; } case IRP_MN_QUERY_BUS_INFORMATION: { DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n"); break; } case IRP_MN_QUERY_ID: { DPRINT1("IRP_MN_QUERY_ID\n"); break; } case IRP_MN_QUERY_CAPABILITIES: { DPRINT1("IRP_MN_QUERY_CAPABILITIES\n"); break; } default: { DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); return ForwardIrpAndForget(DeviceObject, Irp); } } Irp->IoStatus.Information = Information; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }
VOID NTAPI WorkerThread(IN PVOID Context) { PHUB_DEVICE_EXTENSION DeviceExtension; PDEVICE_OBJECT DeviceObject, Pdo; PHUB_CHILDDEVICE_EXTENSION PdoExtension; PURB Urb = NULL; PORTSTATUSANDCHANGE PortStatusAndChange; int PortLoop, DeviceCount; NTSTATUS Status; USB_DEVICE_DESCRIPTOR DevDesc; USB_CONFIGURATION_DESCRIPTOR ConfigDesc; ULONG DevDescSize, ConfigDescSize; PUSB_STRING_DESCRIPTOR StringDesc; USB_STRING_DESCRIPTOR LanguageIdDescriptor; PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context; DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context; DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; /* Determine where in the children array to store this device info */ for (DeviceCount = 0; DeviceCount < USB_MAXCHILDREN; DeviceCount++) { if (DeviceExtension->UsbChildren[DeviceCount] == NULL) { break; } } Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); if (!Urb) { DPRINT1("Failed to allocate memory for URB!\n"); ASSERT(FALSE); } RtlZeroMemory(Urb, sizeof(URB)); for (PortLoop = 0; PortLoop < DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++) { /* Get the port status */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_OUT, 0, USB_REQUEST_GET_STATUS, 0, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get PortStatus!\n"); goto CleanUp; } DPRINT("Notification Port %x:\n", PortLoop + 1); DPRINT("Status %x\n", PortStatusAndChange.Status); DPRINT("Change %x\n", PortStatusAndChange.Change); if (PortStatusAndChange.Change == USB_PORT_STATUS_RESET) { /* Clear the Reset */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_CLEAR_FEATURE, C_PORT_RESET, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Clear the Port Reset with Status %x!\n", Status); goto CleanUp; } UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_OUT, 0, USB_REQUEST_GET_STATUS, 0, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); DPRINT("Status %x\n", PortStatusAndChange.Status); DPRINT("Change %x\n", PortStatusAndChange.Change); /* Create the UsbDevice */ Status = DeviceExtension->HubInterface.CreateUsbDevice(DeviceExtension->RootHubPdo, (PVOID)&DeviceExtension->UsbChildren[DeviceCount], DeviceExtension->RootHubUsbDevice, PortStatusAndChange.Status, PortLoop + 1); DPRINT1("CreateUsbDevice Status %x\n", Status); Status = DeviceExtension->HubInterface.InitializeUsbDevice(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount]); DPRINT1("InitializeUsbDevice Status %x\n", Status); DevDescSize = sizeof(USB_DEVICE_DESCRIPTOR); ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); Status = DeviceExtension->HubInterface.GetUsbDescriptors(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount], (PUCHAR)&DevDesc, &DevDescSize, (PUCHAR)&ConfigDesc, &ConfigDescSize); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Get Usb Deccriptors %x!\n", Status); } DumpDeviceDescriptor(&DevDesc); Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(HUB_CHILDDEVICE_EXTENSION), NULL, FILE_DEVICE_CONTROLLER, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &DeviceExtension->Children[DeviceCount]); if (!NT_SUCCESS(Status)) { DPRINT1("UsbHub; IoCreateDevice failed with status %x\n",Status); goto CleanUp; } Pdo = DeviceExtension->Children[DeviceCount]; DPRINT1("Created New Device with %x\n", Pdo); Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; PdoExtension = Pdo->DeviceExtension; RtlZeroMemory(PdoExtension, sizeof(HUB_CHILDDEVICE_EXTENSION)); PdoExtension->DeviceId = ExAllocatePoolWithTag(NonPagedPool, 32 * sizeof(WCHAR), USB_HUB_TAG); RtlZeroMemory(PdoExtension->DeviceId, 32 * sizeof(WCHAR)); swprintf(PdoExtension->DeviceId, L"USB\\Vid_%04x&Pid_%04x", DevDesc.idVendor, DevDesc.idProduct); /* Get the LANGids */ RtlZeroMemory(&LanguageIdDescriptor, sizeof(USB_STRING_DESCRIPTOR)); UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, 0, 0, &LanguageIdDescriptor, NULL, sizeof(USB_STRING_DESCRIPTOR), NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); /* Get the length of the SerialNumber */ StringDesc = ExAllocatePoolWithTag(PagedPool, 64, USB_HUB_TAG); RtlZeroMemory(StringDesc, 64); StringDesc->bLength = 0; StringDesc->bDescriptorType = 0; UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, DevDesc.iSerialNumber, LanguageIdDescriptor.bString[0], StringDesc, NULL, 64, NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); PdoExtension->InstanceId = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); DPRINT1("PdoExtension->InstanceId %x\n",PdoExtension->InstanceId); RtlZeroMemory(PdoExtension->InstanceId, (StringDesc->bLength + 1) * sizeof(WCHAR)); RtlCopyMemory(PdoExtension->InstanceId, &StringDesc->bString[0], StringDesc->bLength); DPRINT1("------>SerialNumber %S\n", PdoExtension->InstanceId); RtlZeroMemory(StringDesc, 64); StringDesc->bLength = 0; StringDesc->bDescriptorType = 0; UsbBuildGetDescriptorRequest(Urb, sizeof(Urb->UrbControlDescriptorRequest), USB_STRING_DESCRIPTOR_TYPE, DevDesc.iProduct, LanguageIdDescriptor.bString[0], StringDesc, NULL, 64, NULL); Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount]; Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); PdoExtension->TextDescription = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG); RtlZeroMemory(PdoExtension->TextDescription, (StringDesc->bLength + 1) * sizeof(WCHAR)); RtlCopyMemory(PdoExtension->TextDescription, &StringDesc->bString[0], StringDesc->bLength); ExFreePool(StringDesc); DPRINT1("------>TextDescription %S\n", PdoExtension->TextDescription); PdoExtension->IsFDO = FALSE; PdoExtension->Parent = DeviceObject; Pdo->Flags &= ~DO_DEVICE_INITIALIZING; ExFreePool(WorkItemData); ExFreePool(Urb); IoInvalidateDeviceRelations(DeviceExtension->RootHubPdo, BusRelations); return; } /* Is a device connected to this port */ if (PortStatusAndChange.Change == USB_PORT_STATUS_CONNECT) { /* Clear the Connect from ProtChange */ UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_CLEAR_FEATURE, C_PORT_CONNECTION, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Clear the Port Connect!\n"); goto CleanUp; } /* Send the miniport controller a SCE request so when the port resets we can be informed */ WaitForUsbDeviceArrivalNotification(DeviceObject); UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER, sizeof(Urb->UrbControlVendorClassRequest), USBD_TRANSFER_DIRECTION_IN, 0, USB_REQUEST_SET_FEATURE, PORT_RESET, PortLoop + 1, &PortStatusAndChange, 0, sizeof(PORTSTATUSANDCHANGE), 0); Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to Reset the port!\n"); goto CleanUp; } /* At this point the miniport will complete another SCE to inform of Reset completed */ } } CleanUp: ExFreePool(WorkItemData); ExFreePool(Urb); }