NTSTATUS AndroidUsbDeviceObject::SelectInterfaces() { ASSERT_IRQL_PASSIVE(); ASSERT(IsDeviceConfigured()); if (!IsDeviceConfigured()) return STATUS_INTERNAL_ERROR; WDF_USB_DEVICE_SELECT_CONFIG_PARAMS config_params; PWDF_USB_INTERFACE_SETTING_PAIR pairs = NULL; // TODO: We need to find a way (possibly by looking at each // interface descriptor) to get index of the ADB interface in multiinterface // configuration. UCHAR adb_interface_index = 0; if (IsSingleInterfaceDevice()) { // Our device has only one interface, so we don't have to bother with // multiple interfaces at all. GoogleDbgPrint("\n********** Device reports single interface"); // Select single interface configuration WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&config_params); } else { // Configure multiple interfaces ULONG num_interf = GetInterfaceCount(); GoogleDbgPrint("\n********** Device reports %u interfaces", num_interf); // Allocate pairs for each interface pairs = new(PagedPool, GANDR_POOL_TAG_INTERF_PAIRS) WDF_USB_INTERFACE_SETTING_PAIR[num_interf]; ASSERT(NULL != pairs); if (NULL == pairs) return STATUS_INSUFFICIENT_RESOURCES; adb_interface_index = 1; // Initialize each interface pair for (UCHAR pair = 0; pair < num_interf; pair++) { pairs[pair].SettingIndex = 0; pairs[pair].UsbInterface = WdfUsbTargetDeviceGetInterface(wdf_target_device(), pair); ASSERT(NULL != pairs[pair].UsbInterface); if (NULL == pairs[pair].UsbInterface) { delete[] pairs; return STATUS_INTERNAL_ERROR; } } // Select multiinterface configuration WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&config_params, (UCHAR)num_interf, pairs); } NTSTATUS status = WdfUsbTargetDeviceSelectConfig(wdf_target_device(), WDF_NO_OBJECT_ATTRIBUTES, &config_params); if (NULL != pairs) delete[] pairs; // ASSERT(NT_SUCCESS(status)); if (!NT_SUCCESS(status)) return status; #if DBG PrintSelectedConfig(&config_params); #endif // DBG wdf_usb_interface_ = WdfUsbTargetDeviceGetInterface(wdf_target_device(), adb_interface_index); ASSERT(NULL != wdf_usb_interface_); if (NULL == wdf_usb_interface_) return STATUS_INTERNAL_ERROR; configured_pipes_num_ = WdfUsbInterfaceGetNumEndpoints(wdf_usb_interface(), 0); ASSERT(0 != configured_pipes_num_); // Cache selected interface descriptor BYTE setting_index = WdfUsbInterfaceGetConfiguredSettingIndex(wdf_usb_interface()); WdfUsbInterfaceGetDescriptor(wdf_usb_interface(), setting_index, &interface_descriptor_); #if DBG PrintInterfaceDescriptor(interface_descriptor()); #endif // DBG // Iterate over pipes, decoding and saving info about bulk r/w pipes for // easier and faster addressing later on when they get opened for (UCHAR pipe = 0; pipe < configured_pipes_num(); pipe++) { WDF_USB_PIPE_INFORMATION pipe_info; WDF_USB_PIPE_INFORMATION_INIT(&pipe_info); WDFUSBPIPE wdf_pipe_obj = WdfUsbInterfaceGetConfiguredPipe(wdf_usb_interface(), pipe, &pipe_info); ASSERT(NULL != wdf_pipe_obj); if (NULL != wdf_pipe_obj) { if ((WdfUsbPipeTypeBulk == pipe_info.PipeType) && WDF_USB_PIPE_DIRECTION_IN(pipe_info.EndpointAddress)) { // This is a bulk read pipe ASSERT(!IsBulkReadPipeKnown()); bulk_read_pipe_index_ = pipe; } else { ASSERT(!IsBulkWritePipeKnown()); bulk_write_pipe_index_ = pipe; } } #if DBG PrintPipeInformation(&pipe_info, pipe); #endif // DBG } // At the end we must have calculated indexes for both, // bulk read and write pipes ASSERT(!NT_SUCCESS(status) || (IsBulkReadPipeKnown() && IsBulkWritePipeKnown())); return status; }
NTSTATUS ConfigureUsbPipes(PDEVICE_CONTEXT DeviceContext) { NTSTATUS status = STATUS_SUCCESS; BYTE index = 0; WDF_USB_PIPE_INFORMATION pipeConfig; WDFUSBPIPE pipe = NULL; BYTE numEndpoints; // For debug numEndpoints = WdfUsbInterfaceGetNumEndpoints( DeviceContext->UsbInterface, 0 ); KdPrint((__DRIVER_NAME " Found %i EndPoints\n", numEndpoints)); // For debug DeviceContext->UsbInterruptPipe = NULL; DeviceContext->UsbBulkInPipe = NULL; DeviceContext->UsbBulkOutPipe = NULL; WDF_USB_PIPE_INFORMATION_INIT(&pipeConfig); // Init pipe config // // Scan all pipe from USB Interface // do { pipe = WdfUsbInterfaceGetConfiguredPipe(DeviceContext->UsbInterface, index, &pipeConfig); if (NULL == pipe) break; // For debug KdPrint((__DRIVER_NAME " Pipe[%i].PacketSize = %i\n", index, pipeConfig.MaximumPacketSize)); // For debug /*None of our data transfers will have a guarantee that the requested data size is a multiple of the packet size.*/ WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe); if(WdfUsbPipeTypeInterrupt == pipeConfig.PipeType) // Interrupt pipe { KdPrint((__DRIVER_NAME " Found Interrupt Pipe at index %i\n", index)); DeviceContext->UsbInterruptPipe = pipe; } else if(WdfUsbPipeTypeBulk == pipeConfig.PipeType) // Bulk pipe { if(TRUE == WdfUsbTargetPipeIsInEndpoint(pipe)) // In EndPoint of Bulk { KdPrint((__DRIVER_NAME " Found In Endpoint Pipe at index %i\n", index)); DeviceContext->UsbBulkInPipe = pipe; } else if(TRUE == WdfUsbTargetPipeIsOutEndpoint(pipe)) { KdPrint((__DRIVER_NAME " Found Out Endpoint Pipe at index %i\n", index)); DeviceContext->UsbBulkOutPipe = pipe; // Out EndPoint of Bulk } } index++; // Encreate index of Pipe } while (NULL != pipe); // Check for all 3 pipe: interrupt, Bulk In, Bulk Out for our device if((NULL == DeviceContext->UsbInterruptPipe) || (NULL == DeviceContext->UsbBulkInPipe) || (NULL == DeviceContext->UsbBulkOutPipe)) { KdPrint((__DRIVER_NAME "Not all expected USB pipes were found.\n")); return STATUS_INVALID_PARAMETER; } return status; }