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.
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); 00055 if (rc != USB_TYPE_OK) { 00056 USB_ERR("ADD DEVICE FAILD"); 00057 } 00058 USB_DBG_HEX(desc, 8); 00059 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); 00060 ep->setSize(dev_desc->bMaxPacketSize); 00061 00062 int new_addr = USBDeviceConnected::getNewAddress(); 00063 rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0); 00064 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00065 dev->setAddress(new_addr); 00066 wait_ms(100); 00067 00068 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); 00069 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00070 USB_DBG_HEX(desc, sizeof(desc)); 00071 00072 dev->setVid(dev_desc->idVendor); 00073 dev->setPid(dev_desc->idProduct); 00074 dev->setClass(dev_desc->bDeviceClass); 00075 USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d", 00076 parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), 00077 dev->getAddress()); 00078 00079 DeviceLists.push_back(dev); 00080 00081 if (dev->getClass() == HUB_CLASS) { 00082 const int config = 1; 00083 int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); 00084 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00085 wait_ms(100); 00086 Hub(dev); 00087 } 00088 return true; 00089 } 00090 00091 // enumerate a device with the control USBEndpoint 00092 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) 00093 { 00094 if (dev->getClass() == HUB_CLASS) { // skip hub class 00095 return USB_TYPE_OK; 00096 } 00097 uint8_t desc[18]; 00098 USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); 00099 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00100 USB_DBG_HEX(desc, sizeof(desc)); 00101 if (rc != USB_TYPE_OK) { 00102 return rc; 00103 } 00104 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); 00105 dev->setClass(dev_desc->bDeviceClass); 00106 pEnumerator->setVidPid(dev->getVid(), dev->getPid()); 00107 00108 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4); 00109 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00110 USB_DBG_HEX(desc, 4); 00111 00112 int TotalLength = desc[2]|desc[3]<<8; 00113 uint8_t* buf = new uint8_t[TotalLength]; 00114 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength); 00115 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00116 //USB_DBG_HEX(buf, TotalLength); 00117 00118 // Parse the configuration descriptor 00119 parseConfDescr(dev, buf, TotalLength, pEnumerator); 00120 delete[] buf; 00121 // only set configuration if not enumerated before 00122 if (!dev->isEnumerated()) { 00123 USB_DBG("Set configuration 1 on dev: %p", dev); 00124 // sixth step: set configuration (only 1 supported) 00125 int config = 1; 00126 USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); 00127 if (res != USB_TYPE_OK) { 00128 USB_ERR("SET CONF FAILED"); 00129 return res; 00130 } 00131 // Some devices may require this delay 00132 wait_ms(100); 00133 dev->setEnumerated(); 00134 // Now the device is enumerated! 00135 USB_DBG("dev %p is enumerated", dev); 00136 } 00137 return USB_TYPE_OK; 00138 } 00139 00140 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. 00141 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) 00142 { 00143 uint32_t index = 0; 00144 uint32_t len_desc = 0; 00145 uint8_t id = 0; 00146 USBEndpoint * ep = NULL; 00147 uint8_t intf_nb = 0; 00148 bool parsing_intf = false; 00149 uint8_t current_intf = 0; 00150 EndpointDescriptor* ep_desc; 00151 00152 while (index < len) { 00153 len_desc = conf_descr[index]; 00154 id = conf_descr[index+1]; 00155 USB_DBG_HEX(conf_descr+index, len_desc); 00156 switch (id) { 00157 case CONFIGURATION_DESCRIPTOR: 00158 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); 00159 dev->setNbIntf(conf_descr[4]); 00160 break; 00161 case INTERFACE_DESCRIPTOR: 00162 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { 00163 intf_nb++; 00164 current_intf = conf_descr[index + 2]; 00165 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); 00166 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]); 00167 parsing_intf = true; 00168 } else { 00169 parsing_intf = false; 00170 } 00171 break; 00172 case ENDPOINT_DESCRIPTOR: 00173 ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); 00174 if (parsing_intf && (intf_nb <= MAX_INTF) ) { 00175 ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); 00176 ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; 00177 if(pEnumerator->useEndpoint(current_intf, type, dir)) { 00178 ep = new USBEndpoint(dev); 00179 ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress); 00180 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); 00181 dev->addEndpoint(current_intf, ep); 00182 } 00183 } 00184 break; 00185 case HID_DESCRIPTOR: 00186 //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); 00187 break; 00188 default: 00189 break; 00190 } 00191 index += len_desc; 00192 } 00193 } 00194 00195 USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00196 USBEndpoint* ep = dev->getEpCtl(); 00197 SETUP_PACKET setup(requestType, request, value, index, len); 00198 00199 int result = token_setup(ep, &setup, len); // setup stage 00200 USB_TRACE1(result); 00201 if (result < 0) { 00202 return USB_TYPE_ERROR; 00203 } 00204 00205 int read_len = multi_token_in(ep, buf, len); // data stage 00206 USB_TRACE1(read_len); 00207 if (read_len < 0) { 00208 return USB_TYPE_ERROR; 00209 } 00210 00211 setToggle(ep, 1); // DATA1 00212 result = multi_token_out(ep); // status stage 00213 USB_TRACE1(result); 00214 if (result < 0) { 00215 return USB_TYPE_ERROR; 00216 } 00217 ep->setLengthTransferred(read_len); 00218 return USB_TYPE_OK; 00219 } 00220 00221 USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00222 USBEndpoint* ep = dev->getEpCtl(); 00223 SETUP_PACKET setup(requestType, request, value, index, len); 00224 00225 int result = token_setup(ep, &setup, len); // setup stage 00226 USB_TRACE1(result); 00227 if (result < 0) { 00228 return USB_TYPE_ERROR; 00229 } 00230 int write_len = 0; 00231 if (buf != NULL) { 00232 write_len = multi_token_out(ep, buf, len); // data stage 00233 USB_TRACE1(write_len); 00234 if (write_len < 0) { 00235 return USB_TYPE_ERROR; 00236 } 00237 } 00238 00239 setToggle(ep, 1); // DATA1 00240 result = multi_token_in(ep); // status stage 00241 USB_TRACE1(result); 00242 if (result < 0) { 00243 return USB_TYPE_ERROR; 00244 } 00245 ep->setLengthTransferred(write_len); 00246 return USB_TYPE_OK; 00247 } 00248 00249 USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00250 if (blocking == false) { 00251 ep->setBuffer(buf, len); 00252 ep_queue.push(ep); 00253 multi_token_inNB(ep, buf, len); 00254 return USB_TYPE_PROCESSING; 00255 } 00256 int result = multi_token_in(ep, buf, len); 00257 USB_TRACE1(result); 00258 if (result < 0) { 00259 return USB_TYPE_ERROR; 00260 } 00261 ep->setLengthTransferred(result); 00262 return USB_TYPE_OK; 00263 } 00264 00265 USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00266 USB_TEST_ASSERT(blocking); 00267 int result = multi_token_out(ep, buf, len); 00268 USB_TRACE1(result); 00269 if (result < 0) { 00270 return USB_TYPE_ERROR; 00271 } 00272 ep->setLengthTransferred(result); 00273 return USB_TYPE_OK; 00274 } 00275 00276 USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00277 if (blocking == false) { 00278 ep->setBuffer(buf, len); 00279 ep_queue.push(ep); 00280 multi_token_inNB(ep, buf, len); 00281 return USB_TYPE_PROCESSING; 00282 } 00283 int result = multi_token_in(ep, buf, len); 00284 USB_TRACE1(result); 00285 if (result < 0) { 00286 return USB_TYPE_ERROR; 00287 } 00288 ep->setLengthTransferred(result); 00289 return USB_TYPE_OK; 00290 } 00291 00292 USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00293 USB_TEST_ASSERT(blocking); 00294 int result = multi_token_out(ep, buf, len); 00295 USB_TRACE1(result); 00296 if (result < 0) { 00297 return USB_TYPE_ERROR; 00298 } 00299 ep->setLengthTransferred(result); 00300 return USB_TYPE_OK; 00301 } 00302 00303 USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00304 USB_TEST_ASSERT(blocking); 00305 isochronousReadNB(ep, buf, len); 00306 return USB_TYPE_OK; 00307 } 00308 00309 int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) { 00310 USB_TRACE1(size); 00311 if (ep->getState() != USB_TYPE_PROCESSING) { 00312 ep->setState(USB_TYPE_PROCESSING); 00313 ep->setBuffer(data, size); 00314 multi_token_inNB(ep, data, size); 00315 } 00316 if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { 00317 return ep->getLengthTransferred(); 00318 } 00319 return -1; 00320 } 00321 00322 int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) { 00323 USB_TRACE1(size); 00324 return interruptReadNB(ep, data, size); 00325 } 00326 00327 int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { 00328 USB_TRACE1(size); 00329 int result = token_iso_in(ep, data, size); 00330 if (result >= 0) { 00331 ep->setLengthTransferred(result); 00332 } 00333 return result; 00334 } 00335 00336 void USBHost::task() { 00337 USBEndpoint* ep = ep_queue.pop(); 00338 if (ep) { 00339 USB_TEST_ASSERT(ep->getDir() == IN); 00340 if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { 00341 ep->call(); 00342 } else { 00343 ep_queue.push(ep); 00344 } 00345 } 00346 } 00347 00348 void usb_test_assert_internal(const char *expr, const char *file, int line){ 00349 error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr); 00350 } 00351 00352
Generated on Thu Jul 14 2022 09:06:30 by
