Simple USBHost library for LPC4088. Backward compatibility of official-USBHost.
Dependencies: FATFileSystem mbed-rtos
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 #define USB_DEBUG 00019 #include "BaseUsbHostDebug.h" 00020 #define TEST 00021 #include "BaseUsbHostTest.h" 00022 00023 USBHost* USBHost::inst = NULL; 00024 00025 USBHost* USBHost::getHostInst() { 00026 if (inst == NULL) { 00027 inst = new USBHost(); 00028 inst->init(); 00029 } 00030 return inst; 00031 } 00032 00033 void USBHost::poll() 00034 { 00035 if (inst) { 00036 inst->task(); 00037 } 00038 } 00039 00040 USBHost::USBHost() { 00041 } 00042 00043 /* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) { 00044 USBDeviceConnected* dev = new USBDeviceConnected; 00045 USBEndpoint* ep = new USBEndpoint(dev); 00046 dev->init(0, port, lowSpeed); 00047 dev->setAddress(0); 00048 dev->setEpCtl(ep); 00049 uint8_t desc[18]; 00050 wait_ms(100); 00051 00052 int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8); 00053 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00054 if (rc != USB_TYPE_OK) { 00055 USB_ERR("ADD DEVICE FAILD"); 00056 } 00057 USB_DBG_HEX(desc, 8); 00058 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); 00059 ep->setSize(dev_desc->bMaxPacketSize); 00060 00061 int new_addr = USBDeviceConnected::getNewAddress(); 00062 rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0); 00063 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00064 dev->setAddress(new_addr); 00065 wait_ms(100); 00066 00067 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); 00068 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00069 USB_DBG_HEX(desc, sizeof(desc)); 00070 00071 dev->setVid(dev_desc->idVendor); 00072 dev->setPid(dev_desc->idProduct); 00073 dev->setClass(dev_desc->bDeviceClass); 00074 USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d", 00075 parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), 00076 dev->getAddress()); 00077 00078 DeviceLists.push_back(dev); 00079 00080 if (dev->getClass() == HUB_CLASS) { 00081 const int config = 1; 00082 int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); 00083 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00084 wait_ms(100); 00085 Hub(dev); 00086 } 00087 return true; 00088 } 00089 00090 // enumerate a device with the control USBEndpoint 00091 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) 00092 { 00093 if (dev->getClass() == HUB_CLASS) { // skip hub class 00094 return USB_TYPE_OK; 00095 } 00096 uint8_t desc[18]; 00097 USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); 00098 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00099 USB_DBG_HEX(desc, sizeof(desc)); 00100 if (rc != USB_TYPE_OK) { 00101 return rc; 00102 } 00103 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); 00104 dev->setClass(dev_desc->bDeviceClass); 00105 pEnumerator->setVidPid(dev->getVid(), dev->getPid()); 00106 00107 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4); 00108 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00109 USB_DBG_HEX(desc, 4); 00110 00111 int TotalLength = desc[2]|desc[3]<<8; 00112 uint8_t* buf = new uint8_t[TotalLength]; 00113 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength); 00114 USB_TEST_ASSERT(rc == USB_TYPE_OK); 00115 //USB_DBG_HEX(buf, TotalLength); 00116 00117 // Parse the configuration descriptor 00118 parseConfDescr(dev, buf, TotalLength, pEnumerator); 00119 delete[] buf; 00120 // only set configuration if not enumerated before 00121 if (!dev->isEnumerated()) { 00122 USB_DBG("Set configuration 1 on dev: %p", dev); 00123 // sixth step: set configuration (only 1 supported) 00124 int config = 1; 00125 USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); 00126 if (res != USB_TYPE_OK) { 00127 USB_ERR("SET CONF FAILED"); 00128 return res; 00129 } 00130 // Some devices may require this delay 00131 wait_ms(100); 00132 dev->setEnumerated(); 00133 // Now the device is enumerated! 00134 USB_DBG("dev %p is enumerated", dev); 00135 } 00136 return USB_TYPE_OK; 00137 } 00138 00139 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. 00140 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) 00141 { 00142 uint32_t index = 0; 00143 uint32_t len_desc = 0; 00144 uint8_t id = 0; 00145 USBEndpoint * ep = NULL; 00146 uint8_t intf_nb = 0; 00147 bool parsing_intf = false; 00148 uint8_t current_intf = 0; 00149 EndpointDescriptor* ep_desc; 00150 00151 while (index < len) { 00152 len_desc = conf_descr[index]; 00153 id = conf_descr[index+1]; 00154 USB_DBG_HEX(conf_descr+index, len_desc); 00155 switch (id) { 00156 case CONFIGURATION_DESCRIPTOR: 00157 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); 00158 dev->setNbIntf(conf_descr[4]); 00159 break; 00160 case INTERFACE_DESCRIPTOR: 00161 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { 00162 intf_nb++; 00163 current_intf = conf_descr[index + 2]; 00164 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); 00165 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]); 00166 parsing_intf = true; 00167 } else { 00168 parsing_intf = false; 00169 } 00170 break; 00171 case ENDPOINT_DESCRIPTOR: 00172 ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); 00173 if (parsing_intf && (intf_nb <= MAX_INTF) ) { 00174 ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); 00175 ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; 00176 if(pEnumerator->useEndpoint(current_intf, type, dir)) { 00177 ep = new USBEndpoint(dev); 00178 ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress); 00179 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); 00180 dev->addEndpoint(current_intf, ep); 00181 } 00182 } 00183 break; 00184 case HID_DESCRIPTOR: 00185 //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); 00186 break; 00187 default: 00188 break; 00189 } 00190 index += len_desc; 00191 } 00192 } 00193 00194 USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00195 USBEndpoint* ep = dev->getEpCtl(); 00196 return controlRead(ep, requestType, request, value, index, buf, len); 00197 } 00198 00199 USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) { 00200 USBEndpoint* ep = dev->getEpCtl(); 00201 return controlWrite(ep, requestType, request, value, index, buf, len); 00202 } 00203 00204 USB_TYPE USBHost::controlRead(USBEndpoint* ep, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t* buf, uint32_t len) 00205 { 00206 SETUP_PACKET setup(requestType, request, value, index, len); 00207 int result = token_setup(ep, &setup, len); // setup stage 00208 if (result < 0) { 00209 return USB_TYPE_ERROR; 00210 } 00211 00212 result = token_in(ep, buf, len); // data stage 00213 if (result < 0) { 00214 return USB_TYPE_ERROR; 00215 } 00216 int read_len = result; 00217 00218 ep->m_pED->setToggleDATA1(); 00219 result = token_out(ep); // status stage 00220 if (result < 0) { 00221 return USB_TYPE_ERROR; 00222 } 00223 ep->setLengthTransferred(read_len); 00224 return USB_TYPE_OK; 00225 } 00226 00227 USB_TYPE USBHost::controlWrite(USBEndpoint* ep, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) 00228 { 00229 SETUP_PACKET setup(requestType, request, value, index, len); 00230 int result = token_setup(ep, &setup, len); // setup stage 00231 if (result < 0) { 00232 return USB_TYPE_ERROR; 00233 } 00234 int write_len = 0; 00235 if (buf != NULL) { 00236 result = token_out(ep, buf, len); // data stage 00237 if (result < 0) { 00238 return USB_TYPE_ERROR; 00239 } 00240 write_len = result; 00241 } 00242 ep->m_pED->setToggleDATA1(); 00243 result = token_in(ep); // status stage 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) { 00253 ep->setBuffer(buf, len); 00254 ep_queue.push(ep); 00255 token_inNB(ep, buf, len); 00256 return USB_TYPE_PROCESSING; 00257 } 00258 int result = token_in(ep, buf, len); 00259 if (result >= 0) { 00260 ep->setLengthTransferred(result); 00261 return USB_TYPE_OK; 00262 } 00263 return USB_TYPE_ERROR; 00264 } 00265 00266 USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint* ep, uint8_t * buf, uint32_t len, bool blocking) 00267 { 00268 int result = token_out(ep, buf, len); 00269 if (result >= 0) { 00270 ep->setLengthTransferred(result); 00271 return USB_TYPE_OK; 00272 } 00273 return USB_TYPE_ERROR; 00274 } 00275 00276 USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { 00277 if (!blocking) { 00278 ep->setBuffer(buf, len); 00279 ep_queue.push(ep); 00280 token_inNB(ep, buf, len); 00281 return USB_TYPE_PROCESSING; 00282 } 00283 int result = token_in(ep, buf, len); 00284 if (result >= 0) { 00285 ep->setLengthTransferred(result); 00286 return USB_TYPE_OK; 00287 } 00288 return USB_TYPE_ERROR; 00289 } 00290 00291 int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) { 00292 if (ep->getState() != USB_TYPE_PROCESSING) { 00293 ep->setState(USB_TYPE_PROCESSING); 00294 ep->setBuffer(data, size); 00295 token_inNB(ep, data, size); 00296 } 00297 if (token_inNB_result(ep) != USB_TYPE_PROCESSING) { 00298 return ep->getLengthTransferred(); 00299 } 00300 return -1; 00301 } 00302 00303 int USBHost::bulkReadNB(USBEndpoint*ep, uint8_t* data, int size) { 00304 return interruptReadNB(ep, data, size); 00305 } 00306 00307 void USBHost::task() { 00308 USBEndpoint* ep = ep_queue.pop(); 00309 if (ep) { 00310 if (token_inNB_result(ep) == USB_TYPE_OK) { 00311 ep->call(); 00312 } else { 00313 ep_queue.push(ep); 00314 } 00315 } 00316 } 00317
Generated on Tue Jul 12 2022 22:44:17 by 1.7.2