// When device is (re)connected, enumerate endpoints and set policy. // Returns null on success or error message. private string ConfigureDevice(KLST_DEVINFO_HANDLE deviceInfo, bool checkForAccessory = false) { IsWriting = false; IsReading = false; if (State != ComponentState.Unresponsive || checkForAccessory || DriverAPI == null) { // libusbK class contructors can throw exceptions; For instance, if the device is // using the WinUsb driver and already in-use by another application. // This could happen if this App was previsouly aborted. try { if (DriverAPI != null) { DriverClose(); } DriverAPI = new UsbK(deviceInfo); } catch (Exception e) { DriverAPI = null; return("Unable to initialize device:" + e.Message); } } try { DriverAPI.ResetDevice(); } catch (Exception e) { return("Unable to reset device:" + e.Message); } // Find Pipe And Interface. byte interfaceIndex = 0; bool hasRead = false, hasWrite = false; USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; WINUSB_PIPE_INFORMATION PipeInfo; while (DriverAPI.SelectInterface(interfaceIndex, true)) { byte altSettingNumber = 0; while (DriverAPI.QueryInterfaceSettings(altSettingNumber, out InterfaceDescriptor)) { if (AltInterfaceId == -1 || AltInterfaceId == altSettingNumber) { byte pipeIndex = 0; while (DriverAPI.QueryPipe(altSettingNumber, pipeIndex++, out PipeInfo)) { if (PipeInfo.MaximumPacketSize > 0) { if (!hasRead && ((PipeInfo.PipeId == ReadPipeId) || ((((ReadPipeId & 0xF) == 0) || (ReadPipeId == 0xff)) && ((ReadPipeId & 0x80) == (PipeInfo.PipeId & 0x80)))) ) { ReadPipeId = PipeInfo.PipeId; hasRead = true; } if (!hasWrite && ((PipeInfo.PipeId == WritePipeId) || ((((WritePipeId & 0xF) == 0) || (WritePipeId == 0x7f)) && ((WritePipeId & 0x80) == (PipeInfo.PipeId & 0x80)))) ) { WritePipeId = PipeInfo.PipeId; hasWrite = true; if (TransferBufferSize == -1) { TransferBufferSize = PipeInfo.MaximumPacketSize; } } if (hasRead && hasWrite) { goto FindInterfaceDone; } } PipeInfo.PipeId = 0; } } altSettingNumber++; } interfaceIndex++; } FindInterfaceDone: if (!hasRead && !hasWrite) { return("Unable to open i/o pipes:R=" + hasRead + ",W=" + hasWrite + "."); } ReadPipeId |= 0x80; WritePipeId &= 0x7f; if (TransferBufferSize == -1) { TransferBufferSize = 64; } #if false // TODO: should test this. // Set interface alt setting. if (!DriverAPI.SetAltInterface(InterfaceDescriptor.bInterfaceNumber, false, InterfaceDescriptor.bAlternateSetting)) { return("Unable to set Alt Interface"); } #endif bool isAccessory = UsbLinkAccessory.IsAccessory(deviceInfo.Common.Vid, deviceInfo.Common.Pid); // Set configuration for accessory. if (isAccessory) { int configNum = 0; if (GetConfiguration(out configNum)) { if (configNum != 1) { if (!SetConfiguration(1)) { return("Unable to set configuration"); } } } } // In most cases, the pipe timeout policy should be set before using synchronous I/O. // By default, sync transfers wait infinitely for a transfer to complete. // Set the pipe timeout policy to 0 for infinite timeout. int[] pipeTimeoutMS = new[] { 0 }; int[] autoClearStall = new[] { 1 }; DriverAPI.SetPipePolicy(ReadPipeId, (int)PipePolicyType.PIPE_TRANSFER_TIMEOUT, Marshal.SizeOf(typeof(int)), pipeTimeoutMS); DriverAPI.SetPipePolicy(ReadPipeId, (int)PipePolicyType.AUTO_CLEAR_STALL, Marshal.SizeOf(typeof(int)), autoClearStall); DriverAPI.SetPipePolicy(WritePipeId, (int)PipePolicyType.PIPE_TRANSFER_TIMEOUT, Marshal.SizeOf(typeof(int)), pipeTimeoutMS); DriverAPI.SetPipePolicy(WritePipeId, (int)PipePolicyType.AUTO_CLEAR_STALL, Marshal.SizeOf(typeof(int)), autoClearStall); /* * int[] useRawIO = new[] { 1 }; * mUsb.SetPipePolicy(mReadPipeId, (int)PipePolicyType.RAW_IO, * Marshal.SizeOf(typeof(int)), useRawIO); */ // Next, check if it's an accessory. if (checkForAccessory && !isAccessory && UsbLinkAccessory.TryOpeningAccessory(this)) { return("Switching to accessory mode."); } // Finally, check if it's an FTDI device. IsFTDI = FTDIHandler.IsFtdiDevice(this); if (IsFTDI) { if (!FTDIHandler.ConfigureFTDI(this)) { return("Unable to configure FTDI device."); } } return(null); }