// Set usb device to unconfiguration state. NTSTATUS UsbDev::SetToUnconfigure() { NTSTATUS ntStatus; PURB pUrb; ULONG siz; DBGU_TRACE(">>>UsbDev::Unconfigure !\n"); siz = sizeof(struct _URB_SELECT_CONFIGURATION); pUrb = (PURB) ExAllocatePoolWithTag(NonPagedPool, siz, USBDEV_POOLTAG); if (pUrb) { UsbBuildSelectConfigurationRequest(pUrb, (USHORT) siz, NULL); ntStatus = SendAwaitUrb(pUrb); } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } if(!NT_SUCCESS(ntStatus)) DBGU_TRACE("Fail to Unconfigure ! (Error : %x)\n",ntStatus); if(pUrb) ExFreePoolWithTag(pUrb,USBDEV_POOLTAG); return ntStatus; }
// Abort or Reset pipe NTSTATUS UsbDev::PipeAbortOrReset(UCHAR InterfaceNo,UCHAR PipeNo,BOOLEAN Abort) { NTSTATUS ntStatus; PURB pUrb; if (m_pInterface[InterfaceNo]) {//if (m_pInterfaceListEntry) { pUrb = (PURB) ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST), USBDEV_POOLTAG); if (pUrb) { pUrb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST); pUrb->UrbHeader.Function = (USHORT) (Abort ? URB_FUNCTION_ABORT_PIPE : URB_FUNCTION_RESET_PIPE); pUrb->UrbPipeRequest.PipeHandle = m_pInterface[InterfaceNo]->Pipes[PipeNo].PipeHandle; ntStatus = SendAwaitUrb(pUrb); ExFreePoolWithTag(pUrb,USBDEV_POOLTAG); } else { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } } else { ntStatus = STATUS_UNSUCCESSFUL; } //2010/11/18 02:51下午 if(Abort) { m_StopIsoThread[PipeNo] = TRUE; if(InterfaceNo == SELECTED_DATA_INTERFACE_INDEX) { if(&m_DataReadyEvent) { KeSetEvent(&m_DataReadyEvent, 0, FALSE); DBGU_TRACE("PipeAbort KeSetEvent(&m_DataReadyEvent, 0, FALSE)\n"); } } else if(InterfaceNo == SELECTED_MPEG2_INTERFACE_INDEX) { if(&m_MEPG2DataReadyEvent) { KeSetEvent(&m_MEPG2DataReadyEvent, 0, FALSE); DBGU_TRACE("PipeAbort KeSetEvent(&m_MEPG2DataReadyEvent, 0, FALSE)\n"); } } } #if DBG if(Abort) DBGU_TRACE("UsbDev::PipeAbortOrReset ! Num = %d, (ABORT PIPE), Status : %x\n",InterfaceNo, ntStatus); else DBGU_TRACE("UsbDev::PipeAbortOrReset ! Num = %d, (RESET PIPE), Status : %x\n",InterfaceNo, ntStatus); #endif return ntStatus; }
VOID StopDevice(IN PDEVICE_OBJECT fdo, BOOLEAN oktouch /* = FALSE */) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; // Stop polling StopPolling(pdx); // Disable the operational interface IoSetDeviceInterfaceState(&pdx->operationsInterfaceName, FALSE); // Disable the inquiry interface IoSetDeviceInterfaceState(&pdx->inquiriesInterfaceName, FALSE); // wait for polling thread to exit if(pdx->RecoveryThread) { // stop recovery thread pdx->RecoveryExit = TRUE; KeSetEvent(&pdx->RecoveryEvent, 0, FALSE); KeWaitForSingleObject(pdx->RecoveryThread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(pdx->RecoveryThread); pdx->RecoveryThread = NULL; } // If it's okay to touch our hardware (i.e., we're processing an IRP_MN_STOP_DEVICE), // deconfigure the device. if(oktouch) { URB urb; UsbBuildSelectConfigurationRequest(&urb, sizeof(_URB_SELECT_CONFIGURATION), NULL); NTSTATUS status = SendAwaitUrb(fdo, &urb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to deconfigure device\n", status)); } } if(pdx->pcd) { ExFreePool(pdx->pcd); pdx->pcd = NULL; } }
// 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; }
// Set the configuration of the usb device. NTSTATUS UsbDev::SetConfiguration() { NTSTATUS ntStatus = STATUS_SUCCESS; PUSBD_INTERFACE_LIST_ENTRY pTempInterfaceList = NULL, pTempInterfaceList_First = NULL; PUSB_CONFIGURATION_DESCRIPTOR pTemp_pConfigDesc = m_pConfigDesc[m_UsbConfigurationNo]; int i,j,NoOfInterface; PUSB_INTERFACE_DESCRIPTOR pTempInterfaceDesc = NULL; PURB pUrb = NULL; //2010/8/17 03:49下午 KIRQL oldIrql; PUSBD_INTERFACE_INFORMATION interface_temp; //2010/8/16 06:17下午 NoOfInterface = pTemp_pConfigDesc->bNumInterfaces; DBGU_TRACE(">>>UsbDev::SetConfiguration ! NoOfInterface = %d\n",NoOfInterface); pTempInterfaceList_First = pTempInterfaceList = (PUSBD_INTERFACE_LIST_ENTRY) ExAllocatePoolWithTag( NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (NoOfInterface + 1), USBDEV_POOLTAG); //2010/8/23 11:51上午 m_NumberOfInterfaces = NoOfInterface; if(pTempInterfaceList) {// pTempInterfaceList != NULL RtlZeroMemory(pTempInterfaceList, sizeof(USBD_INTERFACE_LIST_ENTRY) * (NoOfInterface + 1)); for(i=0;i<NoOfInterface;i++) {// for loop i pTempInterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseConfigurationDescriptorEx( m_pConfigDesc[0], // Pointer to configuration descriptor m_pConfigDesc[0], // Start position i, // Interface number -1,//0, // Alternate setting -1, -1, -1); if(!pTempInterfaceDesc) break; pTempInterfaceList->InterfaceDescriptor = pTempInterfaceDesc; pTempInterfaceList++; }// for loop i pTempInterfaceList->InterfaceDescriptor = NULL; // Mark the end of the list //pTempInterfaceList = pTempInterfaceList_First; // Pointer to the first entry of the interface list. pUrb = USBD_CreateConfigurationRequestEx(pTemp_pConfigDesc, pTempInterfaceList_First); if(pUrb) {// pUrb != NULL for(i=0;i<NoOfInterface;i++) {// for loop i // Set to interface i, alternater 0 pTempInterfaceList_First[i].Interface->InterfaceNumber = i; pTempInterfaceList_First[i].Interface->AlternateSetting = 0; DBGU_TRACE("No of endpoints : %d\n", pTempInterfaceList_First[i].InterfaceDescriptor->bNumEndpoints); for(j=0;j<pTempInterfaceList_First[i].InterfaceDescriptor->bNumEndpoints;j++) pTempInterfaceList_First[i].Interface->Pipes[j].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; }// for loop i //2010/8/24 05:51下午 interface_temp = &pUrb->UrbSelectConfiguration.Interface; ntStatus = SendAwaitUrb(pUrb); if(!NT_SUCCESS(ntStatus)) {// ntStatus != STATUS_SUCCESS ntStatus = STATUS_IO_DEVICE_ERROR; DBGU_TRACE("Fail to configure usb device !\n"); }// ntStatus != STATUS_SUCCESS else {// ntStatus == STATUS_SUCCESS m_hConfigureation = pUrb->UrbSelectConfiguration.ConfigurationHandle; //Release memory //if(m_pInterfaceListEntry) { // m_pInterfaceListEntry != NULL for(i=0;i<m_NumberOfInterfaces;i++) if(m_pInterface[i]) { ExFreePoolWithTag(m_pInterface[i],USBDEV_POOLTAG); m_pInterface[i] = NULL; DBGU_TRACE("ExFreePoolWithTag m_pInterface[%d]\n",i); } // ExFreePoolWithTag(m_pInterfaceListEntry,USBDEV_POOLTAG); // m_pInterfaceListEntry = NULL; } // m_pInterfaceListEntry != NULL //2010/8/23 11:51上午 //m_NumberOfInterfaces = NoOfInterface; //Copy interface list //m_pInterfaceListEntry = (PUSBD_INTERFACE_LIST_ENTRY) ExAllocatePoolWithTag(NonPagedPool,(m_NumberOfInterfaces * sizeof(USBD_INTERFACE_LIST_ENTRY)), USBDEV_POOLTAG); //if(m_pInterfaceListEntry) {// m_pInterfaceListEntry != NULL for(i=0;i<m_NumberOfInterfaces;i++) {//for loop i //m_pInterfaceListEntry[i].InterfaceDescriptor = pTempInterfaceList_First[i].InterfaceDescriptor; #ifdef __VIDEO_CLASS__ // For Video Class Device if (pTempInterfaceList_First[i].Interface->InterfaceNumber==1) // UVC has 2 interfaces { //2011/5/12 02:22下午 if(BeST5R286) pTempInterfaceList_First[i].Interface->NumberOfPipes = 2; else pTempInterfaceList_First[i].Interface->NumberOfPipes = 1; pTempInterfaceList_First[i].Interface->Length = sizeof(USBD_INTERFACE_INFORMATION); } // james try M2TS. if (pTempInterfaceList_First[i].Interface->InterfaceNumber==2) { pTempInterfaceList_First[i].Interface->NumberOfPipes = 1; pTempInterfaceList_First[i].Interface->Length = sizeof(USBD_INTERFACE_INFORMATION); } #endif //2010/8/24 05:53下午 // m_pInterface[i] = (PUSBD_INTERFACE_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, pTempInterfaceList_First[i].Interface->Length, USBDEV_POOLTAG); if(BeST5R286) m_pInterface[i] = (PUSBD_INTERFACE_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, GET_USBD_INTERFACE_SIZE(2), USBDEV_POOLTAG); else m_pInterface[i] = (PUSBD_INTERFACE_INFORMATION) ExAllocatePoolWithTag(NonPagedPool, interface_temp->Length, USBDEV_POOLTAG); //2010/8/17 05:42下午 //KeAcquireSpinLock(&SetConfigSpinLock, &oldIrql); //2010/8/13 05:20下午 if (m_pInterface[i] && pTempInterfaceList_First[i].Interface && pTempInterfaceList_First[i].Interface->Length >0) //if (m_pInterfaceListEntry[i].Interface) { //2010/8/25 10:52上午 //DBGU_TRACE("RtlCopyMemory Interface[%d] len = %d\n",i,pTempInterfaceList_First[i].Interface->Length); //RtlCopyMemory(m_pInterface[i], pTempInterfaceList_First[i].Interface, pTempInterfaceList_First[i].Interface->Length); DBGU_TRACE("MJ RtlCopyMemory Interface[%d] len = %d\n",i,interface_temp->Length); RtlCopyMemory(m_pInterface[i], interface_temp, interface_temp->Length); m_pInterface[i]->InterfaceNumber = i; m_pInterface[i]->AlternateSetting = 0; if(i==0) m_pInterface[i]->Pipes[0].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; else { if(BeST5R286) m_pInterface[i]->NumberOfPipes = 2; else m_pInterface[i]->NumberOfPipes = 1; } } else { DBGU_TRACE("RtlCopyMemory Interface[%d] STATUS_INSUFFICIENT_RESOURCES\n",i); ntStatus = STATUS_INSUFFICIENT_RESOURCES; } //2010/8/17 03:42下午 //KeReleaseSpinLock(&SetConfigSpinLock, oldIrql); }//for loop i }// m_pInterfaceListEntry != NULL /*else {// m_pInterfaceListEntry == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }*/// m_pInterfaceListEntry == NULL }// ntStatus == STATUS_SUCCESS }// pUrb != NULL else {// pUrb == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }// pUrb == NULL }// pTempInterfaceList != NULL else {// pTempInterfaceList == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }// pTempInterfaceList == NULL if(pUrb) ExFreePool(pUrb); if(pTempInterfaceList_First) { ExFreePoolWithTag(pTempInterfaceList_First,USBDEV_POOLTAG); //2010/8/16 07:00下午 pTempInterfaceList_First = NULL; } return ntStatus; }
// Set the alternate setting of the interface. NTSTATUS UsbDev::SetAlternate(UCHAR AlternateNo, UCHAR InterfaceNo) { NTSTATUS ntStatus = STATUS_SUCCESS; PURB pUrb = NULL; PUSBD_INTERFACE_INFORMATION pInterfaceInfo = NULL; int i; DBGU_TRACE(">>>UsbDev::SetAlternate !\n"); if (m_pInterface[InterfaceNo]) pInterfaceInfo = m_pInterface[InterfaceNo]; if(pInterfaceInfo) {//pInterfaceInfo != NULL #ifdef __VIDEO_CLASS__ // For Video Class Device DBGU_TRACE("Change information for ISO Interface\n"); /* if (InterfaceNo == 1) pInterfaceInfo->NumberOfPipes = 1; if ((InterfaceNo == 1)&&(AlternateNo > 0)) pInterfaceInfo->Length = sizeof(USBD_INTERFACE_INFORMATION); */ // james try M2TS. if (InterfaceNo == 1 || InterfaceNo == 2) { //if(TwoPipeEnable) if(BeST5R286) { pInterfaceInfo->NumberOfPipes = 2; if (AlternateNo > 0) { //2010/10/28 06:45下午 test pInterfaceInfo->Length = GET_USBD_INTERFACE_SIZE(2);//sizeof(USBD_INTERFACE_INFORMATION); //2010/11/18 03:17下午 if(TwoPipeEnable) { m_StopIsoThread[0] = FALSE; m_StopIsoThread[1] = FALSE; } else m_StopIsoThread[0] = FALSE; } } else { pInterfaceInfo->NumberOfPipes = 1; if (AlternateNo > 0) pInterfaceInfo->Length = sizeof(USBD_INTERFACE_INFORMATION); m_StopIsoThread[0] = FALSE; } } #endif pUrb = (PURB) ExAllocatePoolWithTag(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(pInterfaceInfo->NumberOfPipes), USBDEV_POOLTAG); if(pUrb) {//pUrb != NULL pInterfaceInfo->AlternateSetting = AlternateNo; for(i=0;i<pInterfaceInfo->NumberOfPipes;i++) { if (m_fUSBHighSpeed) pInterfaceInfo->Pipes[i].MaximumTransferSize = MAX_TRANSFER_SIZE_2; else pInterfaceInfo->Pipes[i].MaximumTransferSize = MAX_TRANSFER_SIZE; pInterfaceInfo->Pipes[i].PipeFlags = 0; } RtlCopyMemory(&pUrb->UrbSelectInterface.Interface, pInterfaceInfo, pInterfaceInfo->Length); pUrb->UrbHeader.Length = GET_SELECT_INTERFACE_REQUEST_SIZE(pInterfaceInfo->NumberOfPipes); pUrb->UrbHeader.Function = URB_FUNCTION_SELECT_INTERFACE; pUrb->UrbSelectInterface.ConfigurationHandle = m_hConfigureation; ntStatus = SendAwaitUrb(pUrb); if(!NT_SUCCESS(ntStatus)) {//ntStatus != STATUS_SUCCESS DBGU_TRACE("ERR: Fail to set alternate setting !!\n"); ntStatus = STATUS_UNSUCCESSFUL; }//ntStatus != STATUS_SUCCESS else {//ntStatus == STATUS_SUCCESS if(pInterfaceInfo->Length > pUrb->UrbSelectInterface.Interface.Length) pInterfaceInfo->Length = pUrb->UrbSelectInterface.Interface.Length; RtlCopyMemory(pInterfaceInfo, &pUrb->UrbSelectInterface.Interface, pUrb->UrbSelectInterface.Interface.Length); //Display interface information #if DBG DBGU_TRACE(" Interface Information\n"); DBGU_TRACE(" -----------------------------------\n"); DBGU_TRACE(" Length: %x\n",pUrb->UrbSelectInterface.Interface.Length); DBGU_TRACE(" InterfaceNumber: %x\n",pUrb->UrbSelectInterface.Interface.InterfaceNumber); DBGU_TRACE(" AlternateSetting: %x\n", pUrb->UrbSelectInterface.Interface.AlternateSetting); DBGU_TRACE(" NumberOfPipes: %x\n",pUrb->UrbSelectInterface.Interface.NumberOfPipes); DBGU_TRACE(" Class: %x\n",pUrb->UrbSelectInterface.Interface.Class); DBGU_TRACE(" SubClass: %x\n", pUrb->UrbSelectInterface.Interface.SubClass); DBGU_TRACE(" Protocol: %x\n",pUrb->UrbSelectInterface.Interface.Protocol); DBGU_TRACE(" InterfaceHandle: %x\n",pUrb->UrbSelectInterface.Interface.InterfaceHandle); DBGU_TRACE(" -----------------------------------\n"); for(i=0;i<pInterfaceInfo->NumberOfPipes;i++) {// for loop i DBGU_TRACE(" Pipes (%x) Information\n",i); DBGU_TRACE(" -----------------------------------\n"); DBGU_TRACE(" EndpointAddress: %x\n",pUrb->UrbSelectInterface.Interface.Pipes[i].EndpointAddress); DBGU_TRACE(" PipeType: %x\n",pUrb->UrbSelectInterface.Interface.Pipes[i].PipeType); DBGU_TRACE(" PipeHandle: %x\n",pUrb->UrbSelectInterface.Interface.Pipes[i].PipeHandle); DBGU_TRACE(" MaximumPacketSize: %x\n",pUrb->UrbSelectInterface.Interface.Pipes[i].MaximumPacketSize); }// for loop i DBGU_TRACE(" -----------------------------------\n"); #endif }//ntStatus == STATUS_SUCCESS }//pUrb != NULL else {//pUrb == NULL ntStatus = STATUS_INSUFFICIENT_RESOURCES; }//pUrb == NULL }//pInterfaceInfo != NULL else {//pInterfaceInfo == NULL DBGU_TRACE("pInterfaceInfo == NULL !\n"); ntStatus = STATUS_UNSUCCESSFUL; }//pInterfaceInfo == NULL if(pUrb) ExFreePoolWithTag(pUrb,USBDEV_POOLTAG); return ntStatus; }
// Get Usb Configuration Descriptor NTSTATUS UsbDev::GetConfigurationDescriptor() { NTSTATUS ntStatus = STATUS_SUCCESS; PURB pUrb; ULONG siz; UCHAR index; PUSB_CONFIGURATION_DESCRIPTOR pTemp_pConfigDesc = NULL; DBGU_TRACE(">>>UsbDev::GetConfigurationDescriptor !\n"); pUrb = (PURB) ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBDEV_POOLTAG); if(pUrb) {//pUrb != NULL RtlZeroMemory(pUrb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); for(index=0;index<m_DevDesc.bNumConfigurations;index++) {//travel all configurations siz = 64; get_config_descriptor_retry: if(pTemp_pConfigDesc) ExFreePoolWithTag(pTemp_pConfigDesc,USBDEV_POOLTAG); if ((pTemp_pConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePoolWithTag(NonPagedPool, siz, USBDEV_POOLTAG))) {//pTemp_pConfigDesc != NULL RtlZeroMemory(pTemp_pConfigDesc,siz); UsbBuildGetDescriptorRequest( pUrb, (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE, index, 0, pTemp_pConfigDesc, NULL, siz, NULL); ntStatus = SendAwaitUrb(pUrb); if(!NT_SUCCESS(ntStatus)) {//ntStatus != STATUS_SUCCESS DBGU_TRACE("ERR: Fail to get configuration descriptor !!\n"); ExFreePoolWithTag(pTemp_pConfigDesc,USBDEV_POOLTAG); ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; }//ntStatus != STATUS_SUCCESS if ((pUrb->UrbControlDescriptorRequest.TransferBufferLength>0) && \ (pTemp_pConfigDesc->wTotalLength>siz)) { siz = pTemp_pConfigDesc->wTotalLength; goto get_config_descriptor_retry; } m_pConfigDesc[index] = pTemp_pConfigDesc; pTemp_pConfigDesc = NULL; // Print configuration descriptor DBGU_TRACE(" Configuration Descriptor: %x\n",index); DBGU_TRACE(" -------------------------\n"); DBGU_TRACE(" bLength %x\n",m_pConfigDesc[index]->bLength); DBGU_TRACE(" bDescriptorType %x\n",m_pConfigDesc[index]->bDescriptorType); DBGU_TRACE(" wTotalLength %x\n",m_pConfigDesc[index]->wTotalLength); DBGU_TRACE(" bNumInterfaces %x\n",m_pConfigDesc[index]->bNumInterfaces); DBGU_TRACE(" bConfigurationValue %x\n",m_pConfigDesc[index]->bConfigurationValue); DBGU_TRACE(" iConfiguration %x\n",m_pConfigDesc[index]->iConfiguration); DBGU_TRACE(" MaxPower %x\n",m_pConfigDesc[index]->MaxPower); DBGU_TRACE(" -------------------------\n"); }//pTemp_pConfigDesc != NULL else {//pTemp_pConfigDesc == NULL DBGU_TRACE("ERR: Fail to allocate memory for m_pConfigDesc !!\n"); ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; }//pTemp_pConfigDesc == NULL }//travel all configurations }//pUrb != NULL else {//pUrb == NULL DBGU_TRACE("ERR: Fail to allocate memory for pUrb !!\n"); ntStatus = STATUS_INSUFFICIENT_RESOURCES; }//pUrb == NULL if(pUrb) ExFreePoolWithTag(pUrb,USBDEV_POOLTAG); return ntStatus; }
// Get Usb Device Descriptor NTSTATUS UsbDev::GetDeviceDescriptor() { NTSTATUS ntStatus; PURB pUrb; DBGU_TRACE(">>>UsbDev::GetDeviceDescriptor !\n"); pUrb = (PURB) ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST), USBDEV_POOLTAG); if (pUrb) {//pUrb != NULL RtlZeroMemory((void *) pUrb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); UsbBuildGetDescriptorRequest( pUrb, (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, &m_DevDesc, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL); ntStatus = SendAwaitUrb(pUrb); ExFreePoolWithTag(pUrb,USBDEV_POOLTAG); #if DBG if (NT_SUCCESS(ntStatus)) { //Print the infomation of device descriptor DBGU_TRACE(" Device Descriptor:\n"); DBGU_TRACE(" -------------------------\n"); DBGU_TRACE(" bLength %x\n", m_DevDesc.bLength); DBGU_TRACE(" bDescriptorType 0x%x\n", m_DevDesc.bDescriptorType); DBGU_TRACE(" bcdUSB 0x%x\n", m_DevDesc.bcdUSB); DBGU_TRACE(" bDeviceClass 0x%x\n", m_DevDesc.bDeviceClass); DBGU_TRACE(" bDeviceSubClass 0x%x\n", m_DevDesc.bDeviceSubClass); DBGU_TRACE(" bDeviceProtocol 0x%x\n", m_DevDesc.bDeviceProtocol); DBGU_TRACE(" bMaxPacketSize0 0x%x\n", m_DevDesc.bMaxPacketSize0); DBGU_TRACE(" idVendor 0x%x\n", m_DevDesc.idVendor); DBGU_TRACE(" idProduct 0x%x\n", m_DevDesc.idProduct); DBGU_TRACE(" bcdDevice 0x%x\n", m_DevDesc.bcdDevice); DBGU_TRACE(" iManufacturer 0x%x\n", m_DevDesc.iManufacturer); DBGU_TRACE(" iProduct 0x%x\n", m_DevDesc.iProduct); DBGU_TRACE(" iSerialNumber 0x%x\n", m_DevDesc.iSerialNumber); DBGU_TRACE(" bNumConfigurations 0x%x\n", m_DevDesc.bNumConfigurations); DBGU_TRACE(" -------------------------\n"); } else { DBGU_TRACE("ERR: Cannot get device descriptor !!\n"); } #endif }//pUrb != NULL else {//pUrb == NULL DBGU_TRACE("ERR: Fail to allocate memory for pUrb !!\n"); ntStatus = STATUS_INSUFFICIENT_RESOURCES; }//pUrb == NULL return ntStatus; }
NTSTATUS StartDevice( PDEVICE_OBJECT fdo, PCM_PARTIAL_RESOURCE_LIST raw, PCM_PARTIAL_RESOURCE_LIST translated ) { USB_CONFIGURATION_DESCRIPTOR tcd; PUSB_CONFIGURATION_DESCRIPTOR pcd; PUSB_STRING_DESCRIPTOR desc; HANDLE RecoveryHandle; PURB selurb; URB urb; NTSTATUS status; status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; selurb = NULL; pcd = NULL; // Read our device descriptor. The only real purpose to this would be to find out how many // configurations there are so we can read their descriptors. In this simplest of examples, // there's only one configuration. KdPrint((DRIVERNAME " - Start device\n")); UsbBuildGetDescriptorRequest( &urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_DEVICE_DESCRIPTOR_TYPE, 0, LangId, &pdx->dd, NULL, sizeof(pdx->dd), NULL ); status = SendAwaitUrb( fdo, &urb ); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to retrieve device descriptor\n", status)); goto cleanup; } // allocate the buffer for the descriptor; take extra space to null terminate the bString member desc = (PUSB_STRING_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, SPOT_TAG ); if(!desc) { KdPrint((DRIVERNAME " - Unable to allocate %X bytes for string descriptor\n", sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes)); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } pdx->devHash = desc; UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, DeviceId, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to retrieve string descriptor for DeviceId\n", status)); goto cleanup; } // null terminate the buffer; we allocated one more wchar_t for the purpose desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; UpdateDeviceInformation( fdo ); // Read the descriptor of the first configuration. This requires two steps. The first step // reads the fixed-size configuration descriptor alone. The second step reads the // configuration descriptor plus all imbedded interface and endpoint descriptors. UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, LangId, &tcd, NULL, sizeof(tcd), NULL); status = SendAwaitUrb(fdo, &urb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to read configuration descriptor 1\n", status)); goto cleanup; } ULONG size = tcd.wTotalLength; pcd = (PUSB_CONFIGURATION_DESCRIPTOR) ExAllocatePoolWithTag(NonPagedPool, size, SPOT_TAG); if(!pcd) { KdPrint((DRIVERNAME " - Unable to allocate %X bytes for configuration descriptor\n", size)); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, LangId, pcd, NULL, size, NULL); status = SendAwaitUrb(fdo, &urb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to read configuration descriptor 1\n", status)); goto cleanup; } // Locate the descriptor for the one and only interface we expect to find PUSB_INTERFACE_DESCRIPTOR pid = USBD_ParseConfigurationDescriptorEx(pcd, pcd, -1, -1, -1, -1, -1); ASSERT(pid); // Create a URB to use in selecting a configuration. USBD_INTERFACE_LIST_ENTRY interfaces[2] = { {pid, NULL}, {NULL, NULL}, // fence to terminate the array }; selurb = USBD_CreateConfigurationRequestEx(pcd, interfaces); if(!selurb) { KdPrint((DRIVERNAME " - Unable to create configuration request\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } // Verify that the interface describes exactly the endpoints we expect if(pid->bNumEndpoints != 2) { KdPrint((DRIVERNAME " - %d is the wrong number of endpoints\n", pid->bNumEndpoints)); status = STATUS_DEVICE_CONFIGURATION_ERROR; goto cleanup; } PUSB_ENDPOINT_DESCRIPTOR ped = (PUSB_ENDPOINT_DESCRIPTOR) pid; ped = (PUSB_ENDPOINT_DESCRIPTOR) USBD_ParseDescriptors(pcd, tcd.wTotalLength, ped, USB_ENDPOINT_DESCRIPTOR_TYPE); if(!ped || 0 == (ped->bEndpointAddress & 0x80) || ped->bmAttributes != USB_ENDPOINT_TYPE_BULK || ped->wMaxPacketSize > 64) { KdPrint((DRIVERNAME " - Endpoint has wrong attributes\n")); status = STATUS_DEVICE_CONFIGURATION_ERROR; goto cleanup; } ++ped; if(!ped || 0 != (ped->bEndpointAddress & 0x80) || ped->bmAttributes != USB_ENDPOINT_TYPE_BULK || ped->wMaxPacketSize > 64) { KdPrint((DRIVERNAME " - Endpoint has wrong attributes\n")); status = STATUS_DEVICE_CONFIGURATION_ERROR; goto cleanup; } ++ped; PUSBD_INTERFACE_INFORMATION pii = interfaces[0].Interface; ASSERT(pii->NumberOfPipes == pid->bNumEndpoints); // Initialize the maximum transfer size for each of the endpoints. The // default would be PAGE_SIZE. The firmware itself only has a 4096-byte // ring buffer, though. We need to restrict the test applet to that many // bytes. In order to exercise the multi-segment aspect of the transfer code, // therefore, reduce the maximum transfer size to 1024 bytes. pii->Pipes[0].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; pii->Pipes[1].MaximumTransferSize = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; pdx->maxtransfer = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; // Submit the set-configuration request status = SendAwaitUrb(fdo, selurb); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - Error %X trying to select configuration\n", status)); goto cleanup; } // Save the configuration and pipe handles pdx->hconfig = selurb->UrbSelectConfiguration.ConfigurationHandle; pdx->hinpipe = pii->Pipes[0].PipeHandle; pdx->houtpipe = pii->Pipes[1].PipeHandle; // Transfer ownership of the configuration descriptor to the device extension pdx->pcd = pcd; pcd = NULL; // Enable the interface IoSetDeviceInterfaceState(&pdx->operationsInterfaceName, TRUE); // Enable the interface IoSetDeviceInterfaceState(&pdx->inquiriesInterfaceName, TRUE); // create recovery thread status = PsCreateSystemThread(&RecoveryHandle, 0, NULL, NULL, NULL, RecoveryThread, (PVOID)pdx); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - PsCreateSystemThread failed with error %08x\n", status)); goto cleanup; } status = ObReferenceObjectByHandle( RecoveryHandle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)&pdx->RecoveryThread, NULL ); ASSERT(NT_SUCCESS(status)); ZwClose(RecoveryHandle); // Start polling status = StartPolling(pdx); if(!NT_SUCCESS(status)) { KdPrint((DRIVERNAME " - StartPolling failed 0x%08x\n", status)); if(pdx->RecoveryThread) { // shutdown recovery thread pdx->RecoveryExit = TRUE; KeSetEvent(&pdx->RecoveryEvent, 0, FALSE); // wait for polling thread to exit KeWaitForSingleObject(pdx->RecoveryThread, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(pdx->RecoveryThread); pdx->RecoveryThread = NULL; } goto cleanup; } cleanup: if(selurb) ExFreePool(selurb); if(pcd ) ExFreePool(pcd ); // get rid of return codes like STATUS_PENDING if(NT_SUCCESS(status)) { return STATUS_SUCCESS; } return status; }
NTSTATUS UpdateDeviceInformation( PDEVICE_OBJECT fdo ) { PUSB_STRING_DESCRIPTOR desc; UNICODE_STRING dummy; URB urb; int id; NTSTATUS status; KdPrint((DRIVERNAME " - UpdateDeviceInformation\n")); status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; // initialize buffers pdx->manufacturer.Buffer = NULL; pdx->product .Buffer = NULL; pdx->serialNumber.Buffer = NULL; pdx->displayName .Buffer = NULL; desc = NULL; // allocate buffers for all strings pdx->manufacturer.Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); pdx->product .Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); pdx->serialNumber.Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); pdx->displayName .Buffer = (WCHAR*)ExAllocatePoolWithTag(NonPagedPool, StringDescriptorBytes, SPOT_TAG ); if( (pdx->manufacturer.Buffer == NULL) || (pdx->product .Buffer == NULL) || (pdx->serialNumber.Buffer == NULL) || (pdx->displayName .Buffer == NULL) ) { KdPrint((DRIVERNAME " - Unable to allocate memory for device info\n")); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } pdx->manufacturer.Length = 0; pdx->manufacturer.MaximumLength = StringDescriptorBytes; pdx->product .Length = 0; pdx->product .MaximumLength = StringDescriptorBytes; pdx->serialNumber.Length = 0; pdx->serialNumber.MaximumLength = StringDescriptorBytes; pdx->displayName .Length = 0; pdx->displayName .MaximumLength = StringDescriptorBytes; // allocate buffer for device string descriptor requests desc = (PUSB_STRING_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, SPOT_TAG ); if(!desc) { KdPrint((DRIVERNAME " - Unable to allocate %X bytes for string descriptor\n", sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes)); status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } if(0 != pdx->dd.iManufacturer) { // Manufacturer UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, pdx->dd.iManufacturer, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->manufacturer, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->manufacturer, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve manufacturer %08x\n", status )); } } if(0 != pdx->dd.iProduct) { // Product UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, pdx->dd.iProduct, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->product, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->product, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve product %08x\n", status )); } } if(0 != pdx->dd.iSerialNumber) { // Serial Number UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, pdx->dd.iSerialNumber, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->serialNumber, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->serialNumber, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve serial number %08x\n", status )); } } // DisplayName UsbBuildGetDescriptorRequest(&urb, sizeof(_URB_CONTROL_DESCRIPTOR_REQUEST), USB_STRING_DESCRIPTOR_TYPE, DisplayNameId, LangId, desc, NULL, sizeof(USB_STRING_DESCRIPTOR) + StringDescriptorBytes, NULL); status = SendAwaitUrb(fdo, &urb); if(NT_SUCCESS(status)) { desc->bString[ (desc->bLength / 2) - 1 ] = L'\0'; RtlInitUnicodeString( &dummy , desc->bString ); RtlCopyUnicodeString( &pdx->displayName, &dummy ); } else { RtlInitUnicodeString( &dummy , EmptyString ); RtlCopyUnicodeString( &pdx->displayName, &dummy ); KdPrint(( DRIVERNAME " - could not retrieve display name %08x\n", status )); } cleanup: if(desc) ExFreePool( desc ); if(!NT_SUCCESS(status)) { if(pdx->manufacturer.Buffer) ExFreePool( pdx->manufacturer.Buffer ); if(pdx->product .Buffer) ExFreePool( pdx->product .Buffer ); if(pdx->serialNumber.Buffer) ExFreePool( pdx->serialNumber.Buffer ); if(pdx->displayName .Buffer) ExFreePool( pdx->displayName .Buffer ); pdx->manufacturer.Buffer = NULL; pdx->product .Buffer = NULL; pdx->serialNumber.Buffer = NULL; pdx->displayName .Buffer = NULL; } return status; }