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 F401RE-USBHost by
USBHost.cpp
00001 /* mbed USBHost Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "USBHost.h" 00018 00019 #define USB_TRACE1(A) while(0) 00020 #undef USB_TEST_ASSERT 00021 void usb_test_assert_internal(const char *expr, const char *file, int line); 00022 #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} 00023 00024 USBHost* USBHost::inst = NULL; 00025 00026 USBHost* USBHost::getHostInst() { 00027 if (inst == NULL) { 00028 inst = new USBHost(); 00029 inst->init(); 00030 } 00031 return inst; 00032 } 00033 00034 void USBHost::poll() 00035 { 00036 if (inst) { 00037 inst->task(); 00038 } 00039 } 00040 00041 USBHost::USBHost() { 00042 } 00043 00044 /* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) { 00045 USBDeviceConnected* dev = new USBDeviceConnected; 00046 USBEndpoint* ep = new USBEndpoint(dev); 00047 dev->init(0, port, lowSpeed); 00048 dev->setAddress(0); 00049 dev->setEpCtl(ep); 00050 uint8_t desc[18]; 00051 wait_ms(100); 00052 00053 int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8); 00054 USB_TEST_ASSERT(rc == USB_TYPE_OK); // randomly fails if xbone is plugged in when it turns on 00055 if (rc != USB_TYPE_OK) { 00056 USB_ERR("ADD DEVICE FAILD"); 00057 } 00058 00059 USB_DBG_HEX(desc, 8); 00060 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); 00061 ep->setSize(dev_desc->bMaxPacketSize); 00062 00063 int new_addr = USBDeviceConnected::getNewAddress(); 00064 rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0); 00065 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00066 dev->setAddress(new_addr); 00067 wait_ms(100); 00068 00069 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); 00070 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00071 USB_DBG_HEX(desc, sizeof(desc)); 00072 00073 dev->setVid(dev_desc->idVendor); 00074 dev->setPid(dev_desc->idProduct); 00075 dev->setClass(dev_desc->bDeviceClass); 00076 USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d", 00077 parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), 00078 dev->getAddress()); 00079 00080 DeviceLists.push_back(dev); 00081 00082 if (dev->getClass() == HUB_CLASS) { 00083 const int config = 1; 00084 int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); 00085 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00086 wait_ms(100); 00087 Hub(dev); 00088 } 00089 return true; 00090 } 00091 00092 // enumerate a device with the control USBEndpoint 00093 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) 00094 { 00095 if (dev->getClass() == HUB_CLASS) { // skip hub class 00096 return USB_TYPE_OK; 00097 } 00098 uint8_t desc[18]; 00099 USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); 00100 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00101 USB_DBG_HEX(desc, sizeof(desc)); 00102 if (rc != USB_TYPE_OK) { 00103 return rc; 00104 } 00105 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); 00106 dev->setClass(dev_desc->bDeviceClass); 00107 pEnumerator->setVidPid(dev->getVid(), dev->getPid()); 00108 00109 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4); 00110 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00111 USB_DBG_HEX(desc, 4); 00112 00113 int TotalLength = desc[2]|desc[3]<<8; 00114 uint8_t* buf = new uint8_t[TotalLength]; 00115 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength); 00116 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00117 //USB_DBG_HEX(buf, TotalLength); 00118 00119 // Parse the configuration descriptor 00120 parseConfDescr(dev, buf, TotalLength, pEnumerator); 00121 delete[] buf; 00122 // only set configuration if not enumerated before 00123 if (!dev->isEnumerated()) { 00124 USB_DBG("Set configuration 1 on dev: %p", dev); 00125 // sixth step: set configuration (only 1 supported) 00126 int config = 1; 00127 USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); 00128 if (res != USB_TYPE_OK) { 00129 USB_ERR("SET CONF FAILED"); 00130 return res; 00131 } 00132 // Some devices may require this delay 00133 wait_ms(100); 00134 dev->setEnumerated(); 00135 // Now the device is enumerated! 00136 USB_DBG("dev %p is enumerated", dev); 00137 } 00138 return USB_TYPE_OK; 00139 } 00140 00141 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. 00142 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) 00143 { 00144 uint32_t index = 0; 00145 uint32_t len_desc = 0; 00146 uint8_t id = 0; 00147 USBEndpoint * ep = NULL; 00148 uint8_t intf_nb = 0; 00149 bool parsing_intf = false; 00150 uint8_t current_intf = 0; 00151 EndpointDescriptor* ep_desc; 00152 00153 while (index < len) { 00154 len_desc = conf_descr[index]; 00155 id = conf_descr[index+1]; 00156 USB_DBG_HEX(conf_descr+index, len_desc); 00157 switch (id) { 00158 case CONFIGURATION_DESCRIPTOR: 00159 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); 00160 dev->setNbIntf(conf_descr[4]); 00161 break; 00162 case INTERFACE_DESCRIPTOR: 00163 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { 00164 intf_nb++; 00165 current_intf = conf_descr[index + 2]; 00166 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); 00167 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]); 00168 parsing_intf = true; 00169 } else { 00170 parsing_intf = false; 00171 } 00172 break; 00173 case ENDPOINT_DESCRIPTOR: 00174 ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); 00175 if (parsing_intf && (intf_nb <= MAX_INTF) ) { 00176 ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); 00177 ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; 00178 if(pEnumerator->useEndpoint(current_intf, type, dir)) { 00179 ep = new USBEndpoint(dev); 00180 ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress); 00181 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); 00182 dev->addEndpoint(current_intf, ep); 00183 } 00184 } 00185 break; 00186 case HID_DESCRIPTOR: 00187 //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); 00188 break; 00189 default: 00190 break; 00191 } 00192 index += len_desc; 00193 } 00194 } 00195 00196 USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00197 USBEndpoint* ep = dev->getEpCtl(); 00198 SETUP_PACKET setup(requestType, request, value, index, len); 00199 00200 int result = token_setup(ep, &setup, len); // setup stage 00201 USB_TRACE1(result); 00202 if (result < 0) { 00203 return USB_TYPE_ERROR; 00204 } 00205 00206 int read_len = multi_token_in(ep, buf, len); // data stage 00207 USB_TRACE1(read_len); 00208 if (read_len < 0) { 00209 printf("ERROR:failing on data stage\r\n"); 00210 return USB_TYPE_ERROR; 00211 } 00212 00213 setToggle(ep, 1); // DATA1 00214 result = multi_token_out(ep); // status stage 00215 USB_TRACE1(result); 00216 if (result < 0) { 00217 return USB_TYPE_ERROR; 00218 } 00219 ep->setLengthTransferred(read_len); 00220 return USB_TYPE_OK; 00221 } 00222 00223 USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00224 USBEndpoint* ep = dev->getEpCtl(); 00225 SETUP_PACKET setup(requestType, request, value, index, len); 00226 00227 int result = token_setup(ep, &setup, len); // setup stage 00228 USB_TRACE1(result); 00229 if (result < 0) { 00230 return USB_TYPE_ERROR; 00231 } 00232 int write_len = 0; 00233 if (buf != NULL) { 00234 write_len = multi_token_out(ep, buf, len); // data stage 00235 USB_TRACE1(write_len); 00236 if (write_len < 0) { 00237 return USB_TYPE_ERROR; 00238 } 00239 } 00240 00241 setToggle(ep, 1); // DATA1 00242 result = multi_token_in(ep); // status stage 00243 USB_TRACE1(result); 00244 if (result < 0) { 00245 return USB_TYPE_ERROR; 00246 } 00247 ep->setLengthTransferred(write_len); 00248 return USB_TYPE_OK; 00249 } 00250 00251 USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00252 if (blocking == false) { 00253 ep->setBuffer(buf, len); 00254 ep_queue.push(ep); 00255 multi_token_inNB(ep, buf, len); 00256 return USB_TYPE_PROCESSING; 00257 } 00258 int result = multi_token_in(ep, buf, len); 00259 USB_TRACE1(result); 00260 if (result < 0) { 00261 return USB_TYPE_ERROR; 00262 } 00263 ep->setLengthTransferred(result); 00264 return USB_TYPE_OK; 00265 } 00266 00267 USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00268 USB_TEST_ASSERT(blocking); 00269 int result = multi_token_out(ep, buf, len); 00270 USB_TRACE1(result); 00271 if (result < 0) { 00272 return USB_TYPE_ERROR; 00273 } 00274 ep->setLengthTransferred(result); 00275 return USB_TYPE_OK; 00276 } 00277 00278 USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00279 if (blocking == false) { 00280 ep->setBuffer(buf, len); 00281 ep_queue.push(ep); 00282 multi_token_inNB(ep, buf, len); 00283 return USB_TYPE_PROCESSING; 00284 } 00285 int result = multi_token_in(ep, buf, len); 00286 USB_TRACE1(result); 00287 if (result < 0) { 00288 return USB_TYPE_ERROR; 00289 } 00290 ep->setLengthTransferred(result); 00291 return USB_TYPE_OK; 00292 } 00293 00294 USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00295 USB_TEST_ASSERT(blocking); 00296 int result = multi_token_out(ep, buf, len); 00297 USB_TRACE1(result); 00298 if (result < 0) { 00299 return USB_TYPE_ERROR; 00300 } 00301 ep->setLengthTransferred(result); 00302 return USB_TYPE_OK; 00303 } 00304 00305 USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00306 USB_TEST_ASSERT(blocking); 00307 isochronousReadNB(ep, buf, len); 00308 return USB_TYPE_OK; 00309 } 00310 00311 int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) { 00312 USB_TRACE1(size); 00313 if (ep->getState() != USB_TYPE_PROCESSING) { 00314 ep->setState(USB_TYPE_PROCESSING); 00315 ep->setBuffer(data, size); 00316 multi_token_inNB(ep, data, size); 00317 } 00318 if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { 00319 return ep->getLengthTransferred(); 00320 } 00321 return -1; 00322 } 00323 00324 int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) { 00325 USB_TRACE1(size); 00326 return interruptReadNB(ep, data, size); 00327 } 00328 00329 int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { 00330 USB_TRACE1(size); 00331 int result = token_iso_in(ep, data, size); 00332 if (result >= 0) { 00333 ep->setLengthTransferred(result); 00334 } 00335 return result; 00336 } 00337 00338 void USBHost::task() { 00339 USBEndpoint* ep = ep_queue.pop(); 00340 if (ep) { 00341 USB_TEST_ASSERT(ep->getDir() == IN); 00342 if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { 00343 ep->call(); 00344 } else { 00345 ep_queue.push(ep); 00346 } 00347 } 00348 } 00349 00350 void usb_test_assert_internal(const char *expr, const char *file, int line){ 00351 error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr); 00352 } 00353
Generated on Wed Jul 13 2022 03:02:44 by
1.7.2
