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