Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost.cpp Source File

USBHost.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Peter Barrett
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "mbed.h"
00025 #include "USBHost.h"
00026 #include "Utils.h"
00027 
00028 //    Config (default uses x bytes)
00029 #define MAX_DEVICES 8                // Max number of devices
00030 #define MAX_ENDPOINTS_TOTAL 16        // Max number of endpoints total
00031 #define MAX_ENDPOINTS_PER_DEVICE 8    // Max number of endpoints for any one device
00032 
00033 #define  USBLOG 1
00034 #if USBLOG
00035 #define  LOG(...)       printf(__VA_ARGS__)
00036 #else 
00037 #define  LOG(...)       do {} while(0)
00038 #endif
00039 
00040 //Eli Adds
00041 unsigned char USB_Disk_Detected = 0;
00042 unsigned char USB_Disk_Device = 0;
00043 
00044 // USB host structures
00045 
00046 #define USB_RAM_SIZE 16*1024    // AHB SRAM block 1 TODO MACHINE DEPENDENT
00047 #define USB_RAM_BASE 0x2007C000
00048 
00049 #define TOKEN_SETUP 0
00050 #define TOKEN_IN  1
00051 #define TOKEN_OUT 2
00052 
00053 //    Status flags from hub
00054 #define PORT_CONNECTION 0
00055 #define PORT_ENABLE  1
00056 #define PORT_SUSPEND  2
00057 #define PORT_OVER_CURRENT 3
00058 #define PORT_RESET 4
00059 #define PORT_POWER 8
00060 #define PORT_LOW_SPEED 9
00061 
00062 #define C_PORT_CONNECTION 16
00063 #define C_PORT_ENABLE 17
00064 #define C_PORT_SUSPEND 18
00065 #define C_PORT_OVER_CURRENT 19
00066 #define C_PORT_RESET 20
00067 
00068 typedef struct {
00069     u8 bm_request_type;
00070     u8 b_request;
00071     u16 w_value;
00072     u16 w_index;
00073     u16 w_length;
00074 } Setup;
00075 
00076 
00077 //    Hub stuff is kept private just to keep api simple
00078 int SetPortFeature(int device, int feature, int index);
00079 int ClearPortFeature(int device, int feature, int index);
00080 int SetPortPower(int device, int port);
00081 int SetPortReset(int device, int port);
00082 int GetPortStatus(int device, int port, u32* status);
00083 
00084 //===================================================================
00085 //===================================================================
00086 //    Hardware defines
00087 
00088 //    HcControl
00089 #define PeriodicListEnable    0x00000004
00090 #define    IsochronousEnable    0x00000008
00091 #define    ControlListEnable    0x00000010
00092 #define    BulkListEnable        0x00000020
00093 #define    OperationalMask        0x00000080
00094 #define    HostControllerFunctionalState    0x000000C0
00095 
00096 //    HcCommandStatus
00097 #define HostControllerReset    0x00000001
00098 #define ControlListFilled    0x00000002
00099 #define BulkListFilled        0x00000004
00100 
00101 //    HcInterruptStatus Register
00102 #define    WritebackDoneHead        0x00000002
00103 #define    StartofFrame            0x00000004
00104 #define ResumeDetected            0x00000008
00105 #define UnrecoverableError        0x00000010
00106 #define FrameNumberOverflow        0x00000020
00107 #define RootHubStatusChange        0x00000040
00108 #define OwnershipChange            0x00000080
00109 #define MasterInterruptEnable    0x80000000
00110 
00111 //    HcRhStatus
00112 #define SetGlobalPower            0x00010000
00113 #define DeviceRemoteWakeupEnable    0x00008000
00114 
00115 //    HcRhPortStatus (hub 0, port 1)
00116 #define CurrentConnectStatus    0x00000001
00117 #define    PortEnableStatus        0x00000002
00118 #define PortSuspendStatus        0x00000004
00119 #define PortOverCurrentIndicator    0x00000008
00120 #define PortResetStatus            0x00000010
00121 
00122 #define PortPowerStatus            0x00000100
00123 #define LowspeedDevice            0x00000200
00124 #define HighspeedDevice            0x00000400
00125 
00126 #define ConnectStatusChange    (CurrentConnectStatus << 16)
00127 #define PortResetStatusChange    (PortResetStatus << 16)
00128 
00129 
00130 #define  TD_ROUNDING        (u32)0x00040000
00131 #define  TD_SETUP            (u32)0x00000000
00132 #define  TD_IN                (u32)0x00100000
00133 #define  TD_OUT                (u32)0x00080000
00134 #define  TD_DELAY_INT(x)    (u32)((x) << 21)
00135 #define  TD_TOGGLE_0        (u32)0x02000000
00136 #define  TD_TOGGLE_1        (u32)0x03000000
00137 #define  TD_CC                (u32)0xF0000000
00138 
00139 //    HostController EndPoint Descriptor
00140 typedef struct {
00141     volatile u32    Control;
00142     volatile u32    TailTd;
00143     volatile u32    HeadTd;
00144     volatile u32    Next;
00145 } HCED;
00146 
00147 // HostController Transfer Descriptor
00148 typedef struct {
00149     volatile u32    Control;
00150     volatile u32    CurrBufPtr;
00151     volatile u32    Next;
00152     volatile u32    BufEnd;
00153 } HCTD;
00154 
00155 // Host Controller Communication Area
00156 typedef struct {
00157     volatile u32    InterruptTable[32];
00158     volatile u16    FrameNumber;
00159     volatile u16    FrameNumberPad;
00160     volatile u32    DoneHead;
00161     volatile u8        Reserved[120];
00162 } HCCA;
00163 
00164 //====================================================================================
00165 //====================================================================================
00166 
00167 class HostController;
00168 class Endpoint;
00169 class Device;
00170 
00171 //      must be 3*16 bytes long
00172 class Endpoint
00173 {
00174 public:
00175     HCED    EndpointDescriptor;    // Pointer to EndpointDescriptor == Pointer to Endpoint
00176     HCTD    TDHead;
00177 
00178     enum State
00179     {
00180         Free,
00181         NotQueued,
00182         Idle,
00183         SetupQueued,
00184         DataQueued,
00185         StatusQueued,
00186         CallbackPending
00187     };
00188     
00189     volatile u8 CurrentState;
00190     u8        Flags;            // 0x80 In, 0x03 mask endpoint type
00191 
00192     u16        Length;
00193     u8*        Data;
00194     USBCallback Callback;     // Must be a multiple of 16 bytes long
00195     void*  UserData;
00196   
00197     int Address()
00198     {
00199         int ep = (EndpointDescriptor.Control >> 7) & 0xF;
00200         if (ep)
00201             ep |= Flags & 0x80;
00202         return ep;
00203     }
00204     
00205     int Device()
00206     {
00207         return EndpointDescriptor.Control & 0x7F;
00208     }
00209 
00210     int Status()
00211     {
00212         return (TDHead.Control >> 28) & 0xF;
00213     }
00214 
00215     u32 Enqueue(u32 head)
00216     {
00217         if (CurrentState == NotQueued)
00218         {
00219             EndpointDescriptor.Next = head;
00220             head = (u32)&EndpointDescriptor;
00221             CurrentState = Idle;
00222         }
00223         return head;
00224     }
00225 };
00226 
00227 class Device
00228 {
00229 public:
00230     u8    _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2];
00231     u8    Hub;
00232     u8    Port;
00233     u8    Addr;
00234     u8    Pad;
00235 
00236     //    Only if this device is a hub
00237     u8    HubPortCount;    // nonzero if this is a hub
00238     u8    HubInterruptData;
00239     u8    HubMap;
00240     u8    HubMask;
00241 
00242     int Flags;        // 1 = Disconnected
00243 
00244     Setup    SetupBuffer;
00245 
00246     // Allocate endpoint zero
00247     int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed)
00248     {
00249         Hub = hub;
00250         Port = port;
00251         Addr = addr;
00252         Flags = lowSpeed;
00253         memset(_endpointMap,0xFF,sizeof(_endpointMap));
00254         return 0;
00255     }
00256 
00257     int SetEndpointIndex(int ep, int endpointIndex)
00258     {
00259         for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
00260         {
00261             if (_endpointMap[i] == 0xFF)    // Add endpoint to map
00262             {
00263                 _endpointMap[i] = ep;
00264                 _endpointMap[i+1] = endpointIndex;
00265                 return 0;
00266             }
00267         }
00268         return ERR_ENDPOINT_NONE_LEFT;
00269     }
00270 
00271     int GetEndpointIndex(int ep)
00272     {
00273         for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
00274         {
00275             if (_endpointMap[i] == ep)
00276                 return _endpointMap[i+1];
00277             if (_endpointMap[i] == 0xFF)
00278                 break;
00279         }
00280         return -1;
00281     }
00282 };
00283 
00284 class HostController
00285 {
00286 public:
00287     HCCA        CommunicationArea;
00288     Endpoint    Endpoints[MAX_ENDPOINTS_TOTAL];    // Multiple of 16
00289     
00290     Endpoint    EndpointZero;                        // For device enumeration
00291     HCTD        _commonTail;
00292     Setup        _setupZero;
00293     
00294     Device    Devices[MAX_DEVICES];
00295     u32    _frameNumber;            // 32 bit ms counter
00296 
00297     u8    _callbacksPending;        //    Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue
00298     u8    _rootHubStatusChange;    //    Root hub status has changed, set from ISR
00299     u8    _unused0;
00300     u8    _unused1;
00301 
00302     u8    _connectPending;    //    Reset has initiated a connect
00303     u8    _connectCountdown;    //    Number of ms left after reset before we can connect
00304     u8    _connectHub;        //    Will connect on this hub
00305     u8    _connectPort;        //    ... and this port
00306 
00307     u8    SRAM[0];            // Start of free SRAM
00308 
00309     void Loop()
00310     {
00311         u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber;    // extend to 32 bits
00312         _frameNumber += elapsed;
00313 
00314         // Do callbacks, if any
00315         while (_callbacksPending)
00316         {
00317             for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
00318             {
00319                 Endpoint* endpoint = Endpoints + i;
00320                 if (endpoint->CurrentState == Endpoint::CallbackPending)
00321                 {
00322                     _callbacksPending--;
00323                     endpoint->CurrentState = Endpoint::Idle;
00324                     endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData);
00325                 }
00326             }
00327         }
00328 
00329         //    Deal with changes on the root hub
00330         if (_rootHubStatusChange)
00331         {
00332             u32 status = LPC_USB->HcRhPortStatus1;
00333             _rootHubStatusChange = 0;
00334             if (status >> 16)
00335             {
00336                 HubStatusChange(0,1,status);
00337                 LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000;    // clear status changes
00338             }
00339         }
00340 
00341         //    Connect after reset timeout
00342         if (_connectCountdown)
00343         {
00344             if (elapsed >= _connectCountdown)
00345             {
00346                 _connectCountdown = 0;
00347                 Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80);
00348             } else
00349                 _connectCountdown -= elapsed;
00350         }
00351     }
00352 
00353     //    HubInterrupt - bitmap in dev->HubInterruptData
00354     void HubInterrupt(int device)
00355     {
00356         Device* dev = &Devices[device-1];
00357         for (int i = 0; i < dev->HubPortCount; i++)
00358         {
00359             int port = i+1;
00360             if (dev->HubInterruptData & (1 << port))
00361             {
00362                 u32 status = 0;
00363                 GetPortStatus(device,port,&status);
00364                 if (status >> 16)
00365                 {
00366                     if (_connectPending && (status & ConnectStatusChange))
00367                         continue;    // Don't connect again until previous device has been added and addressed
00368 
00369                     HubStatusChange(device,port,status);
00370                     if (status & ConnectStatusChange)
00371                         ClearPortFeature(device,C_PORT_CONNECTION,port);
00372                     if (status & PortResetStatusChange)
00373                         ClearPortFeature(device,C_PORT_RESET,port);
00374                 }
00375             }
00376         }
00377     }
00378 
00379     static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
00380     {
00381         HostController* controller = (HostController*)userData;
00382         if (status == 0)
00383             controller->HubInterrupt(device);
00384         USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData);
00385     }
00386 
00387     int InitHub(int device)
00388     {
00389         u8 buf[16];
00390         int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf));
00391         if (r < 0)
00392             return ERR_HUB_INIT_FAILED;
00393         
00394         //    turn on power on the hubs ports
00395         Device* dev = &Devices[device-1];
00396         int ports = buf[2];
00397         dev->HubPortCount = ports;
00398         for (int i = 0; i < ports; i++)
00399             SetPortPower(device,i+1);
00400         
00401         // Enable hub change interrupts
00402         return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this);
00403     }
00404     
00405     int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval)
00406     {
00407         LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\n",device,ep,attributes,maxPacketSize,interval);
00408         Device* dev = &Devices[device-1];
00409         Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize);
00410         if (!endpoint)
00411             return ERR_ENDPOINT_NONE_LEFT;
00412         dev->SetEndpointIndex(ep,endpoint - Endpoints);
00413         endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed
00414         return 0;  // TODO ed->bInterval
00415     }
00416     
00417     int AddEndpoint(int device, EndpointDescriptor* ed)
00418     {
00419         return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval);
00420     }
00421 
00422     //      allocate a endpoint
00423     Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize)
00424     {
00425         for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
00426         {
00427             Endpoint* ep = &Endpoints[i];
00428             if (ep->CurrentState == 0)
00429             {
00430                 //LOG("Allocated endpoint %d to %02X:%02X\n",i,device,endpointAddress);
00431                 ep->Flags = (endpointAddress & 0x80) | (type & 3);
00432                 ep->CurrentState = Endpoint::NotQueued;
00433                 ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device;
00434                 return ep;
00435             }
00436         }
00437         return 0;
00438     }
00439 
00440     Endpoint* GetEndpoint(int device, int ep)
00441     {
00442         if (device == 0)
00443         {
00444             //printf("WARNING: USING DEVICE 0\n");
00445             return &EndpointZero;
00446         }
00447         if (device > MAX_DEVICES)
00448             return 0;
00449         int i = Devices[device-1].GetEndpointIndex(ep);
00450         if (i == -1)
00451             return 0;
00452         return Endpoints + i;
00453     }
00454 
00455     int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state)
00456     {
00457         //LOG("Transfer %02X T:%d Len:%d S:%d\n",endpoint->Address(),token,len,state);
00458     
00459         int toggle = 0;
00460         if (endpoint->Address() == 0)
00461             toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1;
00462 
00463         if (token != TOKEN_SETUP)
00464             token = (token == TOKEN_IN ? TD_IN : TD_OUT);
00465 
00466         HCTD* head = &endpoint->TDHead;
00467         HCTD* tail = &_commonTail;
00468 
00469         head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; 
00470         head->CurrBufPtr = (u32)data;
00471         head->BufEnd = (u32)(data + len - 1);
00472         head->Next = (u32)tail;
00473 
00474         HCED* ed = &endpoint->EndpointDescriptor;
00475         ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002);    // carry toggle
00476         ed->TailTd = (u32)tail;
00477         
00478         //HCTD* td = head;
00479         //LOG("%04X TD %08X %08X %08X Next:%08X\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
00480         //LOG("%04X ED %08X %08X %08X\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd);
00481         
00482         switch (endpoint->Flags & 3)
00483         {
00484             case ENDPOINT_CONTROL:
00485                 LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED);    // May change state NotQueued->Idle
00486                 endpoint->CurrentState = state;                                               // Get in before an int
00487                 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled;
00488                 LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable;
00489                 break;
00490 
00491             case ENDPOINT_BULK:
00492                 LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED);
00493                 endpoint->CurrentState = state;
00494                 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled;
00495                 LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable;
00496                 break;
00497 
00498             case ENDPOINT_INTERRUPT:
00499                 CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]);
00500                 endpoint->CurrentState = state;
00501                 LPC_USB->HcControl |= PeriodicListEnable;
00502                 break;
00503         }
00504         return 0;
00505     }
00506     
00507     //    Remove an endpoint from an active queue
00508     bool Remove(HCED* ed, volatile HCED** queue)
00509     {
00510         if (*queue == 0)
00511             return false;
00512         if (*queue == (volatile HCED*)ed)
00513         {
00514             *queue = (volatile HCED*)ed->Next;    // At head of queue
00515             return true;
00516         }
00517 
00518         volatile HCED* head = *queue;
00519         while (head)
00520         {
00521             if (head->Next == (u32)ed)
00522             {
00523                 head->Next = ed->Next;
00524                 return true;
00525             }
00526             head = (volatile HCED*)head->Next;
00527         }
00528         return false;
00529     }
00530 
00531     void Release(Endpoint* endpoint)
00532     {
00533         if (endpoint->CurrentState == Endpoint::NotQueued)
00534         {
00535             // Never event used it, nothing to do
00536         }
00537         else
00538         {
00539             HCED* ed = (HCED*)endpoint;
00540             ed->Control |= 0x4000;    // SKIP
00541             switch (endpoint->Flags & 0x03)
00542             {
00543                 case ENDPOINT_CONTROL:
00544                     Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED);
00545                     break;
00546                 case ENDPOINT_BULK:
00547                     Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED);
00548                     break;
00549                 case ENDPOINT_INTERRUPT:
00550                     for (int i = 0; i < 32; i++)
00551                         Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]);
00552                     break;
00553             }
00554 
00555             u16 fn = CommunicationArea.FrameNumber;
00556             while (fn == CommunicationArea.FrameNumber)
00557                 ;    // Wait for next frame
00558 
00559         }
00560 
00561         //    In theory, the endpoint is now dead.
00562         //    TODO: Will Callbacks ever be pending? BUGBUG
00563         memset(endpoint,0,sizeof(Endpoint));
00564     }
00565 
00566     //      Pop the last TD from the list
00567     HCTD* Reverse(HCTD* current) 
00568     { //int n = 0;
00569         HCTD *result = NULL,*temp; 
00570         while (current) 
00571         { //n++;
00572             temp = (HCTD*)current->Next; 
00573             current->Next = (u32)result;
00574             result = current;
00575             current = temp;
00576         }
00577         //if (n>1) printf("%d TD's on Done Queue\n", n);
00578         return result;
00579     }
00580 
00581     //      Called from interrupt...
00582     //      Control endpoints use a state machine to progress through the transfers
00583     void ProcessDoneQueue(u32 tdList)
00584     {
00585         HCTD* list = Reverse((HCTD*)tdList);//because completed transfers were added to the head of the list
00586         while (list)
00587         {//horrible hack: an Endpoint starts with an HCED and an HCTD and apparently all HCTDs are contained in Endpoints this way
00588          //furthermore the sizeof an HCTD equeals the size of an HCED, hence the next expression gives indeed the Endpoint* for the HCTD
00589             Endpoint* endpoint = (Endpoint*)(list-1);
00590             list = (HCTD*)list->Next;
00591             int ep = endpoint->Address();
00592             bool in = endpoint->Flags & 0x80;
00593             int status = (endpoint->TDHead.Control >> 28) & 0xF;
00594 //the printf below is essential for correct working !?!? remove it and some messages will be missed
00595             //LOG("ProcessDoneQueue %02X %08X\n",ep,endpoint->TDHead.Control);
00596 wait_us(0);//200, 100, 50, 20, 10, 5, 2, 1,0 works, deleting the statement does not work
00597 //I suspect it has to do with interrupt priorities rather than with delays
00598             if (status != 0)
00599             {
00600                 LOG("ProcessDoneQueue status %02X %d\n",ep,status);
00601                 endpoint->CurrentState = Endpoint::Idle;
00602             } else {
00603                 switch (endpoint->CurrentState)
00604                 {
00605                     case Endpoint::SetupQueued:
00606                         if (endpoint->Length == 0){
00607                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Skip Data Phase
00608                         } else {//here is a potential deadlock
00609                     //printf("Deadlock Avoidance, ep=%02x, in=%d\n", ep, in);//with printf before transfer -> no deadlock
00610                             Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued);    // Setup is done, now Data
00611                     //printf("SetupQueued->DataQueued\n");//with printf after Transfer ->deadlock
00612                         }
00613                         break;
00614 
00615                     case Endpoint::DataQueued:
00616                         if (endpoint->TDHead.CurrBufPtr)
00617                             endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
00618 
00619                         if (ep == 0){
00620                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
00621                         } else
00622                             endpoint->CurrentState = Endpoint::Idle;
00623                         break;
00624 
00625                     case Endpoint::StatusQueued:    // Transaction is done
00626                         endpoint->CurrentState = Endpoint::Idle;
00627                         break;
00628                 }
00629             }
00630 
00631             //      Complete, flag if we need a callback
00632             if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
00633             {
00634                 endpoint->CurrentState = Endpoint::CallbackPending;
00635                 _callbacksPending++;
00636             }
00637         }
00638     }
00639 
00640     //    Hack to reset devices that don't want to connect
00641     int AddDevice(int hub, int port, bool isLowSpeed)
00642     {
00643         int device = AddDeviceCore(hub,port,isLowSpeed);
00644         if (device < 0)
00645         {
00646             LOG("========RETRY ADD DEVICE========\n");    // This will go for ever.. TODO power cycle root?
00647             Disconnect(hub,port);    // Could not read descriptor at assigned address, reset this port and try again
00648             ResetPort(hub,port);    // Cheap bluetooth dongles often need this on a hotplug
00649             return -1;
00650         }
00651         return device;
00652     }
00653 
00654     int AddDeviceCore(int hub, int port, bool isLowSpeed)
00655     {
00656         int lowSpeed = isLowSpeed ? 0x2000 : 0;
00657         DeviceDescriptor desc;
00658         EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed;               // MaxPacketSize == 8
00659         int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8);
00660         if (r < 0)
00661         {
00662             LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\n");
00663             return r;
00664         }
00665 
00666         EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed;     // Actual MaxPacketSize
00667         r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00668         if (r < 0)
00669             return r;
00670 
00671         LOG("\nClass %02X found %04X:%04X\n\n",desc.bDeviceClass,desc.idVendor,desc.idProduct);
00672 
00673         //      Now assign the device an address, move off EndpointZero
00674         int device = 0;
00675         for (int i = 0; i < MAX_DEVICES; i++)
00676         {
00677             if (Devices[i].Port == 0)
00678             {
00679                 device = i+1;
00680                 break;
00681             }
00682         }
00683         if (!device)
00684             return ERR_DEVICE_NONE_LEFT;
00685 
00686         r = SetAddress(0,device);
00687         if (r)
00688             return r;
00689         DelayMS(2);
00690         
00691         // Now at a nonzero address, create control endpoint
00692         Device* dev = &Devices[device-1];
00693         dev->Init(&desc,hub,port,device,lowSpeed);
00694         AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0);
00695         _connectPending = 0;
00696 
00697         //    Verify this all works
00698         r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00699         if (r < 0)
00700             return r;
00701 
00702         //    Set to interface 0 by default
00703         //    Calls LoadDevice if interface is found
00704         r = SetConfigurationAndInterface(device,1,0,&desc);
00705 
00706         if (desc.bDeviceClass == CLASS_HUB)
00707             InitHub(device);            // Handle hubs in this code
00708 
00709         return device;
00710     }
00711 
00712     // Walk descriptors and create endpoints for a given device
00713     // TODO configuration !=1, alternate settings etc.
00714     int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc)
00715     {
00716         u8 buffer[255];
00717         int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer));
00718         if (err < 0)
00719             return err;
00720 
00721         err = SetConfiguration(device,configuration);
00722         if (err < 0)
00723             return err;
00724 
00725         //    Add the endpoints for this interface
00726         int len = buffer[2] | (buffer[3] << 8);
00727         u8* d = buffer;
00728         u8* end = d + len;
00729         InterfaceDescriptor* found = 0;
00730         while (d < end)
00731         {
00732             if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
00733             {
00734                 InterfaceDescriptor* id = (InterfaceDescriptor*)d;
00735                 if (id->bInterfaceNumber == interfaceNumber)
00736                 {
00737                     found = id;
00738                     d += d[0];
00739                     while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
00740                     {
00741                         switch (d[1])
00742                         {
00743                             case DESCRIPTOR_TYPE_ENDPOINT:
00744                                 AddEndpoint(device,(EndpointDescriptor*)d);
00745                                 break;
00746                             default:
00747                                 LOG("Skipping descriptor %02X (%d bytes)\n",d[1],d[0]);
00748                         }
00749                         d += d[0];
00750                     }
00751                 }
00752             }
00753             d += d[0];
00754         }
00755 
00756         if (!found)
00757             return ERR_INTERFACE_NOT_FOUND;
00758         OnLoadDevice(device,desc,found);
00759         return 0;
00760     }
00761 
00762     void Init()
00763     {
00764         LOG("USB INIT (Controller is %d bytes)\n",sizeof(*this));
00765         memset(this,0,sizeof(HostController));
00766         EndpointZero.CurrentState = Endpoint::NotQueued;
00767         HWInit(&CommunicationArea);
00768         DelayMS(10);
00769     }
00770 
00771     void ResetPort(int hub, int port)
00772     {
00773         LOG("ResetPort Hub:%d Port:%d\n",hub,port);
00774         _connectPending++;            // Only reset/add 1 device at a time
00775         if (hub == 0)
00776             LPC_USB->HcRhPortStatus1 = PortResetStatus;    // Reset Root Hub, port 1
00777         else
00778             SetPortReset(hub,port);    // or reset other hub
00779     }
00780 
00781     void Disconnect(int hub, int port)
00782     {
00783         LOG("Disconnect Hub:%d Port:%d\n",hub,port);    // Mark a device for destruction
00784       
00785       if(port ==USB_Disk_Device)
00786       {
00787         USB_Disk_Detected = 0;
00788       }
00789       
00790         for (int i = 0; i < MAX_DEVICES; i++)
00791         {
00792             Device* dev = Devices + i;
00793             if (dev->Port == port && dev->Hub == hub)
00794             {
00795                 //    Disconnect everything that is attached to this device if it is a hub
00796                 for (int p = 0; p < dev->HubPortCount; p++)
00797                     Disconnect(i+1,p+1);
00798 
00799                 //    Now release endpoints
00800                 for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2)
00801                 {
00802                     u8 endpointIndex = dev->_endpointMap[j];
00803                     if (endpointIndex != 0xFF)
00804                         Release(Endpoints + endpointIndex);
00805                 }
00806                 dev->Port = 0;    // Device is now free
00807                 dev->Flags = 0;
00808                 return;
00809             }
00810           }
00811     }
00812 
00813     // called after reset
00814     void Connect(int hub, int port, bool lowspeed)
00815     {
00816         LOG("Connect Hub:%d Port:%d %s\n",hub,port,lowspeed ? "slow" : "full");
00817         AddDevice(hub,port,lowspeed);
00818     }
00819 
00820     // Called from interrupt
00821     void HubStatusChange(int hub, int port, u32 status)
00822     {
00823         LOG("HubStatusChange Hub:%d Port:%d %08X\n",hub,port,status);
00824         if (status & ConnectStatusChange)
00825         {
00826             if (status & CurrentConnectStatus)    // Connecting
00827                 ResetPort(hub,port);            // Reset to initiate connect (state machine?)
00828             else
00829                 Disconnect(hub,port);
00830         }
00831 
00832         if (status & PortResetStatusChange)
00833         {
00834             if (!(status & PortResetStatus))
00835             {
00836                 _connectCountdown = 200;        // Schedule a connection in 200ms
00837                 if (status & LowspeedDevice)
00838                     port |= 0x80;
00839                 _connectHub = hub;
00840                 _connectPort = port;
00841             }
00842         }
00843     }
00844 
00845     #define HOST_CLK_EN        (1<<0)
00846     #define PORTSEL_CLK_EN    (1<<3)
00847     #define AHB_CLK_EN        (1<<4)
00848     #define CLOCK_MASK        (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
00849 
00850     #define  FRAMEINTERVAL        (12000-1)    // 1ms
00851     #define  DEFAULT_FMINTERVAL    ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL)
00852 
00853     void DelayMS(int ms)
00854     {
00855         u16 f = ms + CommunicationArea.FrameNumber;
00856         while (f != CommunicationArea.FrameNumber)
00857             ;
00858     }
00859 
00860     static void HWInit(HCCA* cca)
00861     {
00862         NVIC_DisableIRQ(USB_IRQn);
00863         
00864         // turn on power for USB
00865         LPC_SC->PCONP        |= (1UL<<31);
00866         // Enable USB host clock, port selection and AHB clock
00867         LPC_USB->USBClkCtrl |= CLOCK_MASK;
00868         // Wait for clocks to become available
00869         while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
00870             ;
00871         
00872         //    We are a Host
00873         LPC_USB->OTGStCtrl |= 1;
00874         LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;                // we don't need port selection clock until we do OTG
00875         
00876         // configure USB pins
00877         LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));    
00878         LPC_PINCON->PINSEL1 |=    ((1<<26)|(1<<28));            // USB D+/D-
00879             
00880         LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22));        // USB_PPWR, USB_OVRCR
00881         LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22));
00882         
00883         LPC_PINCON->PINSEL4 &= ~(3 << 18);                    // USB_CONNECT
00884         LPC_PINCON->PINSEL4 |= (1 << 18);
00885 
00886         //    Reset OHCI block
00887         LPC_USB->HcControl         = 0;
00888         LPC_USB->HcControlHeadED = 0;
00889         LPC_USB->HcBulkHeadED     = 0;
00890         
00891         LPC_USB->HcCommandStatus = HostControllerReset;
00892         LPC_USB->HcFmInterval     = DEFAULT_FMINTERVAL;
00893         LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100;
00894 
00895         LPC_USB->HcControl    = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask;
00896         LPC_USB->HcRhStatus = SetGlobalPower;
00897         
00898         LPC_USB->HcHCCA = (u32)cca;
00899         LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
00900         LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow;
00901 
00902         NVIC_SetPriority(USB_IRQn, 0);
00903         NVIC_EnableIRQ(USB_IRQn);
00904         while (cca->FrameNumber < 10)
00905             ;    // 10ms delay before diving in
00906     }
00907 };
00908 
00909 //====================================================================================
00910 //====================================================================================
00911 //      Host controller instance and Interrupt handler
00912 
00913 static HostController _controller __attribute__((at(USB_RAM_BASE)));
00914 
00915 extern "C" void USB_IRQHandler(void) __irq;
00916 void USB_IRQHandler (void) __irq
00917 {
00918     u32 int_status = LPC_USB->HcInterruptStatus;
00919 
00920     if (int_status & RootHubStatusChange)    //    Root hub status change
00921         _controller._rootHubStatusChange++;    //    Just flag the controller, will be processed in USBLoop
00922 
00923     u32 head = 0;
00924     if (int_status & WritebackDoneHead)
00925     {
00926         head = _controller.CommunicationArea.DoneHead;        // Writeback Done
00927         _controller.CommunicationArea.DoneHead = 0;
00928     }             
00929 //    LPC_USB->HcInterruptStatus = int_status;
00930 
00931     if (head){
00932        _controller.ProcessDoneQueue(head & ~1U);     // TODO - low bit can be set BUGBUG
00933        if (head & 1) {
00934          int othercause = int_status ^ WritebackDoneHead;
00935          printf("HcInterruptStatus = %08X\n", int_status);
00936        }
00937     }
00938     else
00939       int othercause = int_status;
00940     LPC_USB->HcInterruptStatus = int_status;
00941 //See page 435 of OHCI Specification
00942 //if the LSb=1 int_status should be checked for other causes
00943 //if the head=0 there are no TDs on the DoneQueue and int_status should be checked to see what caused this interrupt
00944 }
00945 
00946 //====================================================================================
00947 //====================================================================================
00948 //      API Methods
00949 
00950 void USBInit()
00951 {
00952     return _controller.Init();
00953 }
00954 
00955 void USBLoop()
00956 {
00957     return _controller.Loop();
00958 }
00959 
00960 u8* USBGetBuffer(u32* len)
00961 {
00962     *len = USB_RAM_SIZE - sizeof(HostController);
00963     return _controller.SRAM;
00964 }
00965 
00966 static Setup* GetSetup(int device)
00967 {
00968     if (device == 0)
00969         return &_controller._setupZero;
00970     
00971     if (device < 1 || device > MAX_DEVICES)
00972         return 0;
00973     return &_controller.Devices[device-1].SetupBuffer;
00974 }
00975 
00976 //    Loop until IO on endpoint is complete
00977 static int WaitIODone(Endpoint* endpoint)
00978 {
00979     if (endpoint->CurrentState == Endpoint::NotQueued)
00980         return 0;
00981     while (endpoint->CurrentState != Endpoint::Idle)
00982         USBLoop();    // May generate callbacks, mount or unmount devices etc
00983     int status = endpoint->Status();
00984     if (status == 0)
00985         return endpoint->Length;
00986     return -status;
00987 }
00988 
00989 int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
00990 {
00991     Endpoint* endpoint = _controller.GetEndpoint(device,ep);
00992     if (!endpoint)
00993         return ERR_ENDPOINT_NOT_FOUND;
00994         
00995     WaitIODone(endpoint);
00996     endpoint->Flags = flags;
00997     endpoint->Data = data;
00998     endpoint->Length = length;
00999     endpoint->Callback = callback;
01000     endpoint->UserData = userData;
01001     if (ep == 0)
01002         _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
01003     else
01004         _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
01005     if (callback)
01006         return IO_PENDING;
01007     return WaitIODone(endpoint);
01008 }
01009 
01010 int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData)
01011 {
01012     Setup* setup = GetSetup(device);
01013     if (!setup)
01014         return ERR_DEVICE_NOT_FOUND;
01015         
01016     // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call
01017     WaitIODone(_controller.GetEndpoint(device,0));
01018     
01019     setup->bm_request_type = request_type;
01020     setup->b_request = request;
01021     setup->w_value = value;
01022     setup->w_index = index;
01023     setup->w_length = length;
01024     return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData);
01025 }
01026 
01027 int  USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01028 {
01029     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData);
01030 }
01031 
01032 int  USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01033 {
01034     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData);
01035 }
01036 
01037 int GetDescriptor(int device, int descType,int descIndex, u8* data, int length)
01038 {
01039     return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0);
01040 }
01041 
01042 int GetString(int device, int index, char* dst, int length)
01043 {
01044     u8 buffer[255];
01045     int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer));
01046     if (le < 0)
01047         return le;
01048     if (length < 1)
01049         return -1;
01050     length <<= 1;
01051     if (le > length)
01052         le = length;
01053     for (int j = 2; j < le; j += 2)
01054         *dst++ = buffer[j];
01055     *dst = 0;
01056     return (le>>1)-1;
01057 }
01058 
01059 int SetAddress(int device, int new_addr)
01060 {
01061     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0);
01062 }
01063 
01064 int SetConfiguration(int device, int configNum)
01065 {
01066     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0);
01067 }
01068 
01069 int SetInterface(int device, int ifNum, int altNum)
01070 {
01071     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0);
01072 }
01073 
01074 //    HUB stuff
01075 int SetPortFeature(int device, int feature, int index)
01076 {
01077     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0);
01078 }
01079 
01080 int ClearPortFeature(int device, int feature, int index)
01081 {
01082     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0);
01083 }
01084 
01085 int SetPortPower(int device, int port)
01086 {
01087     int r = SetPortFeature(device,PORT_POWER,port);
01088     _controller.DelayMS(20);    // 80ms to turn on a hubs power... DESCRIPTOR? todo
01089     return r;
01090 }
01091 
01092 int SetPortReset(int device, int port)
01093 {
01094     return SetPortFeature(device,PORT_RESET,port);
01095 }
01096 
01097 int GetPortStatus(int device, int port, u32* status)
01098 {
01099     return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4);
01100 }