int USBGetEndpointDescriptor(void *deviceHandle, int endpoint_index, struct USBEndpointDescriptor *desc) { DWORD bytesReturned = 0; BOOL flag = FALSE; BYTE temp[DEVICE_PATH_SIZE]; int offset = 0; __usb_interface_t *usb; if(0 == desc) { return -1; } if(0 == deviceHandle) { return -2; } usb = (__usb_interface_t *)deviceHandle; memset(temp, 0, sizeof(temp)); flag = WinUsb_GetDescriptor(usb->winUSBHandle, USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, temp, sizeof(temp), &bytesReturned); if(FALSE == flag) { return -1; } /* If we got here without the flag above getting set to false * all appears well. We now should have the following data * in temp: * * Configuration Descriptor (9 bytes) * Interface Descriptor (9 bytes) * Endpoint 0 Descriptor (7 bytes) * Endpoint 1 Descriptor (7 bytes) * Enpoint 2 Descriptor (7 bytes) * Endpoint 3 Descriptor (7 bytes) * <<< and so on (if there are more than 4 endpoints) ... >>> * * Next, parse the descriptors out correctly. We can use the * WinUsb_ParseDescriptors function to search for the descriptor * we want but the implementation of that fucntion means we have to * find the first Endpoint Descriptor, then loop until we've iterated * through to find what we think is the Endpoint Descriptor we need. * It is cumbersome and seems unecessary since the documetation implies * that the resulting data will always be returned in the same order. * Calculating the memory offset and just doing a memcpy is faster. */ offset = sizeof(struct USBConfigurationDescriptor) + sizeof(struct USBInterfaceDescriptor) + (sizeof(struct USBEndpointDescriptor) * endpoint_index) - endpoint_index - 1; memcpy(desc, temp + offset, sizeof(struct USBEndpointDescriptor)); return 0; }
int usb_get_string_simple(usb_dev_handle *dev, int index, char *buf, size_t buflen) { unsigned char temp[MAXIMUM_USB_STRING_LENGTH]; ULONG actlen = 0; if (!WinUsb_GetDescriptor(dev->fd, USB_STRING_DESCRIPTOR_TYPE, index, 0x0409, temp, sizeof(temp), &actlen)) { return -(int)GetLastError(); } // Skip first two bytes of result (descriptor id and length), then take // every other byte as a cheap way to convert Unicode to ASCII unsigned int i, j; for (i = 2, j = 0; i < actlen && j < (buflen-1); i+=2, ++j) buf[j] = temp[i]; buf[j] = '\0'; return strlen(buf); }
static int usb_get_device_desc(struct usb_device *dev) { struct usb_dev_handle *hnd = usb_open(dev); if (!hnd) return 1; ULONG actlen = 0; if (!WinUsb_GetDescriptor(hnd->fd, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, (unsigned char*)&dev->descriptor, sizeof(dev->descriptor), &actlen) || actlen != sizeof(dev->descriptor)) { return 1; } // Descriptor as read from the device is in little-endian format. No need // to convert since this is guaranteed to be Windows which runs only on // little-endian processors. return usb_close(hnd); }
int USBGetInterfaceDescriptor(void *deviceHandle, struct USBInterfaceDescriptor *desc) { DWORD bytesReturned = 0; BOOL flag = FALSE; BYTE temp[DEVICE_PATH_SIZE]; PUSB_COMMON_DESCRIPTOR retval; __usb_interface_t *usb; if(0 == desc) { return -1; } if(0 == deviceHandle) { return -2; } usb = (__usb_interface_t *)deviceHandle; memset(temp, 0, sizeof(temp)); flag = WinUsb_GetDescriptor(usb->winUSBHandle, USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, temp, sizeof(temp), &bytesReturned); if(FALSE == flag) { return -3; } retval = WinUsb_ParseDescriptors(temp, bytesReturned, temp, USB_INTERFACE_DESCRIPTOR_TYPE); if(NULL == retval) { return -4; } memcpy(desc, retval, sizeof(struct USBInterfaceDescriptor)); return 0; }
int __getDeviceDescriptor(WINUSB_INTERFACE_HANDLE handle, struct USBDeviceDescriptor *desc) { DWORD bytesReturned; BOOL flag; if(NULL == handle) { return 0; } if(NULL == desc) { return 0; } flag = WinUsb_GetDescriptor(handle, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0x0409, (PUCHAR)desc, sizeof(struct USBDeviceDescriptor), &bytesReturned); if(FALSE == flag) { return -1; } return 0; }
int USBGetStringDescriptor(void *deviceHandle, unsigned int string_index, char *user_buffer, int maxLength) { __usb_interface_t *usb; char buffer[512]; DWORD bytesReturned; BOOL retval = TRUE; int stringLength = 0; int i = 0; if(0 == deviceHandle) { return -1; } usb = (__usb_interface_t *)deviceHandle; memset(buffer, 0, sizeof(buffer)); retval = WinUsb_GetDescriptor(usb->winUSBHandle, USB_STRING_DESCRIPTOR_TYPE, (UCHAR) string_index, 0x0409, (PUCHAR) buffer, (ULONG)sizeof(buffer), &bytesReturned); if (FALSE == retval) { return -1; } /* The string in the buffer is a string of Unicode characters. This * converts back to a simple ASCII string. If the caller really * wanted Unicode this could be done differently. */ stringLength = (bytesReturned - 2) / 2; for (i = 0; i < stringLength && i < maxLength; i++) { user_buffer[i] = buffer[2 + (i * 2)]; } return stringLength; }
LONG __cdecl _tmain( LONG Argc, LPTSTR * Argv ) /*++ Routine description: Sample program that communicates with a USB device using WinUSB --*/ { DEVICE_DATA deviceData; HRESULT hr; USB_DEVICE_DESCRIPTOR deviceDesc; BOOL bResult; BOOL noDevice; ULONG lengthReceived; UNREFERENCED_PARAMETER(Argc); UNREFERENCED_PARAMETER(Argv); // // Find a device connected to the system that has WinUSB installed using our // INF // hr = OpenDevice(&deviceData, &noDevice); if (FAILED(hr)) { if (noDevice) { printf(_T("Device not connected or driver not installed\n")); } else { printf(_T("Failed looking for device, HRESULT 0x%x\n"), hr); } return 0; } // // Get device descriptor // bResult = WinUsb_GetDescriptor(deviceData.WinusbHandle, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, (PBYTE) &deviceDesc, sizeof(deviceDesc), &lengthReceived); if (FALSE == bResult || lengthReceived != sizeof(deviceDesc)) { printf(_T("Error among LastError %d or lengthReceived %d\n"), FALSE == bResult ? GetLastError() : 0, lengthReceived); CloseDevice(&deviceData); return 0; } // // Print a few parts of the device descriptor // printf(_T("Device found: VID_%04X&PID_%04X; bcdUsb %04X\n"), deviceDesc.idVendor, deviceDesc.idProduct, deviceDesc.bcdUSB); CloseDevice(&deviceData); return 0; }
ADBAPIHANDLE AdbWinUsbInterfaceObject::CreateHandle() { // Open USB device for this inteface Note that WinUsb API // requires the handle to be opened for overlapped I/O. usb_device_handle_ = CreateFile(interface_name().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (INVALID_HANDLE_VALUE == usb_device_handle_) return NULL; // Initialize WinUSB API for this interface if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_)) return NULL; // Cache current interface number that will be used in // WinUsb_Xxx calls performed on this interface. if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_)) return false; // Cache interface properties unsigned long bytes_written; // Cache USB device descriptor if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, reinterpret_cast<PUCHAR>(&usb_device_descriptor_), sizeof(usb_device_descriptor_), &bytes_written)) { return false; } // Cache USB configuration descriptor if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, reinterpret_cast<PUCHAR>(&usb_config_descriptor_), sizeof(usb_config_descriptor_), &bytes_written)) { return false; } // Cache USB interface descriptor if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(), &usb_interface_descriptor_)) { return false; } // Save indexes and IDs for bulk read / write endpoints. We will use them to // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs. for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints; endpoint++) { // Get endpoint information WINUSB_PIPE_INFORMATION pipe_info; if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint, &pipe_info)) { return false; } if (UsbdPipeTypeBulk == pipe_info.PipeType) { // This is a bulk endpoint. Cache its index and ID. if (0 != (pipe_info.PipeId & USB_ENDPOINT_DIRECTION_MASK)) { // Use this endpoint as default bulk read endpoint ATLASSERT(0xFF == def_read_endpoint_); def_read_endpoint_ = endpoint; read_endpoint_id_ = pipe_info.PipeId; } else { // Use this endpoint as default bulk write endpoint ATLASSERT(0xFF == def_write_endpoint_); def_write_endpoint_ = endpoint; write_endpoint_id_ = pipe_info.PipeId; } } } return AdbInterfaceObject::CreateHandle(); }
bool AdbWinUsbInterfaceObject::GetSerialNumber(void* buffer, unsigned long* buffer_char_size, bool ansi) { if (!IsOpened()) { SetLastError(ERROR_INVALID_HANDLE); return false; } if (NULL == buffer_char_size) { SetLastError(ERROR_INVALID_PARAMETER); return false; } // Calculate serial number string size. Note that WinUsb_GetDescriptor // API will not return number of bytes needed to store serial number // string. So we will have to start with a reasonably large preallocated // buffer and then loop through WinUsb_GetDescriptor calls, doubling up // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned. union { // Preallocate reasonably sized buffer on the stack. char small_buffer[64]; USB_STRING_DESCRIPTOR initial_ser_num; }; USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num; // Buffer byte size unsigned long ser_num_size = sizeof(small_buffer); // After successful call to WinUsb_GetDescriptor will contain serial // number descriptor size. unsigned long bytes_written; while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE, usb_device_descriptor_.iSerialNumber, 0x0409, // English (US) reinterpret_cast<PUCHAR>(ser_num), ser_num_size, &bytes_written)) { // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here. if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { if (ser_num != &initial_ser_num) delete[] reinterpret_cast<char*>(ser_num); return false; } // Double up buffer size and reallocate string buffer ser_num_size *= 2; if (ser_num != &initial_ser_num) delete[] reinterpret_cast<char*>(ser_num); try { ser_num = reinterpret_cast<USB_STRING_DESCRIPTOR*>(new char[ser_num_size]); } catch (...) { SetLastError(ERROR_OUTOFMEMORY); return false; } } // Serial number string length unsigned long str_len = (ser_num->bLength - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) / sizeof(wchar_t); // Lets see if requested buffer is big enough to fit the string if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) { // Requested buffer is too small. if (ser_num != &initial_ser_num) delete[] reinterpret_cast<char*>(ser_num); *buffer_char_size = str_len + 1; SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } bool ret = true; if (ansi) { // We need to convert name from wide char to ansi string if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString, static_cast<int>(str_len), reinterpret_cast<PSTR>(buffer), static_cast<int>(*buffer_char_size), NULL, NULL)) { // Zero-terminate output string. reinterpret_cast<char*>(buffer)[str_len] = '\0'; } else { ret = false; } } else { // For wide char output just copy string buffer, // and zero-terminate output string. CopyMemory(buffer, ser_num->bString, bytes_written); reinterpret_cast<wchar_t*>(buffer)[str_len] = L'\0'; } if (ser_num != &initial_ser_num) delete[] reinterpret_cast<char*>(ser_num); return ret; }