| 0 |      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-
 |