/// <summary> /// Get endpoints from descriptor /// </summary> /// <returns></returns> private unsafe bool GetEndpoints() { // @TODO: We should add this to USBDevice byte[] buffer = new byte[512]; byte * ptrToBuf = (byte *)Util.ObjectToVoidPtr(buffer); USBConfigurationDescriptor *descBuf = (USBConfigurationDescriptor *)ptrToBuf; if (!_Device.Request(USBDevice.TYPE_DEVICETOHOST, USBDevice.REQ_GET_DESCRIPTOR, (ushort)((USBDevice.DESC_CONFIGURATION << 8)), 0, 4, (byte *)Util.ObjectToVoidPtr(buffer))) { Heap.Free(buffer); return(false); } if (!_Device.Request(USBDevice.TYPE_DEVICETOHOST, USBDevice.REQ_GET_DESCRIPTOR, (ushort)((USBDevice.DESC_CONFIGURATION << 8)), 0, descBuf->TotalLength, (byte *)Util.ObjectToVoidPtr(buffer))) { Heap.Free(buffer); return(false); } int remaining = descBuf->TotalLength - descBuf->Length; byte *dataStart = ptrToBuf + descBuf->Length; int endPointNum = 0; while (remaining > 0) { int len = dataStart[0]; int type = dataStart[1]; if (type == USBDevice.DESC_ENDPOINT) { if (endPointNum == 0) { _EndPointIn = ((USBEndpointDescriptor *)dataStart)->Address & 0xF; } else if (endPointNum == 1) { _EndPointOut = ((USBEndpointDescriptor *)dataStart)->Address & 0xF; } else { break; } endPointNum++; } dataStart += len; remaining -= len; } Heap.Free(buffer); if (endPointNum != 2) { return(false); } return(true); }
/// <summary> /// Initalize device /// </summary> /// <returns>Success?</returns> public unsafe bool Init() { byte *data = (byte *)Heap.Alloc(sizeof(USBDeviceDescriptor)); for (int i = 0; i < sizeof(USBDeviceDescriptor); i++) { data[i] = 0x1; } /** * Get max packet size */ USBDeviceDescriptor *descriptor = (USBDeviceDescriptor *)data; if (!Request(TYPE_DEVICETOHOST, REQ_GET_DESCRIPTOR, (DESC_DEVICE << 8) | 0, 0, 8, data)) { return(false); } MaxPacketSize = descriptor->MaxpacketSize0; /** * Set new address */ ushort tempAdr = ++NextAddress; if (!Request(TYPE_HOSTTODEVICE, REQ_SET_ADDR, tempAdr, 0, 0, null)) { return(false); } Address = tempAdr; Tasking.CurrentTask.CurrentThread.Sleep(0, 20000); /** * Get descriptor */ if (!Request(TYPE_DEVICETOHOST, REQ_GET_DESCRIPTOR, (DESC_DEVICE << 8) | 0, 0, (ushort)sizeof(USBDeviceDescriptor), data)) { return(false); } /** * Load languages and set default */ LoadLanguages(); if (NumLanguages > 0) { Manfacturer = GetString(Languages[0], descriptor->ManufacturerIndex); Product = GetString(Languages[0], descriptor->ProductIndex); SerialNumber = GetString(Languages[0], descriptor->SerialNumberIndex); } /** * Get configurations */ byte[] buffer = new byte[512]; byte * ptrToBuf = (byte *)Util.ObjectToVoidPtr(buffer); USBConfigurationDescriptor *descBuf = (USBConfigurationDescriptor *)ptrToBuf; for (int i = 0; i < descriptor->NumConfigurations; i++) { if (!Request(TYPE_DEVICETOHOST, REQ_GET_DESCRIPTOR, (ushort)((DESC_CONFIGURATION << 8) | i), 0, 4, (byte *)Util.ObjectToVoidPtr(buffer))) { continue; } if (!Request(TYPE_DEVICETOHOST, REQ_GET_DESCRIPTOR, (ushort)((DESC_CONFIGURATION << 8) | i), 0, descBuf->TotalLength, (byte *)Util.ObjectToVoidPtr(buffer))) { continue; } // Prevent overflow if (descBuf->TotalLength > 512) { continue; } ConfigValue = descBuf->ConfigurationValue; int remaining = descBuf->TotalLength - descBuf->Length; byte *dataStart = ptrToBuf + descBuf->Length; while (remaining > 0) { int len = dataStart[0]; int type = dataStart[1]; if (type == DESC_INTERFACE) { InterfaceDesc = (USBInterfaceDescriptor *)dataStart; } else if (type == DESC_ENDPOINT) { EndPointDesc = (USBEndpointDescriptor *)dataStart; } dataStart += len; remaining -= len; } } if (ConfigValue != 0 && InterfaceDesc != null && EndPointDesc != null) { if (!Request(TYPE_HOSTTODEVICE, REQ_SET_CONFIGURATION, ConfigValue, 0, 0, null)) { return(false); } /** * Init driver here */ State = USBDeviceState.CONFIGURED; IUSBDriver result = USBDrivers.LoadDriver(this); if (result == null) { Console.Write("[USB] No driver found for device with name "); Console.WriteLine(Product); return(false); } Console.Write("[USB] Device configured with name "); Console.WriteLine(Product); USB.RegisterDevice(this); Driver = result; } return(true); }