Committer:
RichardUK
Date:
Wed Sep 19 16:44:32 2012 +0000
Revision:
2:33e7ce63dd6d
Parent:
1:4461071ed964
Testing lib update to another project.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RichardUK 0:63d45df56584 1 /*
RichardUK 0:63d45df56584 2 A host controller driver from the mBed device.
RichardUK 0:63d45df56584 3 Copyright (C) 2012 Richard e Collins - richard.collins@linux.com
RichardUK 0:63d45df56584 4
RichardUK 0:63d45df56584 5 This program is free software: you can redistribute it and/or modify
RichardUK 0:63d45df56584 6 it under the terms of the GNU General Public License as published by
RichardUK 0:63d45df56584 7 the Free Software Foundation, either version 3 of the License, or
RichardUK 0:63d45df56584 8 (at your option) any later version.
RichardUK 0:63d45df56584 9
RichardUK 0:63d45df56584 10 This program is distributed in the hope that it will be useful,
RichardUK 0:63d45df56584 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
RichardUK 0:63d45df56584 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
RichardUK 0:63d45df56584 13 GNU General Public License for more details.
RichardUK 0:63d45df56584 14
RichardUK 0:63d45df56584 15 You should have received a copy of the GNU General Public License
RichardUK 0:63d45df56584 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
RichardUK 0:63d45df56584 17 */
RichardUK 0:63d45df56584 18
RichardUK 0:63d45df56584 19 #include <mbed.h>
RichardUK 0:63d45df56584 20 #include "UsbHost.h"
RichardUK 0:63d45df56584 21 #include "UsbHostController.h"
RichardUK 0:63d45df56584 22 #include "HardwareDefines.h"
RichardUK 0:63d45df56584 23 #include "Debug.h"
RichardUK 0:63d45df56584 24 #include "UsbStructures.h"
RichardUK 0:63d45df56584 25 #include "UsbEnums.h"
RichardUK 0:63d45df56584 26
RichardUK 1:4461071ed964 27 #if 0
RichardUK 1:4461071ed964 28 #define DEBUGV DEBUG
RichardUK 1:4461071ed964 29 #else
RichardUK 1:4461071ed964 30 #define DEBUGV(...) do {} while(0)
RichardUK 0:63d45df56584 31 #endif
RichardUK 0:63d45df56584 32
RichardUK 1:4461071ed964 33
RichardUK 1:4461071ed964 34
RichardUK 0:63d45df56584 35 namespace USB
RichardUK 0:63d45df56584 36 {
RichardUK 0:63d45df56584 37
RichardUK 0:63d45df56584 38 uint32_t controlTransferDataLength = 0;
RichardUK 0:63d45df56584 39
RichardUK 0:63d45df56584 40 Host::Host()
RichardUK 0:63d45df56584 41 {
RichardUK 0:63d45df56584 42 for( int n = 0 ; n < MAX_DEVICES ; n++ )
RichardUK 0:63d45df56584 43 {
RichardUK 0:63d45df56584 44 devices[n] = NULL;
RichardUK 0:63d45df56584 45 }
RichardUK 0:63d45df56584 46
RichardUK 0:63d45df56584 47 driver = HostController::get();
RichardUK 0:63d45df56584 48 driver->Init(this,deviceZero);
RichardUK 0:63d45df56584 49 }
RichardUK 0:63d45df56584 50
RichardUK 0:63d45df56584 51 Host::~Host()
RichardUK 0:63d45df56584 52 {
RichardUK 0:63d45df56584 53 }
RichardUK 0:63d45df56584 54
RichardUK 0:63d45df56584 55 Device* Host::AllocateDevice(int endpointZeroMaxPacketSize,int hubPortStatus)
RichardUK 0:63d45df56584 56 {
RichardUK 0:63d45df56584 57 for( int n = 0 ; n < MAX_DEVICES ; n++ )
RichardUK 0:63d45df56584 58 {
RichardUK 0:63d45df56584 59 if( devices[n] == NULL )
RichardUK 0:63d45df56584 60 {
RichardUK 0:63d45df56584 61 devices[n] = (Device *)driver->AllocateMemoryPoolItem();
RichardUK 1:4461071ed964 62 memset(devices[n],0,sizeof(Device));
RichardUK 0:63d45df56584 63 devices[n]->id = (uint8_t)(n+1);//The device is +1 as device 0 is the host controller.
RichardUK 0:63d45df56584 64 devices[n]->endpointZeroMaxPacketSize = endpointZeroMaxPacketSize;
RichardUK 0:63d45df56584 65 devices[n]->lowspeed = (hubPortStatus&ROOTHUB_LOW_SPEED_DEVICE_ATTACHED) ? 1 : 0;
RichardUK 1:4461071ed964 66 devices[n]->blockOnEP = -1;
RichardUK 0:63d45df56584 67 return devices[n];
RichardUK 0:63d45df56584 68 }
RichardUK 0:63d45df56584 69 }
RichardUK 0:63d45df56584 70 return NULL;
RichardUK 0:63d45df56584 71 }
RichardUK 0:63d45df56584 72
RichardUK 0:63d45df56584 73 void Host::SendControlTransferData(Device* device,int dataToggle)
RichardUK 0:63d45df56584 74 {
RichardUK 1:4461071ed964 75 driver->QueueControlTransfer(
RichardUK 0:63d45df56584 76 device->id,
RichardUK 0:63d45df56584 77 device->controlTransferDirToHost == 1 ? TDD_IN : TDD_OUT,
RichardUK 0:63d45df56584 78 0,
RichardUK 0:63d45df56584 79 device->endpointZeroMaxPacketSize,
RichardUK 0:63d45df56584 80 device->lowspeed,
RichardUK 0:63d45df56584 81 dataToggle,
RichardUK 0:63d45df56584 82 device->controlTransferData,
RichardUK 0:63d45df56584 83 device->controlTransferDataLength);
RichardUK 0:63d45df56584 84
RichardUK 0:63d45df56584 85 device->controlTransferState = CTS_DATA;
RichardUK 0:63d45df56584 86 }
RichardUK 0:63d45df56584 87
RichardUK 0:63d45df56584 88 void Host::SendControlTransferAcknowledge(Device* device,int dataToggle)
RichardUK 0:63d45df56584 89 {
RichardUK 0:63d45df56584 90 //Send empty packet to ACK.
RichardUK 1:4461071ed964 91 driver->QueueControlTransfer(
RichardUK 0:63d45df56584 92 device->id,
RichardUK 0:63d45df56584 93 device->controlTransferDirToHost == 0 ? TDD_IN : TDD_OUT,
RichardUK 0:63d45df56584 94 0,
RichardUK 0:63d45df56584 95 device->endpointZeroMaxPacketSize,
RichardUK 0:63d45df56584 96 device->lowspeed,
RichardUK 0:63d45df56584 97 dataToggle,
RichardUK 0:63d45df56584 98 NULL,0);
RichardUK 0:63d45df56584 99
RichardUK 0:63d45df56584 100 device->controlTransferState = CTS_ACK;
RichardUK 0:63d45df56584 101 }
RichardUK 0:63d45df56584 102
RichardUK 0:63d45df56584 103 Device* Host::getDevice(int deviceID)
RichardUK 0:63d45df56584 104 {
RichardUK 0:63d45df56584 105 if( deviceID == 0 )
RichardUK 0:63d45df56584 106 {
RichardUK 0:63d45df56584 107 return deviceZero;
RichardUK 0:63d45df56584 108 }
RichardUK 0:63d45df56584 109
RichardUK 0:63d45df56584 110 deviceID--;
RichardUK 0:63d45df56584 111 if( deviceID > -1 && deviceID < MAX_DEVICES )
RichardUK 0:63d45df56584 112 {
RichardUK 0:63d45df56584 113 return devices[deviceID];
RichardUK 0:63d45df56584 114 }
RichardUK 0:63d45df56584 115 return NULL;
RichardUK 0:63d45df56584 116 }
RichardUK 0:63d45df56584 117
RichardUK 0:63d45df56584 118 void Host::Update()
RichardUK 0:63d45df56584 119 {
RichardUK 0:63d45df56584 120 driver->Update();
RichardUK 1:4461071ed964 121 //Now the host has been updated service any outstanding transfers.
RichardUK 1:4461071ed964 122 for(int n = 0 ; n < MAX_DEVICES ; n++ )
RichardUK 1:4461071ed964 123 {
RichardUK 1:4461071ed964 124 if( devices[n] != NULL && devices[n]->pendingCallbacks != NULL )
RichardUK 1:4461071ed964 125 {
RichardUK 1:4461071ed964 126 TransferDescriptor *transfer = devices[n]->pendingCallbacks;
RichardUK 1:4461071ed964 127 devices[n]->pendingCallbacks = NULL;
RichardUK 1:4461071ed964 128
RichardUK 1:4461071ed964 129 while( transfer )
RichardUK 1:4461071ed964 130 {
RichardUK 1:4461071ed964 131 TransferDescriptor *next = transfer->nextTD;
RichardUK 1:4461071ed964 132 // DEBUG("onReceive (0x%08x) (0x%08x)",transfer,next);
RichardUK 1:4461071ed964 133
RichardUK 1:4461071ed964 134
RichardUK 1:4461071ed964 135 int deviceEP = transfer->ep | (transfer->direction == TDD_IN ? 0x80 : 0);
RichardUK 1:4461071ed964 136 int reciveLength = transfer->CurrentBufferPointer - transfer->data;
RichardUK 1:4461071ed964 137 transfer->transferCallback->onReceive(devices[n]->id,deviceEP,0,transfer->data,reciveLength);
RichardUK 1:4461071ed964 138
RichardUK 1:4461071ed964 139 driver->FreeMemoryPoolItem(transfer);
RichardUK 1:4461071ed964 140 transfer = next;
RichardUK 1:4461071ed964 141 }
RichardUK 1:4461071ed964 142 }
RichardUK 1:4461071ed964 143 }
RichardUK 0:63d45df56584 144 }
RichardUK 0:63d45df56584 145
RichardUK 0:63d45df56584 146 int Host::getDeviceDescriptor(int deviceID,DeviceDescription &description)
RichardUK 0:63d45df56584 147 {
RichardUK 0:63d45df56584 148 return ControlTransfer(deviceID,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_DEVICE << 8), 0, (uint8_t*)&description, sizeof(description),DEFAULT_TIMEOUT);
RichardUK 0:63d45df56584 149 }
RichardUK 0:63d45df56584 150
RichardUK 0:63d45df56584 151 const uint8_t* Host::getConfigurationDescriptor(int deviceID,int index)
RichardUK 0:63d45df56584 152 {
RichardUK 0:63d45df56584 153 uint8_t* buf = driver->getScratchRam();
RichardUK 0:63d45df56584 154 ControlTransfer(deviceID,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_CONFIG << 8)|index, 0,buf,255,DEFAULT_TIMEOUT);
RichardUK 0:63d45df56584 155 return (const uint8_t*)buf;
RichardUK 0:63d45df56584 156 }
RichardUK 0:63d45df56584 157
RichardUK 0:63d45df56584 158 const char* Host::getStringDescriptor(int deviceID,int index)
RichardUK 0:63d45df56584 159 {
RichardUK 0:63d45df56584 160 Device* dev = getDevice(deviceID);
RichardUK 0:63d45df56584 161 if( dev == NULL )
RichardUK 0:63d45df56584 162 {
RichardUK 0:63d45df56584 163 return "error";
RichardUK 0:63d45df56584 164 }
RichardUK 0:63d45df56584 165
RichardUK 0:63d45df56584 166 uint8_t* buf = driver->getScratchRam();
RichardUK 0:63d45df56584 167 ControlTransfer(deviceID,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_STRING << 8)|index, dev->languageID,buf,255,DEFAULT_TIMEOUT);
RichardUK 0:63d45df56584 168
RichardUK 0:63d45df56584 169 uint8_t* string = buf;
RichardUK 0:63d45df56584 170 int len = buf[0];
RichardUK 0:63d45df56584 171 for( int n = 2 ; n < len ; n += 2 )
RichardUK 0:63d45df56584 172 {
RichardUK 0:63d45df56584 173 *string++ = buf[n];
RichardUK 0:63d45df56584 174 }
RichardUK 0:63d45df56584 175 *string = 0;
RichardUK 0:63d45df56584 176 return (char*)buf;
RichardUK 0:63d45df56584 177 }
RichardUK 0:63d45df56584 178
RichardUK 0:63d45df56584 179 int Host::setConfiguration(int deviceID,int configuration)
RichardUK 0:63d45df56584 180 {
RichardUK 0:63d45df56584 181 return ControlTransfer(deviceID,LIBUSB_ENDPOINT_OUT, LIBUSB_REQUEST_SET_CONFIGURATION,configuration, 0,NULL,0,DEFAULT_TIMEOUT);
RichardUK 0:63d45df56584 182 }
RichardUK 0:63d45df56584 183
RichardUK 0:63d45df56584 184 /*
RichardUK 0:63d45df56584 185 * Control transfer uses three stages, the setup stage where the request is sent.
RichardUK 0:63d45df56584 186 * The optional Data Stage consists of one or multiple IN or OUT transfers.
RichardUK 0:63d45df56584 187 * The setup request indicates the amount of data to be transmitted in this stage.
RichardUK 0:63d45df56584 188 * If it exceeds the maximum packet size, data will be sent in multiple transfers each being the maximum packet length except for the last packet.
RichardUK 0:63d45df56584 189 * Status Stage reports the status of the overall request and this once again varies due to direction of transfer. Status reporting is always performed by the function.
RichardUK 0:63d45df56584 190 */
RichardUK 0:63d45df56584 191 int Host::ControlTransfer(int deviceID,uint8_t requestType, uint8_t request, uint16_t value, uint16_t index,const uint8_t *data, uint16_t length, uint32_t timeout)
RichardUK 0:63d45df56584 192 {
RichardUK 1:4461071ed964 193 DEBUGV("ControlTransfer");
RichardUK 0:63d45df56584 194
RichardUK 0:63d45df56584 195 Device* device = getDevice(deviceID);
RichardUK 0:63d45df56584 196
RichardUK 0:63d45df56584 197 //Remeber the packet we are sending so that when we get the responce from the setup packet we can then ask for or send the data.
RichardUK 0:63d45df56584 198 device->controlTransferData = data;
RichardUK 0:63d45df56584 199 device->controlTransferDataLength = length;
RichardUK 0:63d45df56584 200 device->controlTransferDirToHost = (requestType & LIBUSB_ENDPOINT_IN) ? 1 : 0;
RichardUK 0:63d45df56584 201 device->controlTransferState = CTS_SETUP;
RichardUK 0:63d45df56584 202
RichardUK 0:63d45df56584 203 //First do the setup packet.
RichardUK 0:63d45df56584 204 SetupPacket* sp = (SetupPacket*)driver->AllocateMemoryPoolItem();
RichardUK 0:63d45df56584 205
RichardUK 0:63d45df56584 206 sp->requestType = requestType;
RichardUK 0:63d45df56584 207 sp->request = request;
RichardUK 0:63d45df56584 208 sp->value = value;
RichardUK 0:63d45df56584 209 sp->index = index;
RichardUK 0:63d45df56584 210 sp->length = length;
RichardUK 0:63d45df56584 211
RichardUK 1:4461071ed964 212 DEBUGV("Setup %d %d %d %d %d",sp->requestType,sp->request,sp->value,sp->index,sp->length);
RichardUK 0:63d45df56584 213
RichardUK 1:4461071ed964 214 driver->QueueControlTransfer(deviceID,TDD_SETUP,0,device->endpointZeroMaxPacketSize,device->lowspeed,TOGGLE_DATA0,(const uint8_t*)sp,sizeof(SetupPacket));
RichardUK 0:63d45df56584 215
RichardUK 0:63d45df56584 216 while(device->controlTransferState != CTS_IDLE)
RichardUK 0:63d45df56584 217 {
RichardUK 1:4461071ed964 218 wait_ms(50);
RichardUK 0:63d45df56584 219 };
RichardUK 0:63d45df56584 220
RichardUK 0:63d45df56584 221 //Free this up.
RichardUK 0:63d45df56584 222 driver->FreeMemoryPoolItem(sp);
RichardUK 1:4461071ed964 223 DEBUGV("Done, recived %d",controlTransferDataLength);
RichardUK 0:63d45df56584 224
RichardUK 0:63d45df56584 225 return 0;
RichardUK 0:63d45df56584 226 }
RichardUK 0:63d45df56584 227
RichardUK 1:4461071ed964 228 int Host::BulkTransfer(int deviceID,uint8_t endpoint,const uint8_t* data,int length,TransferCallback* callback)
RichardUK 0:63d45df56584 229 {
RichardUK 1:4461071ed964 230 DEBUGV("BulkTransfer Device(%d) EP(%d) Len(%d) CB(0x%08x)",deviceID,endpoint,length,callback);
RichardUK 0:63d45df56584 231
RichardUK 0:63d45df56584 232 Device* device = getDevice(deviceID);
RichardUK 1:4461071ed964 233 device->blockOnEP = endpoint;
RichardUK 1:4461071ed964 234
RichardUK 1:4461071ed964 235 driver->QueueBulkTransfer(deviceID,(endpoint&LIBUSB_ENDPOINT_IN) ? TDD_IN : TDD_OUT,endpoint&0x7f,device->endpointZeroMaxPacketSize,device->lowspeed,callback,data,length);
RichardUK 0:63d45df56584 236
RichardUK 1:4461071ed964 237 if( callback == NULL )
RichardUK 0:63d45df56584 238 {
RichardUK 1:4461071ed964 239 while( device->blockOnEP == endpoint )
RichardUK 1:4461071ed964 240 {
RichardUK 1:4461071ed964 241 driver->Update();
RichardUK 1:4461071ed964 242 wait_ms(100);
RichardUK 1:4461071ed964 243 }
RichardUK 1:4461071ed964 244 }
RichardUK 0:63d45df56584 245
RichardUK 0:63d45df56584 246 return 0;
RichardUK 0:63d45df56584 247 }
RichardUK 0:63d45df56584 248
RichardUK 0:63d45df56584 249
RichardUK 0:63d45df56584 250 void Host::AddDevice(int hub,int port,int hubPortStatus)
RichardUK 0:63d45df56584 251 {
RichardUK 0:63d45df56584 252 DEBUG("AddDevice(%d,%d,%08x)",hub,port,hubPortStatus);
RichardUK 0:63d45df56584 253 DeviceDescription description;
RichardUK 0:63d45df56584 254 description.length = sizeof(DeviceDescription);
RichardUK 0:63d45df56584 255
RichardUK 0:63d45df56584 256 //Setup device zero.
RichardUK 0:63d45df56584 257 deviceZero->endpointZeroMaxPacketSize = 8;
RichardUK 0:63d45df56584 258 deviceZero->lowspeed = (hubPortStatus&ROOTHUB_LOW_SPEED_DEVICE_ATTACHED) ? 1 : 0;
RichardUK 0:63d45df56584 259
RichardUK 0:63d45df56584 260 //For the enumeration we'll use device zero, once done will set the device address and get the rest of the details.
RichardUK 0:63d45df56584 261 //Now we add the first endpoint, endpoint zero by default.
RichardUK 0:63d45df56584 262 //Once added we'll read the device's config and add endpoints for them.
RichardUK 0:63d45df56584 263 //I add my endpoints to the host controller and leave them there.
RichardUK 0:63d45df56584 264 //I set the direction code so that the direction is read from the transfer descriptor.
RichardUK 0:63d45df56584 265 //This means that I need less endpoint objects.
RichardUK 0:63d45df56584 266 //I leave them attached with not transfers to do. That is ok and as per the spec.
RichardUK 0:63d45df56584 267 //Old devices may only have a max packet size of 8 bytes.
RichardUK 0:63d45df56584 268
RichardUK 0:63d45df56584 269 //Using device 0 for the setup and enum phase of the newley connected device.
RichardUK 0:63d45df56584 270 //We do this just to get some info on the device and then send a 'set address' command.
RichardUK 0:63d45df56584 271 //At that point we'll start using it's real ID.
RichardUK 1:4461071ed964 272 DEBUGV("Getting endpoint zero maxPacketSize");
RichardUK 0:63d45df56584 273 ControlTransfer(0,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_DEVICE << 8), 0, (uint8_t*)&description,8,DEFAULT_TIMEOUT);
RichardUK 0:63d45df56584 274
RichardUK 0:63d45df56584 275
RichardUK 0:63d45df56584 276 //Now allocate the device and it's ID.
RichardUK 1:4461071ed964 277 DEBUGV("Allocating device");
RichardUK 0:63d45df56584 278 Device* device = AllocateDevice(description.maxPacketSize,hubPortStatus);
RichardUK 0:63d45df56584 279
RichardUK 0:63d45df56584 280 //Now correct the endpoint's max packet size. Needs this for when we setup the endpoint descriptor for a transfer.
RichardUK 1:4461071ed964 281 DEBUGV("endpointZeroMaxPacketSize(%d)",device->endpointZeroMaxPacketSize);
RichardUK 0:63d45df56584 282
RichardUK 0:63d45df56584 283 //Set the devices new address.
RichardUK 1:4461071ed964 284 DEBUGV("Setting device address to %d",device->id);
RichardUK 0:63d45df56584 285 ControlTransfer(0,LIBUSB_ENDPOINT_OUT | LIBUSB_RECIPIENT_DEVICE, LIBUSB_REQUEST_SET_ADDRESS, device->id,0,NULL,0,DEFAULT_TIMEOUT);
RichardUK 0:63d45df56584 286
RichardUK 0:63d45df56584 287 //New ID is now set, so we can free the object used when it was called device zero.
RichardUK 0:63d45df56584 288 driver->DetachDevice(0);
RichardUK 0:63d45df56584 289
RichardUK 0:63d45df56584 290 //Now fetch the full device description.
RichardUK 1:4461071ed964 291 DEBUGV("Getting device description");
RichardUK 0:63d45df56584 292 getDeviceDescriptor(device->id,description);
RichardUK 0:63d45df56584 293
RichardUK 1:4461071ed964 294 DEBUGV("idVendor(0x%04x) idProduct(0x%04x)",description.idVendor,description.idProduct);
RichardUK 0:63d45df56584 295
RichardUK 0:63d45df56584 296 //Get the language ID.
RichardUK 0:63d45df56584 297 uint16_t* lang = (uint16_t*)driver->AllocateMemoryPoolItem();
RichardUK 0:63d45df56584 298 ControlTransfer(device->id,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,LIBUSB_DT_STRING<<8,0,(uint8_t*)lang,16,DEFAULT_TIMEOUT);
RichardUK 0:63d45df56584 299 device->languageID = lang[1];
RichardUK 0:63d45df56584 300 driver->FreeMemoryPoolItem(lang);
RichardUK 0:63d45df56584 301
RichardUK 0:63d45df56584 302 //Set the first config by default, will get most things up and running.
RichardUK 0:63d45df56584 303 const USB::ConfigurationDescription* config = (const USB::ConfigurationDescription*)getConfigurationDescriptor(device->id,0);
RichardUK 0:63d45df56584 304 wait_ms(100);
RichardUK 0:63d45df56584 305 setConfiguration(device->id,config->configID);
RichardUK 0:63d45df56584 306 wait_ms(100);
RichardUK 0:63d45df56584 307
RichardUK 0:63d45df56584 308 //Tell the app's inherted code about this new device.
RichardUK 0:63d45df56584 309 onConnected(device->id,description);
RichardUK 0:63d45df56584 310 }
RichardUK 0:63d45df56584 311
RichardUK 0:63d45df56584 312 void Host::TransferDone(TransferDescriptor *transfer)
RichardUK 0:63d45df56584 313 {
RichardUK 1:4461071ed964 314 //This is the endpoint with the dir encoded into it, the way it is done to the applicaition coder.
RichardUK 1:4461071ed964 315 //Needed when we are blocking for a non interput transfer to finish.
RichardUK 1:4461071ed964 316 int epDir = transfer->ep | (transfer->direction==TDD_IN?0x80:0);
RichardUK 1:4461071ed964 317 DEBUGV("TransferDone, device(%d) ep(%d) errorCount(%d) status(%d) direction(%d) dataToggle(%d)",transfer->deviceID,epDir,transfer->errorCount,transfer->conditionCode,transfer->direction,transfer->dataToggle);
RichardUK 0:63d45df56584 318
RichardUK 0:63d45df56584 319 //Get the device this TD that has just been done for.
RichardUK 0:63d45df56584 320 Device* device = getDevice(transfer->deviceID);
RichardUK 0:63d45df56584 321
RichardUK 1:4461071ed964 322 if( transfer->transferType == TT_CONTROL )
RichardUK 0:63d45df56584 323 {
RichardUK 1:4461071ed964 324 //See if this was a setup packet, if so do we have data to ask for, if not then just ack the transaction.
RichardUK 1:4461071ed964 325 //TODO: Error checking!
RichardUK 1:4461071ed964 326 switch( device->controlTransferState )
RichardUK 0:63d45df56584 327 {
RichardUK 1:4461071ed964 328 case CTS_SETUP:
RichardUK 1:4461071ed964 329 if( device->controlTransferData != NULL )
RichardUK 1:4461071ed964 330 {
RichardUK 1:4461071ed964 331 SendControlTransferData(device,transfer->dataToggle);
RichardUK 1:4461071ed964 332 }
RichardUK 1:4461071ed964 333 else
RichardUK 1:4461071ed964 334 {
RichardUK 1:4461071ed964 335 SendControlTransferAcknowledge(device,transfer->dataToggle);
RichardUK 1:4461071ed964 336 }
RichardUK 1:4461071ed964 337 break;
RichardUK 1:4461071ed964 338
RichardUK 1:4461071ed964 339 case CTS_DATA:
RichardUK 1:4461071ed964 340 controlTransferDataLength = (transfer->bufferEnd - device->controlTransferData) + 1;
RichardUK 0:63d45df56584 341 SendControlTransferAcknowledge(device,transfer->dataToggle);
RichardUK 1:4461071ed964 342 break;
RichardUK 1:4461071ed964 343
RichardUK 1:4461071ed964 344 case CTS_ACK:
RichardUK 1:4461071ed964 345 device->controlTransferState = CTS_IDLE;
RichardUK 1:4461071ed964 346 break;
RichardUK 0:63d45df56584 347 }
RichardUK 1:4461071ed964 348 }
RichardUK 1:4461071ed964 349
RichardUK 1:4461071ed964 350 if( transfer->transferCallback != NULL )
RichardUK 1:4461071ed964 351 {
RichardUK 1:4461071ed964 352 transfer->nextTD = device->pendingCallbacks;
RichardUK 1:4461071ed964 353 device->pendingCallbacks = transfer;
RichardUK 1:4461071ed964 354 }
RichardUK 1:4461071ed964 355
RichardUK 1:4461071ed964 356 if( device->blockOnEP == epDir )
RichardUK 1:4461071ed964 357 {
RichardUK 1:4461071ed964 358 device->blockOnEP = -1;
RichardUK 1:4461071ed964 359 }
RichardUK 0:63d45df56584 360
RichardUK 0:63d45df56584 361 }
RichardUK 0:63d45df56584 362
RichardUK 0:63d45df56584 363 };//namespace USB