Android Open Accessory Library化してみました。 バルク転送の使い方が分かっていないため、相変わらず動作は不安定。 I do not understand the usage of the bulk transfer. Please teach someone.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost.cpp Source File

USBHost.cpp

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