|
1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32/drivers/usbcc/chapter9.cpp |
|
15 // Platform independent layer (PIL) of the USB Device controller driver: |
|
16 // Processing of USB spec chapter 9 standard requests. |
|
17 // |
|
18 // |
|
19 |
|
20 /** |
|
21 @file chapter9.cpp |
|
22 @internalTechnology |
|
23 */ |
|
24 |
|
25 #include <drivers/usbc.h> |
|
26 |
|
27 |
|
28 //#define ENABLE_EXCESSIVE_DEBUG_OUTPUT |
|
29 |
|
30 // |
|
31 // The way functions are called after an request has been completed by the PSL: |
|
32 // |
|
33 // Ep0RequestComplete |
|
34 // | |
|
35 // ------------------------------------------------ |
|
36 // | | |
|
37 // ProcessEp0ReceiveDone ProcessEp0TransmitDone |
|
38 // | | |
|
39 // --------------------------------------- | |
|
40 // | | | |
|
41 // ProcessEp0SetupReceived ProcessEp0DataReceived ProcessDataTransferDone |
|
42 // | | |
|
43 // --------------------- --------------- |
|
44 // | | | | |
|
45 // ProcessXXX ProcessDataTransferDone ProceedXXX ProcessDataTransferDone |
|
46 // |
|
47 // XXX = Specific_Request |
|
48 // |
|
49 |
|
50 // |
|
51 // === USB Controller member function implementation - PSL API (protected) ======================== |
|
52 // |
|
53 |
|
54 /** Used to synchronize the Ep0 state machine between the PSL and PIL. |
|
55 Accepts a SETUP packet and returns the next Ep0 state. |
|
56 |
|
57 @param aSetupBuf The SETUP packet just received by the PSL. |
|
58 @return The next Ep0 state. |
|
59 |
|
60 @publishedPartner @released |
|
61 */ |
|
62 TUsbcEp0State DUsbClientController::EnquireEp0NextState(const TUint8* aSetupBuf) const |
|
63 { |
|
64 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::EnquireEp0NextState()")); |
|
65 |
|
66 // This function may be called by the PSL from within an ISR -- so we have |
|
67 // to take care what we do here (and also in all functions that get called |
|
68 // from here). |
|
69 |
|
70 if (SWAP_BYTES_16((reinterpret_cast<const TUint16*>(aSetupBuf)[3])) == 0) // iLength |
|
71 { |
|
72 __KTRACE_OPT(KUSB, Kern::Printf(" --> EEp0StateStatusIn")); |
|
73 return EEp0StateStatusIn; // No-data Control => Status_IN |
|
74 } |
|
75 else if ((aSetupBuf[0] & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev) |
|
76 { |
|
77 __KTRACE_OPT(KUSB, Kern::Printf(" --> EEp0StateDataOut")); |
|
78 return EEp0StateDataOut; // Control Write => Data_OUT |
|
79 } |
|
80 else |
|
81 { |
|
82 __KTRACE_OPT(KUSB, Kern::Printf(" --> EEp0StateDataIn")); |
|
83 return EEp0StateDataIn; // Control Read => Data_IN |
|
84 } |
|
85 } |
|
86 |
|
87 |
|
88 TInt DUsbClientController::ProcessEp0ReceiveDone(TInt aCount) |
|
89 { |
|
90 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0ReceiveDone()")); |
|
91 TInt r; |
|
92 if (iEp0DataReceiving == EFalse) |
|
93 { |
|
94 // It's obviously a Setup packet, so... |
|
95 r = ProcessEp0SetupReceived(aCount); |
|
96 } |
|
97 else |
|
98 { |
|
99 // If it isn't a Setup, it must be data... |
|
100 // (This is actually not quite true, as it could also be - in theory - a new Setup packet |
|
101 // when the host has abandoned, for whatever reason, the previous one which was still |
|
102 // in progress. However no such case is known to have occurred with this driver, or at |
|
103 // least it didn't lead to problems. |
|
104 // Some UDCs have a dedicated interrupt for Setup packets, but so far this driver hasn't |
|
105 // made use of such a feature (as it would require a PSL/PIL API change).) |
|
106 r = ProcessEp0DataReceived(aCount); |
|
107 } |
|
108 return r; |
|
109 } |
|
110 |
|
111 |
|
112 TInt DUsbClientController::ProcessEp0TransmitDone(TInt aCount, TInt aError) |
|
113 { |
|
114 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0TransmitDone()")); |
|
115 // In any case: there's now no longer a write pending |
|
116 iEp0WritePending = EFalse; |
|
117 // If it was a client who set up this transmission, we report to that client |
|
118 if (iEp0ClientDataTransmitting) |
|
119 { |
|
120 iEp0ClientDataTransmitting = EFalse; |
|
121 TUsbcRequestCallback* const p = iRequestCallbacks[KEp0_Tx]; |
|
122 if (p) |
|
123 { |
|
124 __ASSERT_DEBUG((p->iTransferDir == EControllerWrite), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
125 p->iError = aError; |
|
126 p->iTxBytes = aCount; |
|
127 ProcessDataTransferDone(*p); |
|
128 return KErrNone; |
|
129 } |
|
130 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DUsbClientController::ProcessEpTransmitDone: Stalling Ep0")); |
|
131 StallEndpoint(KEp0_In); // request not found |
|
132 return KErrNotFound; |
|
133 } |
|
134 // If _we_ sent the data, we simply do nothing here... |
|
135 return KErrNone; |
|
136 } |
|
137 |
|
138 |
|
139 #define USB_PROCESS_REQUEST(request) \ |
|
140 if (Process ## request(packet) != KErrNone) \ |
|
141 { \ |
|
142 __KTRACE_OPT(KUSB, \ |
|
143 Kern::Printf(" ProcessEp0SetupReceived: Stalling Ep0")); \ |
|
144 StallEndpoint(KEp0_In); \ |
|
145 } |
|
146 |
|
147 TInt DUsbClientController::ProcessEp0SetupReceived(TInt aCount) |
|
148 { |
|
149 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0SetupReceived()")); |
|
150 |
|
151 if (aCount > iEp0MaxPacketSize) |
|
152 { |
|
153 // Fatal error: too much data! |
|
154 aCount = iEp0MaxPacketSize; |
|
155 } |
|
156 |
|
157 // first we split the data into meaningful units: |
|
158 TUsbcSetup packet; |
|
159 Buffer2Setup(iEp0_RxBuf, packet); |
|
160 |
|
161 #if defined(_DEBUG) && defined(ENABLE_EXCESSIVE_DEBUG_OUTPUT) |
|
162 // let's see what we've got: |
|
163 __KTRACE_OPT(KUSB, Kern::Printf(" bmRequestType = 0x%02x", packet.iRequestType)); |
|
164 if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd) |
|
165 { |
|
166 switch (packet.iRequest) |
|
167 { |
|
168 case KUsbRequest_GetStatus: |
|
169 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_STATUS)", |
|
170 KUsbRequest_GetStatus)); |
|
171 break; |
|
172 case KUsbRequest_ClearFeature: |
|
173 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (CLEAR_FEATURE)", |
|
174 KUsbRequest_ClearFeature)); |
|
175 break; |
|
176 case KUsbRequest_SetFeature: |
|
177 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_FEATURE)", |
|
178 KUsbRequest_SetFeature)); |
|
179 break; |
|
180 case KUsbRequest_SetAddress: |
|
181 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_ADDRESS)", |
|
182 KUsbRequest_SetAddress)); |
|
183 break; |
|
184 case KUsbRequest_GetDescriptor: |
|
185 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_DESCRIPTOR)", |
|
186 KUsbRequest_GetDescriptor)); |
|
187 break; |
|
188 case KUsbRequest_SetDescriptor: |
|
189 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_DESCRIPTOR)", |
|
190 KUsbRequest_SetDescriptor)); |
|
191 break; |
|
192 case KUsbRequest_GetConfig: |
|
193 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_CONFIGURATION)", |
|
194 KUsbRequest_GetConfig)); |
|
195 break; |
|
196 case KUsbRequest_SetConfig: |
|
197 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_CONFIGURATION)", |
|
198 KUsbRequest_SetConfig)); |
|
199 break; |
|
200 case KUsbRequest_GetInterface: |
|
201 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (GET_INTERFACE)", |
|
202 KUsbRequest_GetInterface)); |
|
203 break; |
|
204 case KUsbRequest_SetInterface: |
|
205 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SET_INTERFACE)", |
|
206 KUsbRequest_SetInterface)); |
|
207 break; |
|
208 case KUsbRequest_SynchFrame: |
|
209 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (SYNCH_FRAME)", |
|
210 KUsbRequest_SynchFrame)); |
|
211 break; |
|
212 default: |
|
213 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: bRequest = 0x%02x (UNKNWON STANDARD REQUEST)", |
|
214 packet.iRequest)); |
|
215 break; |
|
216 } |
|
217 } |
|
218 else |
|
219 { |
|
220 __KTRACE_OPT(KUSB, Kern::Printf(" bRequest = 0x%02x (NON-STANDARD REQUEST)", |
|
221 packet.iRequest)); |
|
222 } |
|
223 __KTRACE_OPT(KUSB, Kern::Printf(" wValue = 0x%04x", packet.iValue)); |
|
224 __KTRACE_OPT(KUSB, Kern::Printf(" wIndex = 0x%04x", packet.iIndex)); |
|
225 __KTRACE_OPT(KUSB, Kern::Printf(" wLength = 0x%04x", packet.iLength)); |
|
226 #endif // defined(_DEBUG) && defined(ENABLE_EXCESSIVE_DEBUG_OUTPUT) |
|
227 |
|
228 // now the actual analysis |
|
229 if ((packet.iRequestType & KUsbRequestType_TypeMask) == KUsbRequestType_TypeStd) |
|
230 { |
|
231 iEp0ReceivedNonStdRequest = EFalse; |
|
232 switch (packet.iRequest) |
|
233 { |
|
234 case KUsbRequest_GetStatus: |
|
235 switch (packet.iRequestType & KUsbRequestType_DestMask) |
|
236 { // Recipient |
|
237 case KUsbRequestType_DestDevice: |
|
238 USB_PROCESS_REQUEST(GetDeviceStatus); |
|
239 break; |
|
240 case KUsbRequestType_DestIfc: |
|
241 USB_PROCESS_REQUEST(GetInterfaceStatus); |
|
242 break; |
|
243 case KUsbRequestType_DestEp: |
|
244 USB_PROCESS_REQUEST(GetEndpointStatus); |
|
245 break; |
|
246 default: |
|
247 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: GET STATUS - Other or Unknown recipient")); |
|
248 __KTRACE_OPT(KPANIC, Kern::Printf(" -> DUsbClientController::ProcessEp0SetupReceived: " |
|
249 "Stalling Ep0")); |
|
250 StallEndpoint(KEp0_In); |
|
251 break; |
|
252 } |
|
253 break; |
|
254 case KUsbRequest_ClearFeature: |
|
255 case KUsbRequest_SetFeature: |
|
256 switch (packet.iRequestType & KUsbRequestType_DestMask) |
|
257 { // Recipient |
|
258 case KUsbRequestType_DestDevice: |
|
259 USB_PROCESS_REQUEST(SetClearDevFeature); |
|
260 break; |
|
261 case KUsbRequestType_DestIfc: |
|
262 USB_PROCESS_REQUEST(SetClearIfcFeature); |
|
263 break; |
|
264 case KUsbRequestType_DestEp: |
|
265 USB_PROCESS_REQUEST(SetClearEpFeature); |
|
266 break; |
|
267 default: |
|
268 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: SET/CLEAR FEATURE - " |
|
269 "Other or Unknown recipient")); |
|
270 __KTRACE_OPT(KPANIC, Kern::Printf(" -> Stalling Ep0")); |
|
271 StallEndpoint(KEp0_In); |
|
272 break; |
|
273 } |
|
274 break; |
|
275 case KUsbRequest_SetAddress: |
|
276 USB_PROCESS_REQUEST(SetAddress); |
|
277 break; |
|
278 case KUsbRequest_GetDescriptor: |
|
279 USB_PROCESS_REQUEST(GetDescriptor); |
|
280 break; |
|
281 case KUsbRequest_SetDescriptor: |
|
282 USB_PROCESS_REQUEST(SetDescriptor); |
|
283 break; |
|
284 case KUsbRequest_GetConfig: |
|
285 USB_PROCESS_REQUEST(GetConfiguration); |
|
286 break; |
|
287 case KUsbRequest_SetConfig: |
|
288 USB_PROCESS_REQUEST(SetConfiguration); |
|
289 break; |
|
290 case KUsbRequest_GetInterface: |
|
291 USB_PROCESS_REQUEST(GetInterface); |
|
292 break; |
|
293 case KUsbRequest_SetInterface: |
|
294 USB_PROCESS_REQUEST(SetInterface); |
|
295 break; |
|
296 case KUsbRequest_SynchFrame: |
|
297 USB_PROCESS_REQUEST(SynchFrame); |
|
298 break; |
|
299 default: |
|
300 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown/unsupported Std Setup Request")); |
|
301 __KTRACE_OPT(KPANIC, Kern::Printf(" -> Stalling Ep0")); |
|
302 StallEndpoint(KEp0_In); |
|
303 break; |
|
304 } |
|
305 } |
|
306 else |
|
307 { |
|
308 // Type mask != KUsbRequestType_TypeStd => class- or vendor-specific request |
|
309 iEp0ReceivedNonStdRequest = ETrue; |
|
310 const DBase* client = NULL; |
|
311 switch (packet.iRequestType & KUsbRequestType_DestMask) |
|
312 { // Recipient |
|
313 case KUsbRequestType_DestDevice: |
|
314 client = iEp0DeviceControl; |
|
315 break; |
|
316 case KUsbRequestType_DestIfc: |
|
317 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured) |
|
318 { |
|
319 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
320 } |
|
321 else |
|
322 { |
|
323 const TUsbcInterfaceSet* const ifcset_ptr = |
|
324 InterfaceNumber2InterfacePointer(packet.iIndex); |
|
325 if (ifcset_ptr) |
|
326 { |
|
327 if (ifcset_ptr->CurrentInterface()->iNoEp0Requests) |
|
328 { |
|
329 __KTRACE_OPT(KUSB, Kern::Printf(" Recipient says: NoEp0RequestsPlease")); |
|
330 } |
|
331 else |
|
332 { |
|
333 client = ifcset_ptr->iClientId; |
|
334 } |
|
335 } |
|
336 else |
|
337 { |
|
338 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface 0x%02x does not exist", |
|
339 packet.iIndex)); |
|
340 } |
|
341 } |
|
342 break; |
|
343 case KUsbRequestType_DestEp: |
|
344 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured) |
|
345 { |
|
346 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
347 } |
|
348 else if (EndpointExists(packet.iIndex) == EFalse) |
|
349 { |
|
350 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint 0x%02x does not exist", |
|
351 packet.iIndex)); |
|
352 } |
|
353 else |
|
354 { |
|
355 const TInt idx = EpAddr2Idx(packet.iIndex); |
|
356 const TUsbcInterfaceSet* const ifcset_ptr = |
|
357 iRealEndpoints[idx].iLEndpoint->iInterface->iInterfaceSet; |
|
358 if (ifcset_ptr->CurrentInterface()->iNoEp0Requests) |
|
359 { |
|
360 __KTRACE_OPT(KUSB, Kern::Printf(" Recipient says: NoEp0RequestsPlease")); |
|
361 } |
|
362 else |
|
363 { |
|
364 client = ifcset_ptr->iClientId; |
|
365 } |
|
366 } |
|
367 break; |
|
368 default: |
|
369 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Other or Unknown recipient")); |
|
370 break; |
|
371 } |
|
372 if (client != NULL) |
|
373 { |
|
374 // Try to relay packet to the appropriate recipient |
|
375 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
|
376 TUsbcRequestCallback* p; |
|
377 while ((p = iter++) != NULL) |
|
378 { |
|
379 if (p->Owner() == client) |
|
380 { |
|
381 __ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
382 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
383 __KTRACE_OPT(KUSB, Kern::Printf(" Found Ep0 read request")); |
|
384 if (packet.iLength != 0) |
|
385 { |
|
386 if ((packet.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToDev) |
|
387 { |
|
388 // Data transfer & direction OUT => there'll be a DATA_OUT stage |
|
389 __KTRACE_OPT(KUSB, Kern::Printf(" Next is DATA_OUT: setting up DataOutVars")); |
|
390 SetEp0DataOutVars(packet, client); |
|
391 } |
|
392 else if ((packet.iRequestType & KUsbRequestType_DirMask) == KUsbRequestType_DirToHost) |
|
393 { |
|
394 // For possible later use (ZLP). |
|
395 iEp0_TxNonStdCount = packet.iLength; |
|
396 } |
|
397 } |
|
398 memcpy(p->iBufferStart, iEp0_RxBuf, aCount); |
|
399 p->iError = KErrNone; // if it wasn't 'KErrNone' we wouldn't be here |
|
400 *(p->iPacketSize) = aCount; |
|
401 p->iRxPackets = 1; |
|
402 *(p->iPacketIndex) = 0; |
|
403 ProcessDataTransferDone(*p); |
|
404 return KErrNone; |
|
405 } |
|
406 } |
|
407 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 read request not found: setting RxExtra vars (Setup)")); |
|
408 iEp0_RxExtraCount = aCount; |
|
409 iEp0_RxExtraData = ETrue; |
|
410 return KErrNotFound; |
|
411 } |
|
412 else // if (client == NULL) |
|
413 { |
|
414 __KTRACE_OPT(KPANIC, Kern::Printf(" Ep0 request error: Stalling Ep0")); |
|
415 StallEndpoint(KEp0_In); |
|
416 return KErrGeneral; |
|
417 } |
|
418 } |
|
419 return KErrNone; |
|
420 } |
|
421 |
|
422 #undef USB_PROCESS_REQUEST |
|
423 |
|
424 |
|
425 TInt DUsbClientController::ProcessEp0DataReceived(TInt aCount) |
|
426 { |
|
427 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessEp0DataReceived()")); |
|
428 |
|
429 __KTRACE_OPT(KUSB, Kern::Printf(" : %d bytes", aCount)); |
|
430 |
|
431 if (aCount > iEp0MaxPacketSize) |
|
432 { |
|
433 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Too much data")); |
|
434 aCount = iEp0MaxPacketSize; |
|
435 } |
|
436 iEp0DataReceived += aCount; |
|
437 if (iEp0ClientId == NULL) |
|
438 { |
|
439 // it is us (not an app), who owns this transaction |
|
440 switch (iSetup.iRequest) |
|
441 { |
|
442 #ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST |
|
443 case KUsbRequest_SetDescriptor: |
|
444 memcpy(iEp0_RxCollectionBuf + iEp0DataReceived, iEp0_RxBuf, aCount); |
|
445 ProceedSetDescriptor(); |
|
446 break; |
|
447 #endif |
|
448 default: |
|
449 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: invalid request in iSetup")); |
|
450 __KTRACE_OPT(KPANIC, Kern::Printf(" -> DUsbClientController::ProcessEp0DataReceived: Stalling Ep0")); |
|
451 StallEndpoint(KEp0_In); |
|
452 ResetEp0DataOutVars(); |
|
453 break; |
|
454 } |
|
455 } |
|
456 else |
|
457 { |
|
458 // pass the data on to a client |
|
459 TSglQueIter<TUsbcRequestCallback> iter(iEp0ReadRequestCallbacks); |
|
460 TUsbcRequestCallback* p; |
|
461 while ((p = iter++) != NULL) |
|
462 { |
|
463 if (p->Owner() == iEp0ClientId) |
|
464 { |
|
465 __ASSERT_DEBUG((p->iEndpointNum == 0), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
466 __ASSERT_DEBUG((p->iTransferDir == EControllerRead), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
467 __KTRACE_OPT(KUSB, Kern::Printf(" Found Ep0 read request")); |
|
468 memcpy(p->iBufferStart, iEp0_RxBuf, aCount); |
|
469 p->iError = KErrNone; // if it wasn't 'KErrNone' we wouldn't be here |
|
470 *(p->iPacketSize) = aCount; |
|
471 p->iRxPackets = 1; |
|
472 *(p->iPacketIndex) = 0; |
|
473 ProcessDataTransferDone(*p); |
|
474 goto found; |
|
475 } |
|
476 } |
|
477 __KTRACE_OPT(KUSB, Kern::Printf(" Ep0 read request not found: setting RxExtra vars (Data)")); |
|
478 iEp0_RxExtraCount = aCount; |
|
479 iEp0_RxExtraData = ETrue; |
|
480 iEp0DataReceived -= aCount; |
|
481 return KErrNotFound; |
|
482 } |
|
483 found: |
|
484 if (iEp0DataReceived >= iSetup.iLength) |
|
485 { |
|
486 // all data seems now to be here |
|
487 ResetEp0DataOutVars(); |
|
488 } |
|
489 return KErrNone; |
|
490 } |
|
491 |
|
492 |
|
493 // --- The USB Spec Chapter 9 Standard Endpoint Zero Device Requests --- |
|
494 |
|
495 TInt DUsbClientController::ProcessGetDeviceStatus(const TUsbcSetup& aPacket) |
|
496 { |
|
497 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDeviceStatus()")); |
|
498 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress) |
|
499 { |
|
500 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
501 return KErrGeneral; |
|
502 } |
|
503 const TUint16 status = ((DeviceSelfPowered() ? KUsbDevStat_SelfPowered : 0) | |
|
504 (iRmWakeupStatus_Enabled ? KUsbDevStat_RemoteWakeup : 0)); |
|
505 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting device status: 0x%02x", status)); |
|
506 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status); |
|
507 if (SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone) |
|
508 { |
|
509 iEp0WritePending = ETrue; |
|
510 } |
|
511 return KErrNone; |
|
512 } |
|
513 |
|
514 |
|
515 TInt DUsbClientController::ProcessGetInterfaceStatus(const TUsbcSetup& aPacket) |
|
516 { |
|
517 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterfaceStatus()")); |
|
518 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured) |
|
519 { |
|
520 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
521 return KErrGeneral; |
|
522 } |
|
523 if (InterfaceExists(aPacket.iIndex) == EFalse) |
|
524 { |
|
525 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Interface does not exist")); |
|
526 return KErrGeneral; |
|
527 } |
|
528 const TUint16 status = 0x0000; // as of USB Spec 2.0 |
|
529 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting interface status: 0x%02x", status)); |
|
530 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status); |
|
531 if (SetupEndpointZeroWrite(iEp0_TxBuf, sizeof(status)) == KErrNone) |
|
532 { |
|
533 iEp0WritePending = ETrue; |
|
534 } |
|
535 return KErrNone; |
|
536 } |
|
537 |
|
538 |
|
539 TInt DUsbClientController::ProcessGetEndpointStatus(const TUsbcSetup& aPacket) |
|
540 { |
|
541 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetEndpointStatus()")); |
|
542 if (iTrackDeviceState && |
|
543 ((iDeviceState < EUsbcDeviceStateAddress) || |
|
544 (iDeviceState == EUsbcDeviceStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0))) |
|
545 { |
|
546 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
547 return KErrGeneral; |
|
548 } |
|
549 if (EndpointExists(aPacket.iIndex) == EFalse) |
|
550 { |
|
551 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist")); |
|
552 return KErrGeneral; |
|
553 } |
|
554 const TInt ep = EpAddr2Idx(aPacket.iIndex); |
|
555 const TUint16 status = (iRealEndpoints[ep].iHalt) ? KUsbEpStat_Halt : 0; |
|
556 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting endpoint status 0x%02x for real endpoint %d", |
|
557 status, ep)); |
|
558 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = SWAP_BYTES_16(status); |
|
559 if (SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone) |
|
560 { |
|
561 iEp0WritePending = ETrue; |
|
562 } |
|
563 return KErrNone; |
|
564 } |
|
565 |
|
566 |
|
567 TInt DUsbClientController::ProcessSetClearDevFeature(const TUsbcSetup& aPacket) |
|
568 { |
|
569 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearDevFeature()")); |
|
570 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateDefault) |
|
571 { |
|
572 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
573 return KErrGeneral; |
|
574 } |
|
575 |
|
576 TUint test_sel = 0; |
|
577 |
|
578 if (aPacket.iRequest == KUsbRequest_SetFeature) |
|
579 { |
|
580 switch (aPacket.iValue) |
|
581 { |
|
582 case KUsbFeature_RemoteWakeup: |
|
583 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress) |
|
584 { |
|
585 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
586 return KErrGeneral; |
|
587 } |
|
588 iRmWakeupStatus_Enabled = ETrue; |
|
589 break; |
|
590 case KUsbFeature_TestMode: |
|
591 if (!iHighSpeed) |
|
592 { |
|
593 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported in High-Speed mode")); |
|
594 return KErrGeneral; |
|
595 } |
|
596 if (LowByte(aPacket.iIndex) != 0) |
|
597 { |
|
598 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Lower byte of wIndex must be zero")); |
|
599 return KErrGeneral; |
|
600 } |
|
601 test_sel = HighByte(aPacket.iIndex); |
|
602 if ((test_sel < KUsbTestSelector_Test_J) || (test_sel > KUsbTestSelector_Test_Force_Enable)) |
|
603 { |
|
604 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid test selector: %d", test_sel)); |
|
605 return KErrGeneral; |
|
606 } |
|
607 break; |
|
608 case KUsbFeature_B_HnpEnable: |
|
609 if (!iOtgSupport) |
|
610 { |
|
611 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device")); |
|
612 return KErrGeneral; |
|
613 } |
|
614 if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp)) |
|
615 { |
|
616 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP")); |
|
617 return KErrGeneral; |
|
618 } |
|
619 iOtgFuncMap |= KUsbOtgAttr_B_HnpEnable; |
|
620 OtgFeaturesNotify(); |
|
621 break; |
|
622 case KUsbFeature_A_HnpSupport: |
|
623 if (!iOtgSupport) |
|
624 { |
|
625 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device")); |
|
626 return KErrGeneral; |
|
627 } |
|
628 if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp)) |
|
629 { |
|
630 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP")); |
|
631 return KErrGeneral; |
|
632 } |
|
633 iOtgFuncMap |= KUsbOtgAttr_A_HnpSupport; |
|
634 OtgFeaturesNotify(); |
|
635 break; |
|
636 case KUsbFeature_A_AltHnpSupport: |
|
637 if (!iOtgSupport) |
|
638 { |
|
639 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only supported on a OTG device")); |
|
640 return KErrGeneral; |
|
641 } |
|
642 if (!(iOtgFuncMap & KUsbOtgAttr_HnpSupp)) |
|
643 { |
|
644 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Request only valid if OTG device supports HNP")); |
|
645 return KErrGeneral; |
|
646 } |
|
647 iOtgFuncMap |= KUsbOtgAttr_A_AltHnpSupport; |
|
648 OtgFeaturesNotify(); |
|
649 break; |
|
650 default: |
|
651 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested")); |
|
652 return KErrGeneral; |
|
653 } |
|
654 } |
|
655 else // KUsbRequest_ClearFeature |
|
656 { |
|
657 switch (aPacket.iValue) |
|
658 { |
|
659 case KUsbFeature_RemoteWakeup: |
|
660 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress) |
|
661 { |
|
662 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
663 return KErrGeneral; |
|
664 } |
|
665 iRmWakeupStatus_Enabled = EFalse; |
|
666 break; |
|
667 default: |
|
668 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested")); |
|
669 return KErrGeneral; |
|
670 } |
|
671 } |
|
672 |
|
673 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage |
|
674 |
|
675 // 9.4.9: "The transition to test mode of an upstream facing port must not happen until |
|
676 // after the status stage of the request." |
|
677 if (test_sel) |
|
678 { |
|
679 __KTRACE_OPT(KPANIC, Kern::Printf(" Entering HS Test Mode %d", test_sel)); |
|
680 EnterTestMode(test_sel); |
|
681 } |
|
682 |
|
683 return KErrNone; |
|
684 } |
|
685 |
|
686 |
|
687 TInt DUsbClientController::ProcessSetClearIfcFeature(const TUsbcSetup& aPacket) |
|
688 { |
|
689 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearIfcFeature()")); |
|
690 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured) |
|
691 { |
|
692 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
693 return KErrGeneral; |
|
694 } |
|
695 // No interface features defined in USB spec, thus |
|
696 return KErrGeneral; |
|
697 } |
|
698 |
|
699 |
|
700 TInt DUsbClientController::ProcessSetClearEpFeature(const TUsbcSetup& aPacket) |
|
701 { |
|
702 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetClearEpFeature()")); |
|
703 if (iTrackDeviceState && |
|
704 ((iDeviceState < EUsbcDeviceStateAddress) || |
|
705 (iDeviceState == EUsbcDeviceStateAddress && (aPacket.iIndex & KUsbEpAddress_Portmask) != 0))) |
|
706 { |
|
707 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
708 return KErrGeneral; |
|
709 } |
|
710 if (aPacket.iValue != KUsbFeature_EndpointHalt) |
|
711 { |
|
712 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Unknown feature requested")); |
|
713 return KErrGeneral; |
|
714 } |
|
715 if (EndpointExists(aPacket.iIndex) == EFalse) |
|
716 { |
|
717 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist")); |
|
718 return KErrGeneral; |
|
719 } |
|
720 const TInt ep = EpAddr2Idx(aPacket.iIndex); |
|
721 if (iRealEndpoints[ep].iLEndpoint->iInfo.iType == KUsbEpTypeControl || |
|
722 iRealEndpoints[ep].iLEndpoint->iInfo.iType == KUsbEpTypeIsochronous) |
|
723 { |
|
724 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint is Control or Isochronous")); |
|
725 return KErrGeneral; |
|
726 } |
|
727 SetClearHaltFeature(ep, aPacket.iRequest); |
|
728 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage |
|
729 return KErrNone; |
|
730 } |
|
731 |
|
732 |
|
733 TInt DUsbClientController::ProcessSetAddress(const TUsbcSetup& aPacket) |
|
734 { |
|
735 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetAddress()")); |
|
736 if (iTrackDeviceState && iDeviceState > EUsbcDeviceStateAddress) |
|
737 { |
|
738 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
739 return KErrGeneral; |
|
740 } |
|
741 const TUint16 addr = aPacket.iValue; |
|
742 if (addr > 127) |
|
743 { |
|
744 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad address value: %d (>127)", addr)); |
|
745 return KErrGeneral; |
|
746 } |
|
747 if (addr == 0) |
|
748 { |
|
749 // Enter Default state (from Default or Address) |
|
750 NextDeviceState(EUsbcDeviceStateDefault); |
|
751 } |
|
752 __KTRACE_OPT(KUSB, Kern::Printf(" USB address: %d", addr)); |
|
753 // The spec says, under section 9.4.6: |
|
754 // "Stages after the initial Setup packet assume the same device address as the Setup packet. The USB |
|
755 // device does not change its device address until after the Status stage of this request is completed |
|
756 // successfully. Note that this is a difference between this request and all other requests. For all other |
|
757 // requests, the operation indicated must be completed before the Status stage." |
|
758 // Therefore, here we first send the status packet and only then actually execute the request. |
|
759 SendEp0ZeroByteStatusPacket(); |
|
760 SetDeviceAddress(addr); |
|
761 return KErrNone; |
|
762 } |
|
763 |
|
764 |
|
765 TInt DUsbClientController::ProcessGetDescriptor(const TUsbcSetup& aPacket) |
|
766 { |
|
767 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetDescriptor()")); |
|
768 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateDefault) |
|
769 { |
|
770 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
771 return KErrGeneral; |
|
772 } |
|
773 |
|
774 // Make sure we assume the correct speed |
|
775 __ASSERT_DEBUG((iHighSpeed == CurrentlyUsingHighSpeed()), Kern::Fault(KUsbPILPanicCat, __LINE__)); |
|
776 |
|
777 TInt size = 0; |
|
778 const TInt result = iDescriptors.FindDescriptor(HighByte(aPacket.iValue), // Type |
|
779 LowByte(aPacket.iValue), // Index |
|
780 aPacket.iIndex, // Language ID |
|
781 size); |
|
782 |
|
783 if ((result != KErrNone) || (size == 0)) |
|
784 { |
|
785 // This doesn't have to be an error - protocol-wise it's OK. |
|
786 __KTRACE_OPT(KUSB, Kern::Printf(" Couldn't retrieve descriptor")); |
|
787 return KErrGeneral; |
|
788 } |
|
789 |
|
790 __KTRACE_OPT(KUSB, Kern::Printf(" Descriptor found, size: %d (requested: %d)", |
|
791 size, aPacket.iLength)); |
|
792 if (size > KUsbcBufSz_Ep0Tx) |
|
793 { |
|
794 // This should actually not be possible (i.e. we should never get here). |
|
795 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ep0_Tx buffer too small")); |
|
796 } |
|
797 if (size > aPacket.iLength) |
|
798 { |
|
799 // Send only as much data as requested by the host |
|
800 size = aPacket.iLength; |
|
801 } |
|
802 |
|
803 #ifdef ENABLE_EXCESSIVE_DEBUG_OUTPUT |
|
804 __KTRACE_OPT(KUSB, |
|
805 Kern::Printf(" Data: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ...", |
|
806 iEp0_TxBuf[0], iEp0_TxBuf[1], iEp0_TxBuf[2], iEp0_TxBuf[3], |
|
807 iEp0_TxBuf[4], iEp0_TxBuf[5], iEp0_TxBuf[6], iEp0_TxBuf[7])); |
|
808 #endif |
|
809 // If we're about to send less bytes than expected by the host AND our number is a |
|
810 // multiple of the packet size, in order to indicate the end of the control transfer, |
|
811 // we must finally send a zero length data packet (ZLP): |
|
812 const TBool zlp = ((size < aPacket.iLength) && (size % iEp0MaxPacketSize == 0)); |
|
813 if (SetupEndpointZeroWrite(iEp0_TxBuf, size, zlp) == KErrNone) |
|
814 { |
|
815 iEp0WritePending = ETrue; |
|
816 } |
|
817 |
|
818 return KErrNone; |
|
819 } |
|
820 |
|
821 |
|
822 TInt DUsbClientController::ProcessSetDescriptor(const TUsbcSetup& aPacket) |
|
823 { |
|
824 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetDescriptor()")); |
|
825 #ifndef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST |
|
826 return KErrGeneral; |
|
827 #else |
|
828 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress) |
|
829 { |
|
830 // Error: Invalid device state! |
|
831 return KErrGeneral; |
|
832 } |
|
833 if (aPacket.iLength > KUsbcBufSz_Ep0Rx) |
|
834 { |
|
835 // Error: Our Rx buffer is too small! (Raise a defect to make it larger) |
|
836 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Ep0_Rx buffer too small")); |
|
837 return KErrGeneral; |
|
838 } |
|
839 SetEp0DataOutVars(aPacket); |
|
840 SetupEndpointZeroRead(); |
|
841 return KErrNone; |
|
842 #endif |
|
843 } |
|
844 |
|
845 |
|
846 TInt DUsbClientController::ProcessGetConfiguration(const TUsbcSetup& aPacket) |
|
847 { |
|
848 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetConfiguration()")); |
|
849 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress) |
|
850 { |
|
851 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
852 return KErrGeneral; |
|
853 } |
|
854 if (iTrackDeviceState && iDeviceState == EUsbcDeviceStateAddress && iCurrentConfig != 0) |
|
855 { |
|
856 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DeviceState Address && Config != 0")); |
|
857 return KErrGeneral; |
|
858 } |
|
859 if (iTrackDeviceState && iDeviceState == EUsbcDeviceStateConfigured && iCurrentConfig == 0) |
|
860 { |
|
861 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: DeviceState Configured && Config == 0")); |
|
862 return KErrGeneral; |
|
863 } |
|
864 if (aPacket.iLength != 1) // "unspecified behavior" |
|
865 { |
|
866 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: wLength != 1 (= %d)", aPacket.iLength)); |
|
867 } |
|
868 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting configuration value %d", iCurrentConfig)); |
|
869 if (SetupEndpointZeroWrite(&iCurrentConfig, sizeof(iCurrentConfig)) == KErrNone) |
|
870 { |
|
871 iEp0WritePending = ETrue; |
|
872 } |
|
873 return KErrNone; |
|
874 } |
|
875 |
|
876 |
|
877 /** Changes the device's configuration value, including interface setup and/or |
|
878 teardown and state change notification of higher-layer clients. |
|
879 May also be called by the PSL in special cases - therefore publishedPartner. |
|
880 |
|
881 @param aPacket The received Ep0 SET_CONFIGURATION setup request packet. |
|
882 @return KErrGeneral in case of a protocol error, KErrNone otherwise. |
|
883 |
|
884 @publishedPartner @released |
|
885 */ |
|
886 TInt DUsbClientController::ProcessSetConfiguration(const TUsbcSetup& aPacket) |
|
887 { |
|
888 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetConfiguration()")); |
|
889 |
|
890 // This function may be called by the PSL from within an ISR -- so we have |
|
891 // to take care what we do here (and also in all functions that get called |
|
892 // from here). |
|
893 |
|
894 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateAddress) |
|
895 { |
|
896 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
897 return KErrGeneral; |
|
898 } |
|
899 const TUint16 value = aPacket.iValue; |
|
900 if (value > 1) // we support only one configuration |
|
901 { |
|
902 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Configuration value too large: %d", value)); |
|
903 return KErrGeneral; |
|
904 } |
|
905 |
|
906 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration value: %d", value)); |
|
907 ChangeConfiguration(value); |
|
908 |
|
909 // In 9.4.5 under GET_STATUS we read, that after SET_CONFIGURATION the HALT feature |
|
910 // for all endpoints is reset to zero. |
|
911 TInt num = 0; |
|
912 (TAny) DoForEveryEndpointInUse(&DUsbClientController::ClearHaltFeature, num); |
|
913 __KTRACE_OPT(KUSB, Kern::Printf(" Called ClearHaltFeature() for %d endpoints", num)); |
|
914 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage |
|
915 return KErrNone; |
|
916 } |
|
917 |
|
918 |
|
919 TInt DUsbClientController::ProcessGetInterface(const TUsbcSetup& aPacket) |
|
920 { |
|
921 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessGetInterface()")); |
|
922 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured) |
|
923 { |
|
924 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
925 return KErrGeneral; |
|
926 } |
|
927 if (iCurrentConfig == 0) |
|
928 { |
|
929 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device not configured")); |
|
930 return KErrGeneral; |
|
931 } |
|
932 const TInt number = aPacket.iIndex; |
|
933 if (!InterfaceExists(number)) |
|
934 { |
|
935 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad interface index: %d", number)); |
|
936 return KErrGeneral; |
|
937 } |
|
938 // Send alternate setting code of iCurrentInterface of Interface(set) <number> of the current |
|
939 // config (iCurrentConfig). |
|
940 const TUint8 setting = InterfaceNumber2InterfacePointer(number)->iCurrentInterface; |
|
941 __KTRACE_OPT(KUSB, Kern::Printf(" Reporting interface setting %d", setting)); |
|
942 if (SetupEndpointZeroWrite(&setting, 1) == KErrNone) |
|
943 { |
|
944 iEp0WritePending = ETrue; |
|
945 } |
|
946 return KErrNone; |
|
947 } |
|
948 |
|
949 |
|
950 TInt DUsbClientController::ProcessSetInterface(const TUsbcSetup& aPacket) |
|
951 { |
|
952 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSetInterface()")); |
|
953 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured) |
|
954 { |
|
955 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
956 return KErrGeneral; |
|
957 } |
|
958 if (iCurrentConfig == 0) |
|
959 { |
|
960 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Device not configured")); |
|
961 return KErrGeneral; |
|
962 } |
|
963 const TInt number = aPacket.iIndex; |
|
964 if (!InterfaceExists(number)) |
|
965 { |
|
966 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Bad interface index: %d", number)); |
|
967 return KErrGeneral; |
|
968 } |
|
969 const TInt setting = aPacket.iValue; |
|
970 TUsbcInterfaceSet* const ifcset_ptr = InterfaceNumber2InterfacePointer(number); |
|
971 RPointerArray<TUsbcInterface>& ifcs = ifcset_ptr->iInterfaces; |
|
972 if (setting >= ifcs.Count()) |
|
973 { |
|
974 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Alt Setting >= bNumAltSettings: %d", setting)); |
|
975 return KErrGeneral; |
|
976 } |
|
977 __KTRACE_OPT(KUSB, Kern::Printf(" Interface setting:: %d", setting)); |
|
978 // Set iCurrentInterface of Interface(set) <number> of the current config |
|
979 // (iCurrentConfig) to alternate setting <setting>. |
|
980 ChangeInterface(ifcs[setting]); |
|
981 // In 9.4.5 under GET_STATUS we read, that after SET_INTERFACE the HALT feature |
|
982 // for all endpoints (of the now current interface setting) is reset to zero. |
|
983 RPointerArray<TUsbcLogicalEndpoint>& eps = ifcset_ptr->CurrentInterface()->iEndpoints; |
|
984 const TInt num_eps = eps.Count(); |
|
985 for (TInt i = 0; i < num_eps; i++) |
|
986 { |
|
987 const TInt ep_num = EpAddr2Idx(eps[i]->iPEndpoint->iEndpointAddr); |
|
988 (TAny) ClearHaltFeature(ep_num); |
|
989 } |
|
990 SendEp0ZeroByteStatusPacket(); // success: zero bytes data during status stage |
|
991 return KErrNone; |
|
992 } |
|
993 |
|
994 |
|
995 TInt DUsbClientController::ProcessSynchFrame(const TUsbcSetup& aPacket) |
|
996 { |
|
997 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProcessSynchFrame()")); |
|
998 if (iTrackDeviceState && iDeviceState < EUsbcDeviceStateConfigured) |
|
999 { |
|
1000 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Invalid device state")); |
|
1001 return KErrGeneral; |
|
1002 } |
|
1003 const TInt ep = aPacket.iIndex; |
|
1004 if (EndpointExists(ep) == EFalse) |
|
1005 { |
|
1006 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint does not exist")); |
|
1007 return KErrGeneral; |
|
1008 } |
|
1009 if (iRealEndpoints[EpAddr2Idx(ep)].iLEndpoint->iInfo.iType != KUsbEpTypeIsochronous) |
|
1010 { |
|
1011 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint is not isochronous")); |
|
1012 return KErrGeneral; |
|
1013 } |
|
1014 // We always send 0: |
|
1015 *reinterpret_cast<TUint16*>(iEp0_TxBuf) = 0x00; |
|
1016 if (SetupEndpointZeroWrite(iEp0_TxBuf, 2) == KErrNone) |
|
1017 { |
|
1018 iEp0WritePending = ETrue; |
|
1019 } |
|
1020 return KErrNone; |
|
1021 } |
|
1022 |
|
1023 |
|
1024 #ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST |
|
1025 void DUsbClientController::ProceedSetDescriptor() |
|
1026 { |
|
1027 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ProceedSetDescriptor()")); |
|
1028 // iEp0DataReceived already reflects the current buffer state |
|
1029 if (iEp0DataReceived < iSetup.iLength) |
|
1030 { |
|
1031 // Not yet all data received => proceed |
|
1032 return; |
|
1033 } |
|
1034 if (iEp0DataReceived > iSetup.iLength) |
|
1035 { |
|
1036 // Error: more data received than expected |
|
1037 // but we don't care... |
|
1038 } |
|
1039 // at this point: iEp0DataReceived == iSetup.iLength |
|
1040 const TUint8 type = HighByte(iSetup.iValue); |
|
1041 if (type == KUsbDescType_String) |
|
1042 { |
|
1043 // set/add new string descriptor |
|
1044 } |
|
1045 else |
|
1046 { |
|
1047 // set/add new ordinary descriptor |
|
1048 } |
|
1049 TUint8 index = LowByte(iSetup.iValue); |
|
1050 TUint16 langid = iSetup.iIndex; |
|
1051 TUint16 length_total = iSetup.iLength; |
|
1052 } |
|
1053 #endif |
|
1054 |
|
1055 |
|
1056 // --- Secondary (Helper) Functions |
|
1057 |
|
1058 void DUsbClientController::SetClearHaltFeature(TInt aRealEndpoint, TUint8 aRequest) |
|
1059 { |
|
1060 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::SetClearHaltFeature()")); |
|
1061 if (aRequest == KUsbRequest_SetFeature) |
|
1062 { |
|
1063 if (iRealEndpoints[aRealEndpoint].iHalt) |
|
1064 { |
|
1065 // (This condition is not really an error) |
|
1066 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: HALT feature already set")); |
|
1067 return; |
|
1068 } |
|
1069 __KTRACE_OPT(KUSB, Kern::Printf(" setting HALT feature for real endpoint %d", |
|
1070 aRealEndpoint)); |
|
1071 StallEndpoint(aRealEndpoint); |
|
1072 iRealEndpoints[aRealEndpoint].iHalt = ETrue; |
|
1073 } |
|
1074 else // KUsbRequest_ClearFeature |
|
1075 { |
|
1076 if (iRealEndpoints[aRealEndpoint].iHalt == EFalse) |
|
1077 { |
|
1078 // In this case, before we return, the data toggles are reset to DATA0. |
|
1079 __KTRACE_OPT(KUSB, Kern::Printf(" Warning: HALT feature already cleared")); |
|
1080 ResetDataToggle(aRealEndpoint); |
|
1081 return; |
|
1082 } |
|
1083 __KTRACE_OPT(KUSB, Kern::Printf(" clearing HALT feature for real endpoint %d", |
|
1084 aRealEndpoint)); |
|
1085 ResetDataToggle(aRealEndpoint); |
|
1086 ClearStallEndpoint(aRealEndpoint); |
|
1087 iRealEndpoints[aRealEndpoint].iHalt = EFalse; |
|
1088 } |
|
1089 EpStatusNotify(aRealEndpoint); // only called if actually something changed |
|
1090 } |
|
1091 |
|
1092 |
|
1093 TInt DUsbClientController::ClearHaltFeature(TInt aRealEndpoint) |
|
1094 { |
|
1095 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ClearHaltFeature()")); |
|
1096 if (iRealEndpoints[aRealEndpoint].iHalt != EFalse) |
|
1097 { |
|
1098 ClearStallEndpoint(aRealEndpoint); |
|
1099 iRealEndpoints[aRealEndpoint].iHalt = EFalse; |
|
1100 } |
|
1101 return KErrNone; |
|
1102 } |
|
1103 |
|
1104 |
|
1105 void DUsbClientController::ChangeConfiguration(TUint16 aValue) |
|
1106 { |
|
1107 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeConfiguration()")); |
|
1108 // New configuration is the same as the old one: 0 |
|
1109 if (iCurrentConfig == 0 && aValue == 0) |
|
1110 { |
|
1111 // no-op |
|
1112 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration: New == Old == 0 --> exiting")); |
|
1113 return; |
|
1114 } |
|
1115 // New configuration is the same as the old one (but not 0) |
|
1116 if (iCurrentConfig == aValue) |
|
1117 { |
|
1118 // no-op |
|
1119 __KTRACE_OPT(KUSB, Kern::Printf(" Configuration: New == Old == %d --> exiting", aValue)); |
|
1120 return; |
|
1121 } |
|
1122 // Device is already configured |
|
1123 if (iCurrentConfig != 0) |
|
1124 { |
|
1125 __KTRACE_OPT(KUSB, Kern::Printf(" Device was configured: %d", iCurrentConfig)); |
|
1126 // Tear down all interface(set)s of the old configuration |
|
1127 RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets; |
|
1128 for (TInt i = 0; i < ifcsets.Count(); ++i) |
|
1129 { |
|
1130 __KTRACE_OPT(KUSB, Kern::Printf(" Tearing down InterfaceSet %d", i)); |
|
1131 InterfaceSetTeardown(ifcsets[i]); |
|
1132 } |
|
1133 iCurrentConfig = 0; |
|
1134 // Enter Address state (from Configured) |
|
1135 if (iDeviceState == EUsbcDeviceStateConfigured) |
|
1136 NextDeviceState(EUsbcDeviceStateAddress); |
|
1137 } |
|
1138 // Device gets a new configuration |
|
1139 if (aValue != 0) |
|
1140 { |
|
1141 __KTRACE_OPT(KUSB, Kern::Printf(" Device gets new configuration...")); |
|
1142 // Setup all alternate settings 0 of all interfaces |
|
1143 // (Don't separate the next two lines of code.) |
|
1144 iCurrentConfig = aValue; |
|
1145 RPointerArray<TUsbcInterfaceSet>& ifcsets = CurrentConfig()->iInterfaceSets; |
|
1146 const TInt n = ifcsets.Count(); |
|
1147 for (TInt i = 0; i < n; ++i) |
|
1148 { |
|
1149 __KTRACE_OPT(KUSB, Kern::Printf(" Setting up InterfaceSet %d", i)); |
|
1150 InterfaceSetup(ifcsets[i]->iInterfaces[0]); |
|
1151 } |
|
1152 // Enter Configured state (from Address or Configured) |
|
1153 NextDeviceState(EUsbcDeviceStateConfigured); |
|
1154 } |
|
1155 __KTRACE_OPT(KUSB, Kern::Printf(" New configuration: %d", iCurrentConfig)); |
|
1156 return; |
|
1157 } |
|
1158 |
|
1159 |
|
1160 void DUsbClientController::InterfaceSetup(TUsbcInterface* aIfc) |
|
1161 { |
|
1162 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetup()")); |
|
1163 const TInt num_eps = aIfc->iEndpoints.Count(); |
|
1164 for (TInt i = 0; i < num_eps; i++) |
|
1165 { |
|
1166 // Prepare this endpoint for I/O |
|
1167 TUsbcLogicalEndpoint* const ep = aIfc->iEndpoints[i]; |
|
1168 // (TUsbcLogicalEndpoint's FS/HS endpoint sizes and interval values got |
|
1169 // adjusted in its constructor.) |
|
1170 if (iHighSpeed) |
|
1171 { |
|
1172 __KTRACE_OPT(KUSB, Kern::Printf(" Setting Ep info size to %d (HS)", ep->iEpSize_Hs)); |
|
1173 ep->iInfo.iSize = ep->iEpSize_Hs; |
|
1174 } |
|
1175 else |
|
1176 { |
|
1177 __KTRACE_OPT(KUSB, Kern::Printf(" Setting Ep info size to %d (FS)", ep->iEpSize_Fs)); |
|
1178 ep->iInfo.iSize = ep->iEpSize_Fs; |
|
1179 } |
|
1180 const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr); |
|
1181 if (ConfigureEndpoint(idx, ep->iInfo) != KErrNone) |
|
1182 { |
|
1183 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d configuration failed", idx)); |
|
1184 continue; |
|
1185 } |
|
1186 // Should there be a problem with it then we could try resetting the ep |
|
1187 // data toggle at this point (or before the Configure) as well. |
|
1188 __KTRACE_OPT(KUSB, Kern::Printf(" Connecting real ep addr 0x%02x & logical ep #%d", |
|
1189 ep->iPEndpoint->iEndpointAddr, ep->iLEndpointNum)); |
|
1190 ep->iPEndpoint->iLEndpoint = ep; |
|
1191 } |
|
1192 aIfc->iInterfaceSet->iCurrentInterface = aIfc->iSettingCode; |
|
1193 return; |
|
1194 } |
|
1195 |
|
1196 |
|
1197 void DUsbClientController::InterfaceSetTeardown(TUsbcInterfaceSet* aIfcSet) |
|
1198 { |
|
1199 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::InterfaceSetTeardown()")); |
|
1200 if (aIfcSet->iInterfaces.Count() == 0) |
|
1201 { |
|
1202 __KTRACE_OPT(KUSB, Kern::Printf(" No interfaces exist - returning")); |
|
1203 return; |
|
1204 } |
|
1205 RPointerArray<TUsbcLogicalEndpoint>& eps = aIfcSet->CurrentInterface()->iEndpoints; |
|
1206 const TInt num_eps = eps.Count(); |
|
1207 for (TInt i = 0; i < num_eps; i++) |
|
1208 { |
|
1209 TUsbcLogicalEndpoint* const ep = eps[i]; |
|
1210 const TInt idx = EpAddr2Idx(ep->iPEndpoint->iEndpointAddr); |
|
1211 |
|
1212 CancelTransferRequests(idx); |
|
1213 |
|
1214 if (!ep->iPEndpoint->iLEndpoint) |
|
1215 { |
|
1216 __KTRACE_OPT(KUSB, Kern::Printf(" real ep %d not configured: skipping", idx)); |
|
1217 continue; |
|
1218 } |
|
1219 if (ResetDataToggle(idx) != KErrNone) |
|
1220 { |
|
1221 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d data toggle reset failed", idx)); |
|
1222 } |
|
1223 if (DeConfigureEndpoint(idx) != KErrNone) |
|
1224 { |
|
1225 __KTRACE_OPT(KPANIC, Kern::Printf(" Error: Endpoint %d de-configuration failed", idx)); |
|
1226 } |
|
1227 |
|
1228 __KTRACE_OPT(KUSB, Kern::Printf(" disconnecting real ep & logical ep")); |
|
1229 ep->iPEndpoint->iLEndpoint = NULL; |
|
1230 } |
|
1231 if (aIfcSet->CurrentInterface() != 0) |
|
1232 { |
|
1233 __KTRACE_OPT(KUSB, Kern::Printf(" Resetting alternate interface setting to 0")); |
|
1234 aIfcSet->iCurrentInterface = 0; |
|
1235 } |
|
1236 return; |
|
1237 } |
|
1238 |
|
1239 |
|
1240 void DUsbClientController::ChangeInterface(TUsbcInterface* aIfc) |
|
1241 { |
|
1242 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::ChangeInterface()")); |
|
1243 TUsbcInterfaceSet* ifcset = aIfc->iInterfaceSet; |
|
1244 const TUint8 setting = aIfc->iSettingCode; |
|
1245 if (ifcset->iCurrentInterface == setting) |
|
1246 { |
|
1247 __KTRACE_OPT(KUSB, Kern::Printf(" New Ifc == old Ifc: nothing to do")); |
|
1248 return; |
|
1249 } |
|
1250 __KTRACE_OPT(KUSB, Kern::Printf(" Setting new interface setting #%d", setting)); |
|
1251 InterfaceSetTeardown(ifcset); |
|
1252 InterfaceSetup(aIfc); |
|
1253 StatusNotify(static_cast<TUsbcDeviceState>(KUsbAlternateSetting | setting), ifcset->iClientId); |
|
1254 } |
|
1255 |
|
1256 |
|
1257 // aFunction gets called, successively, with the endpoint index of every ep in-use as its argument. |
|
1258 // (BTW: The declaration "type (class::*name)(params)" makes <name> a "pointer to element function".) |
|
1259 // |
|
1260 TInt DUsbClientController::DoForEveryEndpointInUse(TInt (DUsbClientController::*aFunction)(TInt), TInt& aCount) |
|
1261 { |
|
1262 __KTRACE_OPT(KUSB, Kern::Printf("DUsbClientController::DoForEveryEndpointInUse()")); |
|
1263 aCount = 0; |
|
1264 TUsbcConfiguration* const config = CurrentConfig(); |
|
1265 if (!config) |
|
1266 { |
|
1267 __KTRACE_OPT(KUSB, Kern::Printf(" Device is not configured - returning")); |
|
1268 return KErrNone; |
|
1269 } |
|
1270 RPointerArray<TUsbcInterfaceSet>& ifcsets = config->iInterfaceSets; |
|
1271 const TInt num_ifcsets = ifcsets.Count(); |
|
1272 for (TInt i = 0; i < num_ifcsets; i++) |
|
1273 { |
|
1274 RPointerArray<TUsbcLogicalEndpoint>& eps = ifcsets[i]->CurrentInterface()->iEndpoints; |
|
1275 const TInt num_eps = eps.Count(); |
|
1276 for (TInt j = 0; j < num_eps; j++) |
|
1277 { |
|
1278 const TInt ep_num = EpAddr2Idx(eps[j]->iPEndpoint->iEndpointAddr); |
|
1279 const TInt result = (this->*aFunction)(ep_num); |
|
1280 ++aCount; |
|
1281 if (result != KErrNone) |
|
1282 { |
|
1283 return result; |
|
1284 } |
|
1285 } |
|
1286 } |
|
1287 return KErrNone; |
|
1288 } |
|
1289 |
|
1290 |
|
1291 // -eof- |