Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FatFileSystem TB6612FNG2 mbed
Diff: usb/UsbDevice.cpp
- Revision:
- 0:de03cbbcd0ff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/UsbDevice.cpp Mon Nov 30 09:32:15 2015 +0000
@@ -0,0 +1,400 @@
+
+/*
+Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "UsbDevice.h"
+//#define __DEBUG
+#include "mydbg.h"
+
+UsbDevice::UsbDevice( UsbHostMgr* pMgr, int hub, int port, int addr ) : m_pControlEp(NULL), /*m_controlEp( this, 0x00, false, USB_CONTROL, 8 ),*/
+m_pMgr(pMgr), m_connected(false), m_enumerated(false), m_hub(hub), m_port(port), m_addr(addr), m_refs(0),
+m_vid(0), m_pid(0)
+{
+ m_DeviceClass = 0x00;
+ m_InterfaceClass = 0x00;
+}
+
+UsbDevice::~UsbDevice()
+{
+ DBG_ASSERT(0);
+
+ if(m_pControlEp)
+ delete m_pControlEp;
+}
+
+UsbErr UsbDevice::enumerate()
+{
+ VERBOSE("Hub: %d Port: %d\n", m_hub, m_port);
+ UsbErr rc;
+ DBG("%p m_hub=%d m_port=%d\n", this, m_hub, m_port);
+ DBG_ASSERT(m_pMgr);
+ m_pMgr->resetPort(m_hub, m_port);
+
+ wait_ms(400);
+
+ uint8_t temp[8];
+ DBG_ASSERT(m_pControlEp == NULL);
+ m_pControlEp = new UsbEndpoint( this, 0x00, false, USB_CONTROL, sizeof(temp), 0 );
+ DBG_ASSERT(m_pControlEp);
+ //EDCtrl->Control = 8 << 16;/* Put max pkt size = 8 */
+ /* Read first 8 bytes of device desc */
+ DBG_ASSERT(sizeof(temp) >= 8);
+ //rc = controlReceive(
+ // USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR,
+ // (USB_DESCRIPTOR_TYPE_DEVICE << 8) |(0), 0, temp, sizeof(temp));
+ //DBG_ASSERT(rc == USBERR_OK);
+ rc = GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, temp, sizeof(temp));
+ if (rc != USBERR_OK) {
+ DBG("rc=%d\n", rc);
+ DBG_ASSERT(rc == USBERR_OK);
+ return rc;
+ }
+ DBG_ASSERT(rc == USBERR_OK);
+ DBG_BYTES("DeviceDescriptor first 8 bytes", temp, sizeof(temp));
+ DBG_ASSERT(temp[0] == 18); // bLength
+ DBG_ASSERT(temp[1] == 0x01); // bDescriptType
+ if (rc)
+ {
+ DBG("RC=%d",rc);
+ return (rc);
+ }
+ uint8_t bMaxPacketSize = temp[7];
+ DBG_ASSERT(bMaxPacketSize >= 8);
+ DBG("Got descriptor, max ep size is %d\n", bMaxPacketSize);
+
+ m_pControlEp->updateSize(bMaxPacketSize); /* Get max pkt size of endpoint 0 */
+ rc = controlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_ADDRESS, m_addr, 0, NULL, 0); /* Set the device address to m_addr */
+ DBG_ASSERT(rc == USBERR_OK);
+ if (rc)
+ {
+ // PRINT_Err(rc);
+ return (rc);
+ }
+ wait_ms(2);
+ //EDCtrl->Control = (EDCtrl->Control) | 1; /* Modify control pipe with address 1 */
+
+ //Update address
+ m_pControlEp->updateAddr(m_addr);
+ DBG("Ep addr is now %d", m_addr);
+ /**/
+
+ //rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_DEVICE, 0, TDBuffer, 17); //Read full device descriptor
+ //rc = controlReceive(USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR,
+ // (USB_DESCRIPTOR_TYPE_DEVICE << 8)|(0), 0,
+ // m_controlDataBuf, 17);
+ uint8_t DeviceDesc[18];
+ rc = GetDescriptor(USB_DESCRIPTOR_TYPE_DEVICE, 0, DeviceDesc, sizeof(DeviceDesc));
+ DBG_ASSERT(rc == USBERR_OK);
+ DBG_BYTES("DeviceDescriptor", DeviceDesc, sizeof(DeviceDesc));
+ DBG_ASSERT(DeviceDesc[0] == 18);
+ DBG_ASSERT(DeviceDesc[1] == 0x01);
+ DBG_ASSERT(DeviceDesc[17] == 1); // bNumConfiguration
+ if (rc)
+ {
+ //PRINT_Err(rc);
+ return (rc);
+ }
+
+ /*
+ rc = SerialCheckVidPid();
+ if (rc != OK) {
+ PRINT_Err(rc);
+ return (rc);
+ }
+ */
+ /**/
+ m_DeviceClass = DeviceDesc[4];
+ VERBOSE("DeviceClass: %02X\n", m_DeviceClass);
+
+ m_vid = *((uint16_t*)&DeviceDesc[8]);
+ m_pid = *((uint16_t*)&DeviceDesc[10]);
+ VERBOSE("Vender: %04X\n", m_vid);
+ VERBOSE("Product: %04X\n", m_pid);
+ int iManufacture = DeviceDesc[14];
+ if (iManufacture) {
+ char str[64];
+ rc = GetString(iManufacture, str, sizeof(str));
+ DBG_ASSERT(rc == USBERR_OK);
+ VERBOSE("Manufacture: %s\n", str);
+ }
+ int iProduct = DeviceDesc[15];
+ if (iProduct) {
+ char str[64];
+ rc = GetString(iProduct, str, sizeof(str));
+ DBG_ASSERT(rc == USBERR_OK);
+ VERBOSE("Product: %s\n", str);
+ }
+ if (DeviceDesc[4] == 0x09) { // Hub
+ return hub_init();
+ }
+
+ uint8_t ConfigDesc[9];
+ int index = 0;
+ rc = GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, ConfigDesc, sizeof(ConfigDesc));
+ DBG_ASSERT(rc == USBERR_OK);
+ DBG_BYTES("ConfigDescriptor 9bytes", ConfigDesc, sizeof(ConfigDesc));
+ DBG_ASSERT(ConfigDesc[0] == 9);
+ DBG_ASSERT(ConfigDesc[1] == 0x02);
+ int wTotalLength = *((uint16_t*)&ConfigDesc[2]);
+ DBG("TotalLength: %d\n", wTotalLength);
+ int bConfigValue = ConfigDesc[5];
+ DBG_ASSERT(bConfigValue == 1);
+ DBG("ConfigValue: %d\n", bConfigValue);
+ DBG("MaxPower: %d mA\n", ConfigDesc[8]*2);
+
+ uint8_t* buf = new uint8_t[wTotalLength];
+ rc = GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, wTotalLength);
+ DBG_ASSERT(rc == USBERR_OK);
+ DBG_ASSERT(ConfigDesc[1] == 0x02);
+ int pos = 0;
+ while(pos < wTotalLength) {
+ DBG_BYTES("", buf+pos, buf[pos]);
+ if (buf[pos+1] == 4) { // interface ?
+ m_InterfaceClass = buf[pos+5];
+ VERBOSE("InterfaceClass: %02X\n", m_InterfaceClass);
+ break;
+ }
+ pos += buf[pos];
+ }
+ delete[] buf;
+
+ rc = setConfiguration(1);
+ DBG_ASSERT(rc == USBERR_OK);
+ if (rc)
+ {
+ // PRINT_Err(rc);
+ return rc;
+ }
+ wait_ms(100);/* Some devices may require this delay */
+
+ m_enumerated = true;
+ return USBERR_OK;
+}
+
+bool UsbDevice::connected()
+{
+ return m_connected;
+}
+
+bool UsbDevice::enumerated()
+{
+ return m_enumerated;
+}
+
+int UsbDevice::getPid()
+{
+ return m_pid;
+}
+
+int UsbDevice::getVid()
+{
+ return m_vid;
+}
+#if 0
+UsbErr UsbDevice::getConfigurationDescriptor(int config, uint8_t** pBuf)
+{
+ DBG_ASSERT(m_controlDataBuf);
+ //For now olny one config
+ *pBuf = m_controlDataBuf;
+ return USBERR_OK;
+}
+
+UsbErr UsbDevice::getInterfaceDescriptor(int config, int item, uint8_t** pBuf)
+{
+ DBG_ASSERT(m_controlDataBuf);
+ byte* desc_ptr = m_controlDataBuf;
+
+/* if (desc_ptr[1] != USB_DESCRIPTOR_TYPE_CONFIGURATION)
+ {
+ return USBERR_BADCONFIG;
+ }*/
+ DBG_ASSERT(m_controlDataBuf);
+ if(item>=m_controlDataBuf[4])//Interfaces count
+ return USBERR_NOTFOUND;
+
+ desc_ptr += desc_ptr[0];
+
+ *pBuf = NULL;
+
+ while (desc_ptr < m_controlDataBuf + *((uint16_t*)&m_controlDataBuf[2]))
+ {
+
+ switch (desc_ptr[1]) {
+ case USB_DESCRIPTOR_TYPE_INTERFACE:
+ if(desc_ptr[2] == item)
+ {
+ *pBuf = desc_ptr;
+ return USBERR_OK;
+ }
+ desc_ptr += desc_ptr[0]; // Move to next descriptor start
+ break;
+ }
+
+ }
+
+ if(*pBuf == NULL)
+ return USBERR_NOTFOUND;
+
+ return USBERR_OK;
+}
+#endif
+
+UsbErr UsbDevice::setConfiguration(int config)
+{
+ DBG("config=%d\n", config);
+ DBG_ASSERT(config == 1);
+ UsbErr rc = controlSend(
+ USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, // 0x00
+ SET_CONFIGURATION, config, 0, 0, 0);
+ return rc;
+}
+
+UsbErr UsbDevice::controlSend(byte requestType, byte request, word value, word index, const byte* buf, int len)
+{
+ UsbErr rc;
+ fillControlBuf(requestType, request, value, index, len);
+ DBG_ASSERT(m_pControlEp);
+ m_pControlEp->setNextToken(TD_SETUP);
+ rc = m_pControlEp->transfer(m_controlBuf, 8);
+ while(m_pControlEp->status() == USBERR_PROCESSING);
+ rc = (UsbErr) MIN(0, m_pControlEp->status());
+ if(rc)
+ return rc;
+ if(len)
+ {
+ m_pControlEp->setNextToken(TD_OUT);
+ rc = m_pControlEp->transfer((byte*)buf, len);
+ while(m_pControlEp->status() == USBERR_PROCESSING);
+ rc = (UsbErr) MIN(0, m_pControlEp->status());
+ if(rc)
+ return rc;
+ }
+ m_pControlEp->setNextToken(TD_IN);
+ rc = m_pControlEp->transfer(NULL, 0);
+ while(m_pControlEp->status() == USBERR_PROCESSING);
+ rc = (UsbErr) MIN(0, m_pControlEp->status());
+ if(rc)
+ return rc;
+ return USBERR_OK;
+}
+
+UsbErr UsbDevice::controlReceive(byte requestType, byte request, word value, word index, const byte* buf, int len)
+{
+ DBG("buf=%p len=%d\n", buf, len);
+ UsbErr rc;
+ fillControlBuf(requestType, request, value, index, len);
+ DBG_ASSERT(m_pControlEp);
+ m_pControlEp->setNextToken(TD_SETUP);
+ rc = m_pControlEp->transfer(m_controlBuf, 8);
+ while(m_pControlEp->status() == USBERR_PROCESSING);
+ rc = (UsbErr) MIN(0, m_pControlEp->status());
+ if(rc)
+ return rc;
+ if(len)
+ {
+ m_pControlEp->setNextToken(TD_IN);
+ rc = m_pControlEp->transfer( (byte*) buf, len);
+ while(m_pControlEp->status() == USBERR_PROCESSING);
+ rc = (UsbErr) MIN(0, m_pControlEp->status());
+ if(rc)
+ return rc;
+ }
+ m_pControlEp->setNextToken(TD_OUT);
+ rc = m_pControlEp->transfer(NULL, 0);
+ while(m_pControlEp->status() == USBERR_PROCESSING);
+ rc = (UsbErr) MIN(0, m_pControlEp->status());
+ if(rc)
+ return rc;
+ return USBERR_OK;
+}
+
+UsbErr UsbDevice::GetDescriptor(int type, int index, const byte* buf, int len)
+{
+ DBG("type=%02X\n", type);
+ return controlReceive(
+ USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR,
+ (type << 8) |(index), 0, buf, len);
+
+}
+
+UsbErr UsbDevice::GetString(int index, char* buf, int len)
+{
+ DBG("index=%d buf=%p len=%d\n", index, buf, len);
+ DBG_ASSERT(index >= 1);
+ uint8_t temp[4];
+ UsbErr rc;
+ rc = GetDescriptor(USB_DESCRIPTOR_TYPE_STRING, 0, temp, sizeof(temp));
+ DBG_ASSERT(rc == USBERR_OK);
+ DBG_BYTES("LANG_ID", temp, sizeof(temp));
+ DBG_ASSERT(temp[0] == 4);
+ DBG_ASSERT(temp[1] == 0x03);
+
+ rc = GetDescriptor(USB_DESCRIPTOR_TYPE_STRING, index, temp, 2);
+ DBG_ASSERT(rc == USBERR_OK);
+ DBG_BYTES("length check", temp, 2);
+ if (temp[0] == 0x00 && temp[1] == 0x00) { // for pl2303
+ if (len > 0) {
+ strcpy(buf, "");
+ }
+ return rc;
+ }
+ DBG_ASSERT(temp[1] == 0x03);
+ int temp_len = temp[0];
+
+ uint8_t* temp_buf = new uint8_t[temp_len];
+ DBG_ASSERT(temp_buf);
+ rc = GetDescriptor(USB_DESCRIPTOR_TYPE_STRING, index, temp_buf, temp_len);
+ DBG_ASSERT(rc == USBERR_OK);
+ temp_len = temp_buf[0];
+ DBG_HEX(temp_buf, temp_len);
+ int i = 0;
+ for(int pos = 2; pos < temp_len; pos+= 2) {
+ buf[i++] = temp_buf[pos];
+ DBG_ASSERT(i < len-1);
+ }
+ buf[i] = '\0';
+ delete[] temp_buf;
+ return rc;
+}
+
+UsbErr UsbDevice::SetInterfaceAlternate(int interface, int alternate)
+{
+ UsbErr rc = controlSend(
+ USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE,
+ SET_INTERFACE, alternate, interface, NULL, 0);
+ return rc;
+}
+
+void UsbDevice::fillControlBuf(byte requestType, byte request, word value, word index, int len)
+{
+#ifdef __BIG_ENDIAN
+ #error "Must implement BE to LE conv here"
+#endif
+ m_controlBuf[0] = requestType;
+ m_controlBuf[1] = request;
+ //We are in LE so it's fine
+ *((word*)&m_controlBuf[2]) = value;
+ *((word*)&m_controlBuf[4]) = index;
+ *((word*)&m_controlBuf[6]) = (word) len;
+}
+
+