The modified AndroidAccessory Library

Dependents:   ADKTerm droidcycle uva_nc androidservo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost_log.cpp Source File

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