Simple USBHost library for STM32F746NG Discovery board. Only either the Fastspeed or the Highspeed port can be used( not both together)
Dependents: DISCO-F746NG_USB_Host
Fork of KL46Z-USBHost by
USBHost/USBHost.cpp@24:5396b6a93262, 2016-06-13 (annotated)
- Committer:
- DieterGraef
- Date:
- Mon Jun 13 17:21:07 2016 +0000
- Revision:
- 24:5396b6a93262
- Parent:
- 18:61554f238584
- Child:
- 25:7d6d9fc471bf
USB Host for STM32F746 DISCO Board. At the moment you can only use either the High Speed Port or the Fast Speed Port.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 |
18:61554f238584 | 1 | /* mbed USBHost Library |
va009039 |
18:61554f238584 | 2 | * Copyright (c) 2006-2013 ARM Limited |
va009039 |
18:61554f238584 | 3 | * |
va009039 |
18:61554f238584 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
va009039 |
18:61554f238584 | 5 | * you may not use this file except in compliance with the License. |
va009039 |
18:61554f238584 | 6 | * You may obtain a copy of the License at |
va009039 |
18:61554f238584 | 7 | * |
va009039 |
18:61554f238584 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
va009039 |
18:61554f238584 | 9 | * |
va009039 |
18:61554f238584 | 10 | * Unless required by applicable law or agreed to in writing, software |
va009039 |
18:61554f238584 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
va009039 |
18:61554f238584 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
va009039 |
18:61554f238584 | 13 | * See the License for the specific language governing permissions and |
va009039 |
18:61554f238584 | 14 | * limitations under the License. |
va009039 |
18:61554f238584 | 15 | */ |
va009039 |
18:61554f238584 | 16 | |
va009039 | 12:b91fdea8c0a7 | 17 | #include "USBHost.h" |
va009039 | 12:b91fdea8c0a7 | 18 | |
va009039 |
18:61554f238584 | 19 | #define USB_TRACE1(A) while(0) |
va009039 |
18:61554f238584 | 20 | #undef USB_TEST_ASSERT |
va009039 |
18:61554f238584 | 21 | void usb_test_assert_internal(const char *expr, const char *file, int line); |
va009039 |
18:61554f238584 | 22 | #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} |
va009039 |
18:61554f238584 | 23 | |
va009039 | 12:b91fdea8c0a7 | 24 | USBHost* USBHost::inst = NULL; |
va009039 | 12:b91fdea8c0a7 | 25 | |
DieterGraef | 24:5396b6a93262 | 26 | USBHost* USBHost::getHostInst(int IF_Number) { |
va009039 | 12:b91fdea8c0a7 | 27 | if (inst == NULL) { |
DieterGraef | 24:5396b6a93262 | 28 | inst = new USBHost(IF_Number); |
DieterGraef | 24:5396b6a93262 | 29 | inst->init(); |
DieterGraef | 24:5396b6a93262 | 30 | } |
DieterGraef | 24:5396b6a93262 | 31 | if(inst->IF_N!=IF_Number) { |
DieterGraef | 24:5396b6a93262 | 32 | inst = new USBHost(IF_Number); |
va009039 | 12:b91fdea8c0a7 | 33 | inst->init(); |
va009039 | 12:b91fdea8c0a7 | 34 | } |
va009039 | 12:b91fdea8c0a7 | 35 | return inst; |
va009039 | 12:b91fdea8c0a7 | 36 | } |
va009039 | 12:b91fdea8c0a7 | 37 | |
va009039 | 12:b91fdea8c0a7 | 38 | void USBHost::poll() |
va009039 | 12:b91fdea8c0a7 | 39 | { |
va009039 | 12:b91fdea8c0a7 | 40 | if (inst) { |
va009039 | 12:b91fdea8c0a7 | 41 | inst->task(); |
va009039 | 12:b91fdea8c0a7 | 42 | } |
va009039 | 12:b91fdea8c0a7 | 43 | } |
va009039 | 12:b91fdea8c0a7 | 44 | |
DieterGraef | 24:5396b6a93262 | 45 | USBHost::USBHost(int InterfaceNumber):USBHALHost(InterfaceNumber) { |
DieterGraef | 24:5396b6a93262 | 46 | |
va009039 | 12:b91fdea8c0a7 | 47 | } |
va009039 | 12:b91fdea8c0a7 | 48 | |
va009039 | 12:b91fdea8c0a7 | 49 | /* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) { |
va009039 | 12:b91fdea8c0a7 | 50 | USBDeviceConnected* dev = new USBDeviceConnected; |
va009039 | 12:b91fdea8c0a7 | 51 | USBEndpoint* ep = new USBEndpoint(dev); |
va009039 | 12:b91fdea8c0a7 | 52 | dev->init(0, port, lowSpeed); |
va009039 | 12:b91fdea8c0a7 | 53 | dev->setAddress(0); |
va009039 | 12:b91fdea8c0a7 | 54 | dev->setEpCtl(ep); |
va009039 | 12:b91fdea8c0a7 | 55 | uint8_t desc[18]; |
va009039 | 12:b91fdea8c0a7 | 56 | wait_ms(100); |
va009039 | 12:b91fdea8c0a7 | 57 | |
va009039 | 12:b91fdea8c0a7 | 58 | int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8); |
va009039 | 12:b91fdea8c0a7 | 59 | USB_TEST_ASSERT(rc == USB_TYPE_OK); |
va009039 | 12:b91fdea8c0a7 | 60 | if (rc != USB_TYPE_OK) { |
va009039 | 12:b91fdea8c0a7 | 61 | USB_ERR("ADD DEVICE FAILD"); |
va009039 | 12:b91fdea8c0a7 | 62 | } |
va009039 | 12:b91fdea8c0a7 | 63 | USB_DBG_HEX(desc, 8); |
va009039 | 12:b91fdea8c0a7 | 64 | DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); |
va009039 | 12:b91fdea8c0a7 | 65 | ep->setSize(dev_desc->bMaxPacketSize); |
va009039 | 12:b91fdea8c0a7 | 66 | |
va009039 | 12:b91fdea8c0a7 | 67 | int new_addr = USBDeviceConnected::getNewAddress(); |
va009039 | 12:b91fdea8c0a7 | 68 | rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0); |
va009039 | 12:b91fdea8c0a7 | 69 | USB_TEST_ASSERT(rc == USB_TYPE_OK); |
va009039 | 12:b91fdea8c0a7 | 70 | dev->setAddress(new_addr); |
va009039 | 12:b91fdea8c0a7 | 71 | wait_ms(100); |
va009039 | 12:b91fdea8c0a7 | 72 | |
va009039 | 12:b91fdea8c0a7 | 73 | rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); |
va009039 | 12:b91fdea8c0a7 | 74 | USB_TEST_ASSERT(rc == USB_TYPE_OK); |
va009039 | 12:b91fdea8c0a7 | 75 | USB_DBG_HEX(desc, sizeof(desc)); |
va009039 | 12:b91fdea8c0a7 | 76 | |
va009039 | 12:b91fdea8c0a7 | 77 | dev->setVid(dev_desc->idVendor); |
va009039 | 12:b91fdea8c0a7 | 78 | dev->setPid(dev_desc->idProduct); |
va009039 | 12:b91fdea8c0a7 | 79 | dev->setClass(dev_desc->bDeviceClass); |
va009039 | 12:b91fdea8c0a7 | 80 | USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d", |
va009039 | 12:b91fdea8c0a7 | 81 | parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), |
va009039 | 12:b91fdea8c0a7 | 82 | dev->getAddress()); |
va009039 | 12:b91fdea8c0a7 | 83 | |
va009039 | 12:b91fdea8c0a7 | 84 | DeviceLists.push_back(dev); |
va009039 | 12:b91fdea8c0a7 | 85 | |
va009039 | 12:b91fdea8c0a7 | 86 | if (dev->getClass() == HUB_CLASS) { |
va009039 | 12:b91fdea8c0a7 | 87 | const int config = 1; |
va009039 | 12:b91fdea8c0a7 | 88 | int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); |
va009039 | 12:b91fdea8c0a7 | 89 | USB_TEST_ASSERT(rc == USB_TYPE_OK); |
va009039 | 12:b91fdea8c0a7 | 90 | wait_ms(100); |
va009039 | 12:b91fdea8c0a7 | 91 | Hub(dev); |
va009039 | 12:b91fdea8c0a7 | 92 | } |
va009039 | 12:b91fdea8c0a7 | 93 | return true; |
va009039 | 12:b91fdea8c0a7 | 94 | } |
va009039 | 12:b91fdea8c0a7 | 95 | |
va009039 | 12:b91fdea8c0a7 | 96 | // enumerate a device with the control USBEndpoint |
va009039 | 12:b91fdea8c0a7 | 97 | USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) |
va009039 | 12:b91fdea8c0a7 | 98 | { |
va009039 | 12:b91fdea8c0a7 | 99 | if (dev->getClass() == HUB_CLASS) { // skip hub class |
va009039 | 12:b91fdea8c0a7 | 100 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 101 | } |
va009039 | 12:b91fdea8c0a7 | 102 | uint8_t desc[18]; |
va009039 | 12:b91fdea8c0a7 | 103 | USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc)); |
va009039 | 12:b91fdea8c0a7 | 104 | USB_TEST_ASSERT(rc == USB_TYPE_OK); |
va009039 | 12:b91fdea8c0a7 | 105 | USB_DBG_HEX(desc, sizeof(desc)); |
va009039 | 12:b91fdea8c0a7 | 106 | if (rc != USB_TYPE_OK) { |
va009039 | 12:b91fdea8c0a7 | 107 | return rc; |
va009039 | 12:b91fdea8c0a7 | 108 | } |
va009039 | 12:b91fdea8c0a7 | 109 | DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc); |
va009039 | 12:b91fdea8c0a7 | 110 | dev->setClass(dev_desc->bDeviceClass); |
va009039 | 12:b91fdea8c0a7 | 111 | pEnumerator->setVidPid(dev->getVid(), dev->getPid()); |
va009039 | 12:b91fdea8c0a7 | 112 | |
va009039 | 12:b91fdea8c0a7 | 113 | rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4); |
va009039 | 12:b91fdea8c0a7 | 114 | USB_TEST_ASSERT(rc == USB_TYPE_OK); |
va009039 | 12:b91fdea8c0a7 | 115 | USB_DBG_HEX(desc, 4); |
va009039 | 12:b91fdea8c0a7 | 116 | |
va009039 | 12:b91fdea8c0a7 | 117 | int TotalLength = desc[2]|desc[3]<<8; |
va009039 | 12:b91fdea8c0a7 | 118 | uint8_t* buf = new uint8_t[TotalLength]; |
va009039 | 12:b91fdea8c0a7 | 119 | rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength); |
va009039 | 12:b91fdea8c0a7 | 120 | USB_TEST_ASSERT(rc == USB_TYPE_OK); |
va009039 | 12:b91fdea8c0a7 | 121 | //USB_DBG_HEX(buf, TotalLength); |
va009039 | 12:b91fdea8c0a7 | 122 | |
va009039 | 12:b91fdea8c0a7 | 123 | // Parse the configuration descriptor |
va009039 | 12:b91fdea8c0a7 | 124 | parseConfDescr(dev, buf, TotalLength, pEnumerator); |
va009039 | 12:b91fdea8c0a7 | 125 | delete[] buf; |
va009039 | 12:b91fdea8c0a7 | 126 | // only set configuration if not enumerated before |
va009039 | 12:b91fdea8c0a7 | 127 | if (!dev->isEnumerated()) { |
va009039 | 12:b91fdea8c0a7 | 128 | USB_DBG("Set configuration 1 on dev: %p", dev); |
va009039 | 12:b91fdea8c0a7 | 129 | // sixth step: set configuration (only 1 supported) |
va009039 | 12:b91fdea8c0a7 | 130 | int config = 1; |
va009039 | 12:b91fdea8c0a7 | 131 | USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0); |
va009039 | 12:b91fdea8c0a7 | 132 | if (res != USB_TYPE_OK) { |
va009039 | 12:b91fdea8c0a7 | 133 | USB_ERR("SET CONF FAILED"); |
va009039 | 12:b91fdea8c0a7 | 134 | return res; |
va009039 | 12:b91fdea8c0a7 | 135 | } |
va009039 | 12:b91fdea8c0a7 | 136 | // Some devices may require this delay |
va009039 | 12:b91fdea8c0a7 | 137 | wait_ms(100); |
va009039 | 12:b91fdea8c0a7 | 138 | dev->setEnumerated(); |
va009039 | 12:b91fdea8c0a7 | 139 | // Now the device is enumerated! |
va009039 | 12:b91fdea8c0a7 | 140 | USB_DBG("dev %p is enumerated", dev); |
va009039 | 12:b91fdea8c0a7 | 141 | } |
va009039 | 12:b91fdea8c0a7 | 142 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 143 | } |
va009039 | 12:b91fdea8c0a7 | 144 | |
va009039 | 12:b91fdea8c0a7 | 145 | // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. |
va009039 | 12:b91fdea8c0a7 | 146 | void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) |
va009039 | 12:b91fdea8c0a7 | 147 | { |
va009039 | 12:b91fdea8c0a7 | 148 | uint32_t index = 0; |
va009039 | 12:b91fdea8c0a7 | 149 | uint32_t len_desc = 0; |
va009039 | 12:b91fdea8c0a7 | 150 | uint8_t id = 0; |
va009039 | 12:b91fdea8c0a7 | 151 | USBEndpoint * ep = NULL; |
va009039 | 12:b91fdea8c0a7 | 152 | uint8_t intf_nb = 0; |
va009039 | 12:b91fdea8c0a7 | 153 | bool parsing_intf = false; |
va009039 | 12:b91fdea8c0a7 | 154 | uint8_t current_intf = 0; |
va009039 | 12:b91fdea8c0a7 | 155 | EndpointDescriptor* ep_desc; |
DieterGraef | 24:5396b6a93262 | 156 | int epsetup; |
va009039 | 12:b91fdea8c0a7 | 157 | |
va009039 | 12:b91fdea8c0a7 | 158 | while (index < len) { |
va009039 | 12:b91fdea8c0a7 | 159 | len_desc = conf_descr[index]; |
va009039 | 12:b91fdea8c0a7 | 160 | id = conf_descr[index+1]; |
va009039 | 12:b91fdea8c0a7 | 161 | USB_DBG_HEX(conf_descr+index, len_desc); |
va009039 | 12:b91fdea8c0a7 | 162 | switch (id) { |
va009039 | 12:b91fdea8c0a7 | 163 | case CONFIGURATION_DESCRIPTOR: |
va009039 | 12:b91fdea8c0a7 | 164 | USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); |
va009039 | 12:b91fdea8c0a7 | 165 | dev->setNbIntf(conf_descr[4]); |
va009039 | 12:b91fdea8c0a7 | 166 | break; |
va009039 | 12:b91fdea8c0a7 | 167 | case INTERFACE_DESCRIPTOR: |
va009039 | 12:b91fdea8c0a7 | 168 | if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { |
va009039 | 12:b91fdea8c0a7 | 169 | intf_nb++; |
va009039 | 12:b91fdea8c0a7 | 170 | current_intf = conf_descr[index + 2]; |
va009039 | 12:b91fdea8c0a7 | 171 | dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); |
va009039 | 12:b91fdea8c0a7 | 172 | 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 | 12:b91fdea8c0a7 | 173 | parsing_intf = true; |
va009039 | 12:b91fdea8c0a7 | 174 | } else { |
va009039 | 12:b91fdea8c0a7 | 175 | parsing_intf = false; |
va009039 | 12:b91fdea8c0a7 | 176 | } |
va009039 | 12:b91fdea8c0a7 | 177 | break; |
va009039 | 12:b91fdea8c0a7 | 178 | case ENDPOINT_DESCRIPTOR: |
va009039 | 12:b91fdea8c0a7 | 179 | ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); |
va009039 | 12:b91fdea8c0a7 | 180 | if (parsing_intf && (intf_nb <= MAX_INTF) ) { |
va009039 | 12:b91fdea8c0a7 | 181 | ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); |
va009039 | 12:b91fdea8c0a7 | 182 | ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; |
va009039 | 12:b91fdea8c0a7 | 183 | if(pEnumerator->useEndpoint(current_intf, type, dir)) { |
va009039 | 12:b91fdea8c0a7 | 184 | ep = new USBEndpoint(dev); |
va009039 | 12:b91fdea8c0a7 | 185 | ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress); |
va009039 | 12:b91fdea8c0a7 | 186 | USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); |
va009039 | 12:b91fdea8c0a7 | 187 | dev->addEndpoint(current_intf, ep); |
DieterGraef | 24:5396b6a93262 | 188 | epsetup=epint_setup(ep); |
va009039 | 12:b91fdea8c0a7 | 189 | } |
va009039 | 12:b91fdea8c0a7 | 190 | } |
va009039 | 12:b91fdea8c0a7 | 191 | break; |
va009039 | 12:b91fdea8c0a7 | 192 | case HID_DESCRIPTOR: |
va009039 | 12:b91fdea8c0a7 | 193 | //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8); |
va009039 | 12:b91fdea8c0a7 | 194 | break; |
va009039 | 12:b91fdea8c0a7 | 195 | default: |
va009039 | 12:b91fdea8c0a7 | 196 | break; |
va009039 | 12:b91fdea8c0a7 | 197 | } |
va009039 | 12:b91fdea8c0a7 | 198 | index += len_desc; |
va009039 | 12:b91fdea8c0a7 | 199 | } |
va009039 | 12:b91fdea8c0a7 | 200 | } |
va009039 | 12:b91fdea8c0a7 | 201 | |
va009039 | 12:b91fdea8c0a7 | 202 | 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 |
18:61554f238584 | 203 | USBEndpoint* ep = dev->getEpCtl(); |
va009039 |
18:61554f238584 | 204 | SETUP_PACKET setup(requestType, request, value, index, len); |
va009039 |
18:61554f238584 | 205 | |
va009039 |
18:61554f238584 | 206 | int result = token_setup(ep, &setup, len); // setup stage |
va009039 |
18:61554f238584 | 207 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 208 | if (result < 0) { |
va009039 |
18:61554f238584 | 209 | return USB_TYPE_ERROR; |
va009039 |
18:61554f238584 | 210 | } |
va009039 |
18:61554f238584 | 211 | |
va009039 |
18:61554f238584 | 212 | int read_len = multi_token_in(ep, buf, len); // data stage |
va009039 |
18:61554f238584 | 213 | USB_TRACE1(read_len); |
va009039 |
18:61554f238584 | 214 | if (read_len < 0) { |
va009039 |
18:61554f238584 | 215 | return USB_TYPE_ERROR; |
va009039 |
18:61554f238584 | 216 | } |
va009039 |
18:61554f238584 | 217 | |
va009039 |
18:61554f238584 | 218 | setToggle(ep, 1); // DATA1 |
va009039 |
18:61554f238584 | 219 | result = multi_token_out(ep); // status stage |
va009039 |
18:61554f238584 | 220 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 221 | if (result < 0) { |
va009039 |
18:61554f238584 | 222 | return USB_TYPE_ERROR; |
va009039 |
18:61554f238584 | 223 | } |
va009039 |
18:61554f238584 | 224 | ep->setLengthTransferred(read_len); |
va009039 |
18:61554f238584 | 225 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 226 | } |
va009039 | 12:b91fdea8c0a7 | 227 | |
va009039 | 12:b91fdea8c0a7 | 228 | 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 |
18:61554f238584 | 229 | USBEndpoint* ep = dev->getEpCtl(); |
va009039 |
18:61554f238584 | 230 | SETUP_PACKET setup(requestType, request, value, index, len); |
va009039 |
18:61554f238584 | 231 | |
va009039 |
18:61554f238584 | 232 | int result = token_setup(ep, &setup, len); // setup stage |
va009039 |
18:61554f238584 | 233 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 234 | if (result < 0) { |
va009039 |
18:61554f238584 | 235 | return USB_TYPE_ERROR; |
va009039 | 12:b91fdea8c0a7 | 236 | } |
va009039 |
18:61554f238584 | 237 | int write_len = 0; |
va009039 |
18:61554f238584 | 238 | if (buf != NULL) { |
va009039 |
18:61554f238584 | 239 | write_len = multi_token_out(ep, buf, len); // data stage |
va009039 |
18:61554f238584 | 240 | USB_TRACE1(write_len); |
va009039 |
18:61554f238584 | 241 | if (write_len < 0) { |
va009039 |
18:61554f238584 | 242 | return USB_TYPE_ERROR; |
va009039 |
18:61554f238584 | 243 | } |
va009039 |
18:61554f238584 | 244 | } |
va009039 |
18:61554f238584 | 245 | |
va009039 |
18:61554f238584 | 246 | setToggle(ep, 1); // DATA1 |
va009039 |
18:61554f238584 | 247 | result = multi_token_in(ep); // status stage |
va009039 |
18:61554f238584 | 248 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 249 | if (result < 0) { |
va009039 |
18:61554f238584 | 250 | return USB_TYPE_ERROR; |
va009039 |
18:61554f238584 | 251 | } |
va009039 |
18:61554f238584 | 252 | ep->setLengthTransferred(write_len); |
va009039 |
18:61554f238584 | 253 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 254 | } |
va009039 | 12:b91fdea8c0a7 | 255 | |
va009039 | 12:b91fdea8c0a7 | 256 | USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { |
va009039 | 12:b91fdea8c0a7 | 257 | if (blocking == false) { |
va009039 | 12:b91fdea8c0a7 | 258 | ep->setBuffer(buf, len); |
va009039 | 12:b91fdea8c0a7 | 259 | ep_queue.push(ep); |
va009039 |
18:61554f238584 | 260 | multi_token_inNB(ep, buf, len); |
va009039 | 12:b91fdea8c0a7 | 261 | return USB_TYPE_PROCESSING; |
va009039 | 12:b91fdea8c0a7 | 262 | } |
va009039 |
18:61554f238584 | 263 | int result = multi_token_in(ep, buf, len); |
va009039 |
18:61554f238584 | 264 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 265 | if (result < 0) { |
va009039 |
18:61554f238584 | 266 | return USB_TYPE_ERROR; |
va009039 | 12:b91fdea8c0a7 | 267 | } |
va009039 |
18:61554f238584 | 268 | ep->setLengthTransferred(result); |
va009039 |
18:61554f238584 | 269 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 270 | } |
va009039 | 12:b91fdea8c0a7 | 271 | |
va009039 | 12:b91fdea8c0a7 | 272 | USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { |
va009039 | 12:b91fdea8c0a7 | 273 | USB_TEST_ASSERT(blocking); |
va009039 |
18:61554f238584 | 274 | int result = multi_token_out(ep, buf, len); |
va009039 |
18:61554f238584 | 275 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 276 | if (result < 0) { |
va009039 |
18:61554f238584 | 277 | return USB_TYPE_ERROR; |
va009039 | 12:b91fdea8c0a7 | 278 | } |
va009039 |
18:61554f238584 | 279 | ep->setLengthTransferred(result); |
va009039 |
18:61554f238584 | 280 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 281 | } |
va009039 | 12:b91fdea8c0a7 | 282 | |
va009039 | 12:b91fdea8c0a7 | 283 | USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { |
va009039 | 12:b91fdea8c0a7 | 284 | if (blocking == false) { |
va009039 | 12:b91fdea8c0a7 | 285 | ep->setBuffer(buf, len); |
va009039 | 12:b91fdea8c0a7 | 286 | ep_queue.push(ep); |
va009039 |
18:61554f238584 | 287 | multi_token_inNB(ep, buf, len); |
va009039 | 12:b91fdea8c0a7 | 288 | return USB_TYPE_PROCESSING; |
va009039 | 12:b91fdea8c0a7 | 289 | } |
va009039 |
18:61554f238584 | 290 | int result = multi_token_in(ep, buf, len); |
va009039 |
18:61554f238584 | 291 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 292 | if (result < 0) { |
va009039 |
18:61554f238584 | 293 | return USB_TYPE_ERROR; |
va009039 |
18:61554f238584 | 294 | } |
va009039 |
18:61554f238584 | 295 | ep->setLengthTransferred(result); |
va009039 | 12:b91fdea8c0a7 | 296 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 297 | } |
va009039 | 12:b91fdea8c0a7 | 298 | |
va009039 | 12:b91fdea8c0a7 | 299 | USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { |
va009039 | 12:b91fdea8c0a7 | 300 | USB_TEST_ASSERT(blocking); |
va009039 |
18:61554f238584 | 301 | int result = multi_token_out(ep, buf, len); |
va009039 |
18:61554f238584 | 302 | USB_TRACE1(result); |
va009039 |
18:61554f238584 | 303 | if (result < 0) { |
va009039 |
18:61554f238584 | 304 | return USB_TYPE_ERROR; |
va009039 |
18:61554f238584 | 305 | } |
va009039 |
18:61554f238584 | 306 | ep->setLengthTransferred(result); |
va009039 | 12:b91fdea8c0a7 | 307 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 308 | } |
va009039 | 12:b91fdea8c0a7 | 309 | |
va009039 | 12:b91fdea8c0a7 | 310 | USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { |
va009039 |
18:61554f238584 | 311 | USB_TEST_ASSERT(blocking); |
va009039 | 12:b91fdea8c0a7 | 312 | isochronousReadNB(ep, buf, len); |
va009039 | 12:b91fdea8c0a7 | 313 | return USB_TYPE_OK; |
va009039 | 12:b91fdea8c0a7 | 314 | } |
va009039 | 12:b91fdea8c0a7 | 315 | |
va009039 |
18:61554f238584 | 316 | int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) { |
va009039 |
18:61554f238584 | 317 | USB_TRACE1(size); |
va009039 |
18:61554f238584 | 318 | if (ep->getState() != USB_TYPE_PROCESSING) { |
va009039 |
18:61554f238584 | 319 | ep->setState(USB_TYPE_PROCESSING); |
va009039 |
18:61554f238584 | 320 | ep->setBuffer(data, size); |
va009039 |
18:61554f238584 | 321 | multi_token_inNB(ep, data, size); |
va009039 | 12:b91fdea8c0a7 | 322 | } |
va009039 |
18:61554f238584 | 323 | if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { |
va009039 |
18:61554f238584 | 324 | return ep->getLengthTransferred(); |
va009039 | 12:b91fdea8c0a7 | 325 | } |
va009039 |
18:61554f238584 | 326 | return -1; |
va009039 | 12:b91fdea8c0a7 | 327 | } |
va009039 | 12:b91fdea8c0a7 | 328 | |
va009039 |
18:61554f238584 | 329 | int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) { |
va009039 |
18:61554f238584 | 330 | USB_TRACE1(size); |
va009039 |
18:61554f238584 | 331 | return interruptReadNB(ep, data, size); |
va009039 | 12:b91fdea8c0a7 | 332 | } |
va009039 | 12:b91fdea8c0a7 | 333 | |
va009039 | 12:b91fdea8c0a7 | 334 | int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { |
va009039 |
18:61554f238584 | 335 | USB_TRACE1(size); |
va009039 | 12:b91fdea8c0a7 | 336 | int result = token_iso_in(ep, data, size); |
va009039 | 12:b91fdea8c0a7 | 337 | if (result >= 0) { |
va009039 | 12:b91fdea8c0a7 | 338 | ep->setLengthTransferred(result); |
va009039 | 12:b91fdea8c0a7 | 339 | } |
va009039 | 12:b91fdea8c0a7 | 340 | return result; |
va009039 | 12:b91fdea8c0a7 | 341 | } |
va009039 | 12:b91fdea8c0a7 | 342 | |
va009039 |
18:61554f238584 | 343 | void USBHost::task() { |
va009039 | 12:b91fdea8c0a7 | 344 | USBEndpoint* ep = ep_queue.pop(); |
va009039 |
18:61554f238584 | 345 | if (ep) { |
va009039 |
18:61554f238584 | 346 | USB_TEST_ASSERT(ep->getDir() == IN); |
va009039 |
18:61554f238584 | 347 | if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) { |
va009039 |
18:61554f238584 | 348 | ep->call(); |
va009039 |
18:61554f238584 | 349 | } else { |
va009039 |
18:61554f238584 | 350 | ep_queue.push(ep); |
va009039 |
18:61554f238584 | 351 | } |
va009039 | 12:b91fdea8c0a7 | 352 | } |
va009039 | 12:b91fdea8c0a7 | 353 | } |
va009039 |
18:61554f238584 | 354 | |
va009039 |
18:61554f238584 | 355 | void usb_test_assert_internal(const char *expr, const char *file, int line){ |
va009039 |
18:61554f238584 | 356 | error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr); |
va009039 |
18:61554f238584 | 357 | } |
va009039 |
18:61554f238584 | 358 |