The modified AndroidAccessory Library
Dependents: ADKTerm droidcycle uva_nc androidservo ... more
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
Generated on Tue Jul 12 2022 15:55:45 by 1.7.2