Integrating the ublox LISA C200 modem

Fork of SprintUSBModemHTTPClientTest by Donatien Garnier

Committer:
sam_grove
Date:
Tue Oct 08 00:08:22 2013 +0000
Revision:
21:3f45e53afe4f
Parent:
5:3f93dd1d4cb3
Added http client test. Return from post seems to be a bit wonky but haven't looked closely at this

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 5:3f93dd1d4cb3 1 /* Copyright (c) 2010-2012 mbed.org, MIT License
sam_grove 5:3f93dd1d4cb3 2 *
sam_grove 5:3f93dd1d4cb3 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
sam_grove 5:3f93dd1d4cb3 4 * and associated documentation files (the "Software"), to deal in the Software without
sam_grove 5:3f93dd1d4cb3 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
sam_grove 5:3f93dd1d4cb3 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
sam_grove 5:3f93dd1d4cb3 7 * Software is furnished to do so, subject to the following conditions:
sam_grove 5:3f93dd1d4cb3 8 *
sam_grove 5:3f93dd1d4cb3 9 * The above copyright notice and this permission notice shall be included in all copies or
sam_grove 5:3f93dd1d4cb3 10 * substantial portions of the Software.
sam_grove 5:3f93dd1d4cb3 11 *
sam_grove 5:3f93dd1d4cb3 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
sam_grove 5:3f93dd1d4cb3 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
sam_grove 5:3f93dd1d4cb3 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
sam_grove 5:3f93dd1d4cb3 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
sam_grove 5:3f93dd1d4cb3 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
sam_grove 5:3f93dd1d4cb3 17 */
sam_grove 5:3f93dd1d4cb3 18
sam_grove 5:3f93dd1d4cb3 19 #define __DEBUG__ 0 //WARN: ENABLING DEBUGGING HERE WILL PRINTF IN IRQS!! UNEXPECTED BEHAVIOUR MAY RESULT...
sam_grove 5:3f93dd1d4cb3 20 #ifndef __MODULE__
sam_grove 5:3f93dd1d4cb3 21 #define __MODULE__ "USBHost.cpp"
sam_grove 5:3f93dd1d4cb3 22 #endif
sam_grove 5:3f93dd1d4cb3 23
sam_grove 5:3f93dd1d4cb3 24 #include "core/dbg.h"
sam_grove 5:3f93dd1d4cb3 25 #include <cstdint>
sam_grove 5:3f93dd1d4cb3 26
sam_grove 5:3f93dd1d4cb3 27 #include "USBHost.h"
sam_grove 5:3f93dd1d4cb3 28 #include "rtos.h"
sam_grove 5:3f93dd1d4cb3 29
sam_grove 5:3f93dd1d4cb3 30
sam_grove 5:3f93dd1d4cb3 31 #define NB_MAX_INTF 2
sam_grove 5:3f93dd1d4cb3 32
sam_grove 5:3f93dd1d4cb3 33 USBHost * USBHost::instHost = NULL;
sam_grove 5:3f93dd1d4cb3 34
sam_grove 5:3f93dd1d4cb3 35 USBHost::USBHost()
sam_grove 5:3f93dd1d4cb3 36 #if 0 //try not to use this
sam_grove 5:3f93dd1d4cb3 37 : m_usbQueue(), m_usbThread(3, this, &USBHost::usbProcess)
sam_grove 5:3f93dd1d4cb3 38 #endif
sam_grove 5:3f93dd1d4cb3 39 {
sam_grove 5:3f93dd1d4cb3 40 headControlEndpoint = NULL;
sam_grove 5:3f93dd1d4cb3 41 headBulkEndpoint = NULL;
sam_grove 5:3f93dd1d4cb3 42 headInterruptEndpoint = NULL;
sam_grove 5:3f93dd1d4cb3 43 tailControlEndpoint = NULL;
sam_grove 5:3f93dd1d4cb3 44 tailBulkEndpoint = NULL;
sam_grove 5:3f93dd1d4cb3 45 tailInterruptEndpoint = NULL;
sam_grove 5:3f93dd1d4cb3 46
sam_grove 5:3f93dd1d4cb3 47 nb_devices = 0;
sam_grove 5:3f93dd1d4cb3 48 lenReportDescr = 0;
sam_grove 5:3f93dd1d4cb3 49
sam_grove 5:3f93dd1d4cb3 50 controlEndpointAllocated = false;
sam_grove 5:3f93dd1d4cb3 51
sam_grove 5:3f93dd1d4cb3 52 for (int i = 0; i < MAX_DEVICE_NB; i++) {
sam_grove 5:3f93dd1d4cb3 53 deviceInUse[i] = false;
sam_grove 5:3f93dd1d4cb3 54 devices[i].setAddress(i + 1);
sam_grove 5:3f93dd1d4cb3 55 deviceReset[i] = false;
sam_grove 5:3f93dd1d4cb3 56 }
sam_grove 5:3f93dd1d4cb3 57 }
sam_grove 5:3f93dd1d4cb3 58
sam_grove 5:3f93dd1d4cb3 59
sam_grove 5:3f93dd1d4cb3 60 void USBHost::transferCompleted(volatile uint32_t addr) {
sam_grove 5:3f93dd1d4cb3 61 #if 0 //try not to use this
sam_grove 5:3f93dd1d4cb3 62 Interrupt::enter();
sam_grove 5:3f93dd1d4cb3 63 m_usbQueue.post(addr);
sam_grove 5:3f93dd1d4cb3 64 Interrupt::leave();
sam_grove 5:3f93dd1d4cb3 65 #else
sam_grove 5:3f93dd1d4cb3 66
sam_grove 5:3f93dd1d4cb3 67 if(addr == NULL) //Nothing to process?
sam_grove 5:3f93dd1d4cb3 68 {
sam_grove 5:3f93dd1d4cb3 69 return;
sam_grove 5:3f93dd1d4cb3 70 }
sam_grove 5:3f93dd1d4cb3 71
sam_grove 5:3f93dd1d4cb3 72 volatile HCTD* tdList = NULL;
sam_grove 5:3f93dd1d4cb3 73
sam_grove 5:3f93dd1d4cb3 74 //First we must reverse the list order and dequeue each TD
sam_grove 5:3f93dd1d4cb3 75 do
sam_grove 5:3f93dd1d4cb3 76 {
sam_grove 5:3f93dd1d4cb3 77 volatile HCTD* td = (volatile HCTD*)addr;
sam_grove 5:3f93dd1d4cb3 78
sam_grove 5:3f93dd1d4cb3 79 if(td->control & 0xF0000000 != 0)
sam_grove 5:3f93dd1d4cb3 80 {
sam_grove 5:3f93dd1d4cb3 81 WARN("Condition code %02x", td->control >> 28);
sam_grove 5:3f93dd1d4cb3 82 }
sam_grove 5:3f93dd1d4cb3 83
sam_grove 5:3f93dd1d4cb3 84 addr = td->nextTD; //Dequeue from physical list
sam_grove 5:3f93dd1d4cb3 85 td->nextTD = (uint32_t)tdList; //Enqueue into reversed list
sam_grove 5:3f93dd1d4cb3 86 tdList = td;
sam_grove 5:3f93dd1d4cb3 87 } while(addr);
sam_grove 5:3f93dd1d4cb3 88
sam_grove 5:3f93dd1d4cb3 89 //Now we can process the list
sam_grove 5:3f93dd1d4cb3 90 USBEndpoint * volatile iter = NULL;
sam_grove 5:3f93dd1d4cb3 91
sam_grove 5:3f93dd1d4cb3 92 while(tdList != NULL)
sam_grove 5:3f93dd1d4cb3 93 {
sam_grove 5:3f93dd1d4cb3 94 bool found = false;
sam_grove 5:3f93dd1d4cb3 95 volatile HCTD* td = tdList;
sam_grove 5:3f93dd1d4cb3 96 tdList = (volatile HCTD*)td->nextTD; //Dequeue element now as it could be modified below
sam_grove 5:3f93dd1d4cb3 97 for (int i = 0; i < 3; i++) {
sam_grove 5:3f93dd1d4cb3 98 if (found) {
sam_grove 5:3f93dd1d4cb3 99 break;
sam_grove 5:3f93dd1d4cb3 100 }
sam_grove 5:3f93dd1d4cb3 101 iter = (i == 0) ? headControlEndpoint : ( (i == 1) ? headBulkEndpoint : headInterruptEndpoint);
sam_grove 5:3f93dd1d4cb3 102 while (iter != NULL) {
sam_grove 5:3f93dd1d4cb3 103 if (iter->getProcessedTD() == td) {
sam_grove 5:3f93dd1d4cb3 104 DBG("td=%p FOUND ed: %08X", td, (void *)iter->getHCED());
sam_grove 5:3f93dd1d4cb3 105 if (((HCTD *)td)->control >> 28) {
sam_grove 5:3f93dd1d4cb3 106 DBG("TD Error: %d", td->control >> 28);
sam_grove 5:3f93dd1d4cb3 107 iter->setState(USB_TYPE_TDFAIL);
sam_grove 5:3f93dd1d4cb3 108 } else if ((uint32_t)iter->getHCED() & 0x1) {
sam_grove 5:3f93dd1d4cb3 109 DBG("HALTED");
sam_grove 5:3f93dd1d4cb3 110 iter->setState(USB_TYPE_HALTED);
sam_grove 5:3f93dd1d4cb3 111 } else if (!td->currBufPtr) {
sam_grove 5:3f93dd1d4cb3 112 DBG("!%p", iter);
sam_grove 5:3f93dd1d4cb3 113 iter->setState(USB_TYPE_IDLE);
sam_grove 5:3f93dd1d4cb3 114 found=true;
sam_grove 5:3f93dd1d4cb3 115 } else {
sam_grove 5:3f93dd1d4cb3 116 DBG("!%p", iter);
sam_grove 5:3f93dd1d4cb3 117 iter->setState(USB_TYPE_IDLE);
sam_grove 5:3f93dd1d4cb3 118 iter->setLengthTransferred(td->currBufPtr - iter->getBufStart());
sam_grove 5:3f93dd1d4cb3 119 found=true;
sam_grove 5:3f93dd1d4cb3 120 }
sam_grove 5:3f93dd1d4cb3 121 break;
sam_grove 5:3f93dd1d4cb3 122 }
sam_grove 5:3f93dd1d4cb3 123 iter = iter->nextEndpoint();
sam_grove 5:3f93dd1d4cb3 124 }
sam_grove 5:3f93dd1d4cb3 125 }
sam_grove 5:3f93dd1d4cb3 126
sam_grove 5:3f93dd1d4cb3 127
sam_grove 5:3f93dd1d4cb3 128 if (found) {
sam_grove 5:3f93dd1d4cb3 129 iter->unqueueTransfer(td);
sam_grove 5:3f93dd1d4cb3 130
sam_grove 5:3f93dd1d4cb3 131 if (iter->getType() != CONTROL_ENDPOINT) {
sam_grove 5:3f93dd1d4cb3 132 iter->call();
sam_grove 5:3f93dd1d4cb3 133 }
sam_grove 5:3f93dd1d4cb3 134 }
sam_grove 5:3f93dd1d4cb3 135 else
sam_grove 5:3f93dd1d4cb3 136 {
sam_grove 5:3f93dd1d4cb3 137 WARN("TD not found!!!");
sam_grove 5:3f93dd1d4cb3 138 //freeTD((uint8_t *)td); //Device must have been disconnected meanwhile
sam_grove 5:3f93dd1d4cb3 139 //Do notn free TD as it will be freed in the disconnect routine
sam_grove 5:3f93dd1d4cb3 140 }
sam_grove 5:3f93dd1d4cb3 141
sam_grove 5:3f93dd1d4cb3 142 }
sam_grove 5:3f93dd1d4cb3 143 #endif
sam_grove 5:3f93dd1d4cb3 144 }
sam_grove 5:3f93dd1d4cb3 145
sam_grove 5:3f93dd1d4cb3 146 USBHost * USBHost::getHostInst() {
sam_grove 5:3f93dd1d4cb3 147 if (instHost == NULL) {
sam_grove 5:3f93dd1d4cb3 148 instHost = new USBHost();
sam_grove 5:3f93dd1d4cb3 149 instHost->init();
sam_grove 5:3f93dd1d4cb3 150 }
sam_grove 5:3f93dd1d4cb3 151 return instHost;
sam_grove 5:3f93dd1d4cb3 152 }
sam_grove 5:3f93dd1d4cb3 153
sam_grove 5:3f93dd1d4cb3 154
sam_grove 5:3f93dd1d4cb3 155 /*
sam_grove 5:3f93dd1d4cb3 156 * Call in ISR when a device has been connected
sam_grove 5:3f93dd1d4cb3 157 */
sam_grove 5:3f93dd1d4cb3 158 void USBHost::deviceConnected(int hub, int port, bool lowSpeed) {
sam_grove 5:3f93dd1d4cb3 159 WARN("Device connected");
sam_grove 5:3f93dd1d4cb3 160 for (int i = 0; i < MAX_DEVICE_NB; i++) {
sam_grove 5:3f93dd1d4cb3 161 if (!deviceInUse[i]) {
sam_grove 5:3f93dd1d4cb3 162 deviceInUse[i] = true;
sam_grove 5:3f93dd1d4cb3 163 WARN("will call init on device %p: speed: %d", (void *)&devices[i], lowSpeed);
sam_grove 5:3f93dd1d4cb3 164 devices[i].init(hub, port, lowSpeed);
sam_grove 5:3f93dd1d4cb3 165 deviceReset[i] = false;
sam_grove 5:3f93dd1d4cb3 166 break;
sam_grove 5:3f93dd1d4cb3 167 }
sam_grove 5:3f93dd1d4cb3 168 }
sam_grove 5:3f93dd1d4cb3 169
sam_grove 5:3f93dd1d4cb3 170 if (!controlEndpointAllocated) {
sam_grove 5:3f93dd1d4cb3 171 control = newEndpoint(CONTROL_ENDPOINT, OUT, 0x08, 0x00);
sam_grove 5:3f93dd1d4cb3 172 addEndpoint(NULL, 0, (USBEndpoint*)control);
sam_grove 5:3f93dd1d4cb3 173 controlEndpointAllocated = true;
sam_grove 5:3f93dd1d4cb3 174 }
sam_grove 5:3f93dd1d4cb3 175 control->setState(USB_TYPE_IDLE);
sam_grove 5:3f93dd1d4cb3 176 }
sam_grove 5:3f93dd1d4cb3 177
sam_grove 5:3f93dd1d4cb3 178 /*
sam_grove 5:3f93dd1d4cb3 179 * Call in ISR when a device has been disconnected
sam_grove 5:3f93dd1d4cb3 180 */
sam_grove 5:3f93dd1d4cb3 181 void USBHost::deviceDisconnected(int hub, int port, volatile uint32_t addr) {
sam_grove 5:3f93dd1d4cb3 182
sam_grove 5:3f93dd1d4cb3 183 bool controlListState = disableControlList();
sam_grove 5:3f93dd1d4cb3 184 bool bulkListState = disableBulkList();
sam_grove 5:3f93dd1d4cb3 185 bool interruptListState = disableInterruptList();
sam_grove 5:3f93dd1d4cb3 186
sam_grove 5:3f93dd1d4cb3 187 if( addr != 0 ) //If addr == 0, no pending transfers
sam_grove 5:3f93dd1d4cb3 188 {
sam_grove 5:3f93dd1d4cb3 189 transferCompleted(addr); //Finish processing any pending completed TD
sam_grove 5:3f93dd1d4cb3 190 }
sam_grove 5:3f93dd1d4cb3 191
sam_grove 5:3f93dd1d4cb3 192 for (int i = 0; i < MAX_DEVICE_NB; i++) {
sam_grove 5:3f93dd1d4cb3 193 if ((devices[i].getHub() == hub) && (devices[i].getPort() == port)) {
sam_grove 5:3f93dd1d4cb3 194 WARN("device disconnected: %p", (void *)&devices[i]);
sam_grove 5:3f93dd1d4cb3 195 deviceInUse[i] = false;
sam_grove 5:3f93dd1d4cb3 196 deviceReset[i] = false;
sam_grove 5:3f93dd1d4cb3 197 freeDevice((USBDeviceConnected*)&devices[i]);
sam_grove 5:3f93dd1d4cb3 198 control->setState(USB_TYPE_DISCONNECTED); //FIXME There should be one control ep per device, not per host
sam_grove 5:3f93dd1d4cb3 199 break;
sam_grove 5:3f93dd1d4cb3 200 }
sam_grove 5:3f93dd1d4cb3 201 }
sam_grove 5:3f93dd1d4cb3 202 nb_devices--;
sam_grove 5:3f93dd1d4cb3 203
sam_grove 5:3f93dd1d4cb3 204 if (controlListState) enableControlList();
sam_grove 5:3f93dd1d4cb3 205 if (bulkListState) enableBulkList();
sam_grove 5:3f93dd1d4cb3 206 if (interruptListState) enableInterruptList();
sam_grove 5:3f93dd1d4cb3 207 }
sam_grove 5:3f93dd1d4cb3 208
sam_grove 5:3f93dd1d4cb3 209 void USBHost::freeDevice(USBDeviceConnected * dev) {
sam_grove 5:3f93dd1d4cb3 210 USBEndpoint * ep = NULL;
sam_grove 5:3f93dd1d4cb3 211 // HCTD * td = NULL;
sam_grove 5:3f93dd1d4cb3 212 HCED * ed = NULL;
sam_grove 5:3f93dd1d4cb3 213
sam_grove 5:3f93dd1d4cb3 214 for (int j = 0; j < dev->getNbInterface(); j++) {
sam_grove 5:3f93dd1d4cb3 215 DBG("FREE INTF %d, %p, nb_endpot: %d", j, (void *)dev->getInterface(j), dev->getInterface(j)->nb_endpoint);
sam_grove 5:3f93dd1d4cb3 216 for (int i = 0; i < dev->getInterface(j)->nb_endpoint; i++) {
sam_grove 5:3f93dd1d4cb3 217 if ((ep = dev->getEndpoint(j, i)) != NULL) {
sam_grove 5:3f93dd1d4cb3 218 DBG("Freeing USBEndpoint");
sam_grove 5:3f93dd1d4cb3 219 ed = (HCED *)ep->getHCED();
sam_grove 5:3f93dd1d4cb3 220 ed->control |= (1 << 13); //sKip bit
sam_grove 5:3f93dd1d4cb3 221 DBG("Dequeueing USBEndpoint");
sam_grove 5:3f93dd1d4cb3 222 unqueueEndpoint(ep);
sam_grove 5:3f93dd1d4cb3 223
sam_grove 5:3f93dd1d4cb3 224 DBG("Freeing first transfer descriptor");
sam_grove 5:3f93dd1d4cb3 225 freeTD((volatile uint8_t*)ep->getTDList()[0]);
sam_grove 5:3f93dd1d4cb3 226 DBG("Freeing second transfer descriptor");
sam_grove 5:3f93dd1d4cb3 227 freeTD((volatile uint8_t*)ep->getTDList()[1]);
sam_grove 5:3f93dd1d4cb3 228
sam_grove 5:3f93dd1d4cb3 229 DBG("Freeing USBEndpoint descriptor");
sam_grove 5:3f93dd1d4cb3 230 freeED((uint8_t *)ep->getHCED());
sam_grove 5:3f93dd1d4cb3 231 }
sam_grove 5:3f93dd1d4cb3 232 //printBulk();
sam_grove 5:3f93dd1d4cb3 233 //printInt();
sam_grove 5:3f93dd1d4cb3 234 }
sam_grove 5:3f93dd1d4cb3 235 }
sam_grove 5:3f93dd1d4cb3 236 DBG("Disconnecting device");
sam_grove 5:3f93dd1d4cb3 237 dev->disconnect();
sam_grove 5:3f93dd1d4cb3 238 DBG("Device disconnected");
sam_grove 5:3f93dd1d4cb3 239 }
sam_grove 5:3f93dd1d4cb3 240
sam_grove 5:3f93dd1d4cb3 241
sam_grove 5:3f93dd1d4cb3 242 void USBHost::unqueueEndpoint(USBEndpoint * ep) {
sam_grove 5:3f93dd1d4cb3 243 USBEndpoint * prec = NULL;
sam_grove 5:3f93dd1d4cb3 244 USBEndpoint * current = NULL;
sam_grove 5:3f93dd1d4cb3 245 bool found = false;
sam_grove 5:3f93dd1d4cb3 246
sam_grove 5:3f93dd1d4cb3 247 DBG("want to unqueue ep: %p", (void *)ep->getHCED());
sam_grove 5:3f93dd1d4cb3 248
sam_grove 5:3f93dd1d4cb3 249 for (int i = 0; i < 2; i++) {
sam_grove 5:3f93dd1d4cb3 250 if (found) {
sam_grove 5:3f93dd1d4cb3 251 DBG("USBEndpoint unqueued: %p", (void *)ep->getHCED());
sam_grove 5:3f93dd1d4cb3 252 break;
sam_grove 5:3f93dd1d4cb3 253 }
sam_grove 5:3f93dd1d4cb3 254 current = (i == 0) ? (USBEndpoint*)headBulkEndpoint : (USBEndpoint*)headInterruptEndpoint;
sam_grove 5:3f93dd1d4cb3 255 prec = current;
sam_grove 5:3f93dd1d4cb3 256 while (current != NULL) {
sam_grove 5:3f93dd1d4cb3 257 if (current == ep) {
sam_grove 5:3f93dd1d4cb3 258 if (current->nextEndpoint() != NULL) {
sam_grove 5:3f93dd1d4cb3 259 prec->queueEndpoint(current->nextEndpoint());
sam_grove 5:3f93dd1d4cb3 260 if (current == headBulkEndpoint) {
sam_grove 5:3f93dd1d4cb3 261 updateBulkHeadED((uint32_t)current->nextEndpoint()->getHCED());
sam_grove 5:3f93dd1d4cb3 262 headBulkEndpoint = current->nextEndpoint();
sam_grove 5:3f93dd1d4cb3 263 }
sam_grove 5:3f93dd1d4cb3 264 if (current == headInterruptEndpoint) {
sam_grove 5:3f93dd1d4cb3 265 updateInterruptHeadED((uint32_t)current->nextEndpoint()->getHCED());
sam_grove 5:3f93dd1d4cb3 266 headInterruptEndpoint = current->nextEndpoint();
sam_grove 5:3f93dd1d4cb3 267 }
sam_grove 5:3f93dd1d4cb3 268 } else {
sam_grove 5:3f93dd1d4cb3 269 prec->queueEndpoint(NULL);
sam_grove 5:3f93dd1d4cb3 270 if (current == headBulkEndpoint) {
sam_grove 5:3f93dd1d4cb3 271 updateBulkHeadED(0);
sam_grove 5:3f93dd1d4cb3 272 headBulkEndpoint = current->nextEndpoint();
sam_grove 5:3f93dd1d4cb3 273 }
sam_grove 5:3f93dd1d4cb3 274 if (current == headInterruptEndpoint) {
sam_grove 5:3f93dd1d4cb3 275 updateInterruptHeadED(0);
sam_grove 5:3f93dd1d4cb3 276 headInterruptEndpoint = current->nextEndpoint();
sam_grove 5:3f93dd1d4cb3 277 }
sam_grove 5:3f93dd1d4cb3 278 }
sam_grove 5:3f93dd1d4cb3 279 found = true;
sam_grove 5:3f93dd1d4cb3 280 current->setState(USB_TYPE_FREE);
sam_grove 5:3f93dd1d4cb3 281 break;
sam_grove 5:3f93dd1d4cb3 282 }
sam_grove 5:3f93dd1d4cb3 283 prec = current;
sam_grove 5:3f93dd1d4cb3 284 current = current->nextEndpoint();
sam_grove 5:3f93dd1d4cb3 285 }
sam_grove 5:3f93dd1d4cb3 286 }
sam_grove 5:3f93dd1d4cb3 287 //printBulk();
sam_grove 5:3f93dd1d4cb3 288 //printInt();
sam_grove 5:3f93dd1d4cb3 289 }
sam_grove 5:3f93dd1d4cb3 290
sam_grove 5:3f93dd1d4cb3 291
sam_grove 5:3f93dd1d4cb3 292 USBDeviceConnected * USBHost::getDevice(uint8_t index) {
sam_grove 5:3f93dd1d4cb3 293 if ((index >= MAX_DEVICE_NB) || (!deviceInUse[index])) {
sam_grove 5:3f93dd1d4cb3 294 return NULL;
sam_grove 5:3f93dd1d4cb3 295 }
sam_grove 5:3f93dd1d4cb3 296 return (USBDeviceConnected*)&devices[index];
sam_grove 5:3f93dd1d4cb3 297 }
sam_grove 5:3f93dd1d4cb3 298
sam_grove 5:3f93dd1d4cb3 299
sam_grove 5:3f93dd1d4cb3 300
sam_grove 5:3f93dd1d4cb3 301 // create an USBEndpoint descriptor. the USBEndpoint is not linked
sam_grove 5:3f93dd1d4cb3 302 USBEndpoint * USBHost::newEndpoint(ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir, uint32_t size, uint8_t addr) {
sam_grove 5:3f93dd1d4cb3 303 int i = 0;
sam_grove 5:3f93dd1d4cb3 304 HCED * ed = (HCED *)getED();
sam_grove 5:3f93dd1d4cb3 305 HCTD* td_list[2] = { (HCTD*)getTD(), (HCTD*)getTD() };
sam_grove 5:3f93dd1d4cb3 306
sam_grove 5:3f93dd1d4cb3 307 memset((void *)td_list[0], 0x00, sizeof(HCTD));
sam_grove 5:3f93dd1d4cb3 308 memset((void *)td_list[1], 0x00, sizeof(HCTD));
sam_grove 5:3f93dd1d4cb3 309
sam_grove 5:3f93dd1d4cb3 310 // search a free USBEndpoint
sam_grove 5:3f93dd1d4cb3 311 for (i = 0; i < MAX_ENDPOINT; i++) {
sam_grove 5:3f93dd1d4cb3 312 if (endpoints[i].getState() == USB_TYPE_FREE) {
sam_grove 5:3f93dd1d4cb3 313 DBG("Trying to create ep");
sam_grove 5:3f93dd1d4cb3 314 endpoints[i].init(ed, type, dir, size, addr, td_list);
sam_grove 5:3f93dd1d4cb3 315 //endpoints[i].queueTransfer(nullTd);
sam_grove 5:3f93dd1d4cb3 316 DBG("USBEndpoint created (%p): type: %d, dir: %d, size: %d, addr: %d", &endpoints[i], type, dir, size, addr);
sam_grove 5:3f93dd1d4cb3 317 return &endpoints[i];
sam_grove 5:3f93dd1d4cb3 318 }
sam_grove 5:3f93dd1d4cb3 319 }
sam_grove 5:3f93dd1d4cb3 320 DBG("could not allocate more endpoints!!!!");
sam_grove 5:3f93dd1d4cb3 321 return NULL;
sam_grove 5:3f93dd1d4cb3 322 }
sam_grove 5:3f93dd1d4cb3 323
sam_grove 5:3f93dd1d4cb3 324
sam_grove 5:3f93dd1d4cb3 325 USB_TYPE USBHost::resetDevice(USBDeviceConnected * dev) {
sam_grove 5:3f93dd1d4cb3 326 int index = findDevice(dev);
sam_grove 5:3f93dd1d4cb3 327 if ((index != -1) && (!deviceReset[index])) {
sam_grove 5:3f93dd1d4cb3 328 resetPort(dev->getHub(), dev->getPort());
sam_grove 5:3f93dd1d4cb3 329 deviceReset[index] = true;
sam_grove 5:3f93dd1d4cb3 330 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 331 }
sam_grove 5:3f93dd1d4cb3 332 return USB_TYPE_NOTFOUND;
sam_grove 5:3f93dd1d4cb3 333 }
sam_grove 5:3f93dd1d4cb3 334
sam_grove 5:3f93dd1d4cb3 335 // link the USBEndpoint to the linked list and attach an USBEndpoint to a device
sam_grove 5:3f93dd1d4cb3 336 bool USBHost::addEndpoint(USBDeviceConnected * dev, uint8_t intf_nb, USBEndpoint * ep) {
sam_grove 5:3f93dd1d4cb3 337
sam_grove 5:3f93dd1d4cb3 338 if (ep == NULL) {
sam_grove 5:3f93dd1d4cb3 339 return false;
sam_grove 5:3f93dd1d4cb3 340 }
sam_grove 5:3f93dd1d4cb3 341
sam_grove 5:3f93dd1d4cb3 342 DBG("New ep %p", ep);
sam_grove 5:3f93dd1d4cb3 343
sam_grove 5:3f93dd1d4cb3 344 HCED * prevEd;
sam_grove 5:3f93dd1d4cb3 345
sam_grove 5:3f93dd1d4cb3 346 // set device address in the USBEndpoint descriptor
sam_grove 5:3f93dd1d4cb3 347 if (dev == NULL) {
sam_grove 5:3f93dd1d4cb3 348 ep->setDeviceAddress(0);
sam_grove 5:3f93dd1d4cb3 349 } else {
sam_grove 5:3f93dd1d4cb3 350 ep->setDeviceAddress(dev->getAddress());
sam_grove 5:3f93dd1d4cb3 351 }
sam_grove 5:3f93dd1d4cb3 352
sam_grove 5:3f93dd1d4cb3 353 if (dev != NULL && dev->getSpeed()) {
sam_grove 5:3f93dd1d4cb3 354 DBG("add USBEndpoint: set speed");
sam_grove 5:3f93dd1d4cb3 355 ep->setSpeed(dev->getSpeed());
sam_grove 5:3f93dd1d4cb3 356 }
sam_grove 5:3f93dd1d4cb3 357
sam_grove 5:3f93dd1d4cb3 358 // queue the new USBEndpoint on the ED list
sam_grove 5:3f93dd1d4cb3 359 switch (ep->getType()) {
sam_grove 5:3f93dd1d4cb3 360
sam_grove 5:3f93dd1d4cb3 361 case CONTROL_ENDPOINT:
sam_grove 5:3f93dd1d4cb3 362 prevEd = ( HCED*) controlHeadED();
sam_grove 5:3f93dd1d4cb3 363 if (!prevEd) {
sam_grove 5:3f93dd1d4cb3 364 updateControlHeadED((uint32_t) ep->getHCED());
sam_grove 5:3f93dd1d4cb3 365 DBG("First control USBEndpoint: %08X", (uint32_t) ep->getHCED());
sam_grove 5:3f93dd1d4cb3 366 headControlEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 367 tailControlEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 368 return true;
sam_grove 5:3f93dd1d4cb3 369 }
sam_grove 5:3f93dd1d4cb3 370 tailControlEndpoint->queueEndpoint(ep);
sam_grove 5:3f93dd1d4cb3 371 tailControlEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 372 return true;
sam_grove 5:3f93dd1d4cb3 373
sam_grove 5:3f93dd1d4cb3 374 case BULK_ENDPOINT:
sam_grove 5:3f93dd1d4cb3 375 prevEd = ( HCED*) bulkHeadED();
sam_grove 5:3f93dd1d4cb3 376 if (!prevEd) {
sam_grove 5:3f93dd1d4cb3 377 updateBulkHeadED((uint32_t) ep->getHCED());
sam_grove 5:3f93dd1d4cb3 378 //DBG("First bulk USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED());
sam_grove 5:3f93dd1d4cb3 379 headBulkEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 380 tailBulkEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 381 break;
sam_grove 5:3f93dd1d4cb3 382 }
sam_grove 5:3f93dd1d4cb3 383 tailBulkEndpoint->queueEndpoint(ep);
sam_grove 5:3f93dd1d4cb3 384 tailBulkEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 385 break;
sam_grove 5:3f93dd1d4cb3 386
sam_grove 5:3f93dd1d4cb3 387 case INTERRUPT_ENDPOINT:
sam_grove 5:3f93dd1d4cb3 388 prevEd = ( HCED*) interruptHeadED();
sam_grove 5:3f93dd1d4cb3 389 if (!prevEd) {
sam_grove 5:3f93dd1d4cb3 390 updateInterruptHeadED((uint32_t) ep->getHCED());
sam_grove 5:3f93dd1d4cb3 391 //DBG("First interrupt USBEndpoint: %08X\r\n", (uint32_t) ep->getHCED());
sam_grove 5:3f93dd1d4cb3 392 headInterruptEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 393 tailInterruptEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 394 break;
sam_grove 5:3f93dd1d4cb3 395 }
sam_grove 5:3f93dd1d4cb3 396 tailInterruptEndpoint->queueEndpoint(ep);
sam_grove 5:3f93dd1d4cb3 397 tailInterruptEndpoint = ep;
sam_grove 5:3f93dd1d4cb3 398 break;
sam_grove 5:3f93dd1d4cb3 399 default:
sam_grove 5:3f93dd1d4cb3 400 return false;
sam_grove 5:3f93dd1d4cb3 401 }
sam_grove 5:3f93dd1d4cb3 402
sam_grove 5:3f93dd1d4cb3 403 dev->addEndpoint(intf_nb, ep);
sam_grove 5:3f93dd1d4cb3 404 //printBulk();
sam_grove 5:3f93dd1d4cb3 405 //printInt();
sam_grove 5:3f93dd1d4cb3 406
sam_grove 5:3f93dd1d4cb3 407 return true;
sam_grove 5:3f93dd1d4cb3 408 }
sam_grove 5:3f93dd1d4cb3 409
sam_grove 5:3f93dd1d4cb3 410
sam_grove 5:3f93dd1d4cb3 411 int USBHost::findDevice(USBDeviceConnected * dev) {
sam_grove 5:3f93dd1d4cb3 412 for (int i = 0; i < MAX_DEVICE_NB; i++) {
sam_grove 5:3f93dd1d4cb3 413 if (dev == &devices[i]) {
sam_grove 5:3f93dd1d4cb3 414 return i;
sam_grove 5:3f93dd1d4cb3 415 }
sam_grove 5:3f93dd1d4cb3 416 }
sam_grove 5:3f93dd1d4cb3 417 return -1;
sam_grove 5:3f93dd1d4cb3 418 }
sam_grove 5:3f93dd1d4cb3 419
sam_grove 5:3f93dd1d4cb3 420 void USBHost::printBulk() {
sam_grove 5:3f93dd1d4cb3 421 HCED * hced = (HCED *)bulkHeadED();
sam_grove 5:3f93dd1d4cb3 422 HCTD * hctd = NULL;
sam_grove 5:3f93dd1d4cb3 423 printf("---------State of Bulk:--------\r\n");
sam_grove 5:3f93dd1d4cb3 424 while (hced != NULL) {
sam_grove 5:3f93dd1d4cb3 425 printf("hced: %p\r\n", hced);
sam_grove 5:3f93dd1d4cb3 426 hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f));
sam_grove 5:3f93dd1d4cb3 427 while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) {
sam_grove 5:3f93dd1d4cb3 428 printf("\thctd: %p\r\n", hctd);
sam_grove 5:3f93dd1d4cb3 429 hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f));
sam_grove 5:3f93dd1d4cb3 430 }
sam_grove 5:3f93dd1d4cb3 431 printf("\thctd: %p\r\n", hctd);
sam_grove 5:3f93dd1d4cb3 432 hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f));
sam_grove 5:3f93dd1d4cb3 433 }
sam_grove 5:3f93dd1d4cb3 434 printf("--------------------\r\n");
sam_grove 5:3f93dd1d4cb3 435 }
sam_grove 5:3f93dd1d4cb3 436
sam_grove 5:3f93dd1d4cb3 437 void USBHost::printInt() {
sam_grove 5:3f93dd1d4cb3 438 HCED * hced = (HCED *)interruptHeadED();
sam_grove 5:3f93dd1d4cb3 439 HCTD * hctd = NULL;
sam_grove 5:3f93dd1d4cb3 440 printf("---------State of Int:--------\r\n");
sam_grove 5:3f93dd1d4cb3 441 while (hced != NULL) {
sam_grove 5:3f93dd1d4cb3 442 printf("hced: %p\r\n", hced);
sam_grove 5:3f93dd1d4cb3 443 hctd = (HCTD *)((uint32_t)(hced->headTD) & ~(0x0f));
sam_grove 5:3f93dd1d4cb3 444 while (((uint32_t)hctd & ~(0x0f)) != ((hced->tailTD) & ~(0x0f))) {
sam_grove 5:3f93dd1d4cb3 445 printf("\thctd: %p\r\n", hctd);
sam_grove 5:3f93dd1d4cb3 446 hctd = (HCTD *)((uint32_t)(hctd->nextTD) & ~(0x0f));
sam_grove 5:3f93dd1d4cb3 447 }
sam_grove 5:3f93dd1d4cb3 448 printf("\thctd: %p\r\n", hctd);
sam_grove 5:3f93dd1d4cb3 449 hced = (HCED *)((uint32_t)(hced->nextED) & ~(0x0f));
sam_grove 5:3f93dd1d4cb3 450 }
sam_grove 5:3f93dd1d4cb3 451 printf("--------------------\r\n");
sam_grove 5:3f93dd1d4cb3 452 }
sam_grove 5:3f93dd1d4cb3 453
sam_grove 5:3f93dd1d4cb3 454
sam_grove 5:3f93dd1d4cb3 455 // add a transfer on the TD linked list
sam_grove 5:3f93dd1d4cb3 456 USB_TYPE USBHost::addTransfer(USBEndpoint * ed, uint8_t * buf, uint32_t len) {
sam_grove 5:3f93dd1d4cb3 457
sam_grove 5:3f93dd1d4cb3 458 //Check state of the ep
sam_grove 5:3f93dd1d4cb3 459 if( (ed->getState() != USB_TYPE_IDLE) && (ed->getState() != USB_TYPE_TDFAIL) )
sam_grove 5:3f93dd1d4cb3 460 {
sam_grove 5:3f93dd1d4cb3 461 return ed->getState();
sam_grove 5:3f93dd1d4cb3 462 }
sam_grove 5:3f93dd1d4cb3 463
sam_grove 5:3f93dd1d4cb3 464 // allocate a TD which will be freed in TDcompletion
sam_grove 5:3f93dd1d4cb3 465 volatile HCTD * td = ed->getNextTD();
sam_grove 5:3f93dd1d4cb3 466 if (td == NULL) {
sam_grove 5:3f93dd1d4cb3 467 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 468 }
sam_grove 5:3f93dd1d4cb3 469
sam_grove 5:3f93dd1d4cb3 470 DBG("Next td = %p",td);
sam_grove 5:3f93dd1d4cb3 471
sam_grove 5:3f93dd1d4cb3 472 uint32_t token = (ed->isSetup() ? TD_SETUP : ( (ed->getDir() == IN) ? TD_IN : TD_OUT ));
sam_grove 5:3f93dd1d4cb3 473
sam_grove 5:3f93dd1d4cb3 474 uint32_t td_toggle;
sam_grove 5:3f93dd1d4cb3 475
sam_grove 5:3f93dd1d4cb3 476 if (ed->getType() == CONTROL_ENDPOINT) {
sam_grove 5:3f93dd1d4cb3 477 if (ed->isSetup()) {
sam_grove 5:3f93dd1d4cb3 478 td_toggle = TD_TOGGLE_0;
sam_grove 5:3f93dd1d4cb3 479 } else {
sam_grove 5:3f93dd1d4cb3 480 td_toggle = TD_TOGGLE_1;
sam_grove 5:3f93dd1d4cb3 481 }
sam_grove 5:3f93dd1d4cb3 482 } else {
sam_grove 5:3f93dd1d4cb3 483 td_toggle = 0;
sam_grove 5:3f93dd1d4cb3 484 }
sam_grove 5:3f93dd1d4cb3 485
sam_grove 5:3f93dd1d4cb3 486 DBG("Buf=%d, len=%d", buf, len);
sam_grove 5:3f93dd1d4cb3 487 td->control = (TD_ROUNDING | token | TD_DELAY_INT(0) | td_toggle | TD_CC);
sam_grove 5:3f93dd1d4cb3 488 td->currBufPtr = (uint32_t) buf;
sam_grove 5:3f93dd1d4cb3 489 td->bufEnd = (uint32_t)(buf + (len - 1));
sam_grove 5:3f93dd1d4cb3 490
sam_grove 5:3f93dd1d4cb3 491 DBG("Now do queue transfer on ep %p", ed);
sam_grove 5:3f93dd1d4cb3 492
sam_grove 5:3f93dd1d4cb3 493 ed->queueTransfer();
sam_grove 5:3f93dd1d4cb3 494
sam_grove 5:3f93dd1d4cb3 495 DBG("Enable list if needed");
sam_grove 5:3f93dd1d4cb3 496
sam_grove 5:3f93dd1d4cb3 497 switch (ed->getType()) {
sam_grove 5:3f93dd1d4cb3 498 case CONTROL_ENDPOINT:
sam_grove 5:3f93dd1d4cb3 499 enableControlList();
sam_grove 5:3f93dd1d4cb3 500 break;
sam_grove 5:3f93dd1d4cb3 501 case BULK_ENDPOINT:
sam_grove 5:3f93dd1d4cb3 502 enableBulkList();
sam_grove 5:3f93dd1d4cb3 503 break;
sam_grove 5:3f93dd1d4cb3 504 case INTERRUPT_ENDPOINT:
sam_grove 5:3f93dd1d4cb3 505 //printInt();
sam_grove 5:3f93dd1d4cb3 506 enableInterruptList();
sam_grove 5:3f93dd1d4cb3 507 break;
sam_grove 5:3f93dd1d4cb3 508 }
sam_grove 5:3f93dd1d4cb3 509
sam_grove 5:3f93dd1d4cb3 510 DBG("Wait for HC to process TD");
sam_grove 5:3f93dd1d4cb3 511
sam_grove 5:3f93dd1d4cb3 512
sam_grove 5:3f93dd1d4cb3 513 return USB_TYPE_PROCESSING;
sam_grove 5:3f93dd1d4cb3 514 }
sam_grove 5:3f93dd1d4cb3 515
sam_grove 5:3f93dd1d4cb3 516
sam_grove 5:3f93dd1d4cb3 517
sam_grove 5:3f93dd1d4cb3 518 USB_TYPE USBHost::getDeviceDescriptor(USBDeviceConnected * dev, uint8_t * buf) {
sam_grove 5:3f93dd1d4cb3 519 return controlRead( dev,
sam_grove 5:3f93dd1d4cb3 520 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
sam_grove 5:3f93dd1d4cb3 521 GET_DESCRIPTOR,
sam_grove 5:3f93dd1d4cb3 522 (DEVICE_DESCRIPTOR << 8) | (0),
sam_grove 5:3f93dd1d4cb3 523 0,
sam_grove 5:3f93dd1d4cb3 524 buf,
sam_grove 5:3f93dd1d4cb3 525 DEVICE_DESCRIPTOR_LENGTH);
sam_grove 5:3f93dd1d4cb3 526 }
sam_grove 5:3f93dd1d4cb3 527
sam_grove 5:3f93dd1d4cb3 528 USB_TYPE USBHost::getConfigurationDescriptor(USBDeviceConnected * dev, uint8_t * buf, uint16_t * len_conf_descr) {
sam_grove 5:3f93dd1d4cb3 529 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 530 uint16_t total_conf_descr_length = 0;
sam_grove 5:3f93dd1d4cb3 531
sam_grove 5:3f93dd1d4cb3 532 // fourth step: get the beginning of the configuration descriptor to have the total length of the conf descr
sam_grove 5:3f93dd1d4cb3 533 res = controlRead( dev,
sam_grove 5:3f93dd1d4cb3 534 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
sam_grove 5:3f93dd1d4cb3 535 GET_DESCRIPTOR,
sam_grove 5:3f93dd1d4cb3 536 (CONFIGURATION_DESCRIPTOR << 8) | (0),
sam_grove 5:3f93dd1d4cb3 537 0,
sam_grove 5:3f93dd1d4cb3 538 buf,
sam_grove 5:3f93dd1d4cb3 539 CONFIGURATION_DESCRIPTOR_LENGTH);
sam_grove 5:3f93dd1d4cb3 540
sam_grove 5:3f93dd1d4cb3 541 if (res != USB_TYPE_OK) {
sam_grove 5:3f93dd1d4cb3 542 ERR("GET CONF 1 DESCR FAILED");
sam_grove 5:3f93dd1d4cb3 543 return res;
sam_grove 5:3f93dd1d4cb3 544 }
sam_grove 5:3f93dd1d4cb3 545 total_conf_descr_length = buf[2] | (buf[3] << 8);
sam_grove 5:3f93dd1d4cb3 546 if (len_conf_descr != NULL) {
sam_grove 5:3f93dd1d4cb3 547 *len_conf_descr = total_conf_descr_length;
sam_grove 5:3f93dd1d4cb3 548 }
sam_grove 5:3f93dd1d4cb3 549 DBG("TOTAL_LENGTH: %d \t NUM_INTERF: %d", total_conf_descr_length, buf[4]);
sam_grove 5:3f93dd1d4cb3 550
sam_grove 5:3f93dd1d4cb3 551 return controlRead( dev,
sam_grove 5:3f93dd1d4cb3 552 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
sam_grove 5:3f93dd1d4cb3 553 GET_DESCRIPTOR,
sam_grove 5:3f93dd1d4cb3 554 (CONFIGURATION_DESCRIPTOR << 8) | (0),
sam_grove 5:3f93dd1d4cb3 555 0,
sam_grove 5:3f93dd1d4cb3 556 buf,
sam_grove 5:3f93dd1d4cb3 557 total_conf_descr_length);
sam_grove 5:3f93dd1d4cb3 558
sam_grove 5:3f93dd1d4cb3 559 }
sam_grove 5:3f93dd1d4cb3 560
sam_grove 5:3f93dd1d4cb3 561 USB_TYPE USBHost::setConfiguration(USBDeviceConnected * dev, uint8_t conf) {
sam_grove 5:3f93dd1d4cb3 562 return controlWrite( dev,
sam_grove 5:3f93dd1d4cb3 563 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE,
sam_grove 5:3f93dd1d4cb3 564 SET_CONFIGURATION,
sam_grove 5:3f93dd1d4cb3 565 conf,
sam_grove 5:3f93dd1d4cb3 566 0,
sam_grove 5:3f93dd1d4cb3 567 NULL,
sam_grove 5:3f93dd1d4cb3 568 0);
sam_grove 5:3f93dd1d4cb3 569
sam_grove 5:3f93dd1d4cb3 570 }
sam_grove 5:3f93dd1d4cb3 571
sam_grove 5:3f93dd1d4cb3 572
sam_grove 5:3f93dd1d4cb3 573 // enumerate a device with the control USBEndpoint
sam_grove 5:3f93dd1d4cb3 574 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) {
sam_grove 5:3f93dd1d4cb3 575 uint8_t data[384];
sam_grove 5:3f93dd1d4cb3 576 uint16_t total_conf_descr_length = 0;
sam_grove 5:3f93dd1d4cb3 577 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 578
sam_grove 5:3f93dd1d4cb3 579 DBG("data = %p", data);
sam_grove 5:3f93dd1d4cb3 580
sam_grove 5:3f93dd1d4cb3 581 if (dev->isEnumerated()) {
sam_grove 5:3f93dd1d4cb3 582 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 583 }
sam_grove 5:3f93dd1d4cb3 584
sam_grove 5:3f93dd1d4cb3 585 // first step: get the size of USBEndpoint 0
sam_grove 5:3f93dd1d4cb3 586 DBG("Get size of EP 0");
sam_grove 5:3f93dd1d4cb3 587 res = controlRead( dev,
sam_grove 5:3f93dd1d4cb3 588 USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE,
sam_grove 5:3f93dd1d4cb3 589 GET_DESCRIPTOR,
sam_grove 5:3f93dd1d4cb3 590 (DEVICE_DESCRIPTOR << 8) | (0),
sam_grove 5:3f93dd1d4cb3 591 0,
sam_grove 5:3f93dd1d4cb3 592 data,
sam_grove 5:3f93dd1d4cb3 593 8);
sam_grove 5:3f93dd1d4cb3 594
sam_grove 5:3f93dd1d4cb3 595 if (res != USB_TYPE_OK) {
sam_grove 5:3f93dd1d4cb3 596 ERR("Control read failed!!");
sam_grove 5:3f93dd1d4cb3 597 return res;
sam_grove 5:3f93dd1d4cb3 598 }
sam_grove 5:3f93dd1d4cb3 599 dev->setSizeControlEndpoint(data[7]);
sam_grove 5:3f93dd1d4cb3 600 DBG("size control USBEndpoint: %d", dev->getSizeControlEndpoint());
sam_grove 5:3f93dd1d4cb3 601
sam_grove 5:3f93dd1d4cb3 602 DBG("Now set addr");
sam_grove 5:3f93dd1d4cb3 603 // second step: set an address to the device
sam_grove 5:3f93dd1d4cb3 604 res = controlWrite( dev,
sam_grove 5:3f93dd1d4cb3 605 USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE,
sam_grove 5:3f93dd1d4cb3 606 SET_ADDRESS,
sam_grove 5:3f93dd1d4cb3 607 dev->getAddress(),
sam_grove 5:3f93dd1d4cb3 608 0,
sam_grove 5:3f93dd1d4cb3 609 NULL,
sam_grove 5:3f93dd1d4cb3 610 0);
sam_grove 5:3f93dd1d4cb3 611
sam_grove 5:3f93dd1d4cb3 612 if (res != USB_TYPE_OK) {
sam_grove 5:3f93dd1d4cb3 613 DBG("SET ADDR FAILED");
sam_grove 5:3f93dd1d4cb3 614 freeDevice(dev);
sam_grove 5:3f93dd1d4cb3 615 return res;
sam_grove 5:3f93dd1d4cb3 616 }
sam_grove 5:3f93dd1d4cb3 617 dev->activeAddress();
sam_grove 5:3f93dd1d4cb3 618
sam_grove 5:3f93dd1d4cb3 619
sam_grove 5:3f93dd1d4cb3 620 // third step: get the whole device descriptor to see vid, pid
sam_grove 5:3f93dd1d4cb3 621 res = getDeviceDescriptor(dev, data);
sam_grove 5:3f93dd1d4cb3 622
sam_grove 5:3f93dd1d4cb3 623 if (res != USB_TYPE_OK) {
sam_grove 5:3f93dd1d4cb3 624 DBG("GET DEV DESCR FAILED");
sam_grove 5:3f93dd1d4cb3 625 return res;
sam_grove 5:3f93dd1d4cb3 626 }
sam_grove 5:3f93dd1d4cb3 627 dev->setClass(data[4]);
sam_grove 5:3f93dd1d4cb3 628 dev->setSubClass(data[5]);
sam_grove 5:3f93dd1d4cb3 629 dev->setProtocol(data[6]);
sam_grove 5:3f93dd1d4cb3 630 dev->setVid(data[8] | (data[9] << 8));
sam_grove 5:3f93dd1d4cb3 631 dev->setPid(data[10] | (data[11] << 8));
sam_grove 5:3f93dd1d4cb3 632 DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8));
sam_grove 5:3f93dd1d4cb3 633
sam_grove 5:3f93dd1d4cb3 634 pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) );
sam_grove 5:3f93dd1d4cb3 635
sam_grove 5:3f93dd1d4cb3 636 res = getConfigurationDescriptor(dev, data, &total_conf_descr_length);
sam_grove 5:3f93dd1d4cb3 637 if (res != USB_TYPE_OK) {
sam_grove 5:3f93dd1d4cb3 638 return res;
sam_grove 5:3f93dd1d4cb3 639 }
sam_grove 5:3f93dd1d4cb3 640
sam_grove 5:3f93dd1d4cb3 641 // Parse the configuration descriptor
sam_grove 5:3f93dd1d4cb3 642 parseConfDescr(dev, data, total_conf_descr_length, pEnumerator);
sam_grove 5:3f93dd1d4cb3 643
sam_grove 5:3f93dd1d4cb3 644
sam_grove 5:3f93dd1d4cb3 645 // sixth step: set configuration (only 1 supported)
sam_grove 5:3f93dd1d4cb3 646 res = setConfiguration(dev, 1);
sam_grove 5:3f93dd1d4cb3 647
sam_grove 5:3f93dd1d4cb3 648 if (res != USB_TYPE_OK) {
sam_grove 5:3f93dd1d4cb3 649 DBG("SET CONF FAILED");
sam_grove 5:3f93dd1d4cb3 650 freeDevice(dev);
sam_grove 5:3f93dd1d4cb3 651 return res;
sam_grove 5:3f93dd1d4cb3 652 }
sam_grove 5:3f93dd1d4cb3 653
sam_grove 5:3f93dd1d4cb3 654 // Now the device is enumerated!
sam_grove 5:3f93dd1d4cb3 655 dev->setEnumerated();
sam_grove 5:3f93dd1d4cb3 656 DBG("device enumerated!!!!");
sam_grove 5:3f93dd1d4cb3 657
sam_grove 5:3f93dd1d4cb3 658 // Some devices may require this delay
sam_grove 5:3f93dd1d4cb3 659 Thread::wait(100);
sam_grove 5:3f93dd1d4cb3 660
sam_grove 5:3f93dd1d4cb3 661 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 662 }
sam_grove 5:3f93dd1d4cb3 663
sam_grove 5:3f93dd1d4cb3 664 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
sam_grove 5:3f93dd1d4cb3 665 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) {
sam_grove 5:3f93dd1d4cb3 666 uint32_t index = 0;
sam_grove 5:3f93dd1d4cb3 667 uint32_t len_desc = 0;
sam_grove 5:3f93dd1d4cb3 668 uint8_t id = 0;
sam_grove 5:3f93dd1d4cb3 669 int nb_endpoints_used = 0;
sam_grove 5:3f93dd1d4cb3 670 USBEndpoint * ep = NULL;
sam_grove 5:3f93dd1d4cb3 671 uint8_t intf_nb = 0;
sam_grove 5:3f93dd1d4cb3 672 bool parsing_intf = false;
sam_grove 5:3f93dd1d4cb3 673
sam_grove 5:3f93dd1d4cb3 674 while (index < len) {
sam_grove 5:3f93dd1d4cb3 675 len_desc = conf_descr[index];
sam_grove 5:3f93dd1d4cb3 676 id = conf_descr[index+1];
sam_grove 5:3f93dd1d4cb3 677 switch (id) {
sam_grove 5:3f93dd1d4cb3 678 case CONFIGURATION_DESCRIPTOR:
sam_grove 5:3f93dd1d4cb3 679 break;
sam_grove 5:3f93dd1d4cb3 680 case INTERFACE_DESCRIPTOR:
sam_grove 5:3f93dd1d4cb3 681 if(pEnumerator->parseInterface(intf_nb, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]))
sam_grove 5:3f93dd1d4cb3 682 {
sam_grove 5:3f93dd1d4cb3 683 if (intf_nb++ <= NB_MAX_INTF) {
sam_grove 5:3f93dd1d4cb3 684 dev->addInterface(intf_nb - 1, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
sam_grove 5:3f93dd1d4cb3 685 nb_endpoints_used = 0;
sam_grove 5:3f93dd1d4cb3 686 DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", intf_nb - 1, (void *)dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]);
sam_grove 5:3f93dd1d4cb3 687 } else {
sam_grove 5:3f93dd1d4cb3 688 DBG("Drop intf...");
sam_grove 5:3f93dd1d4cb3 689 }
sam_grove 5:3f93dd1d4cb3 690 parsing_intf = true;
sam_grove 5:3f93dd1d4cb3 691 }
sam_grove 5:3f93dd1d4cb3 692 else
sam_grove 5:3f93dd1d4cb3 693 {
sam_grove 5:3f93dd1d4cb3 694 parsing_intf = false;
sam_grove 5:3f93dd1d4cb3 695 }
sam_grove 5:3f93dd1d4cb3 696 break;
sam_grove 5:3f93dd1d4cb3 697 case ENDPOINT_DESCRIPTOR:
sam_grove 5:3f93dd1d4cb3 698 DBG("Ep DESC");
sam_grove 5:3f93dd1d4cb3 699 if (parsing_intf && (intf_nb <= NB_MAX_INTF) ) {
sam_grove 5:3f93dd1d4cb3 700 if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) {
sam_grove 5:3f93dd1d4cb3 701 if( pEnumerator->useEndpoint(intf_nb - 1, (ENDPOINT_TYPE)(conf_descr[index + 3] & 0x03), (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1)) )
sam_grove 5:3f93dd1d4cb3 702 {
sam_grove 5:3f93dd1d4cb3 703 // if the USBEndpoint is isochronous -> skip it (TODO: fix this)
sam_grove 5:3f93dd1d4cb3 704 if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) {
sam_grove 5:3f93dd1d4cb3 705 ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03),
sam_grove 5:3f93dd1d4cb3 706 (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1),
sam_grove 5:3f93dd1d4cb3 707 conf_descr[index + 4] | (conf_descr[index + 5] << 8),
sam_grove 5:3f93dd1d4cb3 708 conf_descr[index + 2] & 0x0f);
sam_grove 5:3f93dd1d4cb3 709 DBG("ADD USBEndpoint %p, on interf %d on device %p", (void *)ep, intf_nb - 1, (void *)dev);
sam_grove 5:3f93dd1d4cb3 710 if (ep != NULL && dev != NULL) {
sam_grove 5:3f93dd1d4cb3 711 addEndpoint(dev, intf_nb - 1, ep);
sam_grove 5:3f93dd1d4cb3 712 } else {
sam_grove 5:3f93dd1d4cb3 713 DBG("EP NULL");
sam_grove 5:3f93dd1d4cb3 714 }
sam_grove 5:3f93dd1d4cb3 715 nb_endpoints_used++;
sam_grove 5:3f93dd1d4cb3 716 } else {
sam_grove 5:3f93dd1d4cb3 717 DBG("ISO USBEndpoint NOT SUPPORTED");
sam_grove 5:3f93dd1d4cb3 718 }
sam_grove 5:3f93dd1d4cb3 719 }
sam_grove 5:3f93dd1d4cb3 720 }
sam_grove 5:3f93dd1d4cb3 721 }
sam_grove 5:3f93dd1d4cb3 722 //DBG("USBEndpoint DESCR");
sam_grove 5:3f93dd1d4cb3 723 break;
sam_grove 5:3f93dd1d4cb3 724 case HID_DESCRIPTOR:
sam_grove 5:3f93dd1d4cb3 725 lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
sam_grove 5:3f93dd1d4cb3 726 break;
sam_grove 5:3f93dd1d4cb3 727 default:
sam_grove 5:3f93dd1d4cb3 728 break;
sam_grove 5:3f93dd1d4cb3 729 }
sam_grove 5:3f93dd1d4cb3 730 index += len_desc;
sam_grove 5:3f93dd1d4cb3 731 }
sam_grove 5:3f93dd1d4cb3 732 }
sam_grove 5:3f93dd1d4cb3 733
sam_grove 5:3f93dd1d4cb3 734
sam_grove 5:3f93dd1d4cb3 735 USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
sam_grove 5:3f93dd1d4cb3 736 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 737
sam_grove 5:3f93dd1d4cb3 738 if (dev == NULL || ep == NULL) {
sam_grove 5:3f93dd1d4cb3 739 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 740 }
sam_grove 5:3f93dd1d4cb3 741
sam_grove 5:3f93dd1d4cb3 742 if ((ep->getDir() != IN) || (ep->getType() != BULK_ENDPOINT)) {
sam_grove 5:3f93dd1d4cb3 743 DBG("wrong dir or bad USBEndpoint type");
sam_grove 5:3f93dd1d4cb3 744 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 745 }
sam_grove 5:3f93dd1d4cb3 746 if (dev->getAddress() != ep->getDeviceAddress()) {
sam_grove 5:3f93dd1d4cb3 747 DBG("USBEndpoint addr and device addr don't match");
sam_grove 5:3f93dd1d4cb3 748 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 749 }
sam_grove 5:3f93dd1d4cb3 750 addTransfer(ep, buf, len);
sam_grove 5:3f93dd1d4cb3 751 if (blocking) {
sam_grove 5:3f93dd1d4cb3 752 unlock();
sam_grove 5:3f93dd1d4cb3 753 while ((res = control->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 754 lock();
sam_grove 5:3f93dd1d4cb3 755 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 756 return res;
sam_grove 5:3f93dd1d4cb3 757 }
sam_grove 5:3f93dd1d4cb3 758 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 759 }
sam_grove 5:3f93dd1d4cb3 760 return USB_TYPE_PROCESSING;
sam_grove 5:3f93dd1d4cb3 761 }
sam_grove 5:3f93dd1d4cb3 762
sam_grove 5:3f93dd1d4cb3 763 USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
sam_grove 5:3f93dd1d4cb3 764 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 765
sam_grove 5:3f93dd1d4cb3 766 if (dev == NULL || ep == NULL) {
sam_grove 5:3f93dd1d4cb3 767 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 768 }
sam_grove 5:3f93dd1d4cb3 769
sam_grove 5:3f93dd1d4cb3 770 if ((ep->getDir() != OUT) || (ep->getType() != BULK_ENDPOINT)) {
sam_grove 5:3f93dd1d4cb3 771 DBG("wrong dir or bad USBEndpoint type");
sam_grove 5:3f93dd1d4cb3 772 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 773 }
sam_grove 5:3f93dd1d4cb3 774 if (dev->getAddress() != ep->getDeviceAddress()) {
sam_grove 5:3f93dd1d4cb3 775 DBG("USBEndpoint addr and device addr don't match");
sam_grove 5:3f93dd1d4cb3 776 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 777 }
sam_grove 5:3f93dd1d4cb3 778 addTransfer(ep, buf, len);
sam_grove 5:3f93dd1d4cb3 779 if (blocking) {
sam_grove 5:3f93dd1d4cb3 780 unlock();
sam_grove 5:3f93dd1d4cb3 781 while ((res = control->getState()) == USB_TYPE_PROCESSING)
sam_grove 5:3f93dd1d4cb3 782 {
sam_grove 5:3f93dd1d4cb3 783 DBG("!!!!!!!!!!!!!wait bulkwrite");
sam_grove 5:3f93dd1d4cb3 784 Thread::wait(100);
sam_grove 5:3f93dd1d4cb3 785 }
sam_grove 5:3f93dd1d4cb3 786 lock();
sam_grove 5:3f93dd1d4cb3 787 DBG("!!!!!!!!!!!!! bulkwrite finished");
sam_grove 5:3f93dd1d4cb3 788 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 789 return res;
sam_grove 5:3f93dd1d4cb3 790 }
sam_grove 5:3f93dd1d4cb3 791 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 792 }
sam_grove 5:3f93dd1d4cb3 793 return USB_TYPE_PROCESSING;
sam_grove 5:3f93dd1d4cb3 794 }
sam_grove 5:3f93dd1d4cb3 795
sam_grove 5:3f93dd1d4cb3 796 USB_TYPE USBHost::interruptWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
sam_grove 5:3f93dd1d4cb3 797 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 798
sam_grove 5:3f93dd1d4cb3 799 if (dev == NULL || ep == NULL) {
sam_grove 5:3f93dd1d4cb3 800 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 801 }
sam_grove 5:3f93dd1d4cb3 802
sam_grove 5:3f93dd1d4cb3 803 if (ep->getState() != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 804 return ep->getState();
sam_grove 5:3f93dd1d4cb3 805 }
sam_grove 5:3f93dd1d4cb3 806
sam_grove 5:3f93dd1d4cb3 807 if ((ep->getDir() != OUT) || (ep->getType() != INTERRUPT_ENDPOINT)) {
sam_grove 5:3f93dd1d4cb3 808 ERR("wrong dir or bad USBEndpoint type: %d, %d", ep->getDir(), ep->getType());
sam_grove 5:3f93dd1d4cb3 809 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 810 }
sam_grove 5:3f93dd1d4cb3 811 if (dev->getAddress() != ep->getDeviceAddress()) {
sam_grove 5:3f93dd1d4cb3 812 ERR("USBEndpoint addr and device addr don't match");
sam_grove 5:3f93dd1d4cb3 813 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 814 }
sam_grove 5:3f93dd1d4cb3 815 addTransfer(ep, buf, len);
sam_grove 5:3f93dd1d4cb3 816 if (blocking) {
sam_grove 5:3f93dd1d4cb3 817 while ((res = ep->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 818 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 819 return res;
sam_grove 5:3f93dd1d4cb3 820 }
sam_grove 5:3f93dd1d4cb3 821 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 822 }
sam_grove 5:3f93dd1d4cb3 823 return USB_TYPE_PROCESSING;
sam_grove 5:3f93dd1d4cb3 824 }
sam_grove 5:3f93dd1d4cb3 825
sam_grove 5:3f93dd1d4cb3 826 USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) {
sam_grove 5:3f93dd1d4cb3 827 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 828
sam_grove 5:3f93dd1d4cb3 829 if (dev == NULL || ep == NULL) {
sam_grove 5:3f93dd1d4cb3 830 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 831 }
sam_grove 5:3f93dd1d4cb3 832
sam_grove 5:3f93dd1d4cb3 833 if (ep->getState() != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 834 return ep->getState();
sam_grove 5:3f93dd1d4cb3 835 }
sam_grove 5:3f93dd1d4cb3 836
sam_grove 5:3f93dd1d4cb3 837 if ((ep->getDir() != IN) || (ep->getType() != INTERRUPT_ENDPOINT)) {
sam_grove 5:3f93dd1d4cb3 838 ERR("wrong dir or bad USBEndpoint type");
sam_grove 5:3f93dd1d4cb3 839 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 840 }
sam_grove 5:3f93dd1d4cb3 841
sam_grove 5:3f93dd1d4cb3 842 if (dev->getAddress() != ep->getDeviceAddress()) {
sam_grove 5:3f93dd1d4cb3 843 ERR("USBEndpoint addr and device addr don't match");
sam_grove 5:3f93dd1d4cb3 844 return USB_TYPE_ERROR;
sam_grove 5:3f93dd1d4cb3 845 }
sam_grove 5:3f93dd1d4cb3 846 addTransfer(ep, buf, len);
sam_grove 5:3f93dd1d4cb3 847 if (blocking) {
sam_grove 5:3f93dd1d4cb3 848 while ((res = ep->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 849 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 850 return res;
sam_grove 5:3f93dd1d4cb3 851 }
sam_grove 5:3f93dd1d4cb3 852 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 853 }
sam_grove 5:3f93dd1d4cb3 854 return USB_TYPE_PROCESSING;
sam_grove 5:3f93dd1d4cb3 855 }
sam_grove 5:3f93dd1d4cb3 856
sam_grove 5:3f93dd1d4cb3 857
sam_grove 5:3f93dd1d4cb3 858 USB_TYPE USBHost::controlRead(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
sam_grove 5:3f93dd1d4cb3 859 int length_transfer = len;
sam_grove 5:3f93dd1d4cb3 860 //DBG("want to transfer: %d bytes\r\n", length_transfer);
sam_grove 5:3f93dd1d4cb3 861 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 862 control->setSpeed(dev->getSpeed());
sam_grove 5:3f93dd1d4cb3 863 control->setSize(dev->getSizeControlEndpoint());
sam_grove 5:3f93dd1d4cb3 864 if (dev->isActiveAddress()) {
sam_grove 5:3f93dd1d4cb3 865 control->setDeviceAddress(dev->getAddress());
sam_grove 5:3f93dd1d4cb3 866 } else {
sam_grove 5:3f93dd1d4cb3 867 control->setDeviceAddress(0);
sam_grove 5:3f93dd1d4cb3 868 }
sam_grove 5:3f93dd1d4cb3 869 fillControlBuf(requestType, request, value, index, len);
sam_grove 5:3f93dd1d4cb3 870 /* DBG("will call transfer: ");
sam_grove 5:3f93dd1d4cb3 871 for (int i = 0; i < 8; i++) {
sam_grove 5:3f93dd1d4cb3 872 DBG("%02X ", setupPacket[i]);
sam_grove 5:3f93dd1d4cb3 873 }*/
sam_grove 5:3f93dd1d4cb3 874 control->setNextToken(TD_SETUP);
sam_grove 5:3f93dd1d4cb3 875 addTransfer(control, (uint8_t*)setupPacket, 8);
sam_grove 5:3f93dd1d4cb3 876 DBG("Now wait for TD to be processed");
sam_grove 5:3f93dd1d4cb3 877 unlock();
sam_grove 5:3f93dd1d4cb3 878 DBG("Unlocked");
sam_grove 5:3f93dd1d4cb3 879 while ((res = control->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 880 lock();
sam_grove 5:3f93dd1d4cb3 881 DBG("TD processed with result %d", res);
sam_grove 5:3f93dd1d4cb3 882 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 883 return res;
sam_grove 5:3f93dd1d4cb3 884 }
sam_grove 5:3f93dd1d4cb3 885
sam_grove 5:3f93dd1d4cb3 886 if (length_transfer) {
sam_grove 5:3f93dd1d4cb3 887 DBG("In data to be transfered...");
sam_grove 5:3f93dd1d4cb3 888 control->setNextToken(TD_IN);
sam_grove 5:3f93dd1d4cb3 889 addTransfer(control, (uint8_t *)buf, length_transfer);
sam_grove 5:3f93dd1d4cb3 890 unlock();
sam_grove 5:3f93dd1d4cb3 891 while ((res = control->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 892 lock();
sam_grove 5:3f93dd1d4cb3 893 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 894 return res;
sam_grove 5:3f93dd1d4cb3 895 }
sam_grove 5:3f93dd1d4cb3 896 }
sam_grove 5:3f93dd1d4cb3 897
sam_grove 5:3f93dd1d4cb3 898 DBG("Transfer NULL packet (OUT)");
sam_grove 5:3f93dd1d4cb3 899 control->setNextToken(TD_OUT);
sam_grove 5:3f93dd1d4cb3 900 addTransfer(control, NULL, 0);
sam_grove 5:3f93dd1d4cb3 901 unlock();
sam_grove 5:3f93dd1d4cb3 902 while ((res = control->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 903 lock();
sam_grove 5:3f93dd1d4cb3 904 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 905 return res;
sam_grove 5:3f93dd1d4cb3 906 }
sam_grove 5:3f93dd1d4cb3 907 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 908 }
sam_grove 5:3f93dd1d4cb3 909
sam_grove 5:3f93dd1d4cb3 910
sam_grove 5:3f93dd1d4cb3 911 USB_TYPE USBHost::controlWrite(USBDeviceConnected * dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
sam_grove 5:3f93dd1d4cb3 912 control->setSpeed(dev->getSpeed());
sam_grove 5:3f93dd1d4cb3 913
sam_grove 5:3f93dd1d4cb3 914 int length_transfer = len;
sam_grove 5:3f93dd1d4cb3 915 USB_TYPE res;
sam_grove 5:3f93dd1d4cb3 916
sam_grove 5:3f93dd1d4cb3 917 control->setSize(dev->getSizeControlEndpoint());
sam_grove 5:3f93dd1d4cb3 918 if (dev->isActiveAddress()) {
sam_grove 5:3f93dd1d4cb3 919 control->setDeviceAddress(dev->getAddress());
sam_grove 5:3f93dd1d4cb3 920 } else {
sam_grove 5:3f93dd1d4cb3 921 control->setDeviceAddress(0);
sam_grove 5:3f93dd1d4cb3 922 }
sam_grove 5:3f93dd1d4cb3 923 fillControlBuf(requestType, request, value, index, len);
sam_grove 5:3f93dd1d4cb3 924 /*DBG("will call transfer: ");
sam_grove 5:3f93dd1d4cb3 925 for (int i = 0; i < 8; i++) {
sam_grove 5:3f93dd1d4cb3 926 printf("%01X ", setupPacket[i]);
sam_grove 5:3f93dd1d4cb3 927 }
sam_grove 5:3f93dd1d4cb3 928 printf("\r\n");*/
sam_grove 5:3f93dd1d4cb3 929 control->setNextToken(TD_SETUP);
sam_grove 5:3f93dd1d4cb3 930 addTransfer(control, (uint8_t*)setupPacket, 8);
sam_grove 5:3f93dd1d4cb3 931 DBG("Now wait for TD to be processed");
sam_grove 5:3f93dd1d4cb3 932 unlock();
sam_grove 5:3f93dd1d4cb3 933 DBG("Unlocked");
sam_grove 5:3f93dd1d4cb3 934 while ((res = control->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 935 lock();
sam_grove 5:3f93dd1d4cb3 936 DBG("TD processed with result %d", res);
sam_grove 5:3f93dd1d4cb3 937 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 938 return res;
sam_grove 5:3f93dd1d4cb3 939 }
sam_grove 5:3f93dd1d4cb3 940
sam_grove 5:3f93dd1d4cb3 941 if (length_transfer) {
sam_grove 5:3f93dd1d4cb3 942 control->setNextToken(TD_OUT);
sam_grove 5:3f93dd1d4cb3 943 addTransfer(control, (uint8_t *)buf, length_transfer);
sam_grove 5:3f93dd1d4cb3 944 unlock();
sam_grove 5:3f93dd1d4cb3 945 while ((res = control->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 946 lock();
sam_grove 5:3f93dd1d4cb3 947 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 948 return res;
sam_grove 5:3f93dd1d4cb3 949 }
sam_grove 5:3f93dd1d4cb3 950 }
sam_grove 5:3f93dd1d4cb3 951
sam_grove 5:3f93dd1d4cb3 952 control->setNextToken(TD_IN);
sam_grove 5:3f93dd1d4cb3 953 addTransfer(control, NULL, 0);
sam_grove 5:3f93dd1d4cb3 954 unlock();
sam_grove 5:3f93dd1d4cb3 955 while ((res = control->getState()) == USB_TYPE_PROCESSING);
sam_grove 5:3f93dd1d4cb3 956 lock();
sam_grove 5:3f93dd1d4cb3 957 if (res != USB_TYPE_IDLE) {
sam_grove 5:3f93dd1d4cb3 958 return res;
sam_grove 5:3f93dd1d4cb3 959 }
sam_grove 5:3f93dd1d4cb3 960 return USB_TYPE_OK;
sam_grove 5:3f93dd1d4cb3 961 }
sam_grove 5:3f93dd1d4cb3 962
sam_grove 5:3f93dd1d4cb3 963
sam_grove 5:3f93dd1d4cb3 964 void USBHost::fillControlBuf(uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, int len) {
sam_grove 5:3f93dd1d4cb3 965 #ifdef __BIG_ENDIAN
sam_grove 5:3f93dd1d4cb3 966 #error "Must implement BE to LE conv here"
sam_grove 5:3f93dd1d4cb3 967 #endif
sam_grove 5:3f93dd1d4cb3 968 setupPacket[0] = requestType;
sam_grove 5:3f93dd1d4cb3 969 setupPacket[1] = request;
sam_grove 5:3f93dd1d4cb3 970 //We are in LE so it's fine
sam_grove 5:3f93dd1d4cb3 971 *((uint32_t*)&setupPacket[2]) = value;
sam_grove 5:3f93dd1d4cb3 972 *((uint32_t*)&setupPacket[4]) = index;
sam_grove 5:3f93dd1d4cb3 973 *((uint32_t*)&setupPacket[6]) = (uint32_t) len;
sam_grove 5:3f93dd1d4cb3 974 }
sam_grove 5:3f93dd1d4cb3 975