XOOMの動作状況を聞き処理を変えてみました。 USBケーブルを抜いた際に処理を終了するようにしました。

Dependencies:   mbed

Committer:
abe00makoto
Date:
Wed May 25 09:34:38 2011 +0000
Revision:
0:9fb6c423e32c
Child:
3:432e5675d240
support ADK

Who changed what in which revision?

UserRevisionLine numberNew contents of line
abe00makoto 0:9fb6c423e32c 1
abe00makoto 0:9fb6c423e32c 2 /*
abe00makoto 0:9fb6c423e32c 3 Copyright (c) 2010 Peter Barrett
abe00makoto 0:9fb6c423e32c 4
abe00makoto 0:9fb6c423e32c 5 Permission is hereby granted, free of charge, to any person obtaining a copy
abe00makoto 0:9fb6c423e32c 6 of this software and associated documentation files (the "Software"), to deal
abe00makoto 0:9fb6c423e32c 7 in the Software without restriction, including without limitation the rights
abe00makoto 0:9fb6c423e32c 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
abe00makoto 0:9fb6c423e32c 9 copies of the Software, and to permit persons to whom the Software is
abe00makoto 0:9fb6c423e32c 10 furnished to do so, subject to the following conditions:
abe00makoto 0:9fb6c423e32c 11
abe00makoto 0:9fb6c423e32c 12 The above copyright notice and this permission notice shall be included in
abe00makoto 0:9fb6c423e32c 13 all copies or substantial portions of the Software.
abe00makoto 0:9fb6c423e32c 14
abe00makoto 0:9fb6c423e32c 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
abe00makoto 0:9fb6c423e32c 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
abe00makoto 0:9fb6c423e32c 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
abe00makoto 0:9fb6c423e32c 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
abe00makoto 0:9fb6c423e32c 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
abe00makoto 0:9fb6c423e32c 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
abe00makoto 0:9fb6c423e32c 21 THE SOFTWARE.
abe00makoto 0:9fb6c423e32c 22 */
abe00makoto 0:9fb6c423e32c 23
abe00makoto 0:9fb6c423e32c 24 #include "mbed.h"
abe00makoto 0:9fb6c423e32c 25 #include "USBHost.h"
abe00makoto 0:9fb6c423e32c 26
abe00makoto 0:9fb6c423e32c 27 // Config (default uses x bytes)
abe00makoto 0:9fb6c423e32c 28 #define MAX_DEVICES 8 // Max number of devices
abe00makoto 0:9fb6c423e32c 29 #define MAX_ENDPOINTS_TOTAL 16 // Max number of endpoints total
abe00makoto 0:9fb6c423e32c 30 #define MAX_ENDPOINTS_PER_DEVICE 8 // Max number of endpoints for any one device
abe00makoto 0:9fb6c423e32c 31
abe00makoto 0:9fb6c423e32c 32 #define USBLOG 1
abe00makoto 0:9fb6c423e32c 33 #if USBLOG
abe00makoto 0:9fb6c423e32c 34 #define LOG(...) printf(__VA_ARGS__)
abe00makoto 0:9fb6c423e32c 35 #else
abe00makoto 0:9fb6c423e32c 36 #define LOG(...) do {} while(0)
abe00makoto 0:9fb6c423e32c 37 #endif
abe00makoto 0:9fb6c423e32c 38
abe00makoto 0:9fb6c423e32c 39 // USB host structures
abe00makoto 0:9fb6c423e32c 40
abe00makoto 0:9fb6c423e32c 41 #define USB_RAM_SIZE 16*1024 // AHB SRAM block 1 TODO MACHINE DEPENDENT
abe00makoto 0:9fb6c423e32c 42 #define USB_RAM_BASE 0x2007C000
abe00makoto 0:9fb6c423e32c 43
abe00makoto 0:9fb6c423e32c 44 #define TOKEN_SETUP 0
abe00makoto 0:9fb6c423e32c 45 #define TOKEN_IN 1
abe00makoto 0:9fb6c423e32c 46 #define TOKEN_OUT 2
abe00makoto 0:9fb6c423e32c 47
abe00makoto 0:9fb6c423e32c 48 // Status flags from hub
abe00makoto 0:9fb6c423e32c 49 #define PORT_CONNECTION 0
abe00makoto 0:9fb6c423e32c 50 #define PORT_ENABLE 1
abe00makoto 0:9fb6c423e32c 51 #define PORT_SUSPEND 2
abe00makoto 0:9fb6c423e32c 52 #define PORT_OVER_CURRENT 3
abe00makoto 0:9fb6c423e32c 53 #define PORT_RESET 4
abe00makoto 0:9fb6c423e32c 54 #define PORT_POWER 8
abe00makoto 0:9fb6c423e32c 55 #define PORT_LOW_SPEED 9
abe00makoto 0:9fb6c423e32c 56
abe00makoto 0:9fb6c423e32c 57 #define C_PORT_CONNECTION 16
abe00makoto 0:9fb6c423e32c 58 #define C_PORT_ENABLE 17
abe00makoto 0:9fb6c423e32c 59 #define C_PORT_SUSPEND 18
abe00makoto 0:9fb6c423e32c 60 #define C_PORT_OVER_CURRENT 19
abe00makoto 0:9fb6c423e32c 61 #define C_PORT_RESET 20
abe00makoto 0:9fb6c423e32c 62
abe00makoto 0:9fb6c423e32c 63 typedef struct {
abe00makoto 0:9fb6c423e32c 64 u8 bm_request_type;
abe00makoto 0:9fb6c423e32c 65 u8 b_request;
abe00makoto 0:9fb6c423e32c 66 u16 w_value;
abe00makoto 0:9fb6c423e32c 67 u16 w_index;
abe00makoto 0:9fb6c423e32c 68 u16 w_length;
abe00makoto 0:9fb6c423e32c 69 } Setup;
abe00makoto 0:9fb6c423e32c 70
abe00makoto 0:9fb6c423e32c 71
abe00makoto 0:9fb6c423e32c 72 // Hub stuff is kept private just to keep api simple
abe00makoto 0:9fb6c423e32c 73 int SetPortFeature(int device, int feature, int index);
abe00makoto 0:9fb6c423e32c 74 int ClearPortFeature(int device, int feature, int index);
abe00makoto 0:9fb6c423e32c 75 int SetPortPower(int device, int port);
abe00makoto 0:9fb6c423e32c 76 int SetPortReset(int device, int port);
abe00makoto 0:9fb6c423e32c 77 int GetPortStatus(int device, int port, u32* status);
abe00makoto 0:9fb6c423e32c 78
abe00makoto 0:9fb6c423e32c 79 //===================================================================
abe00makoto 0:9fb6c423e32c 80 //===================================================================
abe00makoto 0:9fb6c423e32c 81 // Hardware defines
abe00makoto 0:9fb6c423e32c 82
abe00makoto 0:9fb6c423e32c 83 // HcControl
abe00makoto 0:9fb6c423e32c 84 #define PeriodicListEnable 0x00000004
abe00makoto 0:9fb6c423e32c 85 #define IsochronousEnable 0x00000008
abe00makoto 0:9fb6c423e32c 86 #define ControlListEnable 0x00000010
abe00makoto 0:9fb6c423e32c 87 #define BulkListEnable 0x00000020
abe00makoto 0:9fb6c423e32c 88 #define OperationalMask 0x00000080
abe00makoto 0:9fb6c423e32c 89 #define HostControllerFunctionalState 0x000000C0
abe00makoto 0:9fb6c423e32c 90
abe00makoto 0:9fb6c423e32c 91 // HcCommandStatus
abe00makoto 0:9fb6c423e32c 92 #define HostControllerReset 0x00000001
abe00makoto 0:9fb6c423e32c 93 #define ControlListFilled 0x00000002
abe00makoto 0:9fb6c423e32c 94 #define BulkListFilled 0x00000004
abe00makoto 0:9fb6c423e32c 95
abe00makoto 0:9fb6c423e32c 96 // HcInterruptStatus Register
abe00makoto 0:9fb6c423e32c 97 #define WritebackDoneHead 0x00000002
abe00makoto 0:9fb6c423e32c 98 #define StartofFrame 0x00000004
abe00makoto 0:9fb6c423e32c 99 #define ResumeDetected 0x00000008
abe00makoto 0:9fb6c423e32c 100 #define UnrecoverableError 0x00000010
abe00makoto 0:9fb6c423e32c 101 #define FrameNumberOverflow 0x00000020
abe00makoto 0:9fb6c423e32c 102 #define RootHubStatusChange 0x00000040
abe00makoto 0:9fb6c423e32c 103 #define OwnershipChange 0x00000080
abe00makoto 0:9fb6c423e32c 104 #define MasterInterruptEnable 0x80000000
abe00makoto 0:9fb6c423e32c 105
abe00makoto 0:9fb6c423e32c 106 // HcRhStatus
abe00makoto 0:9fb6c423e32c 107 #define SetGlobalPower 0x00010000
abe00makoto 0:9fb6c423e32c 108 #define DeviceRemoteWakeupEnable 0x00008000
abe00makoto 0:9fb6c423e32c 109
abe00makoto 0:9fb6c423e32c 110 // HcRhPortStatus (hub 0, port 1)
abe00makoto 0:9fb6c423e32c 111 #define CurrentConnectStatus 0x00000001
abe00makoto 0:9fb6c423e32c 112 #define PortEnableStatus 0x00000002
abe00makoto 0:9fb6c423e32c 113 #define PortSuspendStatus 0x00000004
abe00makoto 0:9fb6c423e32c 114 #define PortOverCurrentIndicator 0x00000008
abe00makoto 0:9fb6c423e32c 115 #define PortResetStatus 0x00000010
abe00makoto 0:9fb6c423e32c 116
abe00makoto 0:9fb6c423e32c 117 #define PortPowerStatus 0x00000100
abe00makoto 0:9fb6c423e32c 118 #define LowspeedDevice 0x00000200
abe00makoto 0:9fb6c423e32c 119 #define HighspeedDevice 0x00000400
abe00makoto 0:9fb6c423e32c 120
abe00makoto 0:9fb6c423e32c 121 #define ConnectStatusChange (CurrentConnectStatus << 16)
abe00makoto 0:9fb6c423e32c 122 #define PortResetStatusChange (PortResetStatus << 16)
abe00makoto 0:9fb6c423e32c 123
abe00makoto 0:9fb6c423e32c 124
abe00makoto 0:9fb6c423e32c 125 #define TD_ROUNDING (u32)0x00040000
abe00makoto 0:9fb6c423e32c 126 #define TD_SETUP (u32)0x00000000
abe00makoto 0:9fb6c423e32c 127 #define TD_IN (u32)0x00100000
abe00makoto 0:9fb6c423e32c 128 #define TD_OUT (u32)0x00080000
abe00makoto 0:9fb6c423e32c 129 #define TD_DELAY_INT(x) (u32)((x) << 21)
abe00makoto 0:9fb6c423e32c 130 #define TD_TOGGLE_0 (u32)0x02000000
abe00makoto 0:9fb6c423e32c 131 #define TD_TOGGLE_1 (u32)0x03000000
abe00makoto 0:9fb6c423e32c 132 #define TD_CC (u32)0xF0000000
abe00makoto 0:9fb6c423e32c 133
abe00makoto 0:9fb6c423e32c 134 // HostController EndPoint Descriptor
abe00makoto 0:9fb6c423e32c 135 typedef struct {
abe00makoto 0:9fb6c423e32c 136 volatile u32 Control;
abe00makoto 0:9fb6c423e32c 137 volatile u32 TailTd;
abe00makoto 0:9fb6c423e32c 138 volatile u32 HeadTd;
abe00makoto 0:9fb6c423e32c 139 volatile u32 Next;
abe00makoto 0:9fb6c423e32c 140 } HCED;
abe00makoto 0:9fb6c423e32c 141
abe00makoto 0:9fb6c423e32c 142 // HostController Transfer Descriptor
abe00makoto 0:9fb6c423e32c 143 typedef struct {
abe00makoto 0:9fb6c423e32c 144 volatile u32 Control;
abe00makoto 0:9fb6c423e32c 145 volatile u32 CurrBufPtr;
abe00makoto 0:9fb6c423e32c 146 volatile u32 Next;
abe00makoto 0:9fb6c423e32c 147 volatile u32 BufEnd;
abe00makoto 0:9fb6c423e32c 148 } HCTD;
abe00makoto 0:9fb6c423e32c 149
abe00makoto 0:9fb6c423e32c 150 // Host Controller Communication Area
abe00makoto 0:9fb6c423e32c 151 typedef struct {
abe00makoto 0:9fb6c423e32c 152 volatile u32 InterruptTable[32];
abe00makoto 0:9fb6c423e32c 153 volatile u16 FrameNumber;
abe00makoto 0:9fb6c423e32c 154 volatile u16 FrameNumberPad;
abe00makoto 0:9fb6c423e32c 155 volatile u32 DoneHead;
abe00makoto 0:9fb6c423e32c 156 volatile u8 Reserved[120];
abe00makoto 0:9fb6c423e32c 157 } HCCA;
abe00makoto 0:9fb6c423e32c 158
abe00makoto 0:9fb6c423e32c 159 //====================================================================================
abe00makoto 0:9fb6c423e32c 160 //====================================================================================
abe00makoto 0:9fb6c423e32c 161
abe00makoto 0:9fb6c423e32c 162 class HostController;
abe00makoto 0:9fb6c423e32c 163 class Endpoint;
abe00makoto 0:9fb6c423e32c 164 class Device;
abe00makoto 0:9fb6c423e32c 165
abe00makoto 0:9fb6c423e32c 166 // must be 3*16 bytes long
abe00makoto 0:9fb6c423e32c 167 class Endpoint
abe00makoto 0:9fb6c423e32c 168 {
abe00makoto 0:9fb6c423e32c 169 public:
abe00makoto 0:9fb6c423e32c 170 HCED EndpointDescriptor; // Pointer to EndpointDescriptor == Pointer to Endpoint
abe00makoto 0:9fb6c423e32c 171 HCTD TDHead;
abe00makoto 0:9fb6c423e32c 172
abe00makoto 0:9fb6c423e32c 173 enum State
abe00makoto 0:9fb6c423e32c 174 {
abe00makoto 0:9fb6c423e32c 175 Free,
abe00makoto 0:9fb6c423e32c 176 NotQueued,
abe00makoto 0:9fb6c423e32c 177 Idle,
abe00makoto 0:9fb6c423e32c 178 SetupQueued,
abe00makoto 0:9fb6c423e32c 179 DataQueued,
abe00makoto 0:9fb6c423e32c 180 StatusQueued,
abe00makoto 0:9fb6c423e32c 181 CallbackPending
abe00makoto 0:9fb6c423e32c 182 };
abe00makoto 0:9fb6c423e32c 183
abe00makoto 0:9fb6c423e32c 184 volatile u8 CurrentState;
abe00makoto 0:9fb6c423e32c 185 u8 Flags; // 0x80 In, 0x03 mask endpoint type
abe00makoto 0:9fb6c423e32c 186
abe00makoto 0:9fb6c423e32c 187 u16 Length;
abe00makoto 0:9fb6c423e32c 188 u8* Data;
abe00makoto 0:9fb6c423e32c 189 USBCallback Callback; // Must be a multiple of 16 bytes long
abe00makoto 0:9fb6c423e32c 190 void* UserData;
abe00makoto 0:9fb6c423e32c 191
abe00makoto 0:9fb6c423e32c 192 int Address()
abe00makoto 0:9fb6c423e32c 193 {
abe00makoto 0:9fb6c423e32c 194 int ep = (EndpointDescriptor.Control >> 7) & 0xF;
abe00makoto 0:9fb6c423e32c 195 if (ep)
abe00makoto 0:9fb6c423e32c 196 ep |= Flags & 0x80;
abe00makoto 0:9fb6c423e32c 197 return ep;
abe00makoto 0:9fb6c423e32c 198 }
abe00makoto 0:9fb6c423e32c 199
abe00makoto 0:9fb6c423e32c 200 int Device()
abe00makoto 0:9fb6c423e32c 201 {
abe00makoto 0:9fb6c423e32c 202 return EndpointDescriptor.Control & 0x7F;
abe00makoto 0:9fb6c423e32c 203 }
abe00makoto 0:9fb6c423e32c 204
abe00makoto 0:9fb6c423e32c 205 int Status()
abe00makoto 0:9fb6c423e32c 206 {
abe00makoto 0:9fb6c423e32c 207 return (TDHead.Control >> 28) & 0xF;
abe00makoto 0:9fb6c423e32c 208 }
abe00makoto 0:9fb6c423e32c 209
abe00makoto 0:9fb6c423e32c 210 u32 Enqueue(u32 head)
abe00makoto 0:9fb6c423e32c 211 {
abe00makoto 0:9fb6c423e32c 212 if (CurrentState == NotQueued)
abe00makoto 0:9fb6c423e32c 213 {
abe00makoto 0:9fb6c423e32c 214 EndpointDescriptor.Next = head;
abe00makoto 0:9fb6c423e32c 215 head = (u32)&EndpointDescriptor;
abe00makoto 0:9fb6c423e32c 216 CurrentState = Idle;
abe00makoto 0:9fb6c423e32c 217 }
abe00makoto 0:9fb6c423e32c 218 return head;
abe00makoto 0:9fb6c423e32c 219 }
abe00makoto 0:9fb6c423e32c 220 };
abe00makoto 0:9fb6c423e32c 221
abe00makoto 0:9fb6c423e32c 222 class Device
abe00makoto 0:9fb6c423e32c 223 {
abe00makoto 0:9fb6c423e32c 224 public:
abe00makoto 0:9fb6c423e32c 225 u8 _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2];
abe00makoto 0:9fb6c423e32c 226 u8 Hub;
abe00makoto 0:9fb6c423e32c 227 u8 Port;
abe00makoto 0:9fb6c423e32c 228 u8 Addr;
abe00makoto 0:9fb6c423e32c 229 u8 Pad;
abe00makoto 0:9fb6c423e32c 230
abe00makoto 0:9fb6c423e32c 231 // Only if this device is a hub
abe00makoto 0:9fb6c423e32c 232 u8 HubPortCount; // nonzero if this is a hub
abe00makoto 0:9fb6c423e32c 233 u8 HubInterruptData;
abe00makoto 0:9fb6c423e32c 234 u8 HubMap;
abe00makoto 0:9fb6c423e32c 235 u8 HubMask;
abe00makoto 0:9fb6c423e32c 236
abe00makoto 0:9fb6c423e32c 237 int Flags; // 1 = Disconnected
abe00makoto 0:9fb6c423e32c 238
abe00makoto 0:9fb6c423e32c 239 Setup SetupBuffer;
abe00makoto 0:9fb6c423e32c 240
abe00makoto 0:9fb6c423e32c 241 // Allocate endpoint zero
abe00makoto 0:9fb6c423e32c 242 int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed)
abe00makoto 0:9fb6c423e32c 243 {
abe00makoto 0:9fb6c423e32c 244 Hub = hub;
abe00makoto 0:9fb6c423e32c 245 Port = port;
abe00makoto 0:9fb6c423e32c 246 Addr = addr;
abe00makoto 0:9fb6c423e32c 247 Flags = lowSpeed;
abe00makoto 0:9fb6c423e32c 248 memset(_endpointMap,0xFF,sizeof(_endpointMap));
abe00makoto 0:9fb6c423e32c 249 return 0;
abe00makoto 0:9fb6c423e32c 250 }
abe00makoto 0:9fb6c423e32c 251
abe00makoto 0:9fb6c423e32c 252 int SetEndpointIndex(int ep, int endpointIndex)
abe00makoto 0:9fb6c423e32c 253 {
abe00makoto 0:9fb6c423e32c 254 for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
abe00makoto 0:9fb6c423e32c 255 {
abe00makoto 0:9fb6c423e32c 256 if (_endpointMap[i] == 0xFF) // Add endpoint to map
abe00makoto 0:9fb6c423e32c 257 {
abe00makoto 0:9fb6c423e32c 258 _endpointMap[i] = ep;
abe00makoto 0:9fb6c423e32c 259 _endpointMap[i+1] = endpointIndex;
abe00makoto 0:9fb6c423e32c 260 return 0;
abe00makoto 0:9fb6c423e32c 261 }
abe00makoto 0:9fb6c423e32c 262 }
abe00makoto 0:9fb6c423e32c 263 return ERR_ENDPOINT_NONE_LEFT;
abe00makoto 0:9fb6c423e32c 264 }
abe00makoto 0:9fb6c423e32c 265
abe00makoto 0:9fb6c423e32c 266 int GetEndpointIndex(int ep)
abe00makoto 0:9fb6c423e32c 267 {
abe00makoto 0:9fb6c423e32c 268 for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
abe00makoto 0:9fb6c423e32c 269 {
abe00makoto 0:9fb6c423e32c 270 if (_endpointMap[i] == ep)
abe00makoto 0:9fb6c423e32c 271 return _endpointMap[i+1];
abe00makoto 0:9fb6c423e32c 272 if (_endpointMap[i] == 0xFF)
abe00makoto 0:9fb6c423e32c 273 break;
abe00makoto 0:9fb6c423e32c 274 }
abe00makoto 0:9fb6c423e32c 275 return -1;
abe00makoto 0:9fb6c423e32c 276 }
abe00makoto 0:9fb6c423e32c 277 };
abe00makoto 0:9fb6c423e32c 278
abe00makoto 0:9fb6c423e32c 279 class HostController
abe00makoto 0:9fb6c423e32c 280 {
abe00makoto 0:9fb6c423e32c 281 public:
abe00makoto 0:9fb6c423e32c 282 HCCA CommunicationArea;
abe00makoto 0:9fb6c423e32c 283 Endpoint Endpoints[MAX_ENDPOINTS_TOTAL]; // Multiple of 16
abe00makoto 0:9fb6c423e32c 284
abe00makoto 0:9fb6c423e32c 285 Endpoint EndpointZero; // For device enumeration
abe00makoto 0:9fb6c423e32c 286 HCTD _commonTail;
abe00makoto 0:9fb6c423e32c 287 Setup _setupZero;
abe00makoto 0:9fb6c423e32c 288
abe00makoto 0:9fb6c423e32c 289 Device Devices[MAX_DEVICES];
abe00makoto 0:9fb6c423e32c 290 u32 _frameNumber; // 32 bit ms counter
abe00makoto 0:9fb6c423e32c 291
abe00makoto 0:9fb6c423e32c 292 u8 _callbacksPending; // Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue
abe00makoto 0:9fb6c423e32c 293 u8 _rootHubStatusChange; // Root hub status has changed, set from ISR
abe00makoto 0:9fb6c423e32c 294 u8 _unused0;
abe00makoto 0:9fb6c423e32c 295 u8 _unused1;
abe00makoto 0:9fb6c423e32c 296
abe00makoto 0:9fb6c423e32c 297 u8 _connectPending; // Reset has initiated a connect
abe00makoto 0:9fb6c423e32c 298 u8 _connectCountdown; // Number of ms left after reset before we can connect
abe00makoto 0:9fb6c423e32c 299 u8 _connectHub; // Will connect on this hub
abe00makoto 0:9fb6c423e32c 300 u8 _connectPort; // ... and this port
abe00makoto 0:9fb6c423e32c 301
abe00makoto 0:9fb6c423e32c 302 u8 SRAM[0]; // Start of free SRAM
abe00makoto 0:9fb6c423e32c 303
abe00makoto 0:9fb6c423e32c 304 void Loop()
abe00makoto 0:9fb6c423e32c 305 {
abe00makoto 0:9fb6c423e32c 306 u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber; // extend to 32 bits
abe00makoto 0:9fb6c423e32c 307 _frameNumber += elapsed;
abe00makoto 0:9fb6c423e32c 308
abe00makoto 0:9fb6c423e32c 309 // Do callbacks, if any
abe00makoto 0:9fb6c423e32c 310 while (_callbacksPending)
abe00makoto 0:9fb6c423e32c 311 {
abe00makoto 0:9fb6c423e32c 312 for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
abe00makoto 0:9fb6c423e32c 313 {
abe00makoto 0:9fb6c423e32c 314 Endpoint* endpoint = Endpoints + i;
abe00makoto 0:9fb6c423e32c 315 if (endpoint->CurrentState == Endpoint::CallbackPending)
abe00makoto 0:9fb6c423e32c 316 {
abe00makoto 0:9fb6c423e32c 317 _callbacksPending--;
abe00makoto 0:9fb6c423e32c 318 endpoint->CurrentState = Endpoint::Idle;
abe00makoto 0:9fb6c423e32c 319 endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData);
abe00makoto 0:9fb6c423e32c 320 }
abe00makoto 0:9fb6c423e32c 321 }
abe00makoto 0:9fb6c423e32c 322 }
abe00makoto 0:9fb6c423e32c 323
abe00makoto 0:9fb6c423e32c 324 // Deal with changes on the root hub
abe00makoto 0:9fb6c423e32c 325 if (_rootHubStatusChange)
abe00makoto 0:9fb6c423e32c 326 {
abe00makoto 0:9fb6c423e32c 327 u32 status = LPC_USB->HcRhPortStatus1;
abe00makoto 0:9fb6c423e32c 328 _rootHubStatusChange = 0;
abe00makoto 0:9fb6c423e32c 329 if (status >> 16)
abe00makoto 0:9fb6c423e32c 330 {
abe00makoto 0:9fb6c423e32c 331 HubStatusChange(0,1,status);
abe00makoto 0:9fb6c423e32c 332 LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000; // clear status changes
abe00makoto 0:9fb6c423e32c 333 }
abe00makoto 0:9fb6c423e32c 334 }
abe00makoto 0:9fb6c423e32c 335
abe00makoto 0:9fb6c423e32c 336 // Connect after reset timeout
abe00makoto 0:9fb6c423e32c 337 if (_connectCountdown)
abe00makoto 0:9fb6c423e32c 338 {
abe00makoto 0:9fb6c423e32c 339 if (elapsed >= _connectCountdown)
abe00makoto 0:9fb6c423e32c 340 {
abe00makoto 0:9fb6c423e32c 341 _connectCountdown = 0;
abe00makoto 0:9fb6c423e32c 342 Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80);
abe00makoto 0:9fb6c423e32c 343 } else
abe00makoto 0:9fb6c423e32c 344 _connectCountdown -= elapsed;
abe00makoto 0:9fb6c423e32c 345 }
abe00makoto 0:9fb6c423e32c 346 }
abe00makoto 0:9fb6c423e32c 347
abe00makoto 0:9fb6c423e32c 348 // HubInterrupt - bitmap in dev->HubInterruptData
abe00makoto 0:9fb6c423e32c 349 void HubInterrupt(int device)
abe00makoto 0:9fb6c423e32c 350 {
abe00makoto 0:9fb6c423e32c 351 Device* dev = &Devices[device-1];
abe00makoto 0:9fb6c423e32c 352 for (int i = 0; i < dev->HubPortCount; i++)
abe00makoto 0:9fb6c423e32c 353 {
abe00makoto 0:9fb6c423e32c 354 int port = i+1;
abe00makoto 0:9fb6c423e32c 355 if (dev->HubInterruptData & (1 << port))
abe00makoto 0:9fb6c423e32c 356 {
abe00makoto 0:9fb6c423e32c 357 u32 status = 0;
abe00makoto 0:9fb6c423e32c 358 GetPortStatus(device,port,&status);
abe00makoto 0:9fb6c423e32c 359 if (status >> 16)
abe00makoto 0:9fb6c423e32c 360 {
abe00makoto 0:9fb6c423e32c 361 if (_connectPending && (status & ConnectStatusChange))
abe00makoto 0:9fb6c423e32c 362 continue; // Don't connect again until previous device has been added and addressed
abe00makoto 0:9fb6c423e32c 363
abe00makoto 0:9fb6c423e32c 364 HubStatusChange(device,port,status);
abe00makoto 0:9fb6c423e32c 365 if (status & ConnectStatusChange)
abe00makoto 0:9fb6c423e32c 366 ClearPortFeature(device,C_PORT_CONNECTION,port);
abe00makoto 0:9fb6c423e32c 367 if (status & PortResetStatusChange)
abe00makoto 0:9fb6c423e32c 368 ClearPortFeature(device,C_PORT_RESET,port);
abe00makoto 0:9fb6c423e32c 369 }
abe00makoto 0:9fb6c423e32c 370 }
abe00makoto 0:9fb6c423e32c 371 }
abe00makoto 0:9fb6c423e32c 372 }
abe00makoto 0:9fb6c423e32c 373
abe00makoto 0:9fb6c423e32c 374 static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
abe00makoto 0:9fb6c423e32c 375 {
abe00makoto 0:9fb6c423e32c 376 HostController* controller = (HostController*)userData;
abe00makoto 0:9fb6c423e32c 377 if (status == 0)
abe00makoto 0:9fb6c423e32c 378 controller->HubInterrupt(device);
abe00makoto 0:9fb6c423e32c 379 USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData);
abe00makoto 0:9fb6c423e32c 380 }
abe00makoto 0:9fb6c423e32c 381
abe00makoto 0:9fb6c423e32c 382 int InitHub(int device)
abe00makoto 0:9fb6c423e32c 383 {
abe00makoto 0:9fb6c423e32c 384 u8 buf[16];
abe00makoto 0:9fb6c423e32c 385 int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf));
abe00makoto 0:9fb6c423e32c 386 if (r < 0)
abe00makoto 0:9fb6c423e32c 387 return ERR_HUB_INIT_FAILED;
abe00makoto 0:9fb6c423e32c 388
abe00makoto 0:9fb6c423e32c 389 // turn on power on the hubs ports
abe00makoto 0:9fb6c423e32c 390 Device* dev = &Devices[device-1];
abe00makoto 0:9fb6c423e32c 391 int ports = buf[2];
abe00makoto 0:9fb6c423e32c 392 dev->HubPortCount = ports;
abe00makoto 0:9fb6c423e32c 393 for (int i = 0; i < ports; i++)
abe00makoto 0:9fb6c423e32c 394 SetPortPower(device,i+1);
abe00makoto 0:9fb6c423e32c 395
abe00makoto 0:9fb6c423e32c 396 // Enable hub change interrupts
abe00makoto 0:9fb6c423e32c 397 return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this);
abe00makoto 0:9fb6c423e32c 398 }
abe00makoto 0:9fb6c423e32c 399
abe00makoto 0:9fb6c423e32c 400 int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval)
abe00makoto 0:9fb6c423e32c 401 {
abe00makoto 0:9fb6c423e32c 402 LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\r\n",device,ep,attributes,maxPacketSize,interval);
abe00makoto 0:9fb6c423e32c 403 Device* dev = &Devices[device-1];
abe00makoto 0:9fb6c423e32c 404 Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize);
abe00makoto 0:9fb6c423e32c 405 if (!endpoint)
abe00makoto 0:9fb6c423e32c 406 return ERR_ENDPOINT_NONE_LEFT;
abe00makoto 0:9fb6c423e32c 407 dev->SetEndpointIndex(ep,endpoint - Endpoints);
abe00makoto 0:9fb6c423e32c 408 endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed
abe00makoto 0:9fb6c423e32c 409 return 0; // TODO ed->bInterval
abe00makoto 0:9fb6c423e32c 410 }
abe00makoto 0:9fb6c423e32c 411
abe00makoto 0:9fb6c423e32c 412 int AddEndpoint(int device, EndpointDescriptor* ed)
abe00makoto 0:9fb6c423e32c 413 {
abe00makoto 0:9fb6c423e32c 414 return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval);
abe00makoto 0:9fb6c423e32c 415 }
abe00makoto 0:9fb6c423e32c 416
abe00makoto 0:9fb6c423e32c 417 // allocate a endpoint
abe00makoto 0:9fb6c423e32c 418 Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize)
abe00makoto 0:9fb6c423e32c 419 {
abe00makoto 0:9fb6c423e32c 420 for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
abe00makoto 0:9fb6c423e32c 421 {
abe00makoto 0:9fb6c423e32c 422 Endpoint* ep = &Endpoints[i];
abe00makoto 0:9fb6c423e32c 423 if (ep->CurrentState == 0)
abe00makoto 0:9fb6c423e32c 424 {
abe00makoto 0:9fb6c423e32c 425 //LOG("Allocated endpoint %d to %02X:%02X\r\n",i,device,endpointAddress);
abe00makoto 0:9fb6c423e32c 426 ep->Flags = (endpointAddress & 0x80) | (type & 3);
abe00makoto 0:9fb6c423e32c 427 ep->CurrentState = Endpoint::NotQueued;
abe00makoto 0:9fb6c423e32c 428 ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device;
abe00makoto 0:9fb6c423e32c 429 return ep;
abe00makoto 0:9fb6c423e32c 430 }
abe00makoto 0:9fb6c423e32c 431 }
abe00makoto 0:9fb6c423e32c 432 return 0;
abe00makoto 0:9fb6c423e32c 433 }
abe00makoto 0:9fb6c423e32c 434
abe00makoto 0:9fb6c423e32c 435 Endpoint* GetEndpoint(int device, int ep)
abe00makoto 0:9fb6c423e32c 436 {
abe00makoto 0:9fb6c423e32c 437 if (device == 0)
abe00makoto 0:9fb6c423e32c 438 {
abe00makoto 0:9fb6c423e32c 439 //printf("WARNING: USING DEVICE 0\n");
abe00makoto 0:9fb6c423e32c 440 return &EndpointZero;
abe00makoto 0:9fb6c423e32c 441 }
abe00makoto 0:9fb6c423e32c 442 if (device > MAX_DEVICES)
abe00makoto 0:9fb6c423e32c 443 return 0;
abe00makoto 0:9fb6c423e32c 444 int i = Devices[device-1].GetEndpointIndex(ep);
abe00makoto 0:9fb6c423e32c 445 if (i == -1)
abe00makoto 0:9fb6c423e32c 446 return 0;
abe00makoto 0:9fb6c423e32c 447 return Endpoints + i;
abe00makoto 0:9fb6c423e32c 448 }
abe00makoto 0:9fb6c423e32c 449
abe00makoto 0:9fb6c423e32c 450 int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state)
abe00makoto 0:9fb6c423e32c 451 {
abe00makoto 0:9fb6c423e32c 452 //LOG("Transfer %02X T:%d Len:%d S:%d\r\n",endpoint->Address(),token,len,state);
abe00makoto 0:9fb6c423e32c 453
abe00makoto 0:9fb6c423e32c 454 int toggle = 0;
abe00makoto 0:9fb6c423e32c 455 if (endpoint->Address() == 0)
abe00makoto 0:9fb6c423e32c 456 toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1;
abe00makoto 0:9fb6c423e32c 457
abe00makoto 0:9fb6c423e32c 458 if (token != TOKEN_SETUP)
abe00makoto 0:9fb6c423e32c 459 token = (token == TOKEN_IN ? TD_IN : TD_OUT);
abe00makoto 0:9fb6c423e32c 460
abe00makoto 0:9fb6c423e32c 461 HCTD* head = &endpoint->TDHead;
abe00makoto 0:9fb6c423e32c 462 HCTD* tail = &_commonTail;
abe00makoto 0:9fb6c423e32c 463
abe00makoto 0:9fb6c423e32c 464 head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC;
abe00makoto 0:9fb6c423e32c 465 head->CurrBufPtr = (u32)data;
abe00makoto 0:9fb6c423e32c 466 head->BufEnd = (u32)(data + len - 1);
abe00makoto 0:9fb6c423e32c 467 head->Next = (u32)tail;
abe00makoto 0:9fb6c423e32c 468
abe00makoto 0:9fb6c423e32c 469 HCED* ed = &endpoint->EndpointDescriptor;
abe00makoto 0:9fb6c423e32c 470 ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002); // carry toggle
abe00makoto 0:9fb6c423e32c 471 ed->TailTd = (u32)tail;
abe00makoto 0:9fb6c423e32c 472
abe00makoto 0:9fb6c423e32c 473 //HCTD* td = head;
abe00makoto 0:9fb6c423e32c 474 //LOG("%04X TD %08X %08X %08X Next:%08X\r\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
abe00makoto 0:9fb6c423e32c 475 //LOG("%04X ED %08X %08X %08X\r\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd);
abe00makoto 0:9fb6c423e32c 476
abe00makoto 0:9fb6c423e32c 477 switch (endpoint->Flags & 3)
abe00makoto 0:9fb6c423e32c 478 {
abe00makoto 0:9fb6c423e32c 479 case ENDPOINT_CONTROL:
abe00makoto 0:9fb6c423e32c 480 LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED); // May change state NotQueued->Idle
abe00makoto 0:9fb6c423e32c 481 endpoint->CurrentState = state; // Get in before an int
abe00makoto 0:9fb6c423e32c 482 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled;
abe00makoto 0:9fb6c423e32c 483 LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable;
abe00makoto 0:9fb6c423e32c 484 break;
abe00makoto 0:9fb6c423e32c 485
abe00makoto 0:9fb6c423e32c 486 case ENDPOINT_BULK:
abe00makoto 0:9fb6c423e32c 487 LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED);
abe00makoto 0:9fb6c423e32c 488 endpoint->CurrentState = state;
abe00makoto 0:9fb6c423e32c 489 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled;
abe00makoto 0:9fb6c423e32c 490 LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable;
abe00makoto 0:9fb6c423e32c 491 break;
abe00makoto 0:9fb6c423e32c 492
abe00makoto 0:9fb6c423e32c 493 case ENDPOINT_INTERRUPT:
abe00makoto 0:9fb6c423e32c 494 CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]);
abe00makoto 0:9fb6c423e32c 495 endpoint->CurrentState = state;
abe00makoto 0:9fb6c423e32c 496 LPC_USB->HcControl |= PeriodicListEnable;
abe00makoto 0:9fb6c423e32c 497 break;
abe00makoto 0:9fb6c423e32c 498 }
abe00makoto 0:9fb6c423e32c 499 return 0;
abe00makoto 0:9fb6c423e32c 500 }
abe00makoto 0:9fb6c423e32c 501
abe00makoto 0:9fb6c423e32c 502 // Remove an endpoint from an active queue
abe00makoto 0:9fb6c423e32c 503 bool Remove(HCED* ed, volatile HCED** queue)
abe00makoto 0:9fb6c423e32c 504 {
abe00makoto 0:9fb6c423e32c 505 if (*queue == 0)
abe00makoto 0:9fb6c423e32c 506 return false;
abe00makoto 0:9fb6c423e32c 507 if (*queue == (volatile HCED*)ed)
abe00makoto 0:9fb6c423e32c 508 {
abe00makoto 0:9fb6c423e32c 509 *queue = (volatile HCED*)ed->Next; // At head of queue
abe00makoto 0:9fb6c423e32c 510 return true;
abe00makoto 0:9fb6c423e32c 511 }
abe00makoto 0:9fb6c423e32c 512
abe00makoto 0:9fb6c423e32c 513 volatile HCED* head = *queue;
abe00makoto 0:9fb6c423e32c 514 while (head)
abe00makoto 0:9fb6c423e32c 515 {
abe00makoto 0:9fb6c423e32c 516 if (head->Next == (u32)ed)
abe00makoto 0:9fb6c423e32c 517 {
abe00makoto 0:9fb6c423e32c 518 head->Next = ed->Next;
abe00makoto 0:9fb6c423e32c 519 return true;
abe00makoto 0:9fb6c423e32c 520 }
abe00makoto 0:9fb6c423e32c 521 head = (volatile HCED*)head->Next;
abe00makoto 0:9fb6c423e32c 522 }
abe00makoto 0:9fb6c423e32c 523 return false;
abe00makoto 0:9fb6c423e32c 524 }
abe00makoto 0:9fb6c423e32c 525
abe00makoto 0:9fb6c423e32c 526 void Release(Endpoint* endpoint)
abe00makoto 0:9fb6c423e32c 527 {
abe00makoto 0:9fb6c423e32c 528 if (endpoint->CurrentState == Endpoint::NotQueued)
abe00makoto 0:9fb6c423e32c 529 {
abe00makoto 0:9fb6c423e32c 530 // Never event used it, nothing to do
abe00makoto 0:9fb6c423e32c 531 }
abe00makoto 0:9fb6c423e32c 532 else
abe00makoto 0:9fb6c423e32c 533 {
abe00makoto 0:9fb6c423e32c 534 HCED* ed = (HCED*)endpoint;
abe00makoto 0:9fb6c423e32c 535 ed->Control |= 0x4000; // SKIP
abe00makoto 0:9fb6c423e32c 536 switch (endpoint->Flags & 0x03)
abe00makoto 0:9fb6c423e32c 537 {
abe00makoto 0:9fb6c423e32c 538 case ENDPOINT_CONTROL:
abe00makoto 0:9fb6c423e32c 539 Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED);
abe00makoto 0:9fb6c423e32c 540 break;
abe00makoto 0:9fb6c423e32c 541 case ENDPOINT_BULK:
abe00makoto 0:9fb6c423e32c 542 Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED);
abe00makoto 0:9fb6c423e32c 543 break;
abe00makoto 0:9fb6c423e32c 544 case ENDPOINT_INTERRUPT:
abe00makoto 0:9fb6c423e32c 545 for (int i = 0; i < 32; i++)
abe00makoto 0:9fb6c423e32c 546 Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]);
abe00makoto 0:9fb6c423e32c 547 break;
abe00makoto 0:9fb6c423e32c 548 }
abe00makoto 0:9fb6c423e32c 549
abe00makoto 0:9fb6c423e32c 550 u16 fn = CommunicationArea.FrameNumber;
abe00makoto 0:9fb6c423e32c 551 while (fn == CommunicationArea.FrameNumber)
abe00makoto 0:9fb6c423e32c 552 ; // Wait for next frame
abe00makoto 0:9fb6c423e32c 553
abe00makoto 0:9fb6c423e32c 554 }
abe00makoto 0:9fb6c423e32c 555
abe00makoto 0:9fb6c423e32c 556 // In theory, the endpoint is now dead.
abe00makoto 0:9fb6c423e32c 557 // TODO: Will Callbacks ever be pending? BUGBUG
abe00makoto 0:9fb6c423e32c 558 memset(endpoint,0,sizeof(Endpoint));
abe00makoto 0:9fb6c423e32c 559 }
abe00makoto 0:9fb6c423e32c 560
abe00makoto 0:9fb6c423e32c 561 // Pop the last TD from the list
abe00makoto 0:9fb6c423e32c 562 HCTD* Reverse(HCTD* current)
abe00makoto 0:9fb6c423e32c 563 {
abe00makoto 0:9fb6c423e32c 564 HCTD *result = NULL,*temp;
abe00makoto 0:9fb6c423e32c 565 while (current)
abe00makoto 0:9fb6c423e32c 566 {
abe00makoto 0:9fb6c423e32c 567 temp = (HCTD*)current->Next;
abe00makoto 0:9fb6c423e32c 568 current->Next = (u32)result;
abe00makoto 0:9fb6c423e32c 569 result = current;
abe00makoto 0:9fb6c423e32c 570 current = temp;
abe00makoto 0:9fb6c423e32c 571 }
abe00makoto 0:9fb6c423e32c 572 return result;
abe00makoto 0:9fb6c423e32c 573 }
abe00makoto 0:9fb6c423e32c 574
abe00makoto 0:9fb6c423e32c 575 // Called from interrupt...
abe00makoto 0:9fb6c423e32c 576 // Control endpoints use a state machine to progress through the transfers
abe00makoto 0:9fb6c423e32c 577 void ProcessDoneQueue(u32 tdList)
abe00makoto 0:9fb6c423e32c 578 {
abe00makoto 0:9fb6c423e32c 579 HCTD* list = Reverse((HCTD*)tdList);
abe00makoto 0:9fb6c423e32c 580 while (list)
abe00makoto 0:9fb6c423e32c 581 {
abe00makoto 0:9fb6c423e32c 582 Endpoint* endpoint = (Endpoint*)(list-1);
abe00makoto 0:9fb6c423e32c 583 list = (HCTD*)list->Next;
abe00makoto 0:9fb6c423e32c 584 int ep = endpoint->Address();
abe00makoto 0:9fb6c423e32c 585 bool in = endpoint->Flags & 0x80;
abe00makoto 0:9fb6c423e32c 586 int status = (endpoint->TDHead.Control >> 28) & 0xF;
abe00makoto 0:9fb6c423e32c 587
abe00makoto 0:9fb6c423e32c 588 //LOG("ProcessDoneQueue %02X %08X\r\n",ep,endpoint->TDHead.Control);
abe00makoto 0:9fb6c423e32c 589
abe00makoto 0:9fb6c423e32c 590 if (status != 0)
abe00makoto 0:9fb6c423e32c 591 {
abe00makoto 0:9fb6c423e32c 592 //LOG("ProcessDoneQueue status %02X %d\r\n",ep,status);
abe00makoto 0:9fb6c423e32c 593 endpoint->CurrentState = Endpoint::Idle;
abe00makoto 0:9fb6c423e32c 594 } else {
abe00makoto 0:9fb6c423e32c 595 switch (endpoint->CurrentState)
abe00makoto 0:9fb6c423e32c 596 {
abe00makoto 0:9fb6c423e32c 597 case Endpoint::SetupQueued:
abe00makoto 0:9fb6c423e32c 598 if (endpoint->Length == 0)
abe00makoto 0:9fb6c423e32c 599 Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Skip Data Phase
abe00makoto 0:9fb6c423e32c 600 else
abe00makoto 0:9fb6c423e32c 601 Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued); // Setup is done, now Data
abe00makoto 0:9fb6c423e32c 602 break;
abe00makoto 0:9fb6c423e32c 603
abe00makoto 0:9fb6c423e32c 604 case Endpoint::DataQueued:
abe00makoto 0:9fb6c423e32c 605 if (endpoint->TDHead.CurrBufPtr)
abe00makoto 0:9fb6c423e32c 606 endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
abe00makoto 0:9fb6c423e32c 607
abe00makoto 0:9fb6c423e32c 608 if (ep == 0)
abe00makoto 0:9fb6c423e32c 609 Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Data is done, now Status, Control only
abe00makoto 0:9fb6c423e32c 610 else
abe00makoto 0:9fb6c423e32c 611 endpoint->CurrentState = Endpoint::Idle;
abe00makoto 0:9fb6c423e32c 612 break;
abe00makoto 0:9fb6c423e32c 613
abe00makoto 0:9fb6c423e32c 614 case Endpoint::StatusQueued: // Transaction is done
abe00makoto 0:9fb6c423e32c 615 endpoint->CurrentState = Endpoint::Idle;
abe00makoto 0:9fb6c423e32c 616 break;
abe00makoto 0:9fb6c423e32c 617 }
abe00makoto 0:9fb6c423e32c 618 }
abe00makoto 0:9fb6c423e32c 619
abe00makoto 0:9fb6c423e32c 620 // Complete, flag if we need a callback
abe00makoto 0:9fb6c423e32c 621 if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
abe00makoto 0:9fb6c423e32c 622 {
abe00makoto 0:9fb6c423e32c 623 endpoint->CurrentState = Endpoint::CallbackPending;
abe00makoto 0:9fb6c423e32c 624 _callbacksPending++;
abe00makoto 0:9fb6c423e32c 625 }
abe00makoto 0:9fb6c423e32c 626 }
abe00makoto 0:9fb6c423e32c 627 }
abe00makoto 0:9fb6c423e32c 628
abe00makoto 0:9fb6c423e32c 629 // Hack to reset devices that don't want to connect
abe00makoto 0:9fb6c423e32c 630 int AddDevice(int hub, int port, bool isLowSpeed)
abe00makoto 0:9fb6c423e32c 631 {
abe00makoto 0:9fb6c423e32c 632 int device = AddDeviceCore(hub,port,isLowSpeed);
abe00makoto 0:9fb6c423e32c 633 if (device < 0)
abe00makoto 0:9fb6c423e32c 634 {
abe00makoto 0:9fb6c423e32c 635 LOG("========RETRY ADD DEVICE========\r\n"); // This will go for ever.. TODO power cycle root?
abe00makoto 0:9fb6c423e32c 636 Disconnect(hub,port); // Could not read descriptor at assigned address, reset this port and try again
abe00makoto 0:9fb6c423e32c 637 ResetPort(hub,port); // Cheap bluetooth dongles often need this on a hotplug
abe00makoto 0:9fb6c423e32c 638 return -1;
abe00makoto 0:9fb6c423e32c 639 }
abe00makoto 0:9fb6c423e32c 640 return device;
abe00makoto 0:9fb6c423e32c 641 }
abe00makoto 0:9fb6c423e32c 642
abe00makoto 0:9fb6c423e32c 643 int AddDeviceCore(int hub, int port, bool isLowSpeed)
abe00makoto 0:9fb6c423e32c 644 {
abe00makoto 0:9fb6c423e32c 645 int lowSpeed = isLowSpeed ? 0x2000 : 0;
abe00makoto 0:9fb6c423e32c 646 DeviceDescriptor desc;
abe00makoto 0:9fb6c423e32c 647 EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed; // MaxPacketSize == 8
abe00makoto 0:9fb6c423e32c 648 int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8);
abe00makoto 0:9fb6c423e32c 649 if (r < 0)
abe00makoto 0:9fb6c423e32c 650 {
abe00makoto 0:9fb6c423e32c 651 LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\r\n");
abe00makoto 0:9fb6c423e32c 652 return r;
abe00makoto 0:9fb6c423e32c 653 }
abe00makoto 0:9fb6c423e32c 654
abe00makoto 0:9fb6c423e32c 655 EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed; // Actual MaxPacketSize
abe00makoto 0:9fb6c423e32c 656 r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
abe00makoto 0:9fb6c423e32c 657 if (r < 0)
abe00makoto 0:9fb6c423e32c 658 return r;
abe00makoto 0:9fb6c423e32c 659
abe00makoto 0:9fb6c423e32c 660 LOG("\nClass %02X found %04X:%04X\r\n",desc.bDeviceClass,desc.idVendor,desc.idProduct);
abe00makoto 0:9fb6c423e32c 661
abe00makoto 0:9fb6c423e32c 662 // Now assign the device an address, move off EndpointZero
abe00makoto 0:9fb6c423e32c 663 int device = 0;
abe00makoto 0:9fb6c423e32c 664 for (int i = 0; i < MAX_DEVICES; i++)
abe00makoto 0:9fb6c423e32c 665 {
abe00makoto 0:9fb6c423e32c 666 if (Devices[i].Port == 0)
abe00makoto 0:9fb6c423e32c 667 {
abe00makoto 0:9fb6c423e32c 668 device = i+1;
abe00makoto 0:9fb6c423e32c 669 break;
abe00makoto 0:9fb6c423e32c 670 }
abe00makoto 0:9fb6c423e32c 671 }
abe00makoto 0:9fb6c423e32c 672 if (!device)
abe00makoto 0:9fb6c423e32c 673 return ERR_DEVICE_NONE_LEFT;
abe00makoto 0:9fb6c423e32c 674
abe00makoto 0:9fb6c423e32c 675 r = SetAddress(0,device);
abe00makoto 0:9fb6c423e32c 676 if (r)
abe00makoto 0:9fb6c423e32c 677 return r;
abe00makoto 0:9fb6c423e32c 678 DelayMS(2);
abe00makoto 0:9fb6c423e32c 679
abe00makoto 0:9fb6c423e32c 680 // Now at a nonzero address, create control endpoint
abe00makoto 0:9fb6c423e32c 681 Device* dev = &Devices[device-1];
abe00makoto 0:9fb6c423e32c 682 dev->Init(&desc,hub,port,device,lowSpeed);
abe00makoto 0:9fb6c423e32c 683 AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0);
abe00makoto 0:9fb6c423e32c 684 _connectPending = 0;
abe00makoto 0:9fb6c423e32c 685
abe00makoto 0:9fb6c423e32c 686 // Verify this all works
abe00makoto 0:9fb6c423e32c 687 r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
abe00makoto 0:9fb6c423e32c 688 if (r < 0)
abe00makoto 0:9fb6c423e32c 689 return r;
abe00makoto 0:9fb6c423e32c 690
abe00makoto 0:9fb6c423e32c 691 // Set to interface 0 by default
abe00makoto 0:9fb6c423e32c 692 // Calls LoadDevice if interface is found
abe00makoto 0:9fb6c423e32c 693 r = SetConfigurationAndInterface(device,1,0,&desc);
abe00makoto 0:9fb6c423e32c 694
abe00makoto 0:9fb6c423e32c 695 if (desc.bDeviceClass == CLASS_HUB)
abe00makoto 0:9fb6c423e32c 696 InitHub(device); // Handle hubs in this code
abe00makoto 0:9fb6c423e32c 697
abe00makoto 0:9fb6c423e32c 698 return device;
abe00makoto 0:9fb6c423e32c 699 }
abe00makoto 0:9fb6c423e32c 700
abe00makoto 0:9fb6c423e32c 701 // Walk descriptors and create endpoints for a given device
abe00makoto 0:9fb6c423e32c 702 // TODO configuration !=1, alternate settings etc.
abe00makoto 0:9fb6c423e32c 703 int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc)
abe00makoto 0:9fb6c423e32c 704 {
abe00makoto 0:9fb6c423e32c 705 u8 buffer[255];
abe00makoto 0:9fb6c423e32c 706 int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer));
abe00makoto 0:9fb6c423e32c 707 if (err < 0)
abe00makoto 0:9fb6c423e32c 708 return err;
abe00makoto 0:9fb6c423e32c 709
abe00makoto 0:9fb6c423e32c 710 err = SetConfiguration(device,configuration);
abe00makoto 0:9fb6c423e32c 711 if (err < 0)
abe00makoto 0:9fb6c423e32c 712 return err;
abe00makoto 0:9fb6c423e32c 713
abe00makoto 0:9fb6c423e32c 714 // Add the endpoints for this interface
abe00makoto 0:9fb6c423e32c 715 int len = buffer[2] | (buffer[3] << 8);
abe00makoto 0:9fb6c423e32c 716 u8* d = buffer;
abe00makoto 0:9fb6c423e32c 717 u8* end = d + len;
abe00makoto 0:9fb6c423e32c 718 InterfaceDescriptor* found = 0;
abe00makoto 0:9fb6c423e32c 719 while (d < end)
abe00makoto 0:9fb6c423e32c 720 {
abe00makoto 0:9fb6c423e32c 721 if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
abe00makoto 0:9fb6c423e32c 722 {
abe00makoto 0:9fb6c423e32c 723 InterfaceDescriptor* id = (InterfaceDescriptor*)d;
abe00makoto 0:9fb6c423e32c 724 if (id->bInterfaceNumber == interfaceNumber)
abe00makoto 0:9fb6c423e32c 725 {
abe00makoto 0:9fb6c423e32c 726 found = id;
abe00makoto 0:9fb6c423e32c 727 d += d[0];
abe00makoto 0:9fb6c423e32c 728 while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
abe00makoto 0:9fb6c423e32c 729 {
abe00makoto 0:9fb6c423e32c 730 switch (d[1])
abe00makoto 0:9fb6c423e32c 731 {
abe00makoto 0:9fb6c423e32c 732 case DESCRIPTOR_TYPE_ENDPOINT:
abe00makoto 0:9fb6c423e32c 733 AddEndpoint(device,(EndpointDescriptor*)d);
abe00makoto 0:9fb6c423e32c 734 break;
abe00makoto 0:9fb6c423e32c 735 default:
abe00makoto 0:9fb6c423e32c 736 LOG("Skipping descriptor %02X (%d bytes)\r\n",d[1],d[0]);
abe00makoto 0:9fb6c423e32c 737 }
abe00makoto 0:9fb6c423e32c 738 d += d[0];
abe00makoto 0:9fb6c423e32c 739 }
abe00makoto 0:9fb6c423e32c 740 }
abe00makoto 0:9fb6c423e32c 741 }
abe00makoto 0:9fb6c423e32c 742 d += d[0];
abe00makoto 0:9fb6c423e32c 743 }
abe00makoto 0:9fb6c423e32c 744
abe00makoto 0:9fb6c423e32c 745 if (!found)
abe00makoto 0:9fb6c423e32c 746 return ERR_INTERFACE_NOT_FOUND;
abe00makoto 0:9fb6c423e32c 747 OnLoadDevice(device,desc,found);
abe00makoto 0:9fb6c423e32c 748 return 0;
abe00makoto 0:9fb6c423e32c 749 }
abe00makoto 0:9fb6c423e32c 750
abe00makoto 0:9fb6c423e32c 751 void Init()
abe00makoto 0:9fb6c423e32c 752 {
abe00makoto 0:9fb6c423e32c 753 LOG("USB INIT (Controller is %d bytes)\r\n",sizeof(*this));
abe00makoto 0:9fb6c423e32c 754 memset(this,0,sizeof(HostController));
abe00makoto 0:9fb6c423e32c 755 EndpointZero.CurrentState = Endpoint::NotQueued;
abe00makoto 0:9fb6c423e32c 756 HWInit(&CommunicationArea);
abe00makoto 0:9fb6c423e32c 757 DelayMS(10);
abe00makoto 0:9fb6c423e32c 758 }
abe00makoto 0:9fb6c423e32c 759
abe00makoto 0:9fb6c423e32c 760 void ResetPort(int hub, int port)
abe00makoto 0:9fb6c423e32c 761 {
abe00makoto 0:9fb6c423e32c 762 LOG("ResetPort Hub:%d Port:%d\r\n",hub,port);
abe00makoto 0:9fb6c423e32c 763 _connectPending++; // Only reset/add 1 device at a time
abe00makoto 0:9fb6c423e32c 764 if (hub == 0)
abe00makoto 0:9fb6c423e32c 765 LPC_USB->HcRhPortStatus1 = PortResetStatus; // Reset Root Hub, port 1
abe00makoto 0:9fb6c423e32c 766 else
abe00makoto 0:9fb6c423e32c 767 SetPortReset(hub,port); // or reset other hub
abe00makoto 0:9fb6c423e32c 768 }
abe00makoto 0:9fb6c423e32c 769
abe00makoto 0:9fb6c423e32c 770 void Disconnect(int hub, int port)
abe00makoto 0:9fb6c423e32c 771 {
abe00makoto 0:9fb6c423e32c 772 LOG("Disconnect Hub:%d Port:%d\r\n",hub,port); // Mark a device for destruction
abe00makoto 0:9fb6c423e32c 773 for (int i = 0; i < MAX_DEVICES; i++)
abe00makoto 0:9fb6c423e32c 774 {
abe00makoto 0:9fb6c423e32c 775 Device* dev = Devices + i;
abe00makoto 0:9fb6c423e32c 776 if (dev->Port == port && dev->Hub == hub)
abe00makoto 0:9fb6c423e32c 777 {
abe00makoto 0:9fb6c423e32c 778 // Disconnect everything that is attached to this device if it is a hub
abe00makoto 0:9fb6c423e32c 779 for (int p = 0; p < dev->HubPortCount; p++)
abe00makoto 0:9fb6c423e32c 780 Disconnect(i+1,p+1);
abe00makoto 0:9fb6c423e32c 781
abe00makoto 0:9fb6c423e32c 782 // Now release endpoints
abe00makoto 0:9fb6c423e32c 783 for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2)
abe00makoto 0:9fb6c423e32c 784 {
abe00makoto 0:9fb6c423e32c 785 u8 endpointIndex = dev->_endpointMap[j];
abe00makoto 0:9fb6c423e32c 786 if (endpointIndex != 0xFF)
abe00makoto 0:9fb6c423e32c 787 Release(Endpoints + endpointIndex);
abe00makoto 0:9fb6c423e32c 788 }
abe00makoto 0:9fb6c423e32c 789 dev->Port = 0; // Device is now free
abe00makoto 0:9fb6c423e32c 790 dev->Flags = 0;
abe00makoto 0:9fb6c423e32c 791 return;
abe00makoto 0:9fb6c423e32c 792 }
abe00makoto 0:9fb6c423e32c 793 }
abe00makoto 0:9fb6c423e32c 794 }
abe00makoto 0:9fb6c423e32c 795
abe00makoto 0:9fb6c423e32c 796 // called after reset
abe00makoto 0:9fb6c423e32c 797 void Connect(int hub, int port, bool lowspeed)
abe00makoto 0:9fb6c423e32c 798 {
abe00makoto 0:9fb6c423e32c 799 LOG("Connect Hub:%d Port:%d %s\r\n",hub,port,lowspeed ? "slow" : "full");
abe00makoto 0:9fb6c423e32c 800 AddDevice(hub,port,lowspeed);
abe00makoto 0:9fb6c423e32c 801 }
abe00makoto 0:9fb6c423e32c 802
abe00makoto 0:9fb6c423e32c 803 // Called from interrupt
abe00makoto 0:9fb6c423e32c 804 void HubStatusChange(int hub, int port, u32 status)
abe00makoto 0:9fb6c423e32c 805 {
abe00makoto 0:9fb6c423e32c 806 LOG("HubStatusChange Hub:%d Port:%d %08X\r\n",hub,port,status);
abe00makoto 0:9fb6c423e32c 807 if (status & ConnectStatusChange)
abe00makoto 0:9fb6c423e32c 808 {
abe00makoto 0:9fb6c423e32c 809 if (status & CurrentConnectStatus) // Connecting
abe00makoto 0:9fb6c423e32c 810 ResetPort(hub,port); // Reset to initiate connect (state machine?)
abe00makoto 0:9fb6c423e32c 811 else
abe00makoto 0:9fb6c423e32c 812 Disconnect(hub,port);
abe00makoto 0:9fb6c423e32c 813 }
abe00makoto 0:9fb6c423e32c 814
abe00makoto 0:9fb6c423e32c 815 if (status & PortResetStatusChange)
abe00makoto 0:9fb6c423e32c 816 {
abe00makoto 0:9fb6c423e32c 817 if (!(status & PortResetStatus))
abe00makoto 0:9fb6c423e32c 818 {
abe00makoto 0:9fb6c423e32c 819 _connectCountdown = 200; // Schedule a connection in 200ms
abe00makoto 0:9fb6c423e32c 820 if (status & LowspeedDevice)
abe00makoto 0:9fb6c423e32c 821 port |= 0x80;
abe00makoto 0:9fb6c423e32c 822 _connectHub = hub;
abe00makoto 0:9fb6c423e32c 823 _connectPort = port;
abe00makoto 0:9fb6c423e32c 824 }
abe00makoto 0:9fb6c423e32c 825 }
abe00makoto 0:9fb6c423e32c 826 }
abe00makoto 0:9fb6c423e32c 827
abe00makoto 0:9fb6c423e32c 828 #define HOST_CLK_EN (1<<0)
abe00makoto 0:9fb6c423e32c 829 #define PORTSEL_CLK_EN (1<<3)
abe00makoto 0:9fb6c423e32c 830 #define AHB_CLK_EN (1<<4)
abe00makoto 0:9fb6c423e32c 831 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
abe00makoto 0:9fb6c423e32c 832
abe00makoto 0:9fb6c423e32c 833 #define FRAMEINTERVAL (12000-1) // 1ms
abe00makoto 0:9fb6c423e32c 834 #define DEFAULT_FMINTERVAL ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL)
abe00makoto 0:9fb6c423e32c 835
abe00makoto 0:9fb6c423e32c 836 void DelayMS(int ms)
abe00makoto 0:9fb6c423e32c 837 {
abe00makoto 0:9fb6c423e32c 838 u16 f = ms + CommunicationArea.FrameNumber;
abe00makoto 0:9fb6c423e32c 839 while (f != CommunicationArea.FrameNumber)
abe00makoto 0:9fb6c423e32c 840 ;
abe00makoto 0:9fb6c423e32c 841 }
abe00makoto 0:9fb6c423e32c 842
abe00makoto 0:9fb6c423e32c 843 static void HWInit(HCCA* cca)
abe00makoto 0:9fb6c423e32c 844 {
abe00makoto 0:9fb6c423e32c 845 NVIC_DisableIRQ(USB_IRQn);
abe00makoto 0:9fb6c423e32c 846
abe00makoto 0:9fb6c423e32c 847 // turn on power for USB
abe00makoto 0:9fb6c423e32c 848 LPC_SC->PCONP |= (1UL<<31);
abe00makoto 0:9fb6c423e32c 849 // Enable USB host clock, port selection and AHB clock
abe00makoto 0:9fb6c423e32c 850 LPC_USB->USBClkCtrl |= CLOCK_MASK;
abe00makoto 0:9fb6c423e32c 851 // Wait for clocks to become available
abe00makoto 0:9fb6c423e32c 852 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
abe00makoto 0:9fb6c423e32c 853 ;
abe00makoto 0:9fb6c423e32c 854
abe00makoto 0:9fb6c423e32c 855 // We are a Host
abe00makoto 0:9fb6c423e32c 856 LPC_USB->OTGStCtrl |= 1;
abe00makoto 0:9fb6c423e32c 857 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; // we don't need port selection clock until we do OTG
abe00makoto 0:9fb6c423e32c 858
abe00makoto 0:9fb6c423e32c 859 // configure USB pins
abe00makoto 0:9fb6c423e32c 860 LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));
abe00makoto 0:9fb6c423e32c 861 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // USB D+/D-
abe00makoto 0:9fb6c423e32c 862
abe00makoto 0:9fb6c423e32c 863 LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22)); // USB_PPWR, USB_OVRCR
abe00makoto 0:9fb6c423e32c 864 LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22));
abe00makoto 0:9fb6c423e32c 865
abe00makoto 0:9fb6c423e32c 866 LPC_PINCON->PINSEL4 &= ~(3 << 18); // USB_CONNECT
abe00makoto 0:9fb6c423e32c 867 LPC_PINCON->PINSEL4 |= (1 << 18);
abe00makoto 0:9fb6c423e32c 868
abe00makoto 0:9fb6c423e32c 869 // Reset OHCI block
abe00makoto 0:9fb6c423e32c 870 LPC_USB->HcControl = 0;
abe00makoto 0:9fb6c423e32c 871 LPC_USB->HcControlHeadED = 0;
abe00makoto 0:9fb6c423e32c 872 LPC_USB->HcBulkHeadED = 0;
abe00makoto 0:9fb6c423e32c 873
abe00makoto 0:9fb6c423e32c 874 LPC_USB->HcCommandStatus = HostControllerReset;
abe00makoto 0:9fb6c423e32c 875 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL;
abe00makoto 0:9fb6c423e32c 876 LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100;
abe00makoto 0:9fb6c423e32c 877
abe00makoto 0:9fb6c423e32c 878 LPC_USB->HcControl = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask;
abe00makoto 0:9fb6c423e32c 879 LPC_USB->HcRhStatus = SetGlobalPower;
abe00makoto 0:9fb6c423e32c 880
abe00makoto 0:9fb6c423e32c 881 LPC_USB->HcHCCA = (u32)cca;
abe00makoto 0:9fb6c423e32c 882 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
abe00makoto 0:9fb6c423e32c 883 LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow;
abe00makoto 0:9fb6c423e32c 884
abe00makoto 0:9fb6c423e32c 885 NVIC_SetPriority(USB_IRQn, 0);
abe00makoto 0:9fb6c423e32c 886 NVIC_EnableIRQ(USB_IRQn);
abe00makoto 0:9fb6c423e32c 887 while (cca->FrameNumber < 10)
abe00makoto 0:9fb6c423e32c 888 ; // 10ms delay before diving in
abe00makoto 0:9fb6c423e32c 889 }
abe00makoto 0:9fb6c423e32c 890 };
abe00makoto 0:9fb6c423e32c 891
abe00makoto 0:9fb6c423e32c 892 //====================================================================================
abe00makoto 0:9fb6c423e32c 893 //====================================================================================
abe00makoto 0:9fb6c423e32c 894 // Host controller instance and Interrupt handler
abe00makoto 0:9fb6c423e32c 895
abe00makoto 0:9fb6c423e32c 896 static HostController _controller __attribute__((at(USB_RAM_BASE)));
abe00makoto 0:9fb6c423e32c 897
abe00makoto 0:9fb6c423e32c 898 extern "C" void USB_IRQHandler(void) __irq;
abe00makoto 0:9fb6c423e32c 899 void USB_IRQHandler (void) __irq
abe00makoto 0:9fb6c423e32c 900 {
abe00makoto 0:9fb6c423e32c 901 u32 int_status = LPC_USB->HcInterruptStatus;
abe00makoto 0:9fb6c423e32c 902
abe00makoto 0:9fb6c423e32c 903 if(int_status & UnrecoverableError) //Error
abe00makoto 0:9fb6c423e32c 904 {
abe00makoto 0:9fb6c423e32c 905 LOG("USB_IRQHandler UnrecoverableError Please reset\r\n");
abe00makoto 0:9fb6c423e32c 906 }
abe00makoto 0:9fb6c423e32c 907
abe00makoto 0:9fb6c423e32c 908
abe00makoto 0:9fb6c423e32c 909 if (int_status & RootHubStatusChange) // Root hub status change
abe00makoto 0:9fb6c423e32c 910 _controller._rootHubStatusChange++; // Just flag the controller, will be processed in USBLoop
abe00makoto 0:9fb6c423e32c 911
abe00makoto 0:9fb6c423e32c 912 u32 head = 0;
abe00makoto 0:9fb6c423e32c 913 if (int_status & WritebackDoneHead)
abe00makoto 0:9fb6c423e32c 914 {
abe00makoto 0:9fb6c423e32c 915 head = _controller.CommunicationArea.DoneHead; // Writeback Done
abe00makoto 0:9fb6c423e32c 916 _controller.CommunicationArea.DoneHead = 0;
abe00makoto 0:9fb6c423e32c 917 }
abe00makoto 0:9fb6c423e32c 918 LPC_USB->HcInterruptStatus = int_status;
abe00makoto 0:9fb6c423e32c 919
abe00makoto 0:9fb6c423e32c 920 if (head)
abe00makoto 0:9fb6c423e32c 921 _controller.ProcessDoneQueue(head); // TODO - low bit can be set BUGBUG
abe00makoto 0:9fb6c423e32c 922 }
abe00makoto 0:9fb6c423e32c 923
abe00makoto 0:9fb6c423e32c 924 //====================================================================================
abe00makoto 0:9fb6c423e32c 925 //====================================================================================
abe00makoto 0:9fb6c423e32c 926 // API Methods
abe00makoto 0:9fb6c423e32c 927
abe00makoto 0:9fb6c423e32c 928 void USBInit()
abe00makoto 0:9fb6c423e32c 929 {
abe00makoto 0:9fb6c423e32c 930 return _controller.Init();
abe00makoto 0:9fb6c423e32c 931 }
abe00makoto 0:9fb6c423e32c 932
abe00makoto 0:9fb6c423e32c 933 void USBLoop()
abe00makoto 0:9fb6c423e32c 934 {
abe00makoto 0:9fb6c423e32c 935 return _controller.Loop();
abe00makoto 0:9fb6c423e32c 936 }
abe00makoto 0:9fb6c423e32c 937
abe00makoto 0:9fb6c423e32c 938 u8* USBGetBuffer(u32* len)
abe00makoto 0:9fb6c423e32c 939 {
abe00makoto 0:9fb6c423e32c 940 *len = USB_RAM_SIZE - sizeof(HostController);
abe00makoto 0:9fb6c423e32c 941 return _controller.SRAM;
abe00makoto 0:9fb6c423e32c 942 }
abe00makoto 0:9fb6c423e32c 943
abe00makoto 0:9fb6c423e32c 944 static Setup* GetSetup(int device)
abe00makoto 0:9fb6c423e32c 945 {
abe00makoto 0:9fb6c423e32c 946 if (device == 0)
abe00makoto 0:9fb6c423e32c 947 return &_controller._setupZero;
abe00makoto 0:9fb6c423e32c 948
abe00makoto 0:9fb6c423e32c 949 if (device < 1 || device > MAX_DEVICES)
abe00makoto 0:9fb6c423e32c 950 return 0;
abe00makoto 0:9fb6c423e32c 951 return &_controller.Devices[device-1].SetupBuffer;
abe00makoto 0:9fb6c423e32c 952 }
abe00makoto 0:9fb6c423e32c 953
abe00makoto 0:9fb6c423e32c 954 // Loop until IO on endpoint is complete
abe00makoto 0:9fb6c423e32c 955 static int WaitIODone(Endpoint* endpoint)
abe00makoto 0:9fb6c423e32c 956 {
abe00makoto 0:9fb6c423e32c 957 if (endpoint->CurrentState == Endpoint::NotQueued)
abe00makoto 0:9fb6c423e32c 958 return 0;
abe00makoto 0:9fb6c423e32c 959 while (endpoint->CurrentState != Endpoint::Idle)
abe00makoto 0:9fb6c423e32c 960 USBLoop(); // May generate callbacks, mount or unmount devices etc
abe00makoto 0:9fb6c423e32c 961 int status = endpoint->Status();
abe00makoto 0:9fb6c423e32c 962 if (status == 0)
abe00makoto 0:9fb6c423e32c 963 return endpoint->Length;
abe00makoto 0:9fb6c423e32c 964 return -status;
abe00makoto 0:9fb6c423e32c 965 }
abe00makoto 0:9fb6c423e32c 966
abe00makoto 0:9fb6c423e32c 967 int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
abe00makoto 0:9fb6c423e32c 968 {
abe00makoto 0:9fb6c423e32c 969 Endpoint* endpoint = _controller.GetEndpoint(device,ep);
abe00makoto 0:9fb6c423e32c 970 if (!endpoint)
abe00makoto 0:9fb6c423e32c 971 return ERR_ENDPOINT_NOT_FOUND;
abe00makoto 0:9fb6c423e32c 972
abe00makoto 0:9fb6c423e32c 973 WaitIODone(endpoint);
abe00makoto 0:9fb6c423e32c 974 endpoint->Flags = flags;
abe00makoto 0:9fb6c423e32c 975 endpoint->Data = data;
abe00makoto 0:9fb6c423e32c 976 endpoint->Length = length;
abe00makoto 0:9fb6c423e32c 977 endpoint->Callback = callback;
abe00makoto 0:9fb6c423e32c 978 endpoint->UserData = userData;
abe00makoto 0:9fb6c423e32c 979 if (ep == 0)
abe00makoto 0:9fb6c423e32c 980 _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
abe00makoto 0:9fb6c423e32c 981 else
abe00makoto 0:9fb6c423e32c 982 _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
abe00makoto 0:9fb6c423e32c 983 if (callback)
abe00makoto 0:9fb6c423e32c 984 return IO_PENDING;
abe00makoto 0:9fb6c423e32c 985 return WaitIODone(endpoint);
abe00makoto 0:9fb6c423e32c 986 }
abe00makoto 0:9fb6c423e32c 987
abe00makoto 0:9fb6c423e32c 988 int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData)
abe00makoto 0:9fb6c423e32c 989 {
abe00makoto 0:9fb6c423e32c 990 Setup* setup = GetSetup(device);
abe00makoto 0:9fb6c423e32c 991 if (!setup)
abe00makoto 0:9fb6c423e32c 992 return ERR_DEVICE_NOT_FOUND;
abe00makoto 0:9fb6c423e32c 993
abe00makoto 0:9fb6c423e32c 994 // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call
abe00makoto 0:9fb6c423e32c 995 WaitIODone(_controller.GetEndpoint(device,0));
abe00makoto 0:9fb6c423e32c 996
abe00makoto 0:9fb6c423e32c 997 setup->bm_request_type = request_type;
abe00makoto 0:9fb6c423e32c 998 setup->b_request = request;
abe00makoto 0:9fb6c423e32c 999 setup->w_value = value;
abe00makoto 0:9fb6c423e32c 1000 setup->w_index = index;
abe00makoto 0:9fb6c423e32c 1001 setup->w_length = length;
abe00makoto 0:9fb6c423e32c 1002 return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData);
abe00makoto 0:9fb6c423e32c 1003 }
abe00makoto 0:9fb6c423e32c 1004
abe00makoto 0:9fb6c423e32c 1005 int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
abe00makoto 0:9fb6c423e32c 1006 {
abe00makoto 0:9fb6c423e32c 1007 return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData);
abe00makoto 0:9fb6c423e32c 1008 }
abe00makoto 0:9fb6c423e32c 1009
abe00makoto 0:9fb6c423e32c 1010 int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
abe00makoto 0:9fb6c423e32c 1011 {
abe00makoto 0:9fb6c423e32c 1012 return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData);
abe00makoto 0:9fb6c423e32c 1013 }
abe00makoto 0:9fb6c423e32c 1014
abe00makoto 0:9fb6c423e32c 1015 int GetDescriptor(int device, int descType,int descIndex, u8* data, int length)
abe00makoto 0:9fb6c423e32c 1016 {
abe00makoto 0:9fb6c423e32c 1017 return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0);
abe00makoto 0:9fb6c423e32c 1018 }
abe00makoto 0:9fb6c423e32c 1019
abe00makoto 0:9fb6c423e32c 1020 int GetString(int device, int index, char* dst, int length)
abe00makoto 0:9fb6c423e32c 1021 {
abe00makoto 0:9fb6c423e32c 1022 u8 buffer[255];
abe00makoto 0:9fb6c423e32c 1023 int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer));
abe00makoto 0:9fb6c423e32c 1024 if (le < 0)
abe00makoto 0:9fb6c423e32c 1025 return le;
abe00makoto 0:9fb6c423e32c 1026 if (length < 1)
abe00makoto 0:9fb6c423e32c 1027 return -1;
abe00makoto 0:9fb6c423e32c 1028 length <<= 1;
abe00makoto 0:9fb6c423e32c 1029 if (le > length)
abe00makoto 0:9fb6c423e32c 1030 le = length;
abe00makoto 0:9fb6c423e32c 1031 for (int j = 2; j < le; j += 2)
abe00makoto 0:9fb6c423e32c 1032 *dst++ = buffer[j];
abe00makoto 0:9fb6c423e32c 1033 *dst = 0;
abe00makoto 0:9fb6c423e32c 1034 return (le>>1)-1;
abe00makoto 0:9fb6c423e32c 1035 }
abe00makoto 0:9fb6c423e32c 1036
abe00makoto 0:9fb6c423e32c 1037 int SetAddress(int device, int new_addr)
abe00makoto 0:9fb6c423e32c 1038 {
abe00makoto 0:9fb6c423e32c 1039 return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0);
abe00makoto 0:9fb6c423e32c 1040 }
abe00makoto 0:9fb6c423e32c 1041
abe00makoto 0:9fb6c423e32c 1042 int SetConfiguration(int device, int configNum)
abe00makoto 0:9fb6c423e32c 1043 {
abe00makoto 0:9fb6c423e32c 1044 return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0);
abe00makoto 0:9fb6c423e32c 1045 }
abe00makoto 0:9fb6c423e32c 1046
abe00makoto 0:9fb6c423e32c 1047 int SetInterface(int device, int ifNum, int altNum)
abe00makoto 0:9fb6c423e32c 1048 {
abe00makoto 0:9fb6c423e32c 1049 return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0);
abe00makoto 0:9fb6c423e32c 1050 }
abe00makoto 0:9fb6c423e32c 1051
abe00makoto 0:9fb6c423e32c 1052 // HUB stuff
abe00makoto 0:9fb6c423e32c 1053 int SetPortFeature(int device, int feature, int index)
abe00makoto 0:9fb6c423e32c 1054 {
abe00makoto 0:9fb6c423e32c 1055 return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0);
abe00makoto 0:9fb6c423e32c 1056 }
abe00makoto 0:9fb6c423e32c 1057
abe00makoto 0:9fb6c423e32c 1058 int ClearPortFeature(int device, int feature, int index)
abe00makoto 0:9fb6c423e32c 1059 {
abe00makoto 0:9fb6c423e32c 1060 return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0);
abe00makoto 0:9fb6c423e32c 1061 }
abe00makoto 0:9fb6c423e32c 1062
abe00makoto 0:9fb6c423e32c 1063 int SetPortPower(int device, int port)
abe00makoto 0:9fb6c423e32c 1064 {
abe00makoto 0:9fb6c423e32c 1065 int r = SetPortFeature(device,PORT_POWER,port);
abe00makoto 0:9fb6c423e32c 1066 _controller.DelayMS(20); // 80ms to turn on a hubs power... DESCRIPTOR? todo
abe00makoto 0:9fb6c423e32c 1067 return r;
abe00makoto 0:9fb6c423e32c 1068 }
abe00makoto 0:9fb6c423e32c 1069
abe00makoto 0:9fb6c423e32c 1070 int SetPortReset(int device, int port)
abe00makoto 0:9fb6c423e32c 1071 {
abe00makoto 0:9fb6c423e32c 1072 return SetPortFeature(device,PORT_RESET,port);
abe00makoto 0:9fb6c423e32c 1073 }
abe00makoto 0:9fb6c423e32c 1074
abe00makoto 0:9fb6c423e32c 1075 int GetPortStatus(int device, int port, u32* status)
abe00makoto 0:9fb6c423e32c 1076 {
abe00makoto 0:9fb6c423e32c 1077 return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4);
abe00makoto 0:9fb6c423e32c 1078 }