Simple USBHost WebCam for EA LPC4088 QSB/LPC1768 test program

Dependencies:   LPC4088-USBHost mbed

EA LPC4088 QSB/LPC1768をUSBホストにしてWebカメラからJPEG画像を読み取るテストプログラムです。

The usage is the same as KL46Z-USBHostC270_example.
使い方はKL46Z-USBHostC270_exampleと同じです。
動作確認: Logitech C270,Logitech Q200R(Qcam Orbit AF)
/media/uploads/va009039/lpc4088-c270-480x360.jpg

Committer:
va009039
Date:
Thu Apr 24 05:38:45 2014 +0000
Revision:
0:c972ee42b455
first commit,sync rev.29.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:c972ee42b455 1 /* mbed USBHost Library
va009039 0:c972ee42b455 2 * Copyright (c) 2006-2013 ARM Limited
va009039 0:c972ee42b455 3 *
va009039 0:c972ee42b455 4 * Licensed under the Apache License, Version 2.0 (the "License");
va009039 0:c972ee42b455 5 * you may not use this file except in compliance with the License.
va009039 0:c972ee42b455 6 * You may obtain a copy of the License at
va009039 0:c972ee42b455 7 *
va009039 0:c972ee42b455 8 * http://www.apache.org/licenses/LICENSE-2.0
va009039 0:c972ee42b455 9 *
va009039 0:c972ee42b455 10 * Unless required by applicable law or agreed to in writing, software
va009039 0:c972ee42b455 11 * distributed under the License is distributed on an "AS IS" BASIS,
va009039 0:c972ee42b455 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
va009039 0:c972ee42b455 13 * See the License for the specific language governing permissions and
va009039 0:c972ee42b455 14 * limitations under the License.
va009039 0:c972ee42b455 15 */
va009039 0:c972ee42b455 16
va009039 0:c972ee42b455 17 #include "USBHost.h"
va009039 0:c972ee42b455 18 #define USB_DEBUG
va009039 0:c972ee42b455 19 #include "BaseUsbHostDebug.h"
va009039 0:c972ee42b455 20 #define TEST
va009039 0:c972ee42b455 21 #include "BaseUsbHostTest.h"
va009039 0:c972ee42b455 22
va009039 0:c972ee42b455 23 USBHost* USBHost::inst = NULL;
va009039 0:c972ee42b455 24
va009039 0:c972ee42b455 25 USBHost* USBHost::getHostInst() {
va009039 0:c972ee42b455 26 if (inst == NULL) {
va009039 0:c972ee42b455 27 inst = new USBHost();
va009039 0:c972ee42b455 28 inst->init();
va009039 0:c972ee42b455 29 }
va009039 0:c972ee42b455 30 return inst;
va009039 0:c972ee42b455 31 }
va009039 0:c972ee42b455 32
va009039 0:c972ee42b455 33 void USBHost::poll()
va009039 0:c972ee42b455 34 {
va009039 0:c972ee42b455 35 if (inst) {
va009039 0:c972ee42b455 36 inst->task();
va009039 0:c972ee42b455 37 }
va009039 0:c972ee42b455 38 }
va009039 0:c972ee42b455 39
va009039 0:c972ee42b455 40 USBHost::USBHost() {
va009039 0:c972ee42b455 41 }
va009039 0:c972ee42b455 42
va009039 0:c972ee42b455 43 /* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) {
va009039 0:c972ee42b455 44 USBDeviceConnected* dev = new USBDeviceConnected;
va009039 0:c972ee42b455 45 USBEndpoint* ep = new USBEndpoint(dev);
va009039 0:c972ee42b455 46 dev->init(0, port, lowSpeed);
va009039 0:c972ee42b455 47 dev->setAddress(0);
va009039 0:c972ee42b455 48 dev->setEpCtl(ep);
va009039 0:c972ee42b455 49 uint8_t desc[18];
va009039 0:c972ee42b455 50 wait_ms(100);
va009039 0:c972ee42b455 51
va009039 0:c972ee42b455 52 int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8);
va009039 0:c972ee42b455 53 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 0:c972ee42b455 54 if (rc != USB_TYPE_OK) {
va009039 0:c972ee42b455 55 USB_ERR("ADD DEVICE FAILD");
va009039 0:c972ee42b455 56 }
va009039 0:c972ee42b455 57 USB_DBG_HEX(desc, 8);
va009039 0:c972ee42b455 58 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
va009039 0:c972ee42b455 59 ep->setSize(dev_desc->bMaxPacketSize);
va009039 0:c972ee42b455 60
va009039 0:c972ee42b455 61 int new_addr = USBDeviceConnected::getNewAddress();
va009039 0:c972ee42b455 62 rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0);
va009039 0:c972ee42b455 63 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 0:c972ee42b455 64 dev->setAddress(new_addr);
va009039 0:c972ee42b455 65 wait_ms(100);
va009039 0:c972ee42b455 66
va009039 0:c972ee42b455 67 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
va009039 0:c972ee42b455 68 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 0:c972ee42b455 69 USB_DBG_HEX(desc, sizeof(desc));
va009039 0:c972ee42b455 70
va009039 0:c972ee42b455 71 dev->setVid(dev_desc->idVendor);
va009039 0:c972ee42b455 72 dev->setPid(dev_desc->idProduct);
va009039 0:c972ee42b455 73 dev->setClass(dev_desc->bDeviceClass);
va009039 0:c972ee42b455 74 USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d",
va009039 0:c972ee42b455 75 parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(),
va009039 0:c972ee42b455 76 dev->getAddress());
va009039 0:c972ee42b455 77
va009039 0:c972ee42b455 78 DeviceLists.push_back(dev);
va009039 0:c972ee42b455 79
va009039 0:c972ee42b455 80 if (dev->getClass() == HUB_CLASS) {
va009039 0:c972ee42b455 81 const int config = 1;
va009039 0:c972ee42b455 82 int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
va009039 0:c972ee42b455 83 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 0:c972ee42b455 84 wait_ms(100);
va009039 0:c972ee42b455 85 Hub(dev);
va009039 0:c972ee42b455 86 }
va009039 0:c972ee42b455 87 return true;
va009039 0:c972ee42b455 88 }
va009039 0:c972ee42b455 89
va009039 0:c972ee42b455 90 // enumerate a device with the control USBEndpoint
va009039 0:c972ee42b455 91 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
va009039 0:c972ee42b455 92 {
va009039 0:c972ee42b455 93 if (dev->getClass() == HUB_CLASS) { // skip hub class
va009039 0:c972ee42b455 94 return USB_TYPE_OK;
va009039 0:c972ee42b455 95 }
va009039 0:c972ee42b455 96 uint8_t desc[18];
va009039 0:c972ee42b455 97 USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
va009039 0:c972ee42b455 98 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 0:c972ee42b455 99 USB_DBG_HEX(desc, sizeof(desc));
va009039 0:c972ee42b455 100 if (rc != USB_TYPE_OK) {
va009039 0:c972ee42b455 101 return rc;
va009039 0:c972ee42b455 102 }
va009039 0:c972ee42b455 103 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
va009039 0:c972ee42b455 104 dev->setClass(dev_desc->bDeviceClass);
va009039 0:c972ee42b455 105 pEnumerator->setVidPid(dev->getVid(), dev->getPid());
va009039 0:c972ee42b455 106
va009039 0:c972ee42b455 107 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4);
va009039 0:c972ee42b455 108 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 0:c972ee42b455 109 USB_DBG_HEX(desc, 4);
va009039 0:c972ee42b455 110
va009039 0:c972ee42b455 111 int TotalLength = desc[2]|desc[3]<<8;
va009039 0:c972ee42b455 112 uint8_t* buf = new uint8_t[TotalLength];
va009039 0:c972ee42b455 113 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength);
va009039 0:c972ee42b455 114 USB_TEST_ASSERT(rc == USB_TYPE_OK);
va009039 0:c972ee42b455 115 //USB_DBG_HEX(buf, TotalLength);
va009039 0:c972ee42b455 116
va009039 0:c972ee42b455 117 // Parse the configuration descriptor
va009039 0:c972ee42b455 118 parseConfDescr(dev, buf, TotalLength, pEnumerator);
va009039 0:c972ee42b455 119 delete[] buf;
va009039 0:c972ee42b455 120 // only set configuration if not enumerated before
va009039 0:c972ee42b455 121 if (!dev->isEnumerated()) {
va009039 0:c972ee42b455 122 USB_DBG("Set configuration 1 on dev: %p", dev);
va009039 0:c972ee42b455 123 // sixth step: set configuration (only 1 supported)
va009039 0:c972ee42b455 124 int config = 1;
va009039 0:c972ee42b455 125 USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
va009039 0:c972ee42b455 126 if (res != USB_TYPE_OK) {
va009039 0:c972ee42b455 127 USB_ERR("SET CONF FAILED");
va009039 0:c972ee42b455 128 return res;
va009039 0:c972ee42b455 129 }
va009039 0:c972ee42b455 130 // Some devices may require this delay
va009039 0:c972ee42b455 131 wait_ms(100);
va009039 0:c972ee42b455 132 dev->setEnumerated();
va009039 0:c972ee42b455 133 // Now the device is enumerated!
va009039 0:c972ee42b455 134 USB_DBG("dev %p is enumerated", dev);
va009039 0:c972ee42b455 135 }
va009039 0:c972ee42b455 136 return USB_TYPE_OK;
va009039 0:c972ee42b455 137 }
va009039 0:c972ee42b455 138
va009039 0:c972ee42b455 139 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
va009039 0:c972ee42b455 140 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator)
va009039 0:c972ee42b455 141 {
va009039 0:c972ee42b455 142 uint32_t index = 0;
va009039 0:c972ee42b455 143 uint32_t len_desc = 0;
va009039 0:c972ee42b455 144 uint8_t id = 0;
va009039 0:c972ee42b455 145 USBEndpoint * ep = NULL;
va009039 0:c972ee42b455 146 uint8_t intf_nb = 0;
va009039 0:c972ee42b455 147 bool parsing_intf = false;
va009039 0:c972ee42b455 148 uint8_t current_intf = 0;
va009039 0:c972ee42b455 149 EndpointDescriptor* ep_desc;
va009039 0:c972ee42b455 150
va009039 0:c972ee42b455 151 while (index < len) {
va009039 0:c972ee42b455 152 len_desc = conf_descr[index];
va009039 0:c972ee42b455 153 id = conf_descr[index+1];
va009039 0:c972ee42b455 154 USB_DBG_HEX(conf_descr+index, len_desc);
va009039 0:c972ee42b455 155 switch (id) {
va009039 0:c972ee42b455 156 case CONFIGURATION_DESCRIPTOR:
va009039 0:c972ee42b455 157 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]);
va009039 0:c972ee42b455 158 dev->setNbIntf(conf_descr[4]);
va009039 0:c972ee42b455 159 break;
va009039 0:c972ee42b455 160 case INTERFACE_DESCRIPTOR:
va009039 0:c972ee42b455 161 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
va009039 0:c972ee42b455 162 intf_nb++;
va009039 0:c972ee42b455 163 current_intf = conf_descr[index + 2];
va009039 0:c972ee42b455 164 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
va009039 0:c972ee42b455 165 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]);
va009039 0:c972ee42b455 166 parsing_intf = true;
va009039 0:c972ee42b455 167 } else {
va009039 0:c972ee42b455 168 parsing_intf = false;
va009039 0:c972ee42b455 169 }
va009039 0:c972ee42b455 170 break;
va009039 0:c972ee42b455 171 case ENDPOINT_DESCRIPTOR:
va009039 0:c972ee42b455 172 ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index);
va009039 0:c972ee42b455 173 if (parsing_intf && (intf_nb <= MAX_INTF) ) {
va009039 0:c972ee42b455 174 ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03);
va009039 0:c972ee42b455 175 ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT;
va009039 0:c972ee42b455 176 if(pEnumerator->useEndpoint(current_intf, type, dir)) {
va009039 0:c972ee42b455 177 ep = new USBEndpoint(dev);
va009039 0:c972ee42b455 178 ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress);
va009039 0:c972ee42b455 179 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev);
va009039 0:c972ee42b455 180 dev->addEndpoint(current_intf, ep);
va009039 0:c972ee42b455 181 }
va009039 0:c972ee42b455 182 }
va009039 0:c972ee42b455 183 break;
va009039 0:c972ee42b455 184 case HID_DESCRIPTOR:
va009039 0:c972ee42b455 185 //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
va009039 0:c972ee42b455 186 break;
va009039 0:c972ee42b455 187 default:
va009039 0:c972ee42b455 188 break;
va009039 0:c972ee42b455 189 }
va009039 0:c972ee42b455 190 index += len_desc;
va009039 0:c972ee42b455 191 }
va009039 0:c972ee42b455 192 }
va009039 0:c972ee42b455 193
va009039 0:c972ee42b455 194 USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
va009039 0:c972ee42b455 195 USBEndpoint* ep = dev->getEpCtl();
va009039 0:c972ee42b455 196 return controlRead(ep, requestType, request, value, index, buf, len);
va009039 0:c972ee42b455 197 }
va009039 0:c972ee42b455 198
va009039 0:c972ee42b455 199 USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
va009039 0:c972ee42b455 200 USBEndpoint* ep = dev->getEpCtl();
va009039 0:c972ee42b455 201 return controlWrite(ep, requestType, request, value, index, buf, len);
va009039 0:c972ee42b455 202 }
va009039 0:c972ee42b455 203
va009039 0:c972ee42b455 204 USB_TYPE USBHost::controlRead(USBEndpoint* ep, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t* buf, uint32_t len)
va009039 0:c972ee42b455 205 {
va009039 0:c972ee42b455 206 SETUP_PACKET setup(requestType, request, value, index, len);
va009039 0:c972ee42b455 207 int result = token_setup(ep, &setup, len); // setup stage
va009039 0:c972ee42b455 208 if (result < 0) {
va009039 0:c972ee42b455 209 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 210 }
va009039 0:c972ee42b455 211
va009039 0:c972ee42b455 212 result = token_in(ep, buf, len); // data stage
va009039 0:c972ee42b455 213 if (result < 0) {
va009039 0:c972ee42b455 214 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 215 }
va009039 0:c972ee42b455 216 int read_len = result;
va009039 0:c972ee42b455 217
va009039 0:c972ee42b455 218 ep->m_pED->setToggleDATA1();
va009039 0:c972ee42b455 219 result = token_out(ep); // status stage
va009039 0:c972ee42b455 220 if (result < 0) {
va009039 0:c972ee42b455 221 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 222 }
va009039 0:c972ee42b455 223 ep->setLengthTransferred(read_len);
va009039 0:c972ee42b455 224 return USB_TYPE_OK;
va009039 0:c972ee42b455 225 }
va009039 0:c972ee42b455 226
va009039 0:c972ee42b455 227 USB_TYPE USBHost::controlWrite(USBEndpoint* ep, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len)
va009039 0:c972ee42b455 228 {
va009039 0:c972ee42b455 229 SETUP_PACKET setup(requestType, request, value, index, len);
va009039 0:c972ee42b455 230 int result = token_setup(ep, &setup, len); // setup stage
va009039 0:c972ee42b455 231 if (result < 0) {
va009039 0:c972ee42b455 232 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 233 }
va009039 0:c972ee42b455 234 int write_len = 0;
va009039 0:c972ee42b455 235 if (buf != NULL) {
va009039 0:c972ee42b455 236 result = token_out(ep, buf, len); // data stage
va009039 0:c972ee42b455 237 if (result < 0) {
va009039 0:c972ee42b455 238 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 239 }
va009039 0:c972ee42b455 240 write_len = result;
va009039 0:c972ee42b455 241 }
va009039 0:c972ee42b455 242 ep->m_pED->setToggleDATA1();
va009039 0:c972ee42b455 243 result = token_in(ep); // status stage
va009039 0:c972ee42b455 244 if (result < 0) {
va009039 0:c972ee42b455 245 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 246 }
va009039 0:c972ee42b455 247 ep->setLengthTransferred(write_len);
va009039 0:c972ee42b455 248 return USB_TYPE_OK;
va009039 0:c972ee42b455 249 }
va009039 0:c972ee42b455 250
va009039 0:c972ee42b455 251 USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
va009039 0:c972ee42b455 252 if (!blocking) {
va009039 0:c972ee42b455 253 ep->setBuffer(buf, len);
va009039 0:c972ee42b455 254 ep_queue.push(ep);
va009039 0:c972ee42b455 255 token_inNB(ep, buf, len);
va009039 0:c972ee42b455 256 return USB_TYPE_PROCESSING;
va009039 0:c972ee42b455 257 }
va009039 0:c972ee42b455 258 int result = token_in(ep, buf, len);
va009039 0:c972ee42b455 259 if (result >= 0) {
va009039 0:c972ee42b455 260 ep->setLengthTransferred(result);
va009039 0:c972ee42b455 261 return USB_TYPE_OK;
va009039 0:c972ee42b455 262 }
va009039 0:c972ee42b455 263 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 264 }
va009039 0:c972ee42b455 265
va009039 0:c972ee42b455 266 USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint* ep, uint8_t * buf, uint32_t len, bool blocking)
va009039 0:c972ee42b455 267 {
va009039 0:c972ee42b455 268 int result = token_out(ep, buf, len);
va009039 0:c972ee42b455 269 if (result >= 0) {
va009039 0:c972ee42b455 270 ep->setLengthTransferred(result);
va009039 0:c972ee42b455 271 return USB_TYPE_OK;
va009039 0:c972ee42b455 272 }
va009039 0:c972ee42b455 273 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 274 }
va009039 0:c972ee42b455 275
va009039 0:c972ee42b455 276 USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
va009039 0:c972ee42b455 277 if (!blocking) {
va009039 0:c972ee42b455 278 ep->setBuffer(buf, len);
va009039 0:c972ee42b455 279 ep_queue.push(ep);
va009039 0:c972ee42b455 280 token_inNB(ep, buf, len);
va009039 0:c972ee42b455 281 return USB_TYPE_PROCESSING;
va009039 0:c972ee42b455 282 }
va009039 0:c972ee42b455 283 int result = token_in(ep, buf, len);
va009039 0:c972ee42b455 284 if (result >= 0) {
va009039 0:c972ee42b455 285 ep->setLengthTransferred(result);
va009039 0:c972ee42b455 286 return USB_TYPE_OK;
va009039 0:c972ee42b455 287 }
va009039 0:c972ee42b455 288 return USB_TYPE_ERROR;
va009039 0:c972ee42b455 289 }
va009039 0:c972ee42b455 290
va009039 0:c972ee42b455 291 void USBHost::task() {
va009039 0:c972ee42b455 292 USBEndpoint* ep = ep_queue.pop();
va009039 0:c972ee42b455 293 if (ep) {
va009039 0:c972ee42b455 294 if (token_inNB_result(ep) == USB_TYPE_OK) {
va009039 0:c972ee42b455 295 ep->call();
va009039 0:c972ee42b455 296 } else {
va009039 0:c972ee42b455 297 ep_queue.push(ep);
va009039 0:c972ee42b455 298 }
va009039 0:c972ee42b455 299 }
va009039 0:c972ee42b455 300 }
va009039 0:c972ee42b455 301