|
1 // Copyright (c) 2006-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 "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 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 */ |
|
20 #include <mtp/mtpprotocolconstants.h> |
|
21 #include <mtp/tmtptyperesponse.h> |
|
22 |
|
23 #include "cmtpusbepbulkin.h" |
|
24 #include "cmtpusbepbulkout.h" |
|
25 #include "cmtpusbconnection.h" |
|
26 #include "cmtpusbcontainer.h" |
|
27 #include "cmtpusbepcontrol.h" |
|
28 #include "cmtpusbepinterruptin.h" |
|
29 #include "mmtpconnectionmgr.h" |
|
30 #include "mmtpconnectionprotocol.h" |
|
31 #include "mtpbuildoptions.hrh" |
|
32 #include "mtpdebug.h" |
|
33 #include "mtpusbpanic.h" |
|
34 #include "mtpusbprotocolconstants.h" |
|
35 |
|
36 #ifdef _DEBUG |
|
37 #include <e32debug.h> |
|
38 #endif |
|
39 |
|
40 #define UNUSED_VAR(a) (a)=(a) |
|
41 |
|
42 |
|
43 // File type constants. |
|
44 const TInt KMTPNullChunkSize(0x00020000); // 100KB |
|
45 const TUint KUSBHeaderSize = 12; |
|
46 |
|
47 // Class constants. |
|
48 __FLOG_STMT(_LIT8(KComponent,"UsbConnection");) |
|
49 |
|
50 // Endpoint meta data. |
|
51 const CMTPUsbConnection::TEpInfo CMTPUsbConnection::KEndpointMetaData[EMTPUsbEpNumEndpoints] = |
|
52 { |
|
53 {KMTPUsbControlEpBit, KMTPUsbControlEpDir, KMTPUsbControlEpPoll, KMTPUsbControlEpNAKRate, KMTPUsbControlEp, KMTPUsbControlEpType}, // EMTPUsbEpControl |
|
54 {KMTPUsbBulkInEpBit, KMTPUsbBulkInEpDir, KMTPUsbBulkInEpPoll, KMTPUsbBulkInEpNAKRate, KMTPUsbBulkInEp, KMTPUsbBulkInEpType}, // EMTPUsbEpBulkIn |
|
55 {KMTPUsbBulkOutEpBit, KMTPUsbBulkOutEpDir, KMTPUsbBulkOutEpPoll, KMTPUsbBulkOutEpNAKRate, KMTPUsbBulkOutEp, KMTPUsbBulkOutEpType}, // EMTPUsbEpBulkOut |
|
56 {KMTPUsbInterruptEpBit, KMTPUsbInterruptEpDir, KMTPUsbInterruptEpPoll, KMTPUsbInterruptEpNAKRate, KMTPUsbInterruptEp, KMTPUsbInterruptEpType} // EMTPUsbEpInterrupt |
|
57 }; |
|
58 |
|
59 /** |
|
60 USB MTP USB device class connection factory method. |
|
61 @param aConnectionMgr The MTP connection manager interface. |
|
62 @return A pointer to an MTP USB device class connection. Ownership IS |
|
63 transfered. |
|
64 @leave One of the system wide error codes, if a processing failure occurs. |
|
65 */ |
|
66 CMTPUsbConnection* CMTPUsbConnection::NewL(MMTPConnectionMgr& aConnectionMgr) |
|
67 { |
|
68 CMTPUsbConnection* self = new (ELeave) CMTPUsbConnection(aConnectionMgr); |
|
69 CleanupStack::PushL(self); |
|
70 self->ConstructL(); |
|
71 CleanupStack::Pop(self); |
|
72 return self; |
|
73 } |
|
74 |
|
75 /** |
|
76 Destructor. |
|
77 */ |
|
78 CMTPUsbConnection::~CMTPUsbConnection() |
|
79 { |
|
80 __FLOG(_L8("~CMTPUsbConnection - Entry")); |
|
81 |
|
82 // Terminate all endpoint data transfer activity. |
|
83 StopConnection(); |
|
84 |
|
85 // Close the device class endpoints and generic container buffers. |
|
86 iEndpoints.ResetAndDestroy(); |
|
87 delete iUsbBulkContainer; |
|
88 delete iUsbEventContainer; |
|
89 |
|
90 // Stop the USB device. |
|
91 StopUsb(); |
|
92 |
|
93 iNullBuffer.Close(); |
|
94 if (iProtocolLayer) |
|
95 { |
|
96 iProtocolLayer->Unbind(*this); |
|
97 } |
|
98 |
|
99 __FLOG(_L8("~CMTPUsbConnection - Exit")); |
|
100 __FLOG_CLOSE; |
|
101 } |
|
102 |
|
103 void CMTPUsbConnection::BindL(MMTPConnectionProtocol& aProtocol) |
|
104 { |
|
105 __FLOG(_L8("BindL - Entry")); |
|
106 __ASSERT_DEBUG(!iProtocolLayer, Panic(EMTPUsbBadState)); |
|
107 iProtocolLayer = &aProtocol; |
|
108 __FLOG(_L8("BindL - Exit")); |
|
109 } |
|
110 |
|
111 MMTPConnectionProtocol& CMTPUsbConnection::BoundProtocolLayer() |
|
112 { |
|
113 __FLOG(_L8("BoundProtocolLayer - Entry")); |
|
114 __ASSERT_DEBUG(iProtocolLayer, Panic(EMTPUsbBadState)); |
|
115 __FLOG(_L8("BoundProtocolLayer - Exit")); |
|
116 return *iProtocolLayer; |
|
117 } |
|
118 |
|
119 void CMTPUsbConnection::CloseConnection() |
|
120 { |
|
121 __FLOG(_L8("CloseConnection - Entry")); |
|
122 /* |
|
123 Terminate all endpoint data transfer activity, stall all but the control |
|
124 endpoints, and wait for the host to issue a Device Reset Request. |
|
125 */ |
|
126 StopConnection(); |
|
127 TRAPD(err, BulkEndpointsStallL()); |
|
128 UNUSED_VAR(err); |
|
129 __FLOG(_L8("CloseConnection - Exit")); |
|
130 } |
|
131 |
|
132 void CMTPUsbConnection::ReceiveDataL(MMTPType& aData, const TMTPTypeRequest& /*aRequest*/) |
|
133 { |
|
134 __FLOG(_L8("ReceiveDataL - Entry")); |
|
135 |
|
136 // Update the transaction state. |
|
137 SetBulkTransactionState(EDataIToRPhase); |
|
138 |
|
139 // Setup the bulk container and initiate the bulk data receive sequence. |
|
140 iUsbBulkContainer->SetPayloadL(&aData); |
|
141 |
|
142 //Expected containerType pre-setup here in case we don't receive IToR dataphase at all so |
|
143 //Cancel operation can trigger right call inside ReceiveBulkDataCompleteL(). |
|
144 iUsbBulkContainer->SetUint16L(CMTPUsbContainer::EContainerType, EMTPUsbContainerTypeDataBlock); |
|
145 |
|
146 static_cast<CMTPUsbEpBulkOut*>(iEndpoints[EMTPUsbEpBulkOut])->ReceiveBulkDataL(*iUsbBulkContainer); |
|
147 |
|
148 __FLOG(_L8("ReceiveDataL - Exit")); |
|
149 } |
|
150 |
|
151 void CMTPUsbConnection::ReceiveDataCancelL(const TMTPTypeRequest& /*aRequest*/) |
|
152 { |
|
153 __FLOG(_L8("ReceiveDataCancelL - Entry")); |
|
154 |
|
155 // Store the device status code. |
|
156 TUint16 deviceStatus = iDeviceStatusCode; |
|
157 |
|
158 SetDeviceStatus(EMTPUsbDeviceStatusTransactionCancelled); |
|
159 static_cast<CMTPUsbEpBulkOut*>(iEndpoints[EMTPUsbEpBulkOut])->CancelReceiveL(KErrCancel); |
|
160 |
|
161 // Restore it. |
|
162 SetDeviceStatus(deviceStatus); |
|
163 __FLOG(_L8("ReceiveDataCancelL - Exit")); |
|
164 } |
|
165 |
|
166 void CMTPUsbConnection::SendDataL(const MMTPType& aData, const TMTPTypeRequest& aRequest) |
|
167 { |
|
168 __FLOG(_L8("SendDataL - Entry")); |
|
169 ProcessBulkDataInL(aRequest, aData); |
|
170 __FLOG(_L8("SendDataL - Exit")); |
|
171 } |
|
172 |
|
173 void CMTPUsbConnection::SendDataCancelL(const TMTPTypeRequest& /*aRequest*/) |
|
174 { |
|
175 __FLOG(_L8("SendDataCancelL - Entry")); |
|
176 // Store the device status code. |
|
177 TUint16 deviceStatus = iDeviceStatusCode; |
|
178 |
|
179 SetDeviceStatus(EMTPUsbDeviceStatusTransactionCancelled); |
|
180 static_cast<CMTPUsbEpBulkIn*>(iEndpoints[EMTPUsbEpBulkIn])->CancelSendL(KErrCancel); |
|
181 // Restore it. |
|
182 SetDeviceStatus(deviceStatus); |
|
183 __FLOG(_L8("SendDataCancelL - Exit")); |
|
184 } |
|
185 |
|
186 void CMTPUsbConnection::SendEventL(const TMTPTypeEvent& aEvent) |
|
187 { |
|
188 __FLOG(_L8("SendEventL - Entry")); |
|
189 |
|
190 // Reset the event. |
|
191 iMTPEvent.Reset(); |
|
192 MMTPType::CopyL(aEvent, iMTPEvent); |
|
193 |
|
194 switch (ConnectionState()) |
|
195 { |
|
196 case EIdle: |
|
197 case EStalled: |
|
198 // Drop the event. |
|
199 __FLOG(_L8("Dropping the event")); |
|
200 BoundProtocolLayer().SendEventCompleteL(KErrNone, aEvent); |
|
201 break; |
|
202 |
|
203 case EOpen: |
|
204 case EBusy: |
|
205 // Process the event. |
|
206 switch (SuspendState()) |
|
207 { |
|
208 case ENotSuspended: |
|
209 // Only send event if there are no pending events |
|
210 if (!iEventPending) |
|
211 { |
|
212 // Send the event data. |
|
213 __FLOG(_L8("Sending the event")); |
|
214 BufferEventDataL(aEvent); |
|
215 SendEventDataL(); |
|
216 } |
|
217 break; |
|
218 |
|
219 case ESuspended: |
|
220 /* |
|
221 If remote wakeup is enabled then signal remote wakeup and buffer |
|
222 the event. The event will be sent when bus signalling is resumed. |
|
223 Otherwise the event is dropped, and a PTP UnreportedStatus event |
|
224 issued when the host resumes the connection. |
|
225 */ |
|
226 if (iLdd.SignalRemoteWakeup() == KErrNone) |
|
227 { |
|
228 // Remote wakeup is enabled, buffer the event data. |
|
229 __FLOG(_L8("Buffer event data and signal remote wakeup")); |
|
230 BufferEventDataL(aEvent); |
|
231 } |
|
232 else |
|
233 { |
|
234 // Remote wakeup is not enabled, drop the event. |
|
235 __FLOG(_L8("Dropping the event")); |
|
236 BoundProtocolLayer().SendEventCompleteL(KErrNone, aEvent); |
|
237 } |
|
238 |
|
239 /* |
|
240 Update state to trigger the correct processing when the USB connection is resumed. |
|
241 */ |
|
242 SetSuspendState(ESuspendedEventsPending); |
|
243 break; |
|
244 |
|
245 case ESuspendedEventsPending: |
|
246 // Drop the event. |
|
247 __FLOG(_L8("Dropping the event")); |
|
248 BoundProtocolLayer().SendEventCompleteL(KErrNone, aEvent); |
|
249 break; |
|
250 |
|
251 default: |
|
252 __FLOG(_L8("Invalid suspend state")); |
|
253 Panic(EMTPUsbBadState); |
|
254 break; |
|
255 } |
|
256 break; |
|
257 |
|
258 default: |
|
259 __FLOG(_L8("Invalid connection state")); |
|
260 Panic(EMTPUsbBadState); |
|
261 break; |
|
262 } |
|
263 |
|
264 __FLOG(_L8("SendEventL - Exit")); |
|
265 } |
|
266 |
|
267 void CMTPUsbConnection::SendResponseL(const TMTPTypeResponse& aResponse, const TMTPTypeRequest& aRequest) |
|
268 { |
|
269 __FLOG(_L8("SendResponseL - Entry")); |
|
270 __FLOG_VA((_L8("DeviceState: 0x%x TransactionState: 0x%x Connection: 0x%x"), iDeviceStatusCode, iBulkTransactionState, ConnectionState())); |
|
271 |
|
272 // Update the transaction state. |
|
273 SetBulkTransactionState(EResponsePhase); |
|
274 if (SuspendState() != ESuspended && !iIsCancelReceived) |
|
275 { |
|
276 TUint16 opCode(aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode)); |
|
277 TUint16 rspCode(aResponse.Uint16(TMTPTypeResponse::EResponseCode)); |
|
278 __FLOG_VA((_L8("ResponseCode = 0x%04X, Operation Code = 0x%04X"), rspCode, opCode)); |
|
279 |
|
280 if ((opCode == EMTPOpCodeOpenSession) && (rspCode == EMTPRespCodeOK)) |
|
281 { |
|
282 // An session has been opened. Record the active SessionID. |
|
283 iMTPSessionId = aRequest.Uint32(TMTPTypeRequest::ERequestParameter1); |
|
284 __FLOG_VA((_L8("Processing OpenSession response, SessionID = %d"), iMTPSessionId)); |
|
285 } |
|
286 else if (((opCode == EMTPOpCodeCloseSession) || (opCode == EMTPOpCodeResetDevice))&& (rspCode == EMTPRespCodeOK)) |
|
287 { |
|
288 // An session has been closed. Clear the active SessionID. |
|
289 __FLOG_VA((_L8("Processing CloseSession or ResetDevice response, SessionID = %d"), iMTPSessionId)); |
|
290 iMTPSessionId = KMTPSessionNone; |
|
291 } |
|
292 |
|
293 /* |
|
294 Setup the parameter block payload dataset. Note that since this is a |
|
295 variable length dataset, it must first be reset. |
|
296 */ |
|
297 iUsbBulkParameterBlock.Reset(); |
|
298 TBool isNullParamValid = EFalse; |
|
299 TUint numberOfNullParam = 0; |
|
300 /* |
|
301 A special case: for GetNumObjects the first response parameter can be null, which means 0 objects. |
|
302 */ |
|
303 if(opCode == EMTPOpCodeGetNumObjects) |
|
304 { |
|
305 isNullParamValid = ETrue; |
|
306 numberOfNullParam = 1; |
|
307 } |
|
308 iUsbBulkParameterBlock.CopyIn(aResponse, TMTPTypeResponse::EResponseParameter1, TMTPTypeResponse::EResponseParameter5, isNullParamValid, numberOfNullParam); |
|
309 |
|
310 // Setup the bulk container. |
|
311 iUsbBulkContainer->SetPayloadL(const_cast<TMTPUsbParameterPayloadBlock*>(&iUsbBulkParameterBlock)); |
|
312 iUsbBulkContainer->SetUint32L(CMTPUsbContainer::EContainerLength, static_cast<TUint32>(iUsbBulkContainer->Size())); |
|
313 iUsbBulkContainer->SetUint16L(CMTPUsbContainer::EContainerType, EMTPUsbContainerTypeResponseBlock); |
|
314 iUsbBulkContainer->SetUint16L(CMTPUsbContainer::ECode, rspCode); |
|
315 iUsbBulkContainer->SetUint32L(CMTPUsbContainer::ETransactionID, aRequest.Uint32(TMTPTypeRequest::ERequestTransactionID)); |
|
316 |
|
317 // Initiate the bulk data send sequence. |
|
318 __FLOG_VA((_L8("Sending response 0x%04X (%d bytes)"), iUsbBulkContainer->Uint16L(CMTPUsbContainer::ECode), iUsbBulkContainer->Uint32L(CMTPUsbContainer::EContainerLength))); |
|
319 static_cast<CMTPUsbEpBulkIn*>(iEndpoints[EMTPUsbEpBulkIn])->SendBulkDataL(*iUsbBulkContainer); |
|
320 } |
|
321 else |
|
322 { |
|
323 BoundProtocolLayer().SendResponseCompleteL(KErrNone, aResponse, aRequest); |
|
324 } |
|
325 |
|
326 __FLOG(_L8("SendResponseL - Exit")); |
|
327 } |
|
328 |
|
329 void CMTPUsbConnection::TransactionCompleteL(const TMTPTypeRequest& /*aRequest*/) |
|
330 { |
|
331 __FLOG(_L8("TransactionCompleteL - Entry")); |
|
332 |
|
333 __FLOG_VA((_L8("DeviceState: 0x%x TransactionState: 0x%x"), iDeviceStatusCode, iBulkTransactionState)); |
|
334 |
|
335 if (iBulkTransactionState != ERequestPhase) |
|
336 { |
|
337 // Update the transaction state. |
|
338 SetBulkTransactionState(EIdlePhase); |
|
339 |
|
340 // Update the device status |
|
341 SetDeviceStatus(EMTPUsbDeviceStatusOK); |
|
342 |
|
343 // Clear the cancel flag. |
|
344 iIsCancelReceived = EFalse; |
|
345 |
|
346 // Initiate the next request phase bulk data receive sequence. |
|
347 InitiateBulkRequestSequenceL(); |
|
348 } |
|
349 |
|
350 __FLOG(_L8("TransactionCompleteL - Exit")); |
|
351 } |
|
352 |
|
353 void CMTPUsbConnection::Unbind(MMTPConnectionProtocol& /*aProtocol*/) |
|
354 { |
|
355 __FLOG(_L8("Unbind - Entry")); |
|
356 __ASSERT_DEBUG(iProtocolLayer, Panic(EMTPUsbBadState)); |
|
357 iProtocolLayer = NULL; |
|
358 __FLOG(_L8("Unbind - Exit")); |
|
359 } |
|
360 |
|
361 TAny* CMTPUsbConnection::GetExtendedInterface(TUid /*aInterfaceUid*/) |
|
362 { |
|
363 return NULL; |
|
364 } |
|
365 |
|
366 TUint CMTPUsbConnection::GetImplementationUid() |
|
367 { |
|
368 return KMTPUsbTransportImplementationUid; |
|
369 } |
|
370 |
|
371 void CMTPUsbConnection::ReceiveBulkDataCompleteL(TInt aError, MMTPType& /*aData*/) |
|
372 { |
|
373 __FLOG(_L8("ReceiveBulkDataCompleteL - Entry")); |
|
374 if (!BulkRequestErrorHandled(aError)) |
|
375 { |
|
376 TUint type(iUsbBulkContainer->Uint16L(CMTPUsbContainer::EContainerType)); |
|
377 __FLOG_VA((_L8("Received container type 0x%04X"), type)); |
|
378 |
|
379 // The proper behaviour at this point is to stall the end points |
|
380 // but alas Microsoft does not honor this. |
|
381 // The solution is to store the error code, consume all the data |
|
382 // sent and then forward the error code to the upper layers |
|
383 // which will then go through all the phases |
|
384 |
|
385 // Only go here if... |
|
386 if (aError != KErrNone // there is an error |
|
387 && type == EMTPUsbContainerTypeDataBlock // it is a data transfer |
|
388 && iDeviceStatusCode != EMTPUsbDeviceStatusTransactionCancelled // we haven't been cancelled by the initiator |
|
389 ) |
|
390 { |
|
391 __FLOG_VA((_L8("ReceiveBulkDataCompleteL - error: %d"), aError)); |
|
392 iXferError = aError; |
|
393 |
|
394 // Update the transaction state. |
|
395 SetBulkTransactionState(EDataIToRPhase); |
|
396 |
|
397 // Setup the bulk container and initiate the bulk data receive sequence. |
|
398 iNullBuffer.Close(); |
|
399 iNullBuffer.CreateL(KMTPNullChunkSize); |
|
400 iNullBuffer.SetLength(KMTPNullChunkSize); |
|
401 iNull.SetBuffer(iNullBuffer); |
|
402 iUsbBulkContainer->SetPayloadL(&iNull); |
|
403 static_cast<CMTPUsbEpBulkOut*>(iEndpoints[EMTPUsbEpBulkOut])->ResumeReceiveDataL(*iUsbBulkContainer); |
|
404 } |
|
405 else |
|
406 { |
|
407 if (iXferError != KErrNone) |
|
408 { |
|
409 aError = iXferError; |
|
410 iXferError = KErrNone; |
|
411 iNullBuffer.Close(); |
|
412 } |
|
413 |
|
414 switch (type) |
|
415 { |
|
416 case EMTPUsbContainerTypeCommandBlock: |
|
417 ProcessBulkCommandL(aError); |
|
418 break; |
|
419 |
|
420 case EMTPUsbContainerTypeDataBlock: |
|
421 ProcessBulkDataOutL(aError); |
|
422 break; |
|
423 |
|
424 case EMTPUsbContainerTypeResponseBlock: |
|
425 case EMTPUsbContainerTypeEventBlock: |
|
426 default: |
|
427 // Invalid container received, shutdown the bulk data pipe. |
|
428 __FLOG_VA((_L8("Invalid container type = 0x%04X"), type)); |
|
429 CloseConnection(); |
|
430 } |
|
431 // Reset the bulk container. |
|
432 /* A special case for handling MTP framework's synchronous error handling during the request phase. |
|
433 ( ie at the beginning of this function, we are in the request phase, the request is sent to the |
|
434 mtp f/w, which may send a synchronous error response, which will be populated into the usb bulk |
|
435 container and sent out by the bulk In AO. When this function is completing, the response phase |
|
436 has already been reached, and the container is in use by the bulk In AO, so the payload is not |
|
437 reset)*/ |
|
438 if((iBulkTransactionState != EResponsePhase)&&(!isCommandIgnored)) |
|
439 { |
|
440 iUsbBulkContainer->SetPayloadL(NULL); |
|
441 } |
|
442 // clear the flag |
|
443 isCommandIgnored = false; |
|
444 } |
|
445 } |
|
446 |
|
447 __FLOG(_L8("ReceiveBulkDataCompleteL - Exit")); |
|
448 } |
|
449 |
|
450 void CMTPUsbConnection::ReceiveControlRequestDataCompleteL(TInt aError, MMTPType& /*aData*/) |
|
451 { |
|
452 __FLOG(_L8("ReceiveControlRequestDataCompleteL - Entry")); |
|
453 if (!ControlRequestErrorHandled(aError)) |
|
454 { |
|
455 // Complete the control request sequence. |
|
456 static_cast<CMTPUsbEpControl*>(iEndpoints[EMTPUsbEpControl])->SendControlRequestStatus(); |
|
457 |
|
458 if (iUsbControlRequestSetup.Uint8(TMTPUsbControlRequestSetup::EbRequest) == EMTPUsbControlRequestCancel) |
|
459 { |
|
460 // Cancel data received. |
|
461 __FLOG(_L8("Cancel request data received.")); |
|
462 |
|
463 // Setup the event dataset. |
|
464 __FLOG_VA((_L8("Cancellation Code = 0x%04X"), iUsbControlRequestCancelData.Uint16(TMTPUsbControlRequestCancelData::ECancellationCode))); |
|
465 __FLOG_VA((_L8("Transaction ID = 0x%08X"), iUsbControlRequestCancelData.Uint32(TMTPUsbControlRequestCancelData::ETransactionID))); |
|
466 |
|
467 #ifdef _DEBUG |
|
468 // print log about the cacel event |
|
469 RDebug::Print(_L("cancel event received!!!!!!!!!!!!!!!!!Transaction phase is %d ----------------\n"), BoundProtocolLayer().TransactionPhaseL(iMTPSessionId)); |
|
470 RDebug::Print(_L("The Transaction ID want to canceled is %d -------------"), iUsbControlRequestCancelData.Uint32(TMTPUsbControlRequestCancelData::ETransactionID)); |
|
471 RDebug::Print(_L("Current Transaction ID is %d ----------------"),iMTPRequest.Uint32(TMTPTypeRequest::ERequestTransactionID)); |
|
472 #endif |
|
473 |
|
474 isResponseTransactionCancelledNeeded = true; |
|
475 if( BoundProtocolLayer().TransactionPhaseL(iMTPSessionId) > EIdlePhase ) |
|
476 { |
|
477 |
|
478 |
|
479 |
|
480 iMTPEvent.Reset(); |
|
481 iMTPEvent.SetUint16(TMTPTypeEvent::EEventCode, iUsbControlRequestCancelData.Uint16(TMTPUsbControlRequestCancelData::ECancellationCode)); |
|
482 iMTPEvent.SetUint32(TMTPTypeEvent::EEventSessionID, iMTPSessionId); |
|
483 |
|
484 // replace the transaction id in the event with the current transaction id |
|
485 iMTPEvent.SetUint32(TMTPTypeEvent::EEventTransactionID, iMTPRequest.Uint32(TMTPTypeRequest::ERequestTransactionID)); |
|
486 |
|
487 // Set the cancel flag. |
|
488 iIsCancelReceived = ETrue; |
|
489 |
|
490 // Update the device status. |
|
491 SetDeviceStatus(EMTPUsbDeviceStatusBusy); |
|
492 |
|
493 // Notify the protocol layer. |
|
494 if (ConnectionOpen()) |
|
495 { |
|
496 BoundProtocolLayer().ReceivedEventL(iMTPEvent); |
|
497 } |
|
498 } |
|
499 else |
|
500 { |
|
501 |
|
502 #ifdef _DEBUG |
|
503 RDebug::Print(_L("cancel evnet received at idle state, stop data EPs, flush rx data, restart data eps,statusOK\n")); |
|
504 #endif |
|
505 |
|
506 // stop data endpoint |
|
507 DataEndpointsStop(); |
|
508 |
|
509 //flush rx data |
|
510 TInt nbytes = 0; |
|
511 TInt err = iLdd.QueryReceiveBuffer(EndpointNumber(EMTPUsbEpBulkOut), nbytes); |
|
512 #ifdef _DEBUG |
|
513 RDebug::Print(_L("QueryReceiveBuffer()-----err is %d , nbytes is %d"), err, nbytes); |
|
514 #endif |
|
515 |
|
516 // has data, read it |
|
517 if( (err == KErrNone) && (nbytes > 0) ) |
|
518 { |
|
519 // create the read buff |
|
520 RBuf8 readBuf; |
|
521 readBuf.CreateL(nbytes); |
|
522 // synchronously read the data |
|
523 TRequestStatus status; |
|
524 iLdd.ReadOneOrMore(status, EndpointNumber(EMTPUsbEpBulkOut), readBuf); |
|
525 User::WaitForRequest(status); |
|
526 if (KErrNone == status.Int()) |
|
527 { |
|
528 #ifdef _DEBUG |
|
529 RDebug::Print(_L("%d bytes is flushed"), nbytes); |
|
530 #endif |
|
531 } |
|
532 readBuf.Close(); |
|
533 } |
|
534 // initiate bulk request sequence. |
|
535 InitiateBulkRequestSequenceL(); |
|
536 |
|
537 SetDeviceStatus(EMTPUsbDeviceStatusOK); |
|
538 } |
|
539 } |
|
540 |
|
541 // Initiate the next control request sequence. |
|
542 InitiateControlRequestSequenceL(); |
|
543 } |
|
544 __FLOG(_L8("ReceiveControlRequestDataCompleteL - Exit")); |
|
545 } |
|
546 |
|
547 void CMTPUsbConnection::ReceiveControlRequestSetupCompleteL(TInt aError, MMTPType& aData) |
|
548 { |
|
549 __FLOG(_L8("ReceiveControlRequestSetupCompleteL - Entry")); |
|
550 if (!ControlRequestErrorHandled(aError)) |
|
551 { |
|
552 TMTPUsbControlRequestSetup& data(static_cast<TMTPUsbControlRequestSetup&> (aData)); |
|
553 __FLOG_VA((_L8("bRequest = 0x%X"), data.Uint8(TMTPUsbControlRequestSetup::EbRequest))); |
|
554 __FLOG_VA((_L8("wLength = %d bytes"), data.Uint16(TMTPUsbControlRequestSetup::EwLength))); |
|
555 |
|
556 switch (data.Uint8(TMTPUsbControlRequestSetup::EbRequest)) |
|
557 { |
|
558 case EMTPUsbControlRequestCancel: |
|
559 ProcessControlRequestCancelL(data); |
|
560 break; |
|
561 |
|
562 case EMTPUsbControlRequestDeviceReset: |
|
563 ProcessControlRequestDeviceResetL(data); |
|
564 break; |
|
565 |
|
566 case EMTPUsbControlRequestDeviceStatus: |
|
567 ProcessControlRequestDeviceStatusL(data); |
|
568 break; |
|
569 |
|
570 default: |
|
571 __FLOG(_L8("Unrecognised class specific request received")); |
|
572 CloseConnection(); |
|
573 break; |
|
574 } |
|
575 } |
|
576 __FLOG(_L8("ReceiveControlRequestSetupCompleteL - Exit")); |
|
577 } |
|
578 |
|
579 void CMTPUsbConnection::SendBulkDataCompleteL(TInt aError, const MMTPType& /*aData*/) |
|
580 { |
|
581 __FLOG(_L8("SendBulkDataCompleteL - Entry")); |
|
582 |
|
583 #ifdef _DEBUG |
|
584 RDebug::Print(_L("\nCMTPUsbConnection::SendBulkDataCompleteL----entry")); |
|
585 #endif |
|
586 if (!BulkRequestErrorHandled(aError)) |
|
587 { |
|
588 TUint16 containerType(iUsbBulkContainer->Uint16L(CMTPUsbContainer::EContainerType)); |
|
589 |
|
590 #ifdef _DEBUG |
|
591 |
|
592 TUint16 transactionID(iUsbBulkContainer->Uint32L(CMTPUsbContainer::ETransactionID)); |
|
593 RDebug::Print(_L("Time Stamp is :%d"), User::TickCount()); |
|
594 RDebug::Print(_L("the container Type is 0x%x, the transaction ID is 0x%x\n"), containerType,transactionID); |
|
595 #endif |
|
596 |
|
597 if (containerType == EMTPUsbContainerTypeResponseBlock) |
|
598 { |
|
599 // Response block sent. |
|
600 BoundProtocolLayer().SendResponseCompleteL(aError, *static_cast<TMTPTypeResponse*>(iUsbBulkContainer->Payload()), iMTPRequest); |
|
601 |
|
602 // Update the transaction state. |
|
603 if(ERequestPhase != iBulkTransactionState) |
|
604 { |
|
605 SetBulkTransactionState(ECompletingPhase); |
|
606 } |
|
607 } |
|
608 else if (containerType == EMTPUsbContainerTypeDataBlock) |
|
609 { |
|
610 // Data block sent. |
|
611 BoundProtocolLayer().SendDataCompleteL(aError, *iUsbBulkContainer->Payload(), iMTPRequest); |
|
612 } |
|
613 else |
|
614 { |
|
615 __FLOG(_L8("Invalid container type")); |
|
616 Panic(EMTPUsbBadState); |
|
617 } |
|
618 |
|
619 // Reset the bulk container. |
|
620 if(ERequestPhase != iBulkTransactionState) |
|
621 { |
|
622 iUsbBulkContainer->SetPayloadL(NULL); |
|
623 } |
|
624 } |
|
625 __FLOG(_L8("SendBulkDataCompleteL - Exit")); |
|
626 } |
|
627 |
|
628 void CMTPUsbConnection::SendControlRequestDataCompleteL(TInt aError, const MMTPType& /*aData*/) |
|
629 { |
|
630 __FLOG(_L8("SendControlRequestDataCompleteL - Entry")); |
|
631 if (!ControlRequestErrorHandled(aError)) |
|
632 { |
|
633 // Complete the control request sequence. |
|
634 if (iUsbControlRequestSetup.Uint8(TMTPUsbControlRequestSetup::EbRequest) == EMTPUsbControlRequestCancel) |
|
635 { |
|
636 // Cancel request processed, clear the device status. |
|
637 SetDeviceStatus(EMTPUsbDeviceStatusOK); |
|
638 __FLOG(_L8("Cancel Request processed")); |
|
639 } |
|
640 |
|
641 // Initiate the next control request sequence. |
|
642 InitiateControlRequestSequenceL(); |
|
643 } |
|
644 __FLOG(_L8("SendControlRequestDataCompleteL - Exit")); |
|
645 } |
|
646 |
|
647 void CMTPUsbConnection::SendInterruptDataCompleteL(TInt aError, const MMTPType& /*aData*/) |
|
648 { |
|
649 __FLOG(_L8("SendInterruptDataCompleteL - Entry")); |
|
650 iEventPending = EFalse; |
|
651 BoundProtocolLayer().SendEventCompleteL(aError, iMTPEvent); |
|
652 __FLOG(_L8("SendInterruptDataCompleteL - Exit")); |
|
653 } |
|
654 |
|
655 /** |
|
656 Provides the logical endpoint bit position bits of the specified endpoint. |
|
657 @param aId The internal endpoint identifier of the endpoint. |
|
658 @return The logical endpoint bit position bits. |
|
659 */ |
|
660 TUint CMTPUsbConnection::EndpointBitPosition(TUint aId) const |
|
661 { |
|
662 return iEndpointInfo[aId].iBitPosition; |
|
663 } |
|
664 |
|
665 /** |
|
666 Provides the endpoint direction flag bits of the specified endpoint. |
|
667 @param aId The internal endpoint identifier of the endpoint. |
|
668 @return The endpoint direction flag bits. |
|
669 */ |
|
670 TUint CMTPUsbConnection::EndpointDirection(TUint aId) const |
|
671 { |
|
672 return iEndpointInfo[aId].iDirection; |
|
673 } |
|
674 |
|
675 /** |
|
676 Provides the capabilities of the specified endpoint. |
|
677 @param aId The internal endpoint identifier of the endpoint. |
|
678 @leave KErrOverflow, if the USB device does not support the minimum number of |
|
679 endpoints required by the USB MTP device class. |
|
680 */ |
|
681 const TUsbcEndpointCaps& CMTPUsbConnection::EndpointCapsL(TUint aId) |
|
682 { |
|
683 __FLOG(_L8("EndpointCapsL - Entry")); |
|
684 |
|
685 // Verify the the USB device supports the minimum number of endpoints. |
|
686 TInt totalEndpoints = iDeviceCaps().iTotalEndpoints; |
|
687 |
|
688 __FLOG_VA((_L8("% d endpoints available, %d required"), totalEndpoints, KMTPUsbRequiredNumEndpoints)); |
|
689 if (totalEndpoints < KMTPUsbRequiredNumEndpoints) |
|
690 { |
|
691 User::Leave(KErrOverflow); |
|
692 } |
|
693 |
|
694 TUint flags(EndpointDirectionAndType(aId)); |
|
695 __FLOG_VA((_L8("Required EP%d iTypesAndDir = 0x%X"), aId, flags)); |
|
696 |
|
697 TBool found(EFalse); |
|
698 for (TUint i(0); ((!found) && (i < totalEndpoints)); i++) |
|
699 { |
|
700 TUsbcEndpointCaps& caps(iEndpointCapSets[i].iCaps); |
|
701 |
|
702 if ((caps.iTypesAndDir & flags) == flags) |
|
703 { |
|
704 found = ETrue; |
|
705 iEndpointCaps = caps; |
|
706 |
|
707 __FLOG_VA((_L8("Matched EP%d iTypesAndDir = 0x%X"), i, caps.iTypesAndDir)); |
|
708 __FLOG_VA((_L8("Matched EP%d MaxPacketSize = %d"), i, caps.MaxPacketSize())); |
|
709 __FLOG_VA((_L8("Matched EP%d MinPacketSize = %d"), i, caps.MinPacketSize())); |
|
710 } |
|
711 } |
|
712 |
|
713 if (!found) |
|
714 { |
|
715 User::Leave(KErrHardwareNotAvailable); |
|
716 } |
|
717 |
|
718 __FLOG(_L8("EndpointCapsL - Exit")); |
|
719 return iEndpointCaps; |
|
720 } |
|
721 |
|
722 /** |
|
723 Provides the endpoint direction and type flag bits of the specified endpoint. |
|
724 @param aId The internal endpoint identifier of the endpoint. |
|
725 @return The logical endpoint number. |
|
726 */ |
|
727 TUint CMTPUsbConnection::EndpointDirectionAndType(TUint aId) const |
|
728 { |
|
729 return (EndpointDirection(aId) | EndpointType(aId)); |
|
730 } |
|
731 |
|
732 /** |
|
733 Provides the logical endpoint number of the specified endpoint. |
|
734 @param aId The internal endpoint identifier of the endpoint. |
|
735 @return The logical endpoint number. |
|
736 */ |
|
737 TEndpointNumber CMTPUsbConnection::EndpointNumber(TUint aId) const |
|
738 { |
|
739 return iEndpointInfo[aId].iNumber; |
|
740 } |
|
741 |
|
742 /** |
|
743 Provides the endpoint type flag bits of the specified endpoint. |
|
744 @param aId The internal endpoint identifier of the endpoint. |
|
745 @return The endpoint type flag bits. |
|
746 */ |
|
747 TUint CMTPUsbConnection::EndpointType(TUint aId) const |
|
748 { |
|
749 return iEndpointInfo[aId].iType; |
|
750 } |
|
751 |
|
752 /** |
|
753 Provides the USB device client interface. |
|
754 @return The USB device client interface. |
|
755 */ |
|
756 RDevUsbcClient& CMTPUsbConnection::Ldd() |
|
757 { |
|
758 return iLdd; |
|
759 } |
|
760 |
|
761 void CMTPUsbConnection::DoCancel() |
|
762 { |
|
763 __FLOG(_L8("DoCancel - Entry")); |
|
764 iLdd.AlternateDeviceStatusNotifyCancel(); |
|
765 __FLOG(_L8("DoCancel - Exit")); |
|
766 } |
|
767 |
|
768 #ifdef __FLOG_ACTIVE |
|
769 TInt CMTPUsbConnection::RunError(TInt aError) |
|
770 #else |
|
771 TInt CMTPUsbConnection::RunError(TInt /*aError*/) |
|
772 #endif |
|
773 { |
|
774 __FLOG(_L8("RunError - Entry")); |
|
775 __FLOG_VA((_L8("Error = %d"), aError)); |
|
776 |
|
777 // Cancel all the outstanding requests. |
|
778 Cancel(); |
|
779 |
|
780 // Stop the connection, if necessary. |
|
781 StopConnection(); |
|
782 |
|
783 // Stop the control end point. |
|
784 ControlEndpointStop(); |
|
785 |
|
786 // Issue the notify request again. |
|
787 IssueAlternateDeviceStatusNotifyRequest(); |
|
788 |
|
789 __FLOG(_L8("RunError - Exit")); |
|
790 return KErrNone; |
|
791 } |
|
792 |
|
793 void CMTPUsbConnection::RunL() |
|
794 { |
|
795 __FLOG(_L8("RunL - Entry")); |
|
796 |
|
797 if (!(iControllerStateCurrent & KUsbAlternateSetting)) |
|
798 { |
|
799 // Alternative interface setting has not changed. |
|
800 __FLOG_VA((_L8("Alternate device state changed to %d"), iControllerStateCurrent)); |
|
801 |
|
802 if ((SuspendState() & ESuspended) && |
|
803 (iControllerStateCurrent != EUsbcDeviceStateSuspended)) |
|
804 { |
|
805 // Update state. |
|
806 SetSuspendState(ENotSuspended); |
|
807 } |
|
808 |
|
809 switch (iControllerStateCurrent) |
|
810 { |
|
811 case EUsbcDeviceStateUndefined: |
|
812 case EUsbcDeviceStateAttached: |
|
813 case EUsbcDeviceStatePowered: |
|
814 case EUsbcDeviceStateDefault: |
|
815 StopConnection(); |
|
816 ControlEndpointStop(); |
|
817 break; |
|
818 |
|
819 case EUsbcDeviceStateAddress: |
|
820 // Set the Endpoint packet sizes. |
|
821 SetTransportPacketSizeL(); |
|
822 |
|
823 // Stop the control endpoint first, in case there is still |
|
824 // outstanding request. |
|
825 ControlEndpointStop(); |
|
826 |
|
827 // Initiate control endpoint data transfer activity. |
|
828 ControlEndpointStartL(); |
|
829 break; |
|
830 |
|
831 case EUsbcDeviceStateConfigured: |
|
832 { |
|
833 __FLOG(_L8("Device state : EUsbcDeviceStateConfigured")); |
|
834 |
|
835 if (iControllerStatePrevious == EUsbcDeviceStateSuspended) |
|
836 { |
|
837 // Resume connection data transfer activity. |
|
838 ResumeConnectionL(); |
|
839 |
|
840 // Process buffered events. |
|
841 if (SuspendState() == ESuspendedEventsPending) |
|
842 { |
|
843 /* |
|
844 If remote wakeup is enabled then signal remote wakeup |
|
845 before sending the buffered event data. Otherwise issue |
|
846 a PTP UnreportedStatus event. |
|
847 */ |
|
848 |
|
849 // Don't check for pending events since this |
|
850 // is after a suspend |
|
851 if (iRemoteWakeup) |
|
852 { |
|
853 // Send the event data. |
|
854 __FLOG(_L8("Sending buffered event data")); |
|
855 SendEventDataL(); |
|
856 } |
|
857 else |
|
858 { |
|
859 // Send PTP UnreportedStatus event |
|
860 __FLOG(_L8("Sending PTP UnreportedStatus event")); |
|
861 SendUnreportedStatusEventL(); |
|
862 } |
|
863 } |
|
864 } |
|
865 else |
|
866 { |
|
867 //restart the control endpoint |
|
868 ControlEndpointStop(); |
|
869 InitiateControlRequestSequenceL(); |
|
870 |
|
871 //restart the data endpoint |
|
872 StartConnectionL(); |
|
873 } |
|
874 break; |
|
875 |
|
876 case EUsbcDeviceStateSuspended: |
|
877 // Suspend connection activity. |
|
878 SuspendConnectionL(); |
|
879 break; |
|
880 } |
|
881 |
|
882 default: |
|
883 __FLOG(_L8("Invalid alternate device state")); |
|
884 Panic(EMTPUsbBadState); |
|
885 break; |
|
886 } |
|
887 } |
|
888 else |
|
889 { |
|
890 // Alternate interface setting has changed. |
|
891 __FLOG_VA((_L8("Alternate interface setting changed from %d to %d"), iControllerStatePrevious, iControllerStateCurrent)); |
|
892 } |
|
893 |
|
894 |
|
895 // Record the controller state and issue the next notification request. |
|
896 iControllerStatePrevious = iControllerStateCurrent; |
|
897 IssueAlternateDeviceStatusNotifyRequest(); |
|
898 |
|
899 __FLOG(_L8("RunL - Exit")); |
|
900 } |
|
901 |
|
902 /** |
|
903 Constructor. |
|
904 @param aConnectionMgr The MTP connection manager interface. |
|
905 */ |
|
906 CMTPUsbConnection::CMTPUsbConnection(MMTPConnectionMgr& aConnectionMgr) : |
|
907 CActive(EPriorityStandard), |
|
908 iEndpointInfo(KEndpointMetaData, EMTPUsbEpNumEndpoints), |
|
909 iConnectionMgr(&aConnectionMgr) |
|
910 { |
|
911 CActiveScheduler::Add(this); |
|
912 } |
|
913 |
|
914 /** |
|
915 Second phase constructor. |
|
916 @leave One of the system wide error codes, if a processing failure occurs. |
|
917 */ |
|
918 void CMTPUsbConnection::ConstructL() |
|
919 { |
|
920 __FLOG_OPEN(KMTPSubsystem, KComponent); |
|
921 __FLOG(_L8("ConstructL - Entry")); |
|
922 |
|
923 // Start the USB device. |
|
924 StartUsbL(); |
|
925 |
|
926 // Create the device class endpoints. |
|
927 iEndpoints.InsertInOrderL(CMTPUsbEpControl::NewL(EMTPUsbEpControl, *this), CMTPUsbEpBase::LinearOrder); |
|
928 iEndpoints.InsertInOrderL(CMTPUsbEpBulkIn::NewL(EMTPUsbEpBulkIn, *this), CMTPUsbEpBase::LinearOrder); |
|
929 iEndpoints.InsertInOrderL(CMTPUsbEpBulkOut::NewL(EMTPUsbEpBulkOut, *this), CMTPUsbEpBase::LinearOrder); |
|
930 iEndpoints.InsertInOrderL(CMTPUsbEpInterruptIn::NewL(EMTPUsbEpInterrupt, *this), CMTPUsbEpBase::LinearOrder); |
|
931 |
|
932 // Create the generic data container buffers. |
|
933 iUsbBulkContainer = CMTPUsbContainer::NewL(); |
|
934 iUsbEventContainer = CMTPUsbContainer::NewL(); |
|
935 |
|
936 // Initialise the device status. |
|
937 SetDeviceStatus(EMTPUsbDeviceStatusOK); |
|
938 |
|
939 // Fetch the remote wakeup flag. |
|
940 TUsbDeviceCaps dCaps; |
|
941 User::LeaveIfError(iLdd.DeviceCaps(dCaps)); |
|
942 iRemoteWakeup = dCaps().iRemoteWakeup; |
|
943 __FLOG_VA((_L8("iRemote = %d"), iRemoteWakeup)); |
|
944 |
|
945 // Start monitoring the USB device controller state. |
|
946 IssueAlternateDeviceStatusNotifyRequest(); |
|
947 |
|
948 __FLOG(_L8("ConstructL - Exit")); |
|
949 } |
|
950 |
|
951 /** |
|
952 Issues a request for notification of USB device controller state and alternate |
|
953 interface setting changes. |
|
954 */ |
|
955 void CMTPUsbConnection::IssueAlternateDeviceStatusNotifyRequest() |
|
956 { |
|
957 __FLOG(_L8("IssueAlternateDeviceStatusNotifyRequest - Entry")); |
|
958 |
|
959 if (!IsActive()) |
|
960 { |
|
961 iLdd.AlternateDeviceStatusNotify(iStatus, iControllerStateCurrent); |
|
962 } |
|
963 |
|
964 SetActive(); |
|
965 __FLOG(_L8("IssueAlternateDeviceStatusNotifyRequest - Exit")); |
|
966 } |
|
967 |
|
968 /** |
|
969 Populates the asynchronous event interrupt dataset buffer. |
|
970 @leave One of the system wide error codes, if a processing failure occurs. |
|
971 */ |
|
972 void CMTPUsbConnection::BufferEventDataL(const TMTPTypeEvent& aEvent) |
|
973 { |
|
974 __FLOG(_L8("BufferEventData - Entry")); |
|
975 /* |
|
976 Setup the parameter block payload dataset. Note that since this is a |
|
977 variable length dataset, it must first be reset. |
|
978 */ |
|
979 iUsbEventParameterBlock.Reset(); |
|
980 iUsbEventParameterBlock.CopyIn(aEvent, TMTPTypeEvent::EEventParameter1, TMTPTypeEvent::EEventParameter3, EFalse, 0); |
|
981 |
|
982 // Setup the bulk container. |
|
983 iUsbEventContainer->SetPayloadL(const_cast<TMTPUsbParameterPayloadBlock*>(&iUsbEventParameterBlock)); |
|
984 iUsbEventContainer->SetUint32L(CMTPUsbContainer::EContainerLength, iUsbEventContainer->Size()); |
|
985 iUsbEventContainer->SetUint16L(CMTPUsbContainer::EContainerType, EMTPUsbContainerTypeEventBlock); |
|
986 iUsbEventContainer->SetUint16L(CMTPUsbContainer::ECode, aEvent.Uint16(TMTPTypeEvent::EEventCode)); |
|
987 iUsbEventContainer->SetUint32L(CMTPUsbContainer::ETransactionID, aEvent.Uint32(TMTPTypeEvent::EEventTransactionID)); |
|
988 __FLOG(_L8("BufferEventData - Exit")); |
|
989 } |
|
990 |
|
991 /** |
|
992 Initiates an interrupt data send sequence. |
|
993 @leave One of the system wide error codes, if a processing failure occurs. |
|
994 */ |
|
995 void CMTPUsbConnection::SendEventDataL() |
|
996 { |
|
997 __FLOG(_L8("SendEventData - Entry")); |
|
998 __FLOG_VA((_L8("Sending event 0x%4X (%d bytes)"), iUsbEventContainer->Uint16L(CMTPUsbContainer::ECode), iUsbEventContainer->Uint32L(CMTPUsbContainer::EContainerLength))); |
|
999 static_cast<CMTPUsbEpInterruptIn*>(iEndpoints[EMTPUsbEpInterrupt])->SendInterruptDataL(*iUsbEventContainer); |
|
1000 iEventPending = ETrue; |
|
1001 __FLOG(_L8("SendEventData - Exit")); |
|
1002 } |
|
1003 |
|
1004 /** |
|
1005 Issues a PTP UnreportedStatus event. |
|
1006 @leave One of the system wide error codes, if a processing failure occurs. |
|
1007 */ |
|
1008 void CMTPUsbConnection::SendUnreportedStatusEventL() |
|
1009 { |
|
1010 __FLOG(_L8("SendUnreportedStatusEventL - Entry")); |
|
1011 |
|
1012 // Construct an UnreportedStatus event |
|
1013 TMTPTypeEvent mtpEvent; |
|
1014 mtpEvent.SetUint16(TMTPTypeEvent::EEventCode, EMTPEventCodeUnreportedStatus); |
|
1015 mtpEvent.SetUint32(TMTPTypeEvent::EEventSessionID, KMTPSessionNone); |
|
1016 mtpEvent.SetUint32(TMTPTypeEvent::EEventTransactionID, KMTPTransactionIdNone); |
|
1017 SendEventL(mtpEvent); |
|
1018 |
|
1019 __FLOG(_L8("SendUnreportedStatusEventL - Exit")); |
|
1020 } |
|
1021 |
|
1022 /** |
|
1023 Issues a request to the bulk-out endpoint to receive a command block dataset. |
|
1024 @leave One of the system wide error codes, if a processing failure occurs. |
|
1025 */ |
|
1026 void CMTPUsbConnection::InitiateBulkRequestSequenceL() |
|
1027 { |
|
1028 __FLOG(_L8("InitiateBulkRequestSequenceL - Entry")); |
|
1029 CMTPUsbEpBulkOut& bulkOut(*static_cast<CMTPUsbEpBulkOut*>(iEndpoints[EMTPUsbEpBulkOut])); |
|
1030 |
|
1031 // Update the transaction state. |
|
1032 SetBulkTransactionState(ERequestPhase); |
|
1033 |
|
1034 // Setup the bulk container. |
|
1035 iUsbBulkParameterBlock.Reset(); |
|
1036 iUsbBulkContainer->SetPayloadL(&iUsbBulkParameterBlock); |
|
1037 |
|
1038 // Initiate the next request phase bulk data receive sequence. |
|
1039 bulkOut.ReceiveBulkDataL(*iUsbBulkContainer); |
|
1040 |
|
1041 __FLOG(_L8("InitiateBulkRequestSequenceL - Exit")); |
|
1042 } |
|
1043 |
|
1044 /** |
|
1045 Issues a request to the control endpoint to receive a request setup dataset. |
|
1046 @leave One of the system wide error codes, if a processing failure occurs. |
|
1047 */ |
|
1048 void CMTPUsbConnection::InitiateControlRequestSequenceL() |
|
1049 { |
|
1050 __FLOG(_L8("InitiateControlRequestSequenceL - Entry")); |
|
1051 CMTPUsbEpControl& ctrl(*static_cast<CMTPUsbEpControl*>(iEndpoints[EMTPUsbEpControl])); |
|
1052 if (!ctrl.Stalled()) |
|
1053 { |
|
1054 ctrl.ReceiveControlRequestSetupL(iUsbControlRequestSetup); |
|
1055 } |
|
1056 __FLOG(_L8("InitiateControlRequestSequenceL - Exit")); |
|
1057 } |
|
1058 |
|
1059 /** |
|
1060 Processes received USB SIC bulk command block containers received from the |
|
1061 connected host on the bulk out data pipe. |
|
1062 @param aError The error completion status of the bulk data receive request. |
|
1063 @leave One of the system wide error codes, if a processing failure occurs. |
|
1064 */ |
|
1065 #ifdef __FLOG_ACTIVE |
|
1066 void CMTPUsbConnection::ProcessBulkCommandL(TInt aError) |
|
1067 #else |
|
1068 void CMTPUsbConnection::ProcessBulkCommandL(TInt /*aError*/) |
|
1069 #endif |
|
1070 { |
|
1071 __FLOG(_L8("ProcessBulkCommandL - Entry")); |
|
1072 __FLOG_VA((_L8("aError = %d"), aError)); |
|
1073 if (BulkRequestTransactionStateValid(ERequestPhase)) |
|
1074 { |
|
1075 // Request block received. |
|
1076 TUint16 op(iUsbBulkContainer->Uint16L(CMTPUsbContainer::ECode)); |
|
1077 __FLOG_VA((_L8("Command block 0x%04X received"), op)); |
|
1078 |
|
1079 // Reset the iMTPRequest. |
|
1080 iMTPRequest.Reset(); |
|
1081 |
|
1082 // Setup the MTP request dataset buffer. Set Operation Code and TransactionID |
|
1083 iMTPRequest.SetUint16(TMTPTypeRequest::ERequestOperationCode, op); |
|
1084 iMTPRequest.SetUint32(TMTPTypeRequest::ERequestTransactionID, iUsbBulkContainer->Uint32L(CMTPUsbContainer::ETransactionID)); |
|
1085 |
|
1086 // Set SessionID. |
|
1087 if (op == EMTPOpCodeOpenSession) |
|
1088 { |
|
1089 __FLOG(_L8("Processing OpenSession request")); |
|
1090 // Force OpenSession requests to be processed outside an active session. |
|
1091 // It is a known problem for MTP Protocol, it is a workaround here. |
|
1092 iMTPRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, KMTPSessionNone); |
|
1093 } |
|
1094 else if (op == EMTPOpCodeCloseSession || op == EMTPOpCodeResetDevice) |
|
1095 { |
|
1096 __FLOG(_L8("Processing CloseSession or the ResetDevice request")); |
|
1097 // Force CloseSession requests to be processed outside an active session. |
|
1098 // ResetDevice currently behaves the same way as CloseSession. |
|
1099 iMTPRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, KMTPSessionNone); |
|
1100 iMTPRequest.SetUint32(TMTPTypeRequest::ERequestParameter1, iMTPSessionId); |
|
1101 } |
|
1102 else |
|
1103 { |
|
1104 __FLOG_VA((_L8("Processing general request on session %d"), iMTPSessionId)); |
|
1105 // Update the request dataset with the single active session's SessionID. |
|
1106 iMTPRequest.SetUint32(TMTPTypeRequest::ERequestSessionID, iMTPSessionId); |
|
1107 } |
|
1108 |
|
1109 #ifdef _DEBUG |
|
1110 RDebug::Print(_L("The time stamp is: %d"), User::TickCount()); |
|
1111 RDebug::Print(_L("New command comes, Operation code is 0x%x, transaction id is %d \n"), op, iUsbBulkContainer->Uint32L(CMTPUsbContainer::ETransactionID)); |
|
1112 #endif |
|
1113 |
|
1114 TUint commandTransID(iUsbBulkContainer->Uint32L(CMTPUsbContainer::ETransactionID)); |
|
1115 |
|
1116 // process this command as usual |
|
1117 // Update the device status. |
|
1118 SetDeviceStatus(EMTPUsbDeviceStatusBusy); |
|
1119 |
|
1120 // Set Parameter 1 .. Parameter 5. |
|
1121 iUsbBulkParameterBlock.CopyOut(iMTPRequest, TMTPTypeRequest::ERequestParameter1, TMTPTypeRequest::ERequestParameter5); |
|
1122 iUsbBulkParameterBlock.Reset(); |
|
1123 |
|
1124 // Notify the protocol layer. |
|
1125 BoundProtocolLayer().ReceivedRequestL(iMTPRequest); |
|
1126 } |
|
1127 __FLOG(_L8("ProcessBulkCommandL - Exit")); |
|
1128 } |
|
1129 |
|
1130 /** |
|
1131 Processes USB SIC bulk data block containers onto the connected host on the |
|
1132 bulk in data pipe. |
|
1133 @param aRequest The MTP request dataset of the active MTP transaction. |
|
1134 @param aData The MTP data object source. |
|
1135 @leave One of the system wide error codes, if a processing failure occurs. |
|
1136 */ |
|
1137 void CMTPUsbConnection::ProcessBulkDataInL(const TMTPTypeRequest& aRequest, const MMTPType& aData) |
|
1138 { |
|
1139 __FLOG(_L8("ProcessBulkDataInL - Entry")); |
|
1140 |
|
1141 // Update the transaction state. |
|
1142 SetBulkTransactionState(EDataRToIPhase); |
|
1143 |
|
1144 // Setup the bulk container. |
|
1145 iUsbBulkContainer->SetPayloadL(const_cast<MMTPType*>(&aData)); |
|
1146 |
|
1147 TUint64 size(iUsbBulkContainer->Size()); |
|
1148 TUint32 containerLength((size > KMTPUsbContainerLengthMax) ? KMTPUsbContainerLengthMax : static_cast<TUint32>(size)); |
|
1149 iUsbBulkContainer->SetUint32L(CMTPUsbContainer::EContainerLength, containerLength); |
|
1150 |
|
1151 iUsbBulkContainer->SetUint16L(CMTPUsbContainer::EContainerType, EMTPUsbContainerTypeDataBlock); |
|
1152 iUsbBulkContainer->SetUint16L(CMTPUsbContainer::ECode, aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode)); |
|
1153 iUsbBulkContainer->SetUint32L(CMTPUsbContainer::ETransactionID, aRequest.Uint32(TMTPTypeRequest::ERequestTransactionID)); |
|
1154 |
|
1155 // Initiate the bulk data send sequence. |
|
1156 __FLOG_VA((_L8("Sending %d data bytes"), iUsbBulkContainer->Uint32L(CMTPUsbContainer::EContainerLength))); |
|
1157 |
|
1158 #ifdef _DEBUG |
|
1159 RDebug::Print(_L("ProcessBulkDataInL: iIsCancelReceived = %d, SuspendState() is %d \n"),iIsCancelReceived,SuspendState()); |
|
1160 #endif |
|
1161 |
|
1162 // if the cancel event is received before send data. That is, the phase is before DATA R2I, |
|
1163 // Device should not send the transaction data to the host,just like what sendResponse does. |
|
1164 if (SuspendState() != ESuspended && !iIsCancelReceived) |
|
1165 { |
|
1166 TPtr8 headerChunk(NULL, 0); |
|
1167 TBool hasTransportHeader = const_cast<MMTPType&>(aData).ReserveTransportHeader(KUSBHeaderSize, headerChunk); |
|
1168 if(hasTransportHeader) |
|
1169 { |
|
1170 TUint16 containerType = EMTPUsbContainerTypeDataBlock; |
|
1171 TUint16 operationCode = aRequest.Uint16(TMTPTypeRequest::ERequestOperationCode); |
|
1172 TUint32 transId = aRequest.Uint32(TMTPTypeRequest::ERequestTransactionID); |
|
1173 memcpy(const_cast<TUint8*>(headerChunk.Ptr()), &containerLength, sizeof(TUint32)); |
|
1174 memcpy(const_cast<TUint8*>(headerChunk.Ptr()) + 4, &containerType, sizeof(TUint16)); |
|
1175 memcpy(const_cast<TUint8*>(headerChunk.Ptr()) + 6, &operationCode, sizeof(TUint16)); |
|
1176 memcpy(const_cast<TUint8*>(headerChunk.Ptr()) + 8, &transId, sizeof(TUint32)); |
|
1177 static_cast<CMTPUsbEpBulkIn*>(iEndpoints[EMTPUsbEpBulkIn])->SendBulkDataL(aData); |
|
1178 } |
|
1179 else |
|
1180 { |
|
1181 static_cast<CMTPUsbEpBulkIn*>(iEndpoints[EMTPUsbEpBulkIn])->SendBulkDataL(*iUsbBulkContainer); |
|
1182 } |
|
1183 } |
|
1184 else |
|
1185 { |
|
1186 |
|
1187 #ifdef _DEBUG |
|
1188 RDebug::Print(_L("the senddata is canceled!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n")); |
|
1189 #endif |
|
1190 // by pass the calling to lower level send data |
|
1191 SendBulkDataCompleteL(KErrNone, *iUsbBulkContainer); |
|
1192 |
|
1193 } |
|
1194 __FLOG(_L8("ProcessBulkDataInL - Exit")); |
|
1195 } |
|
1196 |
|
1197 /** |
|
1198 Processes received USB SIC bulk data block containers received from the |
|
1199 connected host on the bulk out data pipe. |
|
1200 @param aError The error completion status of the bulk data receive request. |
|
1201 @leave One of the system wide error codes, if a processing failure occurs. |
|
1202 */ |
|
1203 void CMTPUsbConnection::ProcessBulkDataOutL(TInt aError) |
|
1204 { |
|
1205 __FLOG(_L8("ProcessBulkDataOutL - Entry")); |
|
1206 if ((BulkRequestTransactionStateValid(EDataIToRPhase))) |
|
1207 { |
|
1208 // Data block received, notify the protocol layer. |
|
1209 __FLOG_VA((_L8("Data block received (%d bytes)"), iUsbBulkContainer->Uint32L(CMTPUsbContainer::EContainerLength))); |
|
1210 BoundProtocolLayer().ReceiveDataCompleteL(aError, *iUsbBulkContainer->Payload(), iMTPRequest); |
|
1211 } |
|
1212 __FLOG(_L8("ProcessBulkDataOutL - Exit")); |
|
1213 } |
|
1214 |
|
1215 /** |
|
1216 Processes received USB SIC class specific Cancel requests |
|
1217 @param aRequest The USB SIC class specific request setup data. |
|
1218 @leave One of the system wide error codes, if a processing failure occurs. |
|
1219 */ |
|
1220 void CMTPUsbConnection::ProcessControlRequestCancelL(const TMTPUsbControlRequestSetup& /*aRequest*/) |
|
1221 { |
|
1222 __FLOG(_L8("ProcessControlRequestCancelL - Entry")); |
|
1223 static_cast<CMTPUsbEpControl*>(iEndpoints[EMTPUsbEpControl])->ReceiveControlRequestDataL(iUsbControlRequestCancelData); |
|
1224 __FLOG(_L8("Waiting for Cancel Request Data")); |
|
1225 __FLOG(_L8("ProcessControlRequestCancelL - Exit")); |
|
1226 } |
|
1227 |
|
1228 /** |
|
1229 Processes received USB SIC class specific Device Reset requests |
|
1230 @param aRequest The USB SIC class specific request setup data. |
|
1231 @leave One of the system wide error codes, if a processing failure occurs. |
|
1232 */ |
|
1233 void CMTPUsbConnection::ProcessControlRequestDeviceResetL(const TMTPUsbControlRequestSetup& /*aRequest*/) |
|
1234 { |
|
1235 __FLOG(_L8("ProcessControlRequestDeviceResetL - Entry")); |
|
1236 |
|
1237 // Clear stalled endpoints and re-open connection |
|
1238 BulkEndpointsStallClearL(); |
|
1239 StartConnectionL(); |
|
1240 |
|
1241 /* |
|
1242 The Device Reset Request is data-less. Complete the control request |
|
1243 sequence and initiate the next control request sequence. |
|
1244 */ |
|
1245 static_cast<CMTPUsbEpControl*>(iEndpoints[EMTPUsbEpControl])->SendControlRequestStatus(); |
|
1246 StopConnection(); |
|
1247 InitiateControlRequestSequenceL(); |
|
1248 StartConnectionL(); |
|
1249 __FLOG(_L8("ProcessControlRequestDeviceResetL - Exit")); |
|
1250 } |
|
1251 |
|
1252 /** |
|
1253 Processes received USB SIC class specific Get Device Status requests |
|
1254 @param aRequest The USB SIC class specific request setup data. |
|
1255 @leave One of the system wide error codes, if a processing failure occurs. |
|
1256 */ |
|
1257 void CMTPUsbConnection::ProcessControlRequestDeviceStatusL(const TMTPUsbControlRequestSetup& aRequest) |
|
1258 { |
|
1259 __FLOG(_L8("ProcessControlRequestDeviceStatusL - Entry")); |
|
1260 iUsbControlRequestDeviceStatus.Reset(); |
|
1261 |
|
1262 TUint offset = 0; |
|
1263 for(TUint i(EMTPUsbEpControl); i<EMTPUsbEpNumEndpoints; ++i) |
|
1264 { |
|
1265 |
|
1266 if ( IsEpStalled(i) ) |
|
1267 { |
|
1268 TInt epSize(0); |
|
1269 User::LeaveIfError( iLdd.GetEndpointDescriptorSize(KMTPUsbAlternateInterface, i, epSize) ); |
|
1270 |
|
1271 RBuf8 epDesc; //endpoint descriptor, epDesc[2] is the address of endpoint. More info, pls refer to USB Sepc2.0 - 9.6.6 |
|
1272 epDesc.CreateL(epSize); |
|
1273 CleanupClosePushL(epDesc); |
|
1274 User::LeaveIfError( iLdd.GetEndpointDescriptor(KMTPUsbAlternateInterface, i, epDesc) ); |
|
1275 |
|
1276 //Maybe here is a little bit confused. Although an endpoint address is a 8-bit byte in Endpoint Descriptor, |
|
1277 //but in practice, it's requested by host with a 32-bit value, so we plus offset with 4 to reflect this. |
|
1278 TUint32 epAddress = epDesc[KEpAddressOffsetInEpDesc]; |
|
1279 iUsbControlRequestDeviceStatus.SetUint32((offset + TMTPUsbControlRequestDeviceStatus::EParameter1), epAddress); |
|
1280 CleanupStack::PopAndDestroy(); // calls epDesc.Close() |
|
1281 |
|
1282 ++offset; |
|
1283 } |
|
1284 } |
|
1285 |
|
1286 |
|
1287 |
|
1288 |
|
1289 |
|
1290 // if the current status is OK and a cancel event has been received but the device has not respond |
|
1291 // transaction_cancelled yet, return transaction_cancelled firstly. |
|
1292 TUint16 originalStatus = iDeviceStatusCode; |
|
1293 if( (iDeviceStatusCode == EMTPUsbDeviceStatusOK) && isResponseTransactionCancelledNeeded ) |
|
1294 { |
|
1295 SetDeviceStatus(EMTPUsbDeviceStatusTransactionCancelled); |
|
1296 // clear the transaction cancelled flag |
|
1297 isResponseTransactionCancelledNeeded = false; |
|
1298 } |
|
1299 |
|
1300 |
|
1301 |
|
1302 |
|
1303 // Set the Code and wLength fields and send the dataset. |
|
1304 iUsbControlRequestDeviceStatus.SetUint16(TMTPUsbControlRequestDeviceStatus::ECode, iDeviceStatusCode); |
|
1305 iUsbControlRequestDeviceStatus.SetUint16(TMTPUsbControlRequestDeviceStatus::EwLength, iUsbControlRequestDeviceStatus.Size()); |
|
1306 // send the response |
|
1307 static_cast<CMTPUsbEpControl*>(iEndpoints[EMTPUsbEpControl])->SendControlRequestDataL(iUsbControlRequestDeviceStatus); |
|
1308 |
|
1309 // restore the original device status |
|
1310 SetDeviceStatus(originalStatus); |
|
1311 |
|
1312 __FLOG(_L8("ProcessControlRequestDeviceStatusL - Exit")); |
|
1313 } |
|
1314 |
|
1315 /** |
|
1316 Processes bulk transfer request completion error checking. If the completion |
|
1317 status is abnormal then the connection is shutdown. |
|
1318 @param aError bulk transfer request completion error. |
|
1319 @return ETrue if the control request completion status was abnormal, otherwise |
|
1320 EFalse. |
|
1321 @leave One of the system wide error codes, if a processing failure occurs. |
|
1322 */ |
|
1323 TBool CMTPUsbConnection::BulkRequestErrorHandled(TInt aError) |
|
1324 { |
|
1325 __FLOG(_L8("BulkRequestErrorHandled - Entry")); |
|
1326 __FLOG_VA((_L8("Bulk transfer request completion status = %d"), aError)); |
|
1327 TBool ret(EFalse); |
|
1328 |
|
1329 // Only handle USB error codes |
|
1330 if (aError <= KErrUsbDriverBase && |
|
1331 aError >= KErrUsbEpNotReady) |
|
1332 { |
|
1333 switch (aError) |
|
1334 { |
|
1335 case KErrUsbDeviceNotConfigured: |
|
1336 case KErrUsbInterfaceChange: |
|
1337 case KErrUsbDeviceClosing: |
|
1338 case KErrUsbCableDetached: |
|
1339 case KErrUsbDeviceBusReset: |
|
1340 // Interface state is changing (@see RunL). |
|
1341 ret = ETrue; |
|
1342 break; |
|
1343 |
|
1344 default: |
|
1345 // Unknown error on a bulk endpoint, close the connection. |
|
1346 CloseConnection(); |
|
1347 ret = ETrue; |
|
1348 break; |
|
1349 } |
|
1350 } |
|
1351 __FLOG(_L8("BulkRequestErrorHandled - Exit")); |
|
1352 return ret; |
|
1353 } |
|
1354 |
|
1355 /** |
|
1356 Processes bulk transfer request transaction state checking. If the transaction |
|
1357 state is invalid, then the connection is shutdown. |
|
1358 @return ETrue if the control request completion status was abnormal, otherwise |
|
1359 EFalse. |
|
1360 */ |
|
1361 TBool CMTPUsbConnection::BulkRequestTransactionStateValid(TMTPTransactionPhase aExpectedTransactionState) |
|
1362 { |
|
1363 __FLOG(_L8("BulkRequestTransactionStateValid - Entry")); |
|
1364 __FLOG_VA((_L8("Bulk transaction state = %d"), iBulkTransactionState)); |
|
1365 TBool valid(iBulkTransactionState == aExpectedTransactionState); |
|
1366 if (!valid) |
|
1367 { |
|
1368 // Invalid bulk transaction state, close the connection. |
|
1369 __FLOG_VA((_L8("Expected bulk transaction state = %d"), aExpectedTransactionState)); |
|
1370 CloseConnection(); |
|
1371 } |
|
1372 __FLOG(_L8("BulkRequestTransactionStateValid - Exit")); |
|
1373 return valid; |
|
1374 } |
|
1375 |
|
1376 /** |
|
1377 Processes control request completion. If the completion status is abnormal then |
|
1378 the connection is shutdown. |
|
1379 @param aError control request completion error code. |
|
1380 @return ETrue if the control request completion status was abnormal, otherwise |
|
1381 EFalse. |
|
1382 */ |
|
1383 TBool CMTPUsbConnection::ControlRequestErrorHandled(TInt aError) |
|
1384 { |
|
1385 __FLOG(_L8("ControlRequestErrorHandled - Entry")); |
|
1386 __FLOG_VA((_L8("Control request completion status = %d"), aError)); |
|
1387 TBool ret(EFalse); |
|
1388 |
|
1389 if (aError != KErrNone) |
|
1390 { |
|
1391 switch (aError) |
|
1392 { |
|
1393 case KErrCancel: |
|
1394 // Control request sequence cancelled. |
|
1395 break; |
|
1396 |
|
1397 case KErrUsbDeviceNotConfigured: |
|
1398 case KErrUsbInterfaceChange: |
|
1399 case KErrUsbDeviceClosing: |
|
1400 case KErrUsbCableDetached: |
|
1401 case KErrUsbDeviceBusReset: |
|
1402 // Interface state is changing (@see RunL). |
|
1403 break; |
|
1404 |
|
1405 default: |
|
1406 // Unknown error on the control endpoint, shutdown the connection. |
|
1407 CloseConnection(); |
|
1408 break; |
|
1409 } |
|
1410 |
|
1411 // Signal abnormal completion. |
|
1412 ret = ETrue; |
|
1413 } |
|
1414 |
|
1415 __FLOG(_L8("ControlRequestErrorHandled - Exit")); |
|
1416 return ret; |
|
1417 } |
|
1418 |
|
1419 /** |
|
1420 Clears the USB MTP device class configuration descriptor. |
|
1421 */ |
|
1422 void CMTPUsbConnection::ConfigurationDescriptorClear() |
|
1423 { |
|
1424 __FLOG(_L8("ConfigurationDescriptorClear - Entry")); |
|
1425 const TInt KNumInterfacesOffset(4); |
|
1426 |
|
1427 TInt descriptorSize(0); |
|
1428 iLdd.GetConfigurationDescriptorSize(descriptorSize); |
|
1429 |
|
1430 if (static_cast<TUint>(descriptorSize) == KUsbDescSize_Config) |
|
1431 { |
|
1432 TBuf8<KUsbDescSize_Config> descriptor; |
|
1433 if (iLdd.GetConfigurationDescriptor(descriptor) == KErrNone) |
|
1434 { |
|
1435 --descriptor[KNumInterfacesOffset]; |
|
1436 iLdd.SetConfigurationDescriptor(descriptor); |
|
1437 } |
|
1438 } |
|
1439 |
|
1440 __FLOG(_L8("ConfigurationDescriptorClear - Exit")); |
|
1441 } |
|
1442 |
|
1443 /** |
|
1444 Sets the USB MTP device class configuration descriptor. |
|
1445 @leave KErrCorrupt, if the configuration descriptor size is invalid. |
|
1446 @leave One of the system wide error codes, if a processing failure occurs. |
|
1447 */ |
|
1448 void CMTPUsbConnection::ConfigurationDescriptorSetL() |
|
1449 { |
|
1450 __FLOG(_L8("SetupConfigurationDescriptorL - Entry")); |
|
1451 const TInt KNumInterfacesOffset(4); |
|
1452 |
|
1453 TInt descriptorSize(0); |
|
1454 iLdd.GetConfigurationDescriptorSize(descriptorSize); |
|
1455 |
|
1456 if (static_cast<TUint>(descriptorSize) != KUsbDescSize_Config) |
|
1457 { |
|
1458 User::Leave(KErrCorrupt); |
|
1459 } |
|
1460 |
|
1461 TBuf8<KUsbDescSize_Config> descriptor; |
|
1462 User::LeaveIfError(iLdd.GetConfigurationDescriptor(descriptor)); |
|
1463 ++descriptor[KNumInterfacesOffset]; |
|
1464 User::LeaveIfError(iLdd.SetConfigurationDescriptor(descriptor)); |
|
1465 |
|
1466 __FLOG(_L8("SetupConfigurationDescriptorL - Exit")); |
|
1467 } |
|
1468 |
|
1469 /** |
|
1470 Indicates whether the connection state is closed. |
|
1471 */ |
|
1472 TBool CMTPUsbConnection::ConnectionClosed() const |
|
1473 { |
|
1474 return (ConnectionState() < EOpen); |
|
1475 } |
|
1476 |
|
1477 /** |
|
1478 Indicates whether the connection state is open. |
|
1479 */ |
|
1480 TBool CMTPUsbConnection::ConnectionOpen() const |
|
1481 { |
|
1482 return (!ConnectionClosed()); |
|
1483 } |
|
1484 |
|
1485 /** |
|
1486 Starts data transfer activity on the control endpoint. |
|
1487 @leave One of the system wide error codes, if a processing failure occurs. |
|
1488 */ |
|
1489 void CMTPUsbConnection::ControlEndpointStartL() |
|
1490 { |
|
1491 __FLOG(_L8("StartControlEndpoint - Entry")); |
|
1492 InitiateControlRequestSequenceL(); |
|
1493 __FLOG(_L8("StartControlEndpoint - Exit")); |
|
1494 } |
|
1495 |
|
1496 /** |
|
1497 Stops data transfer activity on the control endpoint. |
|
1498 */ |
|
1499 void CMTPUsbConnection::ControlEndpointStop() |
|
1500 { |
|
1501 __FLOG(_L8("ControlEndpointStop - Entry")); |
|
1502 iEndpoints[EMTPUsbEpControl]->Cancel(); |
|
1503 __FLOG(_L8("ControlEndpointStop - Exit")); |
|
1504 } |
|
1505 |
|
1506 /** |
|
1507 Stalls all but the control endpoint. |
|
1508 */ |
|
1509 void CMTPUsbConnection::BulkEndpointsStallL() |
|
1510 { |
|
1511 __FLOG(_L8("BulkEndpointsStallL - Entry")); |
|
1512 EndpointStallL(EMTPUsbEpBulkIn); |
|
1513 EndpointStallL(EMTPUsbEpBulkOut); |
|
1514 SetDeviceStatus(EMTPUsbDeviceStatusTransactionCancelled); |
|
1515 __FLOG(_L8("BulkEndpointsStallL - Exit")); |
|
1516 } |
|
1517 |
|
1518 /** |
|
1519 Clears stall conditions all but the control endpoint. |
|
1520 */ |
|
1521 void CMTPUsbConnection::BulkEndpointsStallClearL() |
|
1522 { |
|
1523 __FLOG(_L8("BulkEndpointsStallClearL - Entry")); |
|
1524 EndpointStallClearL(EMTPUsbEpBulkIn); |
|
1525 EndpointStallClearL(EMTPUsbEpBulkOut); |
|
1526 SetDeviceStatus(EMTPUsbDeviceStatusOK); |
|
1527 __FLOG(_L8("BulkEndpointsStallClearL - Exit")); |
|
1528 } |
|
1529 |
|
1530 /** |
|
1531 Starts data transfer activity on the data endpoints. |
|
1532 @leave One of the system wide error codes, if a processing failure occurs. |
|
1533 */ |
|
1534 void CMTPUsbConnection::DataEndpointsStartL() |
|
1535 { |
|
1536 __FLOG(_L8("DataEndpointsStartL - Entry")); |
|
1537 InitiateBulkRequestSequenceL(); |
|
1538 __FLOG(_L8("DataEndpointsStartL - Exit")); |
|
1539 } |
|
1540 |
|
1541 /** |
|
1542 Stops data transfer activity on all but the control endpoint. |
|
1543 */ |
|
1544 void CMTPUsbConnection::DataEndpointsStop() |
|
1545 { |
|
1546 __FLOG(_L8("DataEndpointsStop - Entry")); |
|
1547 if (ConnectionOpen() && (!(SuspendState() & ESuspended))&& (iControllerStatePrevious != EUsbcDeviceStateSuspended)) |
|
1548 { |
|
1549 __FLOG(_L8("Stopping active endpoints")); |
|
1550 iEndpoints[EMTPUsbEpBulkIn]->Cancel(); |
|
1551 iEndpoints[EMTPUsbEpBulkOut]->Cancel(); |
|
1552 iEndpoints[EMTPUsbEpInterrupt]->Cancel(); |
|
1553 if ((iBulkTransactionState == EDataIToRPhase) && iUsbBulkContainer->Payload()) |
|
1554 { |
|
1555 __FLOG(_L8("Aborting active I to R data phase")); |
|
1556 TRAPD(err, BoundProtocolLayer().ReceiveDataCompleteL(KErrAbort, *iUsbBulkContainer->Payload(), iMTPRequest)); |
|
1557 UNUSED_VAR(err); |
|
1558 } |
|
1559 else if ((iBulkTransactionState == EDataRToIPhase) && iUsbBulkContainer->Payload()) |
|
1560 { |
|
1561 __FLOG(_L8("Aborting active R to I data phase")); |
|
1562 TRAPD(err, BoundProtocolLayer().SendDataCompleteL(KErrAbort, *iUsbBulkContainer->Payload(), iMTPRequest)); |
|
1563 UNUSED_VAR(err); |
|
1564 } |
|
1565 } |
|
1566 #ifdef __FLOG_ACTIVE |
|
1567 else |
|
1568 { |
|
1569 __FLOG(_L8("Endpoints inactive, do nothing")); |
|
1570 } |
|
1571 #endif // __FLOG_ACTIVE |
|
1572 __FLOG(_L8("DataEndpointsStop - Exit")); |
|
1573 } |
|
1574 |
|
1575 void CMTPUsbConnection::EndpointStallL(TMTPUsbEndpointId aId) |
|
1576 { |
|
1577 __FLOG(_L8("EndpointStallL - Entry")); |
|
1578 __FLOG_VA((_L8("Creating stall condition on endpoint %d"), aId)); |
|
1579 __ASSERT_DEBUG((aId < EMTPUsbEpNumEndpoints), Panic(EMTPUsbReserved)); |
|
1580 |
|
1581 // Stall the endpoint. |
|
1582 CMTPUsbEpBase& ep(*iEndpoints[aId]); |
|
1583 ep.Stall(); |
|
1584 |
|
1585 // Stop the connection. |
|
1586 StopConnection(); |
|
1587 |
|
1588 // Update the connection state. |
|
1589 if (!(ConnectionState() & EStalled)) |
|
1590 { |
|
1591 SetConnectionState(EStalled); |
|
1592 } |
|
1593 __FLOG(_L8("EndpointStallL - Exit")); |
|
1594 } |
|
1595 |
|
1596 void CMTPUsbConnection::EndpointStallClearL(TMTPUsbEndpointId aId) |
|
1597 { |
|
1598 __FLOG(_L8("EndpointStallClearL - Entry")); |
|
1599 __FLOG_VA((_L8("Clearing stall condition on endpoint %d"), aId)); |
|
1600 __ASSERT_DEBUG((aId < EMTPUsbEpNumEndpoints), Panic(EMTPUsbReserved)); |
|
1601 |
|
1602 // Check the endoints current stall condition. |
|
1603 CMTPUsbEpBase& ep(*iEndpoints[aId]); |
|
1604 if ( IsEpStalled( aId ) ) |
|
1605 { |
|
1606 // Clear the stalled endpoint. |
|
1607 ep.StallClear(); |
|
1608 |
|
1609 // Update the device status. |
|
1610 if ((aId == EMTPUsbEpControl) && |
|
1611 ((iControllerStateCurrent == EUsbcDeviceStateAddress) || |
|
1612 (iControllerStateCurrent == EUsbcDeviceStateConfigured))) |
|
1613 { |
|
1614 // Control endpoint stall cleared on an active connection. |
|
1615 InitiateControlRequestSequenceL(); |
|
1616 } |
|
1617 else if (!IsEpStalled( aId ) ) |
|
1618 { |
|
1619 // All data endpoint stall conditions are clear. |
|
1620 SetConnectionState(EIdlePhase); |
|
1621 } |
|
1622 } |
|
1623 __FLOG(_L8("EndpointStallClearL - Exit")); |
|
1624 } |
|
1625 |
|
1626 /** |
|
1627 Resumes USB MTP device class processing. |
|
1628 @leave One of the system wide error codes, if a processing failure occurs. |
|
1629 */ |
|
1630 void CMTPUsbConnection::ResumeConnectionL() |
|
1631 { |
|
1632 __FLOG(_L8("ResumeConnectionL - Entry")); |
|
1633 if (ConnectionOpen()) |
|
1634 { |
|
1635 // Restart data transfer activity. |
|
1636 ControlEndpointStartL(); |
|
1637 DataEndpointsStartL(); |
|
1638 } |
|
1639 __FLOG(_L8("ResumeConnectionL - Exit")); |
|
1640 } |
|
1641 |
|
1642 /** |
|
1643 Initiates USB MTP device class processing. |
|
1644 @leave One of the system wide error codes, if a processing failure occurs. |
|
1645 */ |
|
1646 void CMTPUsbConnection::StartConnectionL() |
|
1647 { |
|
1648 __FLOG(_L8("StartConnectionL - Entry")); |
|
1649 |
|
1650 // Notify the connection manager and update state, if necessary. |
|
1651 if (ConnectionClosed()) |
|
1652 { |
|
1653 __FLOG(_L8("Notifying protocol layer connection opened")); |
|
1654 iConnectionMgr->ConnectionOpenedL(*this); |
|
1655 SetConnectionState(EOpen); |
|
1656 InitiateBulkRequestSequenceL(); |
|
1657 } |
|
1658 __FLOG(_L8("StartConnectionL - Exit")); |
|
1659 } |
|
1660 |
|
1661 /** |
|
1662 Halts USB MTP device class processing. |
|
1663 */ |
|
1664 void CMTPUsbConnection::StopConnection() |
|
1665 { |
|
1666 __FLOG(_L8("StopConnection - Entry")); |
|
1667 |
|
1668 // Stop all data transfer activity. |
|
1669 DataEndpointsStop(); |
|
1670 |
|
1671 // Notify the connection manager and update state, if necessary. |
|
1672 if (ConnectionOpen()) |
|
1673 { |
|
1674 __FLOG(_L8("Notifying protocol layer connection closed")); |
|
1675 iConnectionMgr->ConnectionClosed(*this); |
|
1676 SetBulkTransactionState(EUndefined); |
|
1677 SetConnectionState(EIdle); |
|
1678 SetSuspendState(ENotSuspended); |
|
1679 } |
|
1680 |
|
1681 __FLOG(_L8("StopConnection - Exit")); |
|
1682 } |
|
1683 |
|
1684 /** |
|
1685 Suspends USB MTP device class processing. |
|
1686 @leave One of the system wide error codes, if a processing failure occurs. |
|
1687 */ |
|
1688 void CMTPUsbConnection::SuspendConnectionL() |
|
1689 { |
|
1690 __FLOG(_L8("SuspendConnectionL - Entry")); |
|
1691 if (ConnectionOpen()) |
|
1692 { |
|
1693 // Stop all data transfer activity. |
|
1694 DataEndpointsStop(); |
|
1695 } |
|
1696 ControlEndpointStop(); |
|
1697 |
|
1698 // Update state. |
|
1699 SetSuspendState(ESuspended); |
|
1700 __FLOG(_L8("SuspendConnectionL - Exit")); |
|
1701 } |
|
1702 |
|
1703 /** |
|
1704 Configures the USB MTP device class. |
|
1705 @leave One of the system wide error codes, if a processing failure occurs. |
|
1706 */ |
|
1707 void CMTPUsbConnection::StartUsbL() |
|
1708 { |
|
1709 __FLOG(_L8("StartUsbL - Exit")); |
|
1710 |
|
1711 // Open the USB device interface. |
|
1712 User::LeaveIfError(iLdd.Open(KDefaultUsbClientController)); |
|
1713 |
|
1714 // Configure the class descriptors. |
|
1715 ConfigurationDescriptorSetL(); |
|
1716 SetInterfaceDescriptorL(); |
|
1717 |
|
1718 __FLOG(_L8("StartUsbL - Exit")); |
|
1719 } |
|
1720 |
|
1721 /** |
|
1722 This method stops the end points transfer. |
|
1723 */ |
|
1724 void CMTPUsbConnection::StopUsb() |
|
1725 { |
|
1726 __FLOG(_L8("StopUsb - Entry")); |
|
1727 // Stop monitoring the USB device controller state. |
|
1728 iLdd.AlternateDeviceStatusNotifyCancel(); |
|
1729 |
|
1730 // Stop monitoring the USB device controller state. |
|
1731 Cancel(); |
|
1732 |
|
1733 // Clear the configuration descriptor. |
|
1734 ConfigurationDescriptorClear(); |
|
1735 |
|
1736 // Close the USB device interface. |
|
1737 iLdd.ReleaseInterface(KMTPUsbAlternateInterface); |
|
1738 iLdd.Close(); |
|
1739 |
|
1740 __FLOG(_L8("StopUsb - Exit")); |
|
1741 } |
|
1742 |
|
1743 /** |
|
1744 Provides the USB bulk container. |
|
1745 @return The USB bulk container |
|
1746 */ |
|
1747 CMTPUsbContainer& CMTPUsbConnection::BulkContainer() |
|
1748 { |
|
1749 return *iUsbBulkContainer; |
|
1750 } |
|
1751 |
|
1752 /** |
|
1753 Provides the current state of the USB MTP device class connection. |
|
1754 @return The current USB MTP device class connection state. |
|
1755 @see TConnectionState |
|
1756 */ |
|
1757 TInt32 CMTPUsbConnection::ConnectionState() const |
|
1758 { |
|
1759 TInt32 state(iState & EConnectionStateMask); |
|
1760 __FLOG_VA((_L8("Connection state = 0x%08X"), state)); |
|
1761 return (state); |
|
1762 } |
|
1763 |
|
1764 /** |
|
1765 Provides the current USB device suspend state.. |
|
1766 @return The current USB device suspend state. |
|
1767 @see TSuspendState |
|
1768 */ |
|
1769 TInt32 CMTPUsbConnection::SuspendState() const |
|
1770 { |
|
1771 TInt32 state(iState & ESuspendStateMask); |
|
1772 __FLOG_VA((_L8("Suspend state = 0x%08X"), state)); |
|
1773 |
|
1774 return (state); |
|
1775 } |
|
1776 |
|
1777 /** |
|
1778 Sets the bulk transfer transaction state. |
|
1779 @param aState The new connectio state bit flags. |
|
1780 @see TConnectionState |
|
1781 */ |
|
1782 void CMTPUsbConnection::SetBulkTransactionState(TMTPTransactionPhase aState) |
|
1783 { |
|
1784 __FLOG(_L8("SetBulkTransactionState - Entry")); |
|
1785 iBulkTransactionState = aState; |
|
1786 __FLOG_VA((_L8("SetBulkTransactionState state set to 0x%08X"), iBulkTransactionState)); |
|
1787 __FLOG(_L8("SetBulkTransactionState - Exit")); |
|
1788 } |
|
1789 |
|
1790 /** |
|
1791 Sets the MTP USB device class device status Code value. |
|
1792 @param aCode The PIMA 15740 Response Code or Vendor Code value. |
|
1793 */ |
|
1794 void CMTPUsbConnection::SetDeviceStatus(TUint16 aCode) |
|
1795 { |
|
1796 __FLOG(_L8("SetDeviceStatus - Entry")); |
|
1797 iDeviceStatusCode = aCode; |
|
1798 __FLOG_VA((_L8("Device status set to 0x%04X"), iDeviceStatusCode)); |
|
1799 __FLOG(_L8("SetDeviceStatus - Exit")); |
|
1800 } |
|
1801 |
|
1802 /** |
|
1803 Sets the USB MTP device class interface descriptor. |
|
1804 @leave KErrCorrupt, if the configuration descriptor size is invalid. |
|
1805 @leave One of the system wide error codes, if a processing failure occurs. |
|
1806 */ |
|
1807 void CMTPUsbConnection::SetInterfaceDescriptorL() |
|
1808 { |
|
1809 __FLOG(_L8("SetInterfaceDescriptorL - Entry")); |
|
1810 |
|
1811 TUsbcInterfaceInfoBuf ifc; |
|
1812 // Get device capabilities. |
|
1813 User::LeaveIfError(iLdd.DeviceCaps(iDeviceCaps)); |
|
1814 |
|
1815 // Fetch the endpoint capabilities set. |
|
1816 TPtr8 capsPtr(reinterpret_cast<TUint8*>(iEndpointCapSets), sizeof(iEndpointCapSets), sizeof(iEndpointCapSets)); |
|
1817 User::LeaveIfError(iLdd.EndpointCaps(capsPtr)); |
|
1818 // Set the interface endpoint properties. |
|
1819 for (TUint i(EMTPUsbEpBulkIn); (i < EMTPUsbEpNumEndpoints); i++) |
|
1820 { |
|
1821 // Fetch the endpoint capabilities and meta data. |
|
1822 const TUsbcEndpointCaps& caps(EndpointCapsL(i)); |
|
1823 const TEpInfo& info(iEndpointInfo[i]); |
|
1824 |
|
1825 // Define the endpoint properties. |
|
1826 const TUint idx(EndpointNumber(i) - 1); |
|
1827 ifc().iEndpointData[idx].iType = info.iType; |
|
1828 ifc().iEndpointData[idx].iFeatureWord1 = KUsbcEndpointInfoFeatureWord1_DMA|KUsbcEndpointInfoFeatureWord1_DoubleBuffering; |
|
1829 ifc().iEndpointData[idx].iDir = info.iDirection; |
|
1830 |
|
1831 //set endpoint maxpacketsize. |
|
1832 if (info.iType == KMTPUsbInterruptEpType) |
|
1833 { |
|
1834 //As default interface, interrupt endpoint maxpacketsize shall be up to 0x40 |
|
1835 ifc().iEndpointData[idx].iSize = KMaxPacketTypeInterrupt; |
|
1836 } |
|
1837 else |
|
1838 { |
|
1839 ifc().iEndpointData[idx].iSize = caps.MaxPacketSize(); |
|
1840 } |
|
1841 |
|
1842 ifc().iEndpointData[idx].iInterval = info.iInterval; |
|
1843 ifc().iEndpointData[idx].iInterval_Hs = info.iInterval_Hs; |
|
1844 } |
|
1845 |
|
1846 // Set the required interface descriptor values. |
|
1847 ifc().iString = const_cast<TDesC16*>(&KMTPUsbInterfaceString); |
|
1848 ifc().iClass.iClassNum = KMTPUsbInterfaceClassSIC; |
|
1849 ifc().iClass.iSubClassNum = KMTPUsbInterfaceSubClassSIC; |
|
1850 ifc().iClass.iProtocolNum = KMTPUsbInterfaceProtocolSIC; |
|
1851 ifc().iTotalEndpointsUsed = KMTPUsbRequiredNumEndpoints; |
|
1852 |
|
1853 // Allocate 512KB buffer for OUT EndPoint, and 64KB for IN EndPoint |
|
1854 TUint32 bandwidthPriority = EUsbcBandwidthINPlus2 | EUsbcBandwidthOUTMaximum; |
|
1855 |
|
1856 // Write the active interface descriptor. |
|
1857 User::LeaveIfError(iLdd.SetInterface(KMTPUsbAlternateInterface, ifc, bandwidthPriority)); |
|
1858 |
|
1859 __FLOG(_L8("SetInterfaceDescriptorL - Exit")); |
|
1860 } |
|
1861 |
|
1862 /** |
|
1863 Sets the USB MTP device class connection state. |
|
1864 @param aState The new connection state bit flags. |
|
1865 @see TConnectionState |
|
1866 */ |
|
1867 void CMTPUsbConnection::SetConnectionState(TInt32 aState) |
|
1868 { |
|
1869 __FLOG(_L8("SetConnectionState - Entry")); |
|
1870 iState = ((~EConnectionStateMask & iState) | aState); |
|
1871 __FLOG_VA((_L8("Connection state set to 0x%08X"), iState)); |
|
1872 __FLOG(_L8("SetConnectionState - Exit")); |
|
1873 } |
|
1874 |
|
1875 /** |
|
1876 Sets the USB device suspend state. |
|
1877 @param aState The new suspend state bit flags. |
|
1878 @see TSuspendState |
|
1879 */ |
|
1880 void CMTPUsbConnection::SetSuspendState(TInt32 aState) |
|
1881 { |
|
1882 __FLOG(_L8("SetSuspendState - Entry")); |
|
1883 iState = ((~ESuspendStateMask & iState) | aState); |
|
1884 __FLOG_VA((_L8("Connection state set to 0x%08X"), iState)); |
|
1885 __FLOG(_L8("SetSuspendState - Exit")); |
|
1886 } |
|
1887 |
|
1888 /** |
|
1889 This method is called when EUsbcDeviceStateAddress state is reached. |
|
1890 It sets the transport packet size based on the host type the device is |
|
1891 connected to. |
|
1892 */ |
|
1893 void CMTPUsbConnection::SetTransportPacketSizeL() |
|
1894 { |
|
1895 __FLOG(_L8("SetTransportPacketSizeL - Entry")); |
|
1896 if(iLdd.CurrentlyUsingHighSpeed()) |
|
1897 { |
|
1898 __FLOG(_L8("HS USB connection")); |
|
1899 iEndpoints[EMTPUsbEpControl]->SetMaxPacketSizeL(KMaxPacketTypeControlHS); |
|
1900 iEndpoints[EMTPUsbEpBulkIn]->SetMaxPacketSizeL(KMaxPacketTypeBulkHS); |
|
1901 iEndpoints[EMTPUsbEpBulkOut]->SetMaxPacketSizeL(KMaxPacketTypeBulkHS); |
|
1902 } |
|
1903 else |
|
1904 { |
|
1905 __FLOG(_L8("FS USB connection")); |
|
1906 iEndpoints[EMTPUsbEpControl]->SetMaxPacketSizeL(KMaxPacketTypeControlFS); |
|
1907 iEndpoints[EMTPUsbEpBulkIn]->SetMaxPacketSizeL(KMaxPacketTypeBulkFS); |
|
1908 iEndpoints[EMTPUsbEpBulkOut]->SetMaxPacketSizeL(KMaxPacketTypeBulkFS); |
|
1909 } |
|
1910 iEndpoints[EMTPUsbEpInterrupt]->SetMaxPacketSizeL(KMaxPacketTypeInterrupt); |
|
1911 |
|
1912 __FLOG(_L8("SetTransportPacketSizeL - Exit")); |
|
1913 } |
|
1914 |
|
1915 TBool CMTPUsbConnection::IsEpStalled(const TUint& aEpNumber) |
|
1916 { |
|
1917 const TEndpointNumber number( static_cast<TEndpointNumber>(aEpNumber) ); |
|
1918 TEndpointState state; |
|
1919 iLdd.EndpointStatus(number, state); |
|
1920 return ( EEndpointStateStalled == state ); |
|
1921 } |