Christian Burri / Mbed 2 deprecated autonomous Robot Android

Dependencies:   mbed

Fork of autonomous Robot Android by Christian Burri

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 
00025 
00026 #include "mbed.h"
00027 #include "USBHost.h"
00028 #ifndef  USBHOST_LOG
00029 
00030 #define DESC_INDEX 0
00031 
00032 //    Config (default uses x bytes)
00033 #define MAX_DEVICES 8                // Max number of devices
00034 #define MAX_ENDPOINTS_TOTAL 16        // Max number of endpoints total
00035 #define MAX_ENDPOINTS_PER_DEVICE 8    // Max number of endpoints for any one device
00036 
00037 #define  USBLOG 0
00038 #if USBLOG
00039 #define  LOG(...)       printf(__VA_ARGS__)
00040 #else 
00041 #define  LOG(...)       do {} while(0)
00042 #endif
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                     LOG("Sorting Callbacks %i\r\n\r",endpoint->CurrentState);
00323                     _callbacksPending--;
00324                     endpoint->CurrentState = Endpoint::Idle;
00325                     LOG("SatusChanged %i\r\n\r",endpoint->CurrentState);
00326                     LOG("CallBack DataSize:%d",endpoint->Length);
00327                     endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData);
00328                 }
00329             }
00330         }
00331 
00332         //    Deal with changes on the root hub
00333         if (_rootHubStatusChange)
00334         {
00335             u32 status = LPC_USB->HcRhPortStatus1;
00336             _rootHubStatusChange = 0;
00337             if (status >> 16)
00338             {
00339                 HubStatusChange(0,1,status);
00340                 LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000;    // clear status changes
00341             }
00342         }
00343 
00344         //    Connect after reset timeout
00345         if (_connectCountdown)
00346         {
00347             if (elapsed >= _connectCountdown)
00348             {
00349                 _connectCountdown = 0;
00350                 Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80);
00351             } else
00352                 _connectCountdown -= elapsed;
00353         }
00354     }
00355 
00356     //    HubInterrupt - bitmap in dev->HubInterruptData
00357     void HubInterrupt(int device)
00358     {
00359         Device* dev = &Devices[device-1];
00360         for (int i = 0; i < dev->HubPortCount; i++)
00361         {
00362             int port = i+1;
00363             if (dev->HubInterruptData & (1 << port))
00364             {
00365                 u32 status = 0;
00366                 GetPortStatus(device,port,&status);
00367                 if (status >> 16)
00368                 {
00369                     if (_connectPending && (status & ConnectStatusChange))
00370                         continue;    // Don't connect again until previous device has been added and addressed
00371 
00372                     HubStatusChange(device,port,status);
00373                     if (status & ConnectStatusChange)
00374                         ClearPortFeature(device,C_PORT_CONNECTION,port);
00375                     if (status & PortResetStatusChange)
00376                         ClearPortFeature(device,C_PORT_RESET,port);
00377                 }
00378             }
00379         }
00380     }
00381 
00382     static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
00383     {
00384         HostController* controller = (HostController*)userData;
00385         if (status == 0)
00386             controller->HubInterrupt(device);
00387         USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData);
00388     }
00389 
00390     int InitHub(int device)
00391     {
00392         u8 buf[16];
00393         int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf));
00394         if (r < 0)
00395             return ERR_HUB_INIT_FAILED;
00396         
00397         //    turn on power on the hubs ports
00398         Device* dev = &Devices[device-1];
00399         int ports = buf[2];
00400         dev->HubPortCount = ports;
00401         for (int i = 0; i < ports; i++)
00402             SetPortPower(device,i+1);
00403         
00404         // Enable hub change interrupts
00405         return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this);
00406     }
00407     
00408     int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval)
00409     {
00410         LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\r\r\n",device,ep,attributes,maxPacketSize,interval);
00411         Device* dev = &Devices[device-1];
00412         Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize);
00413         if (!endpoint)
00414             return ERR_ENDPOINT_NONE_LEFT;
00415         dev->SetEndpointIndex(ep,endpoint - Endpoints);
00416         endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed
00417         return 0;  // TODO ed->bInterval
00418     }
00419     
00420     int AddEndpoint(int device, EndpointDescriptor* ed)
00421     {
00422         return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval);
00423     }
00424 
00425     //      allocate a endpoint
00426     Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize)
00427     {
00428         for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
00429         {
00430             Endpoint* ep = &Endpoints[i];
00431             if (ep->CurrentState == 0)
00432             {
00433                 //LOG("Allocated endpoint %d to %02X:%02X\r\r\n",i,device,endpointAddress);
00434                 ep->Flags = (endpointAddress & 0x80) | (type & 3);
00435                 ep->CurrentState = Endpoint::NotQueued;
00436                 ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device;
00437                 return ep;
00438             }
00439         }
00440         return 0;
00441     }
00442 
00443     Endpoint* GetEndpoint(int device, int ep)
00444     {
00445         if (device == 0)
00446         {
00447             //printf("WARNING: USING DEVICE 0\r\n");
00448             return &EndpointZero;
00449         }
00450         if (device > MAX_DEVICES)
00451             return 0;
00452         int i = Devices[device-1].GetEndpointIndex(ep);
00453         if (i == -1)
00454             return 0;
00455         return Endpoints + i;
00456     }
00457 
00458     int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state)
00459     {
00460         //LOG("Transfer %02X T:%d Len:%d S:%d\r\r\n",endpoint->Address(),token,len,state);
00461     
00462         int toggle = 0;
00463         if (endpoint->Address() == 0)
00464             toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1;
00465 
00466         if (token != TOKEN_SETUP)
00467             token = (token == TOKEN_IN ? TD_IN : TD_OUT);
00468 
00469         HCTD* head = &endpoint->TDHead;
00470         HCTD* tail = &_commonTail;
00471 
00472         head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; 
00473         head->CurrBufPtr = (u32)data;
00474         head->BufEnd = (u32)(data + len - 1);
00475         head->Next = (u32)tail;
00476 
00477         HCED* ed = &endpoint->EndpointDescriptor;
00478         ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002);    // carry toggle
00479         ed->TailTd = (u32)tail;
00480         
00481         //HCTD* td = head;
00482         //LOG("%04X TD %08X %08X %08X Next:%08X\r\r\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
00483         //LOG("%04X ED %08X %08X %08X\r\r\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd);
00484         
00485         switch (endpoint->Flags & 3)
00486         {
00487             case ENDPOINT_CONTROL:
00488                 LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED);    // May change state NotQueued->Idle
00489                 endpoint->CurrentState = state;                                               // Get in before an int
00490                 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled;
00491                 LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable;
00492                 break;
00493 
00494             case ENDPOINT_BULK:
00495                 LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED);
00496                 endpoint->CurrentState = state;
00497                 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled;
00498                 LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable;
00499                 break;
00500 
00501             case ENDPOINT_INTERRUPT:
00502                 CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]);
00503                 endpoint->CurrentState = state;
00504                 LPC_USB->HcControl |= PeriodicListEnable;
00505                 break;
00506         }
00507         return 0;
00508     }
00509     
00510     //    Remove an endpoint from an active queue
00511     bool Remove(HCED* ed, volatile HCED** queue)
00512     {
00513         if (*queue == 0)
00514             return false;
00515         if (*queue == (volatile HCED*)ed)
00516         {
00517             *queue = (volatile HCED*)ed->Next;    // At head of queue
00518             return true;
00519         }
00520 
00521         volatile HCED* head = *queue;
00522         while (head)
00523         {
00524             if (head->Next == (u32)ed)
00525             {
00526                 head->Next = ed->Next;
00527                 return true;
00528             }
00529             head = (volatile HCED*)head->Next;
00530         }
00531         return false;
00532     }
00533 
00534     void Release(Endpoint* endpoint)
00535     {
00536         if (endpoint->CurrentState == Endpoint::NotQueued)
00537         {
00538             // Never event used it, nothing to do
00539         }
00540         else
00541         {
00542             HCED* ed = (HCED*)endpoint;
00543             ed->Control |= 0x4000;    // SKIP
00544             switch (endpoint->Flags & 0x03)
00545             {
00546                 case ENDPOINT_CONTROL:
00547                     Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED);
00548                     break;
00549                 case ENDPOINT_BULK:
00550                     Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED);
00551                     break;
00552                 case ENDPOINT_INTERRUPT:
00553                     for (int i = 0; i < 32; i++)
00554                         Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]);
00555                     break;
00556             }
00557 
00558             u16 fn = CommunicationArea.FrameNumber;
00559             while (fn == CommunicationArea.FrameNumber)
00560                 ;    // Wait for next frame
00561 
00562         }
00563 
00564         //    In theory, the endpoint is now dead.
00565         //    TODO: Will Callbacks ever be pending? BUGBUG
00566         memset(endpoint,0,sizeof(Endpoint));
00567     }
00568 
00569     //      Pop the last TD from the list
00570     HCTD* Reverse(HCTD* current) 
00571     { 
00572         HCTD *result = NULL,*temp; 
00573         while (current) 
00574         { 
00575             temp = (HCTD*)current->Next; 
00576             current->Next = (u32)result;
00577             result = current;
00578             current = temp;
00579         }
00580         return result;
00581     }
00582 
00583     //      Called from interrupt...
00584     //      Control endpoints use a state machine to progress through the transfers
00585     void ProcessDoneQueue(u32 tdList)
00586     {
00587         HCTD* list = Reverse((HCTD*)tdList);
00588         while (list)
00589         {
00590             Endpoint* endpoint = (Endpoint*)(list-1);
00591             list = (HCTD*)list->Next;
00592             int ep = endpoint->Address();
00593             bool in = endpoint->Flags & 0x80;
00594             int status = (endpoint->TDHead.Control >> 28) & 0xF;
00595 
00596             //LOG("ProcessDoneQueue %02X %08X\r\r\n",ep,endpoint->TDHead.Control);
00597 
00598             if (status != 0)
00599             {
00600                 LOG("ProcessDoneQueue status %02X %d\r\r\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
00609                             Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued);    // Setup is done, now Data
00610                         break;
00611 
00612                     case Endpoint::DataQueued:
00613                         if (endpoint->TDHead.CurrBufPtr)
00614                             endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
00615 
00616                         if (ep == 0)
00617                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
00618                         else
00619                             endpoint->CurrentState = Endpoint::Idle;
00620                         break;
00621 
00622                     case Endpoint::StatusQueued:    // Transaction is done
00623                         endpoint->CurrentState = Endpoint::Idle;
00624                         break;
00625                 }
00626             }
00627 
00628             //      Complete, flag if we need a callback
00629             if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
00630             {
00631                 endpoint->CurrentState = Endpoint::CallbackPending;
00632                 _callbacksPending++;
00633             }
00634         }
00635     }
00636 
00637     //    Hack to reset devices that don't want to connect
00638     int AddDevice(int hub, int port, bool isLowSpeed)
00639     {
00640         int device = AddDeviceCore(hub,port,isLowSpeed);
00641         if (device < 0)
00642         {
00643             LOG("========RETRY ADD DEVICE========\r\r\n");    // This will go for ever.. TODO power cycle root?
00644             Disconnect(hub,port);    // Could not read descriptor at assigned address, reset this port and try again
00645             ResetPort(hub,port);    // Cheap bluetooth dongles often need this on a hotplug
00646             return -1;
00647         }
00648         return device;
00649     }
00650 
00651     int AddDeviceCore(int hub, int port, bool isLowSpeed)
00652     {
00653         int lowSpeed = isLowSpeed ? 0x2000 : 0;
00654         DeviceDescriptor desc;
00655         EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed;               // MaxPacketSize == 8
00656         int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8);
00657         if (r < 0)
00658         {
00659             LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\r\r\n");
00660             return r;
00661         }
00662 
00663         EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed;     // Actual MaxPacketSize
00664         r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00665         if (r < 0)
00666             return r;
00667 
00668         LOG("\r\nClass %02X found %04X:%04X\r\r\n",desc.bDeviceClass,desc.idVendor,desc.idProduct);
00669 
00670         //      Now assign the device an address, move off EndpointZero
00671         int device = 0;
00672         for (int i = 0; i < MAX_DEVICES; i++)
00673         {
00674             if (Devices[i].Port == 0)
00675             {
00676                 device = i+1;
00677                 break;
00678             }
00679         }
00680         if (!device)
00681             return ERR_DEVICE_NONE_LEFT;
00682 
00683         r = SetAddress(0,device);
00684         if (r)
00685             return r;
00686         DelayMS(2);
00687         
00688         // Now at a nonzero address, create control endpoint
00689         Device* dev = &Devices[device-1];
00690         dev->Init(&desc,hub,port,device,lowSpeed);
00691         AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0);
00692         _connectPending = 0;
00693 
00694         //    Verify this all works
00695         r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00696         if (r < 0)
00697             return r;
00698 
00699         //    Set to interface 0 by default
00700         //    Calls LoadDevice if interface is found
00701         //r = SetConfigurationAndInterface(device,1,0,&desc);
00702         r = SetConfigurationAndInterface(device,1,1,&desc);
00703         //r = SetConfigurationAndInterface(device,1,0,&desc);
00704 
00705         if (desc.bDeviceClass == CLASS_HUB)
00706             InitHub(device);            // Handle hubs in this code
00707 
00708         return device;
00709     }
00710 
00711     // Walk descriptors and create endpoints for a given device
00712     // TODO configuration !=1, alternate settings etc.
00713     int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc)
00714     {
00715         u8 buffer[255];
00716         int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,DESC_INDEX,buffer,sizeof(buffer));
00717         if (err < 0)
00718             return err;
00719 
00720         err = SetConfiguration(device,configuration);
00721         if (err < 0)
00722             return err;
00723 
00724         //    Add the endpoints for this interface
00725         int len = buffer[2] | (buffer[3] << 8);
00726         u8* d = buffer;
00727         u8* end = d + len;
00728         InterfaceDescriptor* found = 0;
00729         while (d < end)
00730         {
00731             if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
00732             {
00733                 InterfaceDescriptor* id = (InterfaceDescriptor*)d;
00734                 if (id->bInterfaceNumber == interfaceNumber)
00735                 {
00736                     found = id;
00737                     d += d[0];
00738                     while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
00739                     {
00740                         switch (d[1])
00741                         {
00742                             case DESCRIPTOR_TYPE_ENDPOINT:
00743                                 AddEndpoint(device,(EndpointDescriptor*)d);
00744                                 break;
00745                             default:
00746                                 LOG("Skipping descriptor %02X (%d bytes)\r\r\n",d[1],d[0]);
00747                         }
00748                         d += d[0];
00749                     }
00750                 }
00751             }
00752             d += d[0];
00753         }
00754 
00755         if (!found)
00756             return ERR_INTERFACE_NOT_FOUND;
00757         OnLoadDevice(device,desc,found);
00758         return 0;
00759     }
00760 
00761     void Init()
00762     {
00763         LOG("USB INIT (Controller is %d bytes)\r\r\n",sizeof(*this));
00764         memset(this,0,sizeof(HostController));
00765         EndpointZero.CurrentState = Endpoint::NotQueued;
00766         HWInit(&CommunicationArea);
00767         DelayMS(10);
00768     }
00769 
00770     void ResetPort(int hub, int port)
00771     {        
00772         LOG("ResetPort Hub:%d Port:%d\r\r\n",hub,port);
00773         _connectPending++;            // Only reset/add 1 device at a time
00774         if (hub == 0)
00775             LPC_USB->HcRhPortStatus1 = PortResetStatus;    // Reset Root Hub, port 1
00776         else
00777             SetPortReset(hub,port);    // or reset other hub
00778     }
00779 
00780     void Disconnect(int hub, int port)
00781     {
00782         LOG("Disconnect Hub:%d Port:%d\r\r\n",hub,port);    // Mark a device for destruction
00783         for (int i = 0; i < MAX_DEVICES; i++)
00784         {
00785             Device* dev = Devices + i;
00786             if (dev->Port == port && dev->Hub == hub)
00787             {
00788                 //    Disconnect everything that is attached to this device if it is a hub
00789                 for (int p = 0; p < dev->HubPortCount; p++)
00790                     Disconnect(i+1,p+1);
00791 
00792                 //    Now release endpoints
00793                 for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2)
00794                 {
00795                     u8 endpointIndex = dev->_endpointMap[j];
00796                     if (endpointIndex != 0xFF)
00797                         Release(Endpoints + endpointIndex);
00798                 }
00799                 dev->Port = 0;    // Device is now free
00800                 dev->Flags = 0;
00801                 return;
00802             }
00803         }
00804     }
00805 
00806     // called after reset
00807     void Connect(int hub, int port, bool lowspeed)
00808     {
00809         LOG("Connect Hub:%d Port:%d %s\r\r\n",hub,port,lowspeed ? "slow" : "full");
00810         AddDevice(hub,port,lowspeed);
00811     }
00812 
00813     // Called from interrupt
00814     void HubStatusChange(int hub, int port, u32 status)
00815     {
00816         LOG("HubStatusChange Hub:%d Port:%d %08X\r\r\n",hub,port,status);
00817         if (status & ConnectStatusChange)
00818         {
00819             if (status & CurrentConnectStatus)    // Connecting
00820                 ResetPort(hub,port);            // Reset to initiate connect (state machine?)
00821             else
00822                 Disconnect(hub,port);
00823         }
00824 
00825         if (status & PortResetStatusChange)
00826         {
00827             if (!(status & PortResetStatus))
00828             {
00829                 _connectCountdown = 200;        // Schedule a connection in 200ms
00830                 if (status & LowspeedDevice)
00831                     port |= 0x80;
00832                 _connectHub = hub;
00833                 _connectPort = port;
00834             }
00835         }
00836     }
00837 
00838     #define HOST_CLK_EN        (1<<0)
00839     #define PORTSEL_CLK_EN    (1<<3)
00840     #define AHB_CLK_EN        (1<<4)
00841     #define CLOCK_MASK        (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
00842 
00843     #define  FRAMEINTERVAL        (12000-1)    // 1ms
00844     #define  DEFAULT_FMINTERVAL    ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL)
00845 
00846     void DelayMS(int ms)
00847     {
00848         u16 f = ms + CommunicationArea.FrameNumber;
00849         while (f != CommunicationArea.FrameNumber)
00850             ;
00851     }
00852 
00853     static void HWInit(HCCA* cca)
00854     {
00855         NVIC_DisableIRQ(USB_IRQn);
00856         
00857         // turn on power for USB
00858         LPC_SC->PCONP        |= (1UL<<31);
00859         // Enable USB host clock, port selection and AHB clock
00860         LPC_USB->USBClkCtrl |= CLOCK_MASK;
00861         // Wait for clocks to become available
00862         while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
00863             ;
00864         
00865         //    We are a Host
00866         LPC_USB->OTGStCtrl |= 1;
00867         LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;                // we don't need port selection clock until we do OTG
00868         
00869         // configure USB pins
00870         LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));    
00871         LPC_PINCON->PINSEL1 |=    ((1<<26)|(1<<28));            // USB D+/D-
00872             
00873         LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22));        // USB_PPWR, USB_OVRCR
00874         LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22));
00875         
00876         LPC_PINCON->PINSEL4 &= ~(3 << 18);                    // USB_CONNECT
00877         LPC_PINCON->PINSEL4 |= (1 << 18);
00878 
00879         //    Reset OHCI block
00880         LPC_USB->HcControl         = 0;
00881         LPC_USB->HcControlHeadED = 0;
00882         LPC_USB->HcBulkHeadED     = 0;
00883         
00884         LPC_USB->HcCommandStatus = HostControllerReset;
00885         LPC_USB->HcFmInterval     = DEFAULT_FMINTERVAL;
00886         LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100;
00887 
00888         LPC_USB->HcControl    = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask;
00889         LPC_USB->HcRhStatus = SetGlobalPower;
00890         
00891         LPC_USB->HcHCCA = (u32)cca;
00892         LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
00893         LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow;
00894 
00895         NVIC_SetPriority(USB_IRQn, 0);
00896         NVIC_EnableIRQ(USB_IRQn);
00897         while (cca->FrameNumber < 10)
00898             ;    // 10ms delay before diving in
00899     }
00900 };
00901 
00902 //====================================================================================
00903 //====================================================================================
00904 //      Host controller instance and Interrupt handler
00905 
00906 static HostController _controller __attribute__((at(USB_RAM_BASE)));
00907 
00908 extern "C" void USB_IRQHandler(void) __irq;
00909 void USB_IRQHandler (void) __irq
00910 {
00911     u32 int_status = LPC_USB->HcInterruptStatus;
00912 
00913     if(int_status & UnrecoverableError) //Error
00914     {
00915       LOG("USB_IRQHandler UnrecoverableError Please reset\r\r\n");
00916     }
00917 
00918 
00919     if (int_status & RootHubStatusChange)    //    Root hub status change
00920         _controller._rootHubStatusChange++;    //    Just flag the controller, will be processed in USBLoop
00921 
00922     u32 head = 0;
00923     if (int_status & WritebackDoneHead)
00924     {
00925         head = _controller.CommunicationArea.DoneHead;        // Writeback Done
00926         _controller.CommunicationArea.DoneHead = 0;
00927     }             
00928     LPC_USB->HcInterruptStatus = int_status;
00929 
00930     if (head)
00931        _controller.ProcessDoneQueue(head);     // TODO - low bit can be set BUGBUG
00932 }
00933 
00934 //====================================================================================
00935 //====================================================================================
00936 //      API Methods
00937 
00938 void USBInit()
00939 {
00940     return _controller.Init();
00941 }
00942 
00943 void USBLoop()
00944 {
00945     
00946     return _controller.Loop();
00947     
00948 }
00949 
00950 u8* USBGetBuffer(u32* len)
00951 {
00952     *len = USB_RAM_SIZE - sizeof(HostController);
00953     return _controller.SRAM;
00954 }
00955 
00956 static Setup* GetSetup(int device)
00957 {
00958     if (device == 0)
00959         return &_controller._setupZero;
00960     
00961     if (device < 1 || device > MAX_DEVICES)
00962         return 0;
00963     return &_controller.Devices[device-1].SetupBuffer;
00964 }
00965 
00966 //    Loop until IO on endpoint is complete
00967 static int WaitIODone(Endpoint* endpoint)
00968 {
00969     LOG("Waiting\r\n\r");
00970     if (endpoint->CurrentState == Endpoint::NotQueued)
00971         return 0;
00972     while (endpoint->CurrentState != Endpoint::Idle)
00973         //LOG("Loopz");
00974         USBLoop();    // May generate callbacks, mount or unmount devices etc
00975     int status = endpoint->Status();
00976     if (status == 0)
00977         return endpoint->Length;
00978         LOG("DATA SENT\r\n\r");
00979     return -status;
00980 }
00981 
00982 int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
00983 {
00984     Endpoint* endpoint = _controller.GetEndpoint(device,ep);
00985     if (!endpoint)
00986         return ERR_ENDPOINT_NOT_FOUND;
00987         
00988     WaitIODone(endpoint);
00989     LOG("before ep=%x,callback=%p\r\r\n",endpoint,endpoint->Callback);
00990     endpoint->Flags = flags;
00991     endpoint->Data = data;
00992     endpoint->Length = length;
00993     endpoint->Callback = callback;
00994     endpoint->UserData = userData;
00995     LOG("ep=%x,callback=%p\r\r\n",ep,callback);
00996     if (ep == 0)
00997         _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
00998     else
00999         _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
01000     if (callback)
01001         return IO_PENDING;
01002     return WaitIODone(endpoint);
01003 }
01004 
01005 int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData)
01006 {
01007     Setup* setup = GetSetup(device);
01008     if (!setup)
01009         return ERR_DEVICE_NOT_FOUND;
01010         
01011     // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call
01012     WaitIODone(_controller.GetEndpoint(device,0));
01013     
01014     setup->bm_request_type = request_type;
01015     setup->b_request = request;
01016     setup->w_value = value;
01017     setup->w_index = index;
01018     setup->w_length = length;
01019     return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData);
01020 }
01021 
01022 int  USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01023 {
01024     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData);
01025 }
01026 
01027 int  USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01028 {
01029     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData);
01030 }
01031 
01032 int GetDescriptor(int device, int descType,int descIndex, u8* data, int length)
01033 {
01034     return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0);
01035 }
01036 
01037 int GetString(int device, int index, char* dst, int length)
01038 {
01039     u8 buffer[255];
01040     int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer));
01041     if (le < 0)
01042         return le;
01043     if (length < 1)
01044         return -1;
01045     length <<= 1;
01046     if (le > length)
01047         le = length;
01048     for (int j = 2; j < le; j += 2)
01049         *dst++ = buffer[j];
01050     *dst = 0;
01051     return (le>>1)-1;
01052 }
01053 
01054 int SetAddress(int device, int new_addr)
01055 {
01056     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0);
01057 }
01058 
01059 int SetConfiguration(int device, int configNum)
01060 {
01061     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0);
01062 }
01063 
01064 int SetInterface(int device, int ifNum, int altNum)
01065 {
01066     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0);
01067 }
01068 
01069 //    HUB stuff
01070 int SetPortFeature(int device, int feature, int index)
01071 {
01072     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0);
01073 }
01074 
01075 int ClearPortFeature(int device, int feature, int index)
01076 {
01077     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0);
01078 }
01079 
01080 int SetPortPower(int device, int port)
01081 {
01082     int r = SetPortFeature(device,PORT_POWER,port);
01083     _controller.DelayMS(20);    // 80ms to turn on a hubs power... DESCRIPTOR? todo
01084     return r;
01085 }
01086 
01087 int SetPortReset(int device, int port)
01088 {
01089     return SetPortFeature(device,PORT_RESET,port);
01090 }
01091 
01092 int GetPortStatus(int device, int port, u32* status)
01093 {
01094     return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4);
01095 }
01096 
01097 #endif