Almost identical to USBHostShell; reads all endpoint descriptors

Dependents:   myBlueUSB mbed_TANK_Kinect myBlueUSB_ros myBlueUSB_localfix

Revision:
1:05d0fe737d3b
Parent:
0:d6bff1c2dab1
--- a/USBHost.cpp	Mon Apr 04 16:42:56 2011 +0000
+++ b/USBHost.cpp	Wed May 04 09:12:55 2011 +0000
@@ -23,6 +23,7 @@
 
 #include "mbed.h"
 #include "USBHost.h"
+#include "Utils.h"
 
 //    Config (default uses x bytes)
 #define MAX_DEVICES 8                // Max number of devices
@@ -560,15 +561,16 @@
 
     //      Pop the last TD from the list
     HCTD* Reverse(HCTD* current) 
-    { 
+    { //int n = 0;
         HCTD *result = NULL,*temp; 
         while (current) 
-        { 
+        { //n++;
             temp = (HCTD*)current->Next; 
             current->Next = (u32)result;
             result = current;
             current = temp;
         }
+        //if (n>1) printf("%d TD's on Done Queue\n", n);
         return result;
     }
 
@@ -576,17 +578,19 @@
     //      Control endpoints use a state machine to progress through the transfers
     void ProcessDoneQueue(u32 tdList)
     {
-        HCTD* list = Reverse((HCTD*)tdList);
+        HCTD* list = Reverse((HCTD*)tdList);//because completed transfers were added to the head of the list
         while (list)
-        {
+        {//horrible hack: an Endpoint starts with an HCED and an HCTD and apparently all HCTDs are contained in Endpoints this way
+         //furthermore the sizeof an HCTD equeals the size of an HCED, hence the next expression gives indeed the Endpoint* for the HCTD
             Endpoint* endpoint = (Endpoint*)(list-1);
             list = (HCTD*)list->Next;
             int ep = endpoint->Address();
             bool in = endpoint->Flags & 0x80;
             int status = (endpoint->TDHead.Control >> 28) & 0xF;
-
+//the printf below is essential for correct working !?!? remove it and some messages will be missed
             //LOG("ProcessDoneQueue %02X %08X\n",ep,endpoint->TDHead.Control);
-
+wait_us(0);//200, 100, 50, 20, 10, 5, 2, 1,0 works, deleting the statement does not work
+//I suspect it has to do with interrupt priorities rather than with delays
             if (status != 0)
             {
                 LOG("ProcessDoneQueue status %02X %d\n",ep,status);
@@ -595,19 +599,22 @@
                 switch (endpoint->CurrentState)
                 {
                     case Endpoint::SetupQueued:
-                        if (endpoint->Length == 0)
+                        if (endpoint->Length == 0){
                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Skip Data Phase
-                        else
+                        } else {//here is a potential deadlock
+                    //printf("Deadlock Avoidance, ep=%02x, in=%d\n", ep, in);//with printf before transfer -> no deadlock
                             Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued);    // Setup is done, now Data
+                    //printf("SetupQueued->DataQueued\n");//with printf after Transfer ->deadlock
+                        }
                         break;
 
                     case Endpoint::DataQueued:
                         if (endpoint->TDHead.CurrBufPtr)
                             endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
 
-                        if (ep == 0)
+                        if (ep == 0){
                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
-                        else
+                        } else
                             endpoint->CurrentState = Endpoint::Idle;
                         break;
 
@@ -909,10 +916,21 @@
         head = _controller.CommunicationArea.DoneHead;        // Writeback Done
         _controller.CommunicationArea.DoneHead = 0;
     }             
-    LPC_USB->HcInterruptStatus = int_status;
+//    LPC_USB->HcInterruptStatus = int_status;
 
-    if (head)
-       _controller.ProcessDoneQueue(head);     // TODO - low bit can be set BUGBUG
+    if (head){
+       _controller.ProcessDoneQueue(head & ~1U);     // TODO - low bit can be set BUGBUG
+       if (head & 1) {
+         int othercause = int_status ^ WritebackDoneHead;
+         printf("HcInterruptStatus = %08X\n", int_status);
+       }
+    }
+    else
+      int othercause = int_status;
+    LPC_USB->HcInterruptStatus = int_status;
+//See page 435 of OHCI Specification
+//if the LSb=1 int_status should be checked for other causes
+//if the head=0 there are no TDs on the DoneQueue and int_status should be checked to see what caused this interrupt
 }
 
 //====================================================================================