/// <summary> /// Gets the device string descriptor from the specified device. /// </summary> /// <param name="device">The device info of the device to get the descriptor from.</param> /// <returns>True if USB transfer completed successfully. Otherwise, false.</returns> public static StringInfo GetDeviceStringDescriptor(USBDeviceInfo device) { #if USB_TRACE DBGMSG("USB: GET_DESCRIPTOR string"); #endif StringInfo result = null; StringDescriptor* descriptor = (StringDescriptor*)FOS_System.Heap.AllocZeroed((uint)sizeof(StringDescriptor), "USBManager : GetDeviceStringDescriptor"); try { ushort size = (ushort)sizeof(StringDescriptor); USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, 0, 64); device.hc.SETUPTransaction(transfer, 8, 0x80, 6, 3, 0, 0, size); device.hc.INTransaction(transfer, false, descriptor, size); device.hc.OUTTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); if (transfer.success) { if (descriptor->length > 0) { int totalLangs = 0; for (int i = 0; i < 10; i++) { if (descriptor->languageID[i] >= 0x0400 && descriptor->languageID[i] <= 0x0465) { totalLangs++; } } result = new StringInfo() { LanguageIds = new ushort[totalLangs] }; totalLangs = 0; for (int i = 0; i < 10; i++) { if (descriptor->languageID[i] >= 0x0400 && descriptor->languageID[i] <= 0x0465) { result.LanguageIds[totalLangs++] = descriptor->languageID[i]; } } } else { result = new StringInfo() { LanguageIds = new ushort[0] }; } #if USB_TRACE ShowString(result); #endif } } finally { FOS_System.Heap.Free(descriptor); } return result; }
/// <summary> /// Gets a unicode string descriptor from the specified device. /// </summary> /// <param name="device">The device info of the device to get the descriptor from.</param> /// <param name="stringIndex">The index of the string descriptor to get.</param> /// <returns>True if USB transfer completed successfully. Otherwise, false.</returns> public static UnicodeString GetUnicodeStringDescriptor(USBDeviceInfo device, byte stringIndex) { #if USB_TRACE DBGMSG(((FOS_System.String)"USB: GET_DESCRIPTOR string, endpoint: 0 stringIndex: ") + stringIndex); #endif if (stringIndex == 0) { return new UnicodeString() { StringType = 0, Value = "[NONE]" }; } UnicodeString result = new UnicodeString() { StringType = 0, Value = "[Failed to load]" }; //64 byte buffer ushort bufferSize = 64; StringDescriptorUnicode* buffer = (StringDescriptorUnicode*)FOS_System.Heap.AllocZeroed(bufferSize, "USBManager : GetUnicodeStringDescriptor"); try { USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, 0, bufferSize); device.hc.SETUPTransaction(transfer, 8, 0x80, 6, 3, stringIndex, 0x0409, bufferSize); device.hc.INTransaction(transfer, false, buffer, bufferSize); device.hc.OUTTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); if (transfer.success) { result = new UnicodeString() { StringType = buffer->descriptorType, Value = buffer->length > 0 ? FOS_System.ByteConverter.GetASCIIStringFromUTF16((byte*)buffer->widechar, 0, buffer->length) : "" }; #if USB_TRACE ShowUnicodeString(result); #endif } } finally { FOS_System.Heap.Free(buffer); } return result; }
/// <summary> /// Gets the device descriptor from the specified device. /// </summary> /// <param name="device">The device info of the device to get the descriptor from.</param> /// <returns>True if USB transfer completed successfully. Otherwise, false.</returns> public static bool GetDeviceDescriptor(USBDeviceInfo device, bool first8BytesOnly = false) { #if USB_TRACE DBGMSG("USB: GET_DESCRIPTOR Device"); #endif DeviceDescriptor* descriptor = (DeviceDescriptor*)FOS_System.Heap.AllocZeroed((uint)sizeof(DeviceDescriptor), "USBManager : GetDeviceDescriptor"); USBTransfer transfer = new USBTransfer(); try { device.hc.SetupTransfer(device, transfer, USBTransferType.Control, 0, 64); device.hc.SETUPTransaction(transfer, 8, 0x80, 6, 1, 0, 0, (first8BytesOnly ? (ushort)8u : (ushort)18u)); device.hc.INTransaction(transfer, false, descriptor, (first8BytesOnly ? (ushort)8u : (ushort)18u)); device.hc.OUTTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); if (transfer.success) { #if EHCI_TRACE byte* bpDescriptor = (byte*)descriptor; for (int i = 0; i < sizeof(DeviceDescriptor); i++) { DBGMSG(((FOS_System.String)"i=") + i + ", bpDescriptor[i]=" + bpDescriptor[i]); } #endif ParseDeviceDescriptor(descriptor, device); #if USB_TRACE ShowDevice(device); BasicConsole.DelayOutput(4); #endif } } finally { FOS_System.Heap.Free(descriptor); } return transfer.success; }
/// <summary> /// Gets the configuration descriptor from the specified device. /// </summary> /// <param name="device">The device info of the device to get the descriptor from.</param> /// <returns>True if USB transfer completed successfully. Otherwise, false.</returns> public static unsafe bool GetConfigurationDescriptors(USBDeviceInfo device) { #if USB_TRACE DBGMSG("USB: GET_DESCRIPTOR Config"); #endif //64 byte buffer ushort bufferSize = 64; byte* buffer = (byte*)FOS_System.Heap.AllocZeroed(bufferSize, "USBManager: GetConfigDescriptor"); bool success = false; try { USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, 0, bufferSize); device.hc.SETUPTransaction(transfer, 8, 0x80, 6, 2, 0, 0, bufferSize); device.hc.INTransaction(transfer, false, buffer, 64); device.hc.OUTTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); success = transfer.success; if (transfer.success) { byte currentConfig = GetConfiguration(device); // parse to config (len=9,type=2), interface (len=9,type=4) or endpoint (len=7,type=5) #if USB_TRACE DBGMSG("---------------------------------------------------------------------"); #endif byte* addr = buffer; byte* lastByte = addr + bufferSize; ushort numEndpoints = 1; // First pass. Retrieve usb_interfaceDescriptor which contains the number of endpoints while (addr < lastByte) { byte type = *(addr + 1); byte length = *addr; if (length == 9 && type == 2) { ConfigurationDescriptor* descriptor = (ConfigurationDescriptor*)addr; Configuration config = new Configuration(); config.Attribs = (Configuration.Attributes)descriptor->attributes; config.Selector = descriptor->configurationValue; config.MaxPower = descriptor->maxPower; config.NumInterfaces = descriptor->numInterfaces; if (currentConfig == config.Selector) { config.Description = GetUnicodeStringDescriptor(device, descriptor->configuration); } else { config.Description = new UnicodeString() { StringType = 0, Value = "[Unable to load at this time]" }; } device.Configurations.Add(config); #if USB_TRACE ShowConfiguration(config); #endif } else if (length == 9 && type == 4) { InterfaceDescriptor* descriptor = (InterfaceDescriptor*)addr; Interface interf = new Interface(); interf.InterfaceNumber = descriptor->interfaceNumber; interf.AlternateSetting = descriptor->alternateSetting; interf.Class = descriptor->interfaceClass; interf.Subclass = descriptor->interfaceSubclass; interf.Protocol = descriptor->interfaceProtocol; interf.Description = GetUnicodeStringDescriptor(device, descriptor->StringIndex); interf.NumEndpoints = descriptor->numEndpoints; device.Interfaces.Add(interf); #if USB_TRACE ShowInterface(interf); #endif if (interf.Class == 8) { // store interface number for mass storage transfers device.MSD_InterfaceNum = interf.InterfaceNumber; device.InterfaceClass = interf.Class; device.InterfaceSubclass = interf.Subclass; } numEndpoints += interf.NumEndpoints; } else if (length == 7 && type == 5) { //Skip endpoints in first pass } else { #if USB_TRACE DBGMSG(((FOS_System.String)"Unknown descriptor: Length=") + length + ", Type=" + type); #endif if (length == 0) { break; } } addr += length; } FOS_System.Object endpointZero = device.Endpoints[0]; device.Endpoints.Empty(); device.Endpoints.Add(endpointZero); for (int i = 0; i < numEndpoints - 1; i++) { device.Endpoints.Add(new Endpoint()); } // Second pass. Fill in endpoint information addr = buffer; while (addr < lastByte) { byte type = *(addr + 1); byte length = *addr; if (length == 7 && type == 5) { EndpointDescriptor* descriptor = (EndpointDescriptor*)addr; byte ep_id = (byte)(descriptor->endpointAddress & 0xF); #if USB_TRACE if (ep_id >= numEndpoints) { DBGMSG("ep_id >= numEndpoints!!"); } #endif Endpoint endpoint = (Endpoint)device.Endpoints[ep_id]; endpoint.MPS = descriptor->maxPacketSize; endpoint.Type = Endpoint.Types.BIDIR; // Can be overwritten below endpoint.Address = (byte)(descriptor->endpointAddress & 0xF); endpoint.Attributes = descriptor->attributes; endpoint.Interval = descriptor->interval; // store endpoint numbers for IN/OUT mass storage transfers, attributes must be 0x2, because there are also endpoints with attributes 0x3(interrupt) if ((descriptor->endpointAddress & 0x80) > 0 && descriptor->attributes == 0x2) { if (ep_id < 3) { device.MSD_INEndpointID = ep_id; } endpoint.Type = Endpoint.Types.IN; } if ((descriptor->endpointAddress & 0x80) == 0 && descriptor->attributes == 0x2) { if (ep_id < 3) { device.MSD_OUTEndpointID = ep_id; } endpoint.Type = Endpoint.Types.OUT; } #if USB_TRACE ShowEndpoint(endpoint); #endif } else if (length == 0) { break; } addr += length; } } } finally { FOS_System.Heap.Free(buffer); } return success; }
/// <summary> /// Sets the USB device address of the specified device to the specified value. /// </summary> /// <param name="device">The device to set the address of.</param> /// <param name="addr">The address to set to.</param> /// <returns>The address it was set to.</returns> public static byte SetDeviceAddress(USBDeviceInfo device, byte addr) { #if USB_TRACE DBGMSG(""); DBGMSG("USB: SET_ADDRESS"); #endif byte new_address = addr; // indicated port number USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, 0, 64); device.hc.SETUPTransaction(transfer, 8, 0x00, 5, 0, new_address, 0, 0); device.hc.INTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); #if USB_TRACE DBGMSG(((FOS_System.String)" > New address: ") + new_address); BasicConsole.DelayOutput(4); #endif return new_address; }
/// <summary> /// Clears the HALT feature on the specified endpoint. /// </summary> /// <param name="device">The device info of the device to which the endpoint belongs.</param> /// <param name="endpoint">The endpoint number from which to clear the halt.</param> public static void ClearFeatureHALT(USBDeviceInfo device, byte endpoint) { #if USB_TRACE DBGMSG(((FOS_System.String)"USB: ClearFeatureHALT, endpoint: ") + endpoint); #endif USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, endpoint, 64); device.hc.SETUPTransaction(transfer, 8, 0x02, 1, 0, 0, endpoint, 0); device.hc.INTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); #if USB_TRACE DBGMSG(((FOS_System.String)"Cleared HALT at endpoint: ") + endpoint); #endif }
/// <summary> /// Gets the specified endpoint's status. /// </summary> /// <param name="device">The device info of the device to get the information from.</param> /// <param name="endpoint">The number of the endpoint to check the status of.</param> /// <returns>The status value.</returns> public static unsafe ushort GetStatus(USBDeviceInfo device, byte endpoint) { #if USB_TRACE DBGMSG(((FOS_System.String)"USB: GetStatus, endpoint: ") + endpoint); #endif ushort status; USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, endpoint, 64); device.hc.SETUPTransaction(transfer, 8, 0x02, 0, 0, 0, endpoint, 2); device.hc.INTransaction(transfer, false, &status, 2); device.hc.OUTTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); #if USB_TRACE DBGMSG(((FOS_System.String)"Got status. Status=") + status + " for endpoint " + endpoint); #endif return status; }
/// <summary> /// Sets the current configuration number of the specified device. /// </summary> /// <param name="device">The device info of the device to set the information in.</param> /// <param name="configuration">The configuration number to set.</param> public static void SetConfiguration(USBDeviceInfo device, byte configuration) { #if USB_TRACE DBGMSG(((FOS_System.String)"USB: SET_CONFIGURATION ") + configuration); #endif USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, 0, 64); device.hc.SETUPTransaction(transfer, 8, 0x00, 9, 0, configuration, 0, 0); // SETUP DATA0, 8 byte, request type, SET_CONFIGURATION(9), hi(reserved), configuration, index=0, length=0 device.hc.INTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); }
/// <summary> /// Gets the current configuration number from the specified device. /// </summary> /// <param name="device">The device info of the device to get the information from.</param> /// <returns>The current configuration value.</returns> public static unsafe byte GetConfiguration(USBDeviceInfo device) { #if USB_TRACE DBGMSG("USB: GET_CONFIGURATION"); #endif uint configuration; USBTransfer transfer = new USBTransfer(); device.hc.SetupTransfer(device, transfer, USBTransferType.Control, 0, 64); device.hc.SETUPTransaction(transfer, 8, 0x80, 8, 0, 0, 0, 1); device.hc.INTransaction(transfer, false, &configuration, 1); device.hc.OUTTransaction(transfer, true, null, 0); device.hc.IssueTransfer(transfer); return (byte)configuration; }