The modified AndroidAccessory Library

Dependents:   ADKTerm droidcycle uva_nc androidservo ... more

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