Beispiel #1
0
        /// <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;
        }
Beispiel #2
0
        /// <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;
        }
Beispiel #3
0
        /// <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;
        }
Beispiel #4
0
        /// <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;
        }
Beispiel #5
0
        /// <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;
        }
Beispiel #6
0
        /// <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
        }
Beispiel #7
0
        /// <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;
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
        /// <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;
        }