public UsbCbiTransport(IUsbHost host, int deviceAddress) { var device = host.GetConnectedDeviceInfo((byte)deviceAddress); if (device == null) { throw new InvalidOperationException($"There's no device connected with address {deviceAddress}"); } //HACK: Detect Konamiman's Traxdata FDD by VID+PID, //since it's a fully compliant CBI+UFI FDD but it identifies itself with class = FFh UsbInterface iface; if (device.VendorId == 0x0644 && device.ProductId == 1) { iface = device.InterfacesForCurrentConfiguration.First(); } else { iface = device.InterfacesForCurrentConfiguration.Where(i => i.Class == 8 && i.Subclass == 4 && i.Protocol == 0) .SingleOrDefault(); } if (iface == null) { throw new InvalidOperationException("The device does not implement mass storage with the CBI transport on any of the interfaces for the current configuration"); } this.deviceAddress = deviceAddress; this.host = host; bulkInEndpoint = iface.Endpoints.Where(e => e.Type == UsbEndpointType.Bulk && e.DataDirection == UsbDataDirection.IN).First(); bulkOutEndpoint = iface.Endpoints.Where(e => e.Type == UsbEndpointType.Bulk && e.DataDirection == UsbDataDirection.OUT).First(); interruptEndpoint = iface.Endpoints.Where(e => e.Type == UsbEndpointType.Interrupt).First(); adsc = new UsbSetupPacket(0, 0x21); adsc.wIndexL = iface.InterfaceNumber; }
//Descriptors appear concatenated as follows: // configuration descriptor // interface 0, alt setting 0 descriptor // endpoint 0 for interface 0 alt setting 0 descriptor // endpoint 1 for interface 0 alt setting 0 descriptor // interface 0, alt setting 1 descriptor // endpoint 0 for interface 0 alt setting 1 descriptor // endpoint 1 for interface 0 alt setting 1 descriptor // interface 1, alt setting 0 descriptor // endpoint 0 for interface 1 alt setting 0 descriptor // endpoint 1 for interface 1 alt setting 0 descriptor // interface 2, alt setting 0 descriptor // endpoint 0 for interface 2 alt setting 0 descriptor // endpoint 1 for interface 2 alt setting 0 descriptor private UsbInterface[] GetInterfacesInfo(byte[] configurationDescriptor) { var remainingDescriptorBytes = configurationDescriptor; void GoToNextDescriptor() { if (remainingDescriptorBytes.Length > 0) { remainingDescriptorBytes = remainingDescriptorBytes.Skip(remainingDescriptorBytes[0]).ToArray(); } } byte DescriptorByteAt(int index) => remainingDescriptorBytes[index]; var interfacesCount = DescriptorByteAt(4); var interfaces = new UsbInterface[interfacesCount]; GoToNextDescriptor(); //1st interface descriptor for (var interfaceIndex = 0; interfaceIndex < interfacesCount; interfaceIndex++) { var endpointsCount = DescriptorByteAt(4); var alternateSettingIndex = DescriptorByteAt(3); //TODO: Add support for alternate settings if (alternateSettingIndex != 0) { GoToNextDescriptor(); //1st endpoint descriptor for (int i = 0; i < endpointsCount; i++) { GoToNextDescriptor(); //Next endpoint descriptor } continue; } var interfaceNumber = DescriptorByteAt(2); var @class = DescriptorByteAt(5); var subclass = DescriptorByteAt(6); var protocol = DescriptorByteAt(7); var endpoints = new UsbEndpoint[endpointsCount]; GoToNextDescriptor(); //1st endpoint descriptor for (var endpointIndex = 0; endpointIndex < endpointsCount; endpointIndex++) { endpoints[endpointIndex] = new UsbEndpoint( number: DescriptorByteAt(2), type: (UsbEndpointType)DescriptorByteAt(3), maxPacketSize: DescriptorByteAt(4) | DescriptorByteAt(5)); GoToNextDescriptor(); //Next endpoint descriptor } interfaces[interfaceIndex] = new UsbInterface(interfaceNumber, @class, subclass, protocol, endpoints); GoToNextDescriptor(); //Next interface descriptor } return(interfaces.Where(i => i != null).ToArray()); }