|
1 /* |
|
2 * Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <e32std.h> |
|
19 #include <d32usbc.h> |
|
20 #include "CdcControlInterfaceReader.h" |
|
21 #include "AcmPanic.h" |
|
22 #include "AcmUtils.h" |
|
23 #include "CdcControlInterfaceRequestHandler.h" |
|
24 #include "AcmConstants.h" |
|
25 #include <usb/usblogger.h> |
|
26 |
|
27 #ifdef __FLOG_ACTIVE |
|
28 _LIT8(KLogComponent, "ECACM"); |
|
29 #endif |
|
30 |
|
31 CCdcControlInterfaceReader::CCdcControlInterfaceReader( |
|
32 MCdcCommsClassRequestHandler& aParent, |
|
33 RDevUsbcClient& aLdd) |
|
34 : CActive(KEcacmAOPriority), |
|
35 iParent(aParent), |
|
36 iLdd(aLdd) |
|
37 /** |
|
38 * Constructor. |
|
39 * |
|
40 * @param aParent Observer (ACM port) |
|
41 * @param aLdd The USB LDD handle to be used. |
|
42 */ |
|
43 { |
|
44 CActiveScheduler::Add(this); |
|
45 ReadMessageHeader(); |
|
46 } |
|
47 |
|
48 CCdcControlInterfaceReader::~CCdcControlInterfaceReader() |
|
49 /** |
|
50 * Destructor |
|
51 */ |
|
52 { |
|
53 LOG_FUNC |
|
54 |
|
55 Cancel(); //Call CActive::Cancel() |
|
56 } |
|
57 |
|
58 CCdcControlInterfaceReader* CCdcControlInterfaceReader::NewL( |
|
59 MCdcCommsClassRequestHandler& aParent, |
|
60 RDevUsbcClient& aLdd) |
|
61 /** |
|
62 * Create a new CCdcControlInterfaceReader object and start reading |
|
63 * |
|
64 * @param aParent Observer (ACM port) |
|
65 * @param aLdd The USB LDD handle to be used. |
|
66 */ |
|
67 { |
|
68 LOG_STATIC_FUNC_ENTRY |
|
69 |
|
70 CCdcControlInterfaceReader* self = new(ELeave) CCdcControlInterfaceReader( |
|
71 aParent, |
|
72 aLdd); |
|
73 return self; |
|
74 } |
|
75 |
|
76 void CCdcControlInterfaceReader::RunL() |
|
77 /** |
|
78 * This function will be called when a read completes. |
|
79 */ |
|
80 { |
|
81 LOGTEXT2(_L8(">>CCdcControlInterfaceReader::RunL iStatus=%d"), iStatus.Int()); |
|
82 HandleReadCompletion(iStatus.Int()); |
|
83 LOGTEXT(_L8("<<CCdcControlInterfaceReader::RunL")); |
|
84 } |
|
85 |
|
86 void CCdcControlInterfaceReader::DoCancel() |
|
87 /** |
|
88 * Cancel an outstanding read. |
|
89 */ |
|
90 { |
|
91 LOG_FUNC |
|
92 iLdd.ReadCancel(EEndpoint0); |
|
93 } |
|
94 |
|
95 void CCdcControlInterfaceReader::HandleReadCompletion(TInt aError) |
|
96 /** |
|
97 * This will be called when a new packet has been received. |
|
98 * Since "Header" packets may have an associated "Data" packet, which is sent |
|
99 * immediately following the header, this class implements a state machine. |
|
100 * Therefore, it will wait until both "Header" and, if necessary, "Data" |
|
101 * packets have been received before decoding. |
|
102 * |
|
103 * @param aError Error |
|
104 */ |
|
105 { |
|
106 LOGTEXT2(_L8(">>CCdcControlInterfaceReader::HandleReadCompletion " |
|
107 "aError=%d"), aError); |
|
108 |
|
109 if ( aError ) |
|
110 { |
|
111 ReadMessageHeader(); |
|
112 LOGTEXT(_L8("<<CCdcControlInterfaceReader::HandleReadCompletion")); |
|
113 return; |
|
114 } |
|
115 |
|
116 LOGTEXT2(_L8("\tcompleted with iState=%d"),iState); |
|
117 switch ( iState) |
|
118 { |
|
119 case EWaitingForHeader: |
|
120 { |
|
121 DecodeMessageHeader(); |
|
122 } |
|
123 break; |
|
124 |
|
125 case EWaitingForData: |
|
126 { |
|
127 DecodeMessageData(); |
|
128 } |
|
129 break; |
|
130 |
|
131 default: |
|
132 { |
|
133 _USB_PANIC(KAcmPanicCat, EPanicIllegalState); |
|
134 } |
|
135 break; |
|
136 } |
|
137 |
|
138 LOGTEXT(_L8("<<CCdcControlInterfaceReader::HandleReadCompletion")); |
|
139 } |
|
140 |
|
141 void CCdcControlInterfaceReader::DecodeMessageHeader() |
|
142 /** |
|
143 * This function decodes a message header. It determines whether the host |
|
144 * requires some data in response and dispatches the request appropriately. |
|
145 */ |
|
146 { |
|
147 LOG_FUNC |
|
148 |
|
149 if ( TUsbRequestHdr::Decode(iMessageHeader, iRequestHeader) != KErrNone ) |
|
150 { |
|
151 LOGTEXT(_L8("\t- Unable to decode request header!")); |
|
152 // Stall bus- unknown message. If this fails, there's nothing we can |
|
153 // do. |
|
154 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
155 ReadMessageHeader(); |
|
156 return; |
|
157 } |
|
158 |
|
159 LOGTEXT2(_L8("\t- New read! Request 0x%x"), iRequestHeader.iRequest); |
|
160 |
|
161 if ( iRequestHeader.IsDataResponseRequired() ) |
|
162 { |
|
163 DecodeMessageDataWithResponseRequired(); |
|
164 } |
|
165 else if ( iRequestHeader.iLength == 0 ) |
|
166 { |
|
167 iMessageData.SetLength(0); |
|
168 DecodeMessageData(); |
|
169 } |
|
170 else |
|
171 { |
|
172 ReadMessageData(iRequestHeader.iLength); |
|
173 } |
|
174 } |
|
175 |
|
176 void CCdcControlInterfaceReader::DecodeMessageDataWithResponseRequired() |
|
177 /** |
|
178 * Decode a message which requires data to be sent to the host in response. |
|
179 */ |
|
180 { |
|
181 LOG_FUNC |
|
182 |
|
183 LOGTEXT2(_L8("\t- New read! Request 0x%x"), iRequestHeader.iRequest); |
|
184 TBuf8<KAcmControlReadBufferLength> returnBuffer; |
|
185 |
|
186 switch ( iRequestHeader.iRequest ) |
|
187 { |
|
188 case KGetEncapsulated: |
|
189 { |
|
190 if ( iParent.HandleGetEncapResponse(returnBuffer) == KErrNone ) |
|
191 { |
|
192 // Write Back data here |
|
193 // At least ack the packet or host will keep sending. If this |
|
194 // fails, the host will ask again until we do successfully reply. |
|
195 static_cast<void>(iLdd.SendEp0StatusPacket()); |
|
196 } |
|
197 else |
|
198 { |
|
199 // Stall bus- unknown message. If this fails, there's nothing we |
|
200 // can do. |
|
201 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
202 } |
|
203 } |
|
204 break; |
|
205 |
|
206 case KGetCommFeature: |
|
207 { |
|
208 if ( iParent.HandleGetCommFeature(iRequestHeader.iValue, returnBuffer) |
|
209 == KErrNone ) |
|
210 { |
|
211 TRequestStatus status; |
|
212 iLdd.Write(status, EEndpoint0, |
|
213 returnBuffer, |
|
214 returnBuffer.Length(), |
|
215 EFalse); |
|
216 User::WaitForRequest(status); |
|
217 // If this failed, the host will ask again until we do |
|
218 // successfully reply. |
|
219 } |
|
220 else |
|
221 { |
|
222 // Stall bus- unknown message. If this fails, there's nothing we |
|
223 // can do. |
|
224 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
225 } |
|
226 } |
|
227 break; |
|
228 |
|
229 case KGetLineCoding: |
|
230 { |
|
231 if ( iParent.HandleGetLineCoding(returnBuffer) == KErrNone ) |
|
232 { |
|
233 TRequestStatus status; |
|
234 iLdd.Write(status, EEndpoint0, |
|
235 returnBuffer, |
|
236 7, |
|
237 EFalse); |
|
238 User::WaitForRequest(status); |
|
239 } |
|
240 else |
|
241 { |
|
242 // Stall bus- unknown message. If this fails, there's nothing we |
|
243 // can do. |
|
244 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
245 } |
|
246 } |
|
247 break; |
|
248 |
|
249 default: |
|
250 { |
|
251 LOGTEXT2(_L8("\t- request number not recognised (%d)"), |
|
252 iRequestHeader.iRequest); |
|
253 // Stall bus- unknown message. If this fails, there's nothing we can |
|
254 // do. |
|
255 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
256 } |
|
257 break; |
|
258 } |
|
259 |
|
260 ReadMessageHeader(); |
|
261 } |
|
262 |
|
263 void CCdcControlInterfaceReader::DecodeMessageData() |
|
264 /** |
|
265 * Decode a message that does not require any data to be sent to the host in |
|
266 * response. In all the requests here, the completion of the class-specific |
|
267 * function is ack'ed by sending an endpoint zero status packet. The request |
|
268 * can be nack'ed by signalling an endpoint zero request error. |
|
269 */ |
|
270 { |
|
271 LOG_FUNC |
|
272 |
|
273 if ( iMessageData.Length() != iRequestHeader.iLength ) |
|
274 { |
|
275 LOGTEXT(_L8("\t- Data length is incorrect")); |
|
276 ReadMessageHeader(); |
|
277 return; |
|
278 } |
|
279 |
|
280 LOGTEXT2(_L8("\tNew read! Request %d"), iRequestHeader.iRequest); |
|
281 |
|
282 switch ( iRequestHeader.iRequest ) |
|
283 { |
|
284 case KSendEncapsulated: |
|
285 if(iParent.HandleSendEncapCommand(iMessageData) == KErrNone) |
|
286 { |
|
287 // If this fails, the host will send again. |
|
288 static_cast<void>(iLdd.SendEp0StatusPacket()); |
|
289 } |
|
290 else |
|
291 { |
|
292 // Stall bus- unknown message. If this fails, there's nothing we |
|
293 // can do. |
|
294 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
295 } |
|
296 break; |
|
297 case KSetCommFeature: |
|
298 if(iParent.HandleSetCommFeature(iRequestHeader.iValue,iMessageData) |
|
299 == KErrNone) |
|
300 { |
|
301 // If this fails, the host will send again. |
|
302 static_cast<void>(iLdd.SendEp0StatusPacket()); |
|
303 } |
|
304 else |
|
305 { |
|
306 // Stall bus- unknown message. If this fails, there's nothing we |
|
307 // can do. |
|
308 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
309 } |
|
310 break; |
|
311 case KClearCommFeature: |
|
312 if(iParent.HandleClearCommFeature(iRequestHeader.iValue) == KErrNone) |
|
313 { |
|
314 // If this fails, the host will send again. |
|
315 static_cast<void>(iLdd.SendEp0StatusPacket()); |
|
316 } |
|
317 else |
|
318 { |
|
319 // Stall bus- unknown message. If this fails, there's nothing we |
|
320 // can do. |
|
321 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
322 } |
|
323 break; |
|
324 case KSetLineCoding: |
|
325 if(iParent.HandleSetLineCoding(iMessageData) == KErrNone) |
|
326 { |
|
327 // If this fails, the host will send again. |
|
328 static_cast<void>(iLdd.SendEp0StatusPacket()); |
|
329 } |
|
330 else |
|
331 { |
|
332 // Stall bus- unknown message. If this fails, there's nothing we |
|
333 // can do. |
|
334 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
335 } |
|
336 break; |
|
337 case KSetControlLineState: |
|
338 if(iParent.HandleSetControlLineState( |
|
339 // See CDC spec table 69 (UART state bitmap values)... |
|
340 (iRequestHeader.iValue & 0x0002) ? ETrue : EFalse, // bTxCarrier |
|
341 (iRequestHeader.iValue & 0x0001) ? ETrue : EFalse) // bRxCarrier |
|
342 == KErrNone) |
|
343 { |
|
344 // If this fails, the host will send again. |
|
345 static_cast<void>(iLdd.SendEp0StatusPacket()); |
|
346 } |
|
347 else |
|
348 { |
|
349 // Stall bus- unknown message. If this fails, there's nothing we |
|
350 // can do. |
|
351 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
352 } |
|
353 break; |
|
354 case KSendBreak: |
|
355 // The time value sent from the host is in milliseconds. |
|
356 if(iParent.HandleSendBreak(iRequestHeader.iValue) == KErrNone) |
|
357 { |
|
358 // If this fails, the host will send again. |
|
359 static_cast<void>(iLdd.SendEp0StatusPacket()); |
|
360 } |
|
361 else |
|
362 { |
|
363 // Stall bus- unknown message. If this fails, there's nothing we |
|
364 // can do. |
|
365 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
366 } |
|
367 break; |
|
368 default: |
|
369 LOGTEXT2(_L8("\t***request number not recognised (%d)"), |
|
370 iRequestHeader.iRequest); |
|
371 // Stall bus- unknown message. If this fails, there's nothing we can |
|
372 // do. |
|
373 static_cast<void>(iLdd.EndpointZeroRequestError()); |
|
374 break; |
|
375 } |
|
376 |
|
377 ReadMessageHeader(); |
|
378 } |
|
379 |
|
380 void CCdcControlInterfaceReader::ReadMessageHeader() |
|
381 /** |
|
382 * Post a read request and set the state to indicate that we're waiting for a |
|
383 * message header. |
|
384 */ |
|
385 { |
|
386 LOG_FUNC |
|
387 |
|
388 iState = EWaitingForHeader; |
|
389 |
|
390 iLdd.ReadPacket(iStatus, EEndpoint0, iMessageHeader, KUsbRequestHdrSize); |
|
391 SetActive(); |
|
392 } |
|
393 |
|
394 void CCdcControlInterfaceReader::ReadMessageData(TUint aLength) |
|
395 /** |
|
396 * Post a read request and set the state to indicate that we're waiting for |
|
397 * some message data. |
|
398 * |
|
399 * @param aLength Length of data to read. |
|
400 */ |
|
401 { |
|
402 LOG_FUNC |
|
403 |
|
404 LOGTEXT2(_L8("\tqueuing read, length = %d"),aLength); |
|
405 |
|
406 iState = EWaitingForData; |
|
407 |
|
408 iLdd.Read(iStatus, EEndpoint0, iMessageData, static_cast<TInt>(aLength)); |
|
409 SetActive(); |
|
410 } |
|
411 |
|
412 // |
|
413 // End of file |