Revision:
1:4461071ed964
Parent:
0:63d45df56584
--- a/UsbHost.cpp	Sun Jul 08 20:18:58 2012 +0000
+++ b/UsbHost.cpp	Wed Sep 19 16:39:23 2012 +0000
@@ -24,12 +24,14 @@
 #include "UsbStructures.h"
 #include "UsbEnums.h"
 
-//Do #if 0 to enable debug log on the host controller driver.
-#if 1
-#undef DEBUG
-#define  DEBUG(...)       do {} while(0)
+#if 0
+#define DEBUGV DEBUG
+#else
+#define  DEBUGV(...)       do {} while(0)
 #endif
 
+
+
 namespace USB
 {
 
@@ -57,10 +59,11 @@
         if( devices[n] == NULL )
         {
             devices[n] = (Device *)driver->AllocateMemoryPoolItem();
+            memset(devices[n],0,sizeof(Device));
             devices[n]->id = (uint8_t)(n+1);//The device is +1 as device 0 is the host controller.
             devices[n]->endpointZeroMaxPacketSize = endpointZeroMaxPacketSize;
             devices[n]->lowspeed = (hubPortStatus&ROOTHUB_LOW_SPEED_DEVICE_ATTACHED) ? 1 : 0;
-
+            devices[n]->blockOnEP = -1;
             return devices[n];
         }
     }
@@ -69,7 +72,7 @@
 
 void Host::SendControlTransferData(Device* device,int dataToggle)
 {
-    driver->QueueControlTransferStage(
+    driver->QueueControlTransfer(
                 device->id,
                 device->controlTransferDirToHost == 1 ? TDD_IN : TDD_OUT,
                 0,
@@ -85,7 +88,7 @@
 void Host::SendControlTransferAcknowledge(Device* device,int dataToggle)
 {                        
     //Send empty packet to ACK.
-    driver->QueueControlTransferStage(
+    driver->QueueControlTransfer(
                 device->id,
                 device->controlTransferDirToHost == 0 ? TDD_IN : TDD_OUT,
                 0,
@@ -115,6 +118,29 @@
 void Host::Update()
 {
     driver->Update();
+    //Now the host has been updated service any outstanding transfers.
+    for(int n = 0 ; n < MAX_DEVICES ; n++ )
+    {
+        if( devices[n] != NULL && devices[n]->pendingCallbacks != NULL )
+        {
+            TransferDescriptor *transfer = devices[n]->pendingCallbacks;
+            devices[n]->pendingCallbacks = NULL;
+            
+            while( transfer )
+            {
+                TransferDescriptor *next = transfer->nextTD;
+//                DEBUG("onReceive (0x%08x) (0x%08x)",transfer,next);
+
+                
+                int deviceEP = transfer->ep | (transfer->direction == TDD_IN ? 0x80 : 0);
+                int reciveLength = transfer->CurrentBufferPointer - transfer->data;
+                transfer->transferCallback->onReceive(devices[n]->id,deviceEP,0,transfer->data,reciveLength);
+             
+                driver->FreeMemoryPoolItem(transfer);
+                transfer = next;   
+            }
+        }
+    }
 }
 
 int Host::getDeviceDescriptor(int deviceID,DeviceDescription &description)
@@ -164,7 +190,7 @@
  */
 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)
 {
-    DEBUG("ControlTransfer");
+    DEBUGV("ControlTransfer");
 
     Device* device = getDevice(deviceID);
     
@@ -183,35 +209,39 @@
     sp->index = index;
     sp->length = length;
     
-    DEBUG("Setup %d %d %d %d %d",sp->requestType,sp->request,sp->value,sp->index,sp->length);
+    DEBUGV("Setup %d %d %d %d %d",sp->requestType,sp->request,sp->value,sp->index,sp->length);
     
-    driver->QueueControlTransferStage(deviceID,TDD_SETUP,0,device->endpointZeroMaxPacketSize,device->lowspeed,TOGGLE_DATA0,(const uint8_t*)sp,sizeof(SetupPacket));
+    driver->QueueControlTransfer(deviceID,TDD_SETUP,0,device->endpointZeroMaxPacketSize,device->lowspeed,TOGGLE_DATA0,(const uint8_t*)sp,sizeof(SetupPacket));
     
     while(device->controlTransferState != CTS_IDLE)
     {
-        wait_ms(100);
+        wait_ms(50);
     };
         
     //Free this up.
     driver->FreeMemoryPoolItem(sp);
-    DEBUG("Done, recived %d",controlTransferDataLength);
+    DEBUGV("Done, recived %d",controlTransferDataLength);
 
     return 0;
 }
 
-int Host::BulkTransfer(int deviceID,uint8_t endpoint,const uint8_t* data,int length,int callbackID)
+int Host::BulkTransfer(int deviceID,uint8_t endpoint,const uint8_t* data,int length,TransferCallback* callback)
 {
-    DEBUG("ControlTransfer");
+    DEBUGV("BulkTransfer Device(%d) EP(%d) Len(%d) CB(0x%08x)",deviceID,endpoint,length,callback);
 
     Device* device = getDevice(deviceID);
-/*    
-    driver->QueueControlTransferStage(deviceID,(endpoint&LIBUSB_ENDPOINT_IN) ? TDD_IN : TDD_OUT,endpoint,device->endpointZeroMaxPacketSize,device->lowspeed,TOGGLE_DATA0,data,length);
+    device->blockOnEP = endpoint;
+    
+    driver->QueueBulkTransfer(deviceID,(endpoint&LIBUSB_ENDPOINT_IN) ? TDD_IN : TDD_OUT,endpoint&0x7f,device->endpointZeroMaxPacketSize,device->lowspeed,callback,data,length);
     
-    while(device->controlTransferState != CTS_IDLE)
+    if( callback == NULL )
     {
-        wait_ms(100);
-    };
-    */
+        while( device->blockOnEP == endpoint )
+        {
+            driver->Update();
+            wait_ms(100);
+        }
+    }
     
     return 0;
 }
@@ -239,29 +269,29 @@
     //Using device 0 for the setup and enum phase of the newley connected device.
     //We do this just to get some info on the device and then send a 'set address' command.
     //At that point we'll start using it's real ID.
-    DEBUG("Getting endpoint zero maxPacketSize");
+    DEBUGV("Getting endpoint zero maxPacketSize");
     ControlTransfer(0,LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,(LIBUSB_DT_DEVICE << 8), 0, (uint8_t*)&description,8,DEFAULT_TIMEOUT);
 
     
     //Now allocate the device and it's ID.
-    DEBUG("Allocating device");
+    DEBUGV("Allocating device");
     Device* device = AllocateDevice(description.maxPacketSize,hubPortStatus);
     
     //Now correct the endpoint's max packet size. Needs this for when we setup the endpoint descriptor for a transfer.
-    DEBUG("endpointZeroMaxPacketSize(%d)",device->endpointZeroMaxPacketSize);
+    DEBUGV("endpointZeroMaxPacketSize(%d)",device->endpointZeroMaxPacketSize);
     
     //Set the devices new address.
-    DEBUG("Setting device address to %d",device->id);
+    DEBUGV("Setting device address to %d",device->id);
     ControlTransfer(0,LIBUSB_ENDPOINT_OUT | LIBUSB_RECIPIENT_DEVICE, LIBUSB_REQUEST_SET_ADDRESS, device->id,0,NULL,0,DEFAULT_TIMEOUT);
     
     //New ID is now set, so we can free the object used when it was called device zero.
     driver->DetachDevice(0);
     
     //Now fetch the full device description.
-    DEBUG("Getting device description");
+    DEBUGV("Getting device description");
     getDeviceDescriptor(device->id,description);
     
-    DEBUG("idVendor(0x%04x) idProduct(0x%04x)",description.idVendor,description.idProduct);
+    DEBUGV("idVendor(0x%04x) idProduct(0x%04x)",description.idVendor,description.idProduct);
     
     //Get the language ID.
     uint16_t* lang = (uint16_t*)driver->AllocateMemoryPoolItem();
@@ -281,35 +311,53 @@
 
 void Host::TransferDone(TransferDescriptor *transfer)
 {
-    DEBUG("TransferDone, device(%d) errorCount(%d) status(%d) direction(%d) dataToggle(%d)",transfer->deviceID,transfer->errorCount,transfer->conditionCode,transfer->direction,transfer->dataToggle);
+    //This is the endpoint with the dir encoded into it, the way it is done to the applicaition coder.
+    //Needed when we are blocking for a non interput transfer to finish.
+    int epDir = transfer->ep | (transfer->direction==TDD_IN?0x80:0);
+    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);
 
     //Get the device this TD that has just been done for.
     Device* device = getDevice(transfer->deviceID);
     
-    //See if this was a setup packet, if so do we have data to ask for, if not then just ack the transaction.
-    //TODO: Error checking!
-    switch( device->controlTransferState )
+    if( transfer->transferType == TT_CONTROL )
     {
-    case CTS_SETUP:
-        if( device->controlTransferData != NULL )
+        //See if this was a setup packet, if so do we have data to ask for, if not then just ack the transaction.
+        //TODO: Error checking!
+        switch( device->controlTransferState )
         {
-            SendControlTransferData(device,transfer->dataToggle);
-        }
-        else
-        {
+        case CTS_SETUP:
+            if( device->controlTransferData != NULL )
+            {
+                SendControlTransferData(device,transfer->dataToggle);
+            }
+            else
+            {
+                SendControlTransferAcknowledge(device,transfer->dataToggle);
+            }
+            break;
+            
+        case CTS_DATA:
+            controlTransferDataLength = (transfer->bufferEnd - device->controlTransferData) + 1;
             SendControlTransferAcknowledge(device,transfer->dataToggle);
+            break;
+    
+        case CTS_ACK:
+            device->controlTransferState = CTS_IDLE;
+            break;
         }
-        break;
-        
-    case CTS_DATA:
-        controlTransferDataLength = (transfer->bufferEnd - device->controlTransferData) + 1;
-        SendControlTransferAcknowledge(device,transfer->dataToggle);
-        break;
+    }
+    
+    if( transfer->transferCallback != NULL )
+    {
+        transfer->nextTD = device->pendingCallbacks;
+        device->pendingCallbacks = transfer;
+    }
+    
+    if( device->blockOnEP == epDir )
+    {
+        device->blockOnEP = -1;
+    }
 
-    case CTS_ACK:
-        device->controlTransferState = CTS_IDLE;
-        break;
-    }
 }
 
 };//namespace USB