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