A compilation of code from different sources to provide support for a Playstation 3 controller via bluetooth on the m3pi.

Dependencies:   TextLCD mbed

Fork of mbed_TANK_PS3 by Yasuhiko YAMAMOTO

Committer:
srsmitherman
Date:
Sun Dec 30 05:16:28 2012 +0000
Revision:
1:ae49669c5e92
Parent:
0:44619612f575
Child:
2:895f70862eb9
Bluetooth PS3 interface for m3pi. User must pair bluetooth dongle address to PS3 controller with other program. Works but needs tweaking.

Who changed what in which revision?

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