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.
Fork of USBHost_DISCO-F746NG by
Diff: USBHost/USBHost.cpp
- Revision:
- 8:6463cd1964c0
- Parent:
- 7:9a20482c9a7a
- Child:
- 9:7f9f64cf5ded
--- a/USBHost/USBHost.cpp Tue Jan 28 06:50:12 2014 +0000
+++ b/USBHost/USBHost.cpp Fri Jan 31 13:45:07 2014 +0000
@@ -20,8 +20,13 @@
#define USB_DBG_ERRSTAT() while(0)
#endif
+#ifdef _USB_TEST
#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
+#else
+#define USB_TEST_ASSERT(A) while(0)
+#define USB_TEST_ASSERT_FALSE(A) while(0)
+#endif
#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0);
@@ -37,136 +42,190 @@
}
USBHost::USBHost() {
+ DeviceLists_count = 0;
}
-/* virtual */ bool USBHost::enumeration() {
- USBEndpoint* ep = &ep_ctl_in_out;
- uint8_t desc[64];
- ep->setAddress(0);
- ep->setSize(8); // max packet size
- dev.addr = 0;
+/* virtual */ bool USBHost::addDevice(int hub, int port, bool lowSpeed) {
+ USBDeviceConnected* dev = new USBDeviceConnected;
+ USBEndpoint* ep = new USBEndpoint;
+ ep->setDevice(dev);
+ dev->init(hub, port, lowSpeed);
+ dev->setAddress(0);
+ dev->setEpCtl(ep);
+ uint8_t desc[18];
wait_ms(100);
- SETUP_PACKET setup_get_descriptor = {0x80, GET_DESCRIPTOR, 1<<8, 0, 0};
- int result = ControlRead(&setup_get_descriptor, desc, ep->getSize());
- if (result < ep->getSize()) {
- USB_DBG("result=%d %02x", result, LastStatus);
- USB_DBG_ERRSTAT();
- return false;
- }
- USB_DBG_HEX(desc, result);
- USB_DBG_ERRSTAT();
+
+ int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ USB_DBG_HEX(desc, 8);
DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
ep->setSize(dev_desc->bMaxPacketSize);
- SETUP_PACKET setup_set_address = {0x00, SET_ADDRESS, 1, 0, 0};
- result = ControlWrite(&setup_set_address);
- if (result < 0) {
- USB_DBG("result=%d %02x", result, LastStatus);
- USB_DBG_ERRSTAT();
- return false;
- }
+ int new_addr = USBDeviceConnected::getNewAddress();
+ rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ dev->setAddress(new_addr);
wait_ms(100);
- dev.addr = 1;
+
+ rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ USB_DBG_HEX(desc, sizeof(desc));
- result = ControlRead(&setup_get_descriptor, desc, sizeof(desc));
- if (result < 8) {
- USB_DBG("result=%d", result);
- USB_DBG_ERRSTAT();
- return false;
+ dev->setVid(dev_desc->idVendor);
+ dev->setPid(dev_desc->idProduct);
+ dev->setClass(dev_desc->bDeviceClass);
+ USB_INFO("hub: %d port: %d speed: %s vid: %04x pid: %04x class: %02x addr: %d\n",
+ hub, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(),
+ dev->getAddress());
+
+ USB_TEST_ASSERT(DeviceLists_count < MAX_DEVICE_CONNECTED);
+ DeviceLists[DeviceLists_count++] = dev;
+
+ if (dev->getClass() == HUB_CLASS) {
+ const int config = 1;
+ int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ wait_ms(100);
+ Hub(dev);
}
- USB_DBG_HEX(desc, result);
- USB_DBG_ERRSTAT();
+ return true;
+}
- dev.vid = dev_desc->idVendor;
- dev.pid = dev_desc->idProduct;
- USB_INFO("USB VID: %04x, PID: %04x\n", dev.vid, dev.pid);
- if (dev_desc->bDeviceClass == HUB_CLASS) {
- USB_INFO("USB hub not supported.\n\n");
- exit(1);
+// enumerate a device with the control USBEndpoint
+USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
+{
+ if (dev->getClass() == HUB_CLASS) { // skip hub class
+ return USB_TYPE_OK;
}
+ uint8_t desc[18];
+ USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ USB_DBG_HEX(desc, sizeof(desc));
+ if (rc != USB_TYPE_OK) {
+ return rc;
+ }
+ DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
+ dev->setClass(dev_desc->bDeviceClass);
+ pEnumerator->setVidPid(dev->getVid(), dev->getPid());
- setup_get_descriptor.wValue = 2<<8; // config descriptor
- result = ControlRead(&setup_get_descriptor, desc, 4);
- if (result != 4) {
- USB_DBG("result=%d", result);
- USB_DBG_ERRSTAT();
- return false;
- }
+ rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
USB_DBG_HEX(desc, 4);
- USB_DBG_ERRSTAT();
int TotalLength = desc[2]|desc[3]<<8;
uint8_t* buf = new uint8_t[TotalLength];
- result = ControlRead(&setup_get_descriptor, buf, TotalLength);
- if (result != TotalLength) {
- USB_DBG("result=%d TotalLength=%d %02x", result, TotalLength, LastStatus);
- USB_DBG_ERRSTAT();
- return false;
+ rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ //USB_DBG_HEX(buf, TotalLength);
+
+ // Parse the configuration descriptor
+ parseConfDescr(dev, buf, TotalLength, pEnumerator);
+ delete[] buf;
+ // only set configuration if not enumerated before
+ if (!dev->isEnumerated()) {
+ USB_DBG("Set configuration 1 on dev: %p", dev);
+ // sixth step: set configuration (only 1 supported)
+ int config = 1;
+ USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
+ if (res != USB_TYPE_OK) {
+ USB_DBG("SET CONF FAILED");
+ return res;
+ }
+ // Some devices may require this delay
+ wait_ms(100);
+ dev->setEnumerated();
+ // Now the device is enumerated!
+ USB_DBG("dev %p is enumerated", dev);
}
- USB_DBG_HEX(buf, TotalLength);
- USB_DBG_ERRSTAT();
+ return USB_TYPE_OK;
+}
- for(int i = 0; i < TotalLength; ) {
- int Length = buf[i];
- uint8_t DescriptorType = buf[i+1];
- if (DescriptorType == 0x05) { // endpoint
- EndpointDescriptor* desc = reinterpret_cast<EndpointDescriptor*>(buf+i);
- USBEndpoint* ep = NULL;
- if (desc->bmAttributes == 0x03) { // interrupt
- if (desc->bEndpointAddress & 0x80) {
- ep = &ep_int_in;
+// this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
+void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator)
+{
+ uint32_t index = 0;
+ uint32_t len_desc = 0;
+ uint8_t id = 0;
+ int nb_endpoints_used = 0;
+ USBEndpoint * ep = NULL;
+ uint8_t intf_nb = 0;
+ bool parsing_intf = false;
+ uint8_t current_intf = 0;
+ EndpointDescriptor* ep_desc;
+
+ while (index < len) {
+ len_desc = conf_descr[index];
+ id = conf_descr[index+1];
+ switch (id) {
+ case CONFIGURATION_DESCRIPTOR:
+ USB_DBG("dev: %p has %d intf", dev, conf_descr[4]);
+ dev->setNbIntf(conf_descr[4]);
+ break;
+ case INTERFACE_DESCRIPTOR:
+ if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
+ if (intf_nb++ <= MAX_INTF) {
+ current_intf = conf_descr[index + 2];
+ dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
+ nb_endpoints_used = 0;
+ USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]);
+ } else {
+ USB_DBG("Drop intf...");
+ }
+ parsing_intf = true;
+ } else {
+ parsing_intf = false;
}
- } else if (desc->bmAttributes == 0x02) { // bulk
- ep = (desc->bEndpointAddress & 0x80) ? &ep_bulk_in : &ep_bulk_out;
- }
- if (ep) {
- ep->setAddress(desc->bEndpointAddress);
- ep->setSize(desc->wMaxPacketSize);
- }
+ break;
+ case ENDPOINT_DESCRIPTOR:
+ ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index);
+ if (parsing_intf && (intf_nb <= MAX_INTF) ) {
+ if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) {
+ ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03);
+ ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT;
+ if(pEnumerator->useEndpoint(current_intf, type, dir)) {
+ ep = new USBEndpoint;
+ ep->setDevice(dev);
+ ep->setType(type);
+ ep->setAddress(ep_desc->bEndpointAddress);
+ ep->setSize(ep_desc->wMaxPacketSize);
+ USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev);
+ dev->addEndpoint(current_intf, ep);
+ nb_endpoints_used++;
+ }
+ }
+ }
+ break;
+ case HID_DESCRIPTOR:
+ //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
+ break;
+ default:
+ break;
}
- USB_DBG_HEX(buf+i, Length);
- i += Length;
+ index += len_desc;
}
- delete[] buf;
-
- // config = 1
- SETUP_PACKET setup_set_config = {0x00, SET_CONFIGURATION, 1, 0, 0};
- result = ControlWrite(&setup_set_config);
- if (result < 0) {
- USB_DBG("set config: %02x", LastStatus);
- USB_DBG_ERRSTAT();
- if (lowSpeed && LastStatus == STALL) { // TODO:
- wait_ms(100);
- return true;
- }
- return false;
- }
- wait_ms(100);
- return true;
}
USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
SETUP_PACKET setup = {requestType, request, value, index};
- int result = ControlRead(&setup, buf, len);
- USB_DBG2("result=%d %02x", result, LastStatus);
+ int result = ControlRead(dev, &setup, buf, len);
+ //USB_DBG2("result=%d %02x", result, LastStatus);
return (result >= 0) ? USB_TYPE_OK : USB_TYPE_ERROR;
}
USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
SETUP_PACKET setup = {requestType, request, value, index};
- int result = ControlWrite(&setup, buf, len);
+ int result = ControlWrite(dev, &setup, buf, len);
if (result >= 0) {
return USB_TYPE_OK;
}
USB_DBG("result=%d %02x", result, LastStatus);
- USB_DBG_ERRSTAT();
USB_DBG_HEX(buf, len);
return USB_TYPE_ERROR;
}
USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
USB_TEST_ASSERT(blocking);
- int result = BulkRead(buf, len);
+ int result = BulkRead(ep, buf, len);
if (result >= 0) {
return USB_TYPE_OK;
}
@@ -176,7 +235,7 @@
USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
USB_TEST_ASSERT(blocking);
- int result = BulkWrite(buf, len);
+ int result = BulkWrite(ep, buf, len);
if (result >= 0) {
return USB_TYPE_OK;
}
@@ -184,18 +243,19 @@
return USB_TYPE_ERROR;
}
-USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
- USB_TEST_ASSERT(blocking);
- int result = InterruptRead(buf, len);
+USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
+ int result = InterruptRead(ep, buf, len);
if (result >= 0) {
return USB_TYPE_OK;
}
return USB_TYPE_ERROR;
}
-int USBHost::ControlRead(SETUP_PACKET* setup, uint8_t* data, int size) {
- USBEndpoint* ep = &ep_ctl_in_out;
- setAddr(dev.addr);
+int USBHost::ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) {
+ USB_TEST_ASSERT(dev);
+ USBEndpoint* ep = dev->getEpCtl();
+ USB_TEST_ASSERT(ep);
+ setAddr(dev->getAddress(), dev->getSpeed());
token_setup(ep, setup, size); // setup stage
if (LastStatus != ACK) {
USB_DBG("setup %02x", LastStatus);
@@ -220,16 +280,20 @@
if (result < 0) {
USB_DBG("status token_out %02x", LastStatus);
if (LastStatus == STALL) {
+ ep->setLengthTransferred(read_len);
return read_len;
}
return result;
}
+ ep->setLengthTransferred(read_len);
return read_len;
}
-int USBHost::ControlWrite(SETUP_PACKET* setup, uint8_t* data, int size) {
- USBEndpoint* ep = &ep_ctl_in_out;
- setAddr(dev.addr);
+int USBHost::ControlWrite(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) {
+ USB_TEST_ASSERT(dev);
+ USBEndpoint* ep = dev->getEpCtl();
+ USB_TEST_ASSERT(ep);
+ setAddr(dev->getAddress(), dev->getSpeed());
token_setup(ep, setup, size); // setup stage
if (LastStatus != ACK) {
USB_DBG("setup %02x", LastStatus);
@@ -248,12 +312,15 @@
USB_DBG("result=%d %02x", result, LastStatus);
//return result;
}
+ ep->setLengthTransferred(write_len);
return write_len;
}
-int USBHost::InterruptRead(uint8_t* data, int size) {
- USBEndpoint* ep = &ep_int_in;
- setAddr(dev.addr);
+int USBHost::InterruptRead(USBEndpoint* ep, uint8_t* data, int size) {
+ USB_TEST_ASSERT(ep);
+ USBDeviceConnected* dev = ep->getDevice();
+ USB_TEST_ASSERT(dev);
+ setAddr(dev->getAddress(), dev->getSpeed());
setEndpoint();
const int retryLimit = 0;
int read_len = 0;
@@ -267,7 +334,7 @@
}
break;
}
- USB_DBG("token_in result=%d %02x", result, LastStatus);
+ //USB_DBG("token_in result=%d %02x", result, LastStatus);
return result;
}
read_len += result;
@@ -275,12 +342,15 @@
break;
}
}
+ ep->setLengthTransferred(read_len);
return read_len;
}
-int USBHost::BulkRead(uint8_t* data, int size, int timeout_ms) {
- USBEndpoint* ep = &ep_bulk_in;
- setAddr(dev.addr);
+int USBHost::BulkRead(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) {
+ USB_TEST_ASSERT(ep);
+ USBDeviceConnected* dev = ep->getDevice();
+ USB_TEST_ASSERT(dev);
+ setAddr(dev->getAddress());
setEndpoint();
int retryLimit = (timeout_ms == 0) ? 0 : 10;
int read_len = 0;
@@ -295,7 +365,7 @@
}
break;
}
- USB_DBG("token_in result=%d %02x", result, LastStatus);
+ //USB_DBG("token_in result=%d %02x", result, LastStatus);
return result;
}
read_len += result;
@@ -307,12 +377,15 @@
break;
}
}
+ ep->setLengthTransferred(read_len);
return read_len;
}
-int USBHost::BulkWrite(const uint8_t* data, int size) {
- USBEndpoint* ep = &ep_bulk_out;
- setAddr(dev.addr);
+int USBHost::BulkWrite(USBEndpoint* ep, const uint8_t* data, int size) {
+ USB_TEST_ASSERT(ep);
+ USBDeviceConnected* dev = ep->getDevice();
+ USB_TEST_ASSERT(dev);
+ setAddr(dev->getAddress());
setEndpoint();
int write_len = 0;
for(int n = 0; write_len < size; n++) {
@@ -333,11 +406,18 @@
break;
}
}
+ ep->setLengthTransferred(write_len);
return write_len;
}
int USBHost::IsochronousRead(USBEndpoint* ep, uint8_t* data, int size) {
- setAddr(dev.addr);
- return token_iso_in(ep, data, size);
+ USBDeviceConnected* dev = ep->getDevice();
+ USB_TEST_ASSERT(dev);
+ setAddr(dev->getAddress());
+ int result = token_iso_in(ep, data, size);
+ if (result >= 0) {
+ ep->setLengthTransferred(result);
+ }
+ return result;
}
