os/kernelhwsrv/bsptemplate/asspandvariant/template_assp/pa_usbc.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// template\template_assp\pa_usbc.cpp
sl@0
    15
// Platform-dependent USB client controller layer (USB PSL).
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
sl@0
    20
#include <template_assp.h>									// /assp/template_assp/
sl@0
    21
#include <template_assp_priv.h>								// /assp/template_assp/
sl@0
    22
sl@0
    23
#include <drivers/usbc.h>
sl@0
    24
sl@0
    25
#include "pa_usbc.h"										// .
sl@0
    26
sl@0
    27
// Debug support
sl@0
    28
#ifdef _DEBUG
sl@0
    29
static const char KUsbPanicCat[] = "USB PSL";
sl@0
    30
#endif
sl@0
    31
sl@0
    32
sl@0
    33
// Define USB_SUPPORTS_PREMATURE_STATUS_IN to enable proper handling of a premature STATUS_IN stage, i.e. a
sl@0
    34
// situation where the host sends less data than first announced and instead of more data (OUT) will send an
sl@0
    35
// IN token to start the status stage. What we do in order to implement this here is to prime the TX fifo with
sl@0
    36
// a ZLP immediately when we find out that we're dealing with a DATA_OUT request. This way, as soon as the
sl@0
    37
// premature IN token is received, we complete the transaction by sending off the ZLP. If we don't prime the
sl@0
    38
// TX fifo then there is no way for us to recognise a premature status because the IN token itself doesn't
sl@0
    39
// raise an interrupt. We would simply wait forever for more data, or rather we would time out and the host
sl@0
    40
// would move on and send the next Setup packet.
sl@0
    41
// The reason why we would not want to implement the proper behaviour is this: After having primed the TX fifo
sl@0
    42
// with a ZLP, it is impossible for a user to reject such a (class/vendor specific) Setup request, basically
sl@0
    43
// because the successful status stage happens automatically. At the time the user has received and decoded
sl@0
    44
// the Setup request there's for her no way to stall Ep0 in order to show to the host that this Setup packet
sl@0
    45
// is invalid or inappropriate or whatever, because she cannot prevent the status stage from happening.
sl@0
    46
// (All this is strictly true only if the amount of data in the data stage is less than or equal to Ep0's max
sl@0
    47
//	packet size. However this is almost always the case.)
sl@0
    48
//#define USB_SUPPORTS_PREMATURE_STATUS_IN
sl@0
    49
sl@0
    50
sl@0
    51
static const TUsbcEndpointCaps DeviceEndpoints[KUsbTotalEndpoints] =
sl@0
    52
	{
sl@0
    53
	//                                                      Hardware #    iEndpoints index
sl@0
    54
	{KEp0MaxPktSzMask,	(KUsbEpTypeControl	   | KUsbEpDirOut)}, //	 0 -  0
sl@0
    55
	{KEp0MaxPktSzMask,	(KUsbEpTypeControl	   | KUsbEpDirIn )}, //	 0 -  1
sl@0
    56
	{KUsbEpNotAvailable, KUsbEpNotAvailable},				// --- Not present
sl@0
    57
	{KBlkMaxPktSzMask,	(KUsbEpTypeBulk		   | KUsbEpDirIn )}, //	 1 -  3
sl@0
    58
	{KBlkMaxPktSzMask,	(KUsbEpTypeBulk		   | KUsbEpDirOut)}, //	 2 -  4
sl@0
    59
	{KUsbEpNotAvailable, KUsbEpNotAvailable},				// --- Not present
sl@0
    60
	{KUsbEpNotAvailable, KUsbEpNotAvailable},				// --- Not present
sl@0
    61
	{KIsoMaxPktSzMask,	(KUsbEpTypeIsochronous | KUsbEpDirIn )}, //	 3 -  7
sl@0
    62
	{KIsoMaxPktSzMask,	(KUsbEpTypeIsochronous | KUsbEpDirOut)}, //	 4 -  8
sl@0
    63
	{KUsbEpNotAvailable, KUsbEpNotAvailable},				// --- Not present
sl@0
    64
	{KUsbEpNotAvailable, KUsbEpNotAvailable},				// --- Not present
sl@0
    65
	{KIntMaxPktSzMask,	(KUsbEpTypeInterrupt   | KUsbEpDirIn )}, //	 5 - 11
sl@0
    66
	};
sl@0
    67
sl@0
    68
sl@0
    69
// --- TEndpoint --------------------------------------------------------------
sl@0
    70
sl@0
    71
TEndpoint::TEndpoint()
sl@0
    72
//
sl@0
    73
// Constructor
sl@0
    74
//
sl@0
    75
	: iRxBuf(NULL), iReceived(0), iLength(0), iZlpReqd(EFalse), iNoBuffer(EFalse), iDisabled(EFalse),
sl@0
    76
	  iPackets(0), iLastError(KErrNone), iRequest(NULL), iRxTimer(RxTimerCallback, this),
sl@0
    77
	  iRxTimerSet(EFalse), iRxMoreDataRcvd(EFalse), iPacketIndex(NULL), iPacketSize(NULL)
sl@0
    78
	{
sl@0
    79
	__KTRACE_OPT(KUSB, Kern::Printf("TEndpoint::TEndpoint"));
sl@0
    80
	}
sl@0
    81
sl@0
    82
sl@0
    83
void TEndpoint::RxTimerCallback(TAny* aPtr)
sl@0
    84
//
sl@0
    85
// (This function is static.)
sl@0
    86
//
sl@0
    87
	{
sl@0
    88
	__KTRACE_OPT(KUSB, Kern::Printf("TEndpoint::RxTimerCallback"));
sl@0
    89
sl@0
    90
	TEndpoint* const ep = static_cast<TEndpoint*>(aPtr);
sl@0
    91
	if (!ep)
sl@0
    92
		{
sl@0
    93
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !ep"));
sl@0
    94
		}
sl@0
    95
	else if (!ep->iRxTimerSet)
sl@0
    96
		{
sl@0
    97
		// Timer 'stop' substitute (instead of stopping it,
sl@0
    98
		// we just let it expire after clearing iRxTimerSet)
sl@0
    99
		__KTRACE_OPT(KUSB, Kern::Printf("!ep->iRxTimerSet - returning"));
sl@0
   100
		}
sl@0
   101
	else if (!ep->iRxBuf)
sl@0
   102
		{
sl@0
   103
		// Request already completed
sl@0
   104
		__KTRACE_OPT(KUSB, Kern::Printf("!ep->iRxBuf - returning"));
sl@0
   105
		}
sl@0
   106
	else if (ep->iRxMoreDataRcvd)
sl@0
   107
		{
sl@0
   108
		__KTRACE_OPT(KUSB, Kern::Printf(" > rx timer cb: not yet completing..."));
sl@0
   109
		ep->iRxMoreDataRcvd = EFalse;
sl@0
   110
		ep->iRxTimer.Again(KRxTimerTimeout);
sl@0
   111
		}
sl@0
   112
	else
sl@0
   113
		{
sl@0
   114
		__KTRACE_OPT(KUSB, Kern::Printf(" > rx timer cb: completing now..."));
sl@0
   115
		*ep->iPacketSize = ep->iReceived;
sl@0
   116
		ep->iController->RxComplete(ep);
sl@0
   117
		}
sl@0
   118
	}
sl@0
   119
sl@0
   120
sl@0
   121
// --- TTemplateAsspUsbcc public ---------------------------------------------------
sl@0
   122
sl@0
   123
TTemplateAsspUsbcc::TTemplateAsspUsbcc()
sl@0
   124
//
sl@0
   125
// Constructor.
sl@0
   126
//
sl@0
   127
	: iCableConnected(ETrue), iBusIsPowered(EFalse),
sl@0
   128
	  iInitialized(EFalse), iUsbClientConnectorCallback(UsbClientConnectorCallback),
sl@0
   129
	  iEp0Configured(EFalse)
sl@0
   130
	{
sl@0
   131
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::TTemplateAsspUsbcc"));
sl@0
   132
sl@0
   133
	iAssp = static_cast<TemplateAssp*>(Arch::TheAsic());
sl@0
   134
sl@0
   135
	iSoftwareConnectable = iAssp->UsbSoftwareConnectable();
sl@0
   136
sl@0
   137
	iCableDetectable = iAssp->UsbClientConnectorDetectable();
sl@0
   138
sl@0
   139
	if (iCableDetectable)
sl@0
   140
		{
sl@0
   141
		// Register our callback for detecting USB cable insertion/removal.
sl@0
   142
		// We ignore the error code: if the registration fails, we just won't get any events.
sl@0
   143
		// (Which of course is bad enough...)
sl@0
   144
		(void) iAssp->RegisterUsbClientConnectorCallback(iUsbClientConnectorCallback, this);
sl@0
   145
		// Call the callback straight away so we get the proper PIL state from the beginning.
sl@0
   146
		(void) UsbClientConnectorCallback(this);
sl@0
   147
		}
sl@0
   148
sl@0
   149
	for (TInt i = 0; i < KUsbTotalEndpoints; i++)
sl@0
   150
		{
sl@0
   151
		iEndpoints[i].iController = this;
sl@0
   152
		}
sl@0
   153
	}
sl@0
   154
sl@0
   155
sl@0
   156
TInt TTemplateAsspUsbcc::Construct()
sl@0
   157
//
sl@0
   158
// Construct.
sl@0
   159
//
sl@0
   160
	{
sl@0
   161
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Construct"));
sl@0
   162
sl@0
   163
	TUsbcDeviceDescriptor* DeviceDesc = TUsbcDeviceDescriptor::New(
sl@0
   164
		0x00,												// aDeviceClass
sl@0
   165
		0x00,												// aDeviceSubClass
sl@0
   166
		0x00,												// aDeviceProtocol
sl@0
   167
		KEp0MaxPktSz,										// aMaxPacketSize0
sl@0
   168
		KUsbVendorId,										// aVendorId
sl@0
   169
		KUsbProductId,										// aProductId
sl@0
   170
		KUsbDevRelease,										// aDeviceRelease
sl@0
   171
		1);													// aNumConfigurations
sl@0
   172
	if (!DeviceDesc)
sl@0
   173
		{
sl@0
   174
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for dev desc failed."));
sl@0
   175
		return KErrGeneral;
sl@0
   176
		}
sl@0
   177
sl@0
   178
	TUsbcConfigDescriptor* ConfigDesc = TUsbcConfigDescriptor::New(
sl@0
   179
		1,													// aConfigurationValue
sl@0
   180
		ETrue,												// aSelfPowered (see 12.4.2 "Bus-Powered Devices")
sl@0
   181
		ETrue,												// aRemoteWakeup
sl@0
   182
		0);													// aMaxPower (mA)
sl@0
   183
	if (!ConfigDesc)
sl@0
   184
		{
sl@0
   185
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for config desc failed."));
sl@0
   186
		return KErrGeneral;
sl@0
   187
		}
sl@0
   188
sl@0
   189
	TUsbcLangIdDescriptor* StringDescLang = TUsbcLangIdDescriptor::New(KUsbLangId);
sl@0
   190
	if (!StringDescLang)
sl@0
   191
		{
sl@0
   192
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for lang id $ desc failed."));
sl@0
   193
		return KErrGeneral;
sl@0
   194
		}
sl@0
   195
sl@0
   196
	// ('sizeof(x) - 2' because 'wchar_t KStringXyz' created a wide string that ends in '\0\0'.)
sl@0
   197
sl@0
   198
	TUsbcStringDescriptor* StringDescManu =
sl@0
   199
		TUsbcStringDescriptor::New(TPtr8(
sl@0
   200
									   const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringManufacturer)),
sl@0
   201
									   sizeof(KStringManufacturer) - 2, sizeof(KStringManufacturer) - 2));
sl@0
   202
	if (!StringDescManu)
sl@0
   203
		{
sl@0
   204
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for manufacturer $ desc failed."));
sl@0
   205
		return KErrGeneral;
sl@0
   206
		}
sl@0
   207
sl@0
   208
	TUsbcStringDescriptor* StringDescProd =
sl@0
   209
		TUsbcStringDescriptor::New(TPtr8(
sl@0
   210
									   const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringProduct)),
sl@0
   211
									   sizeof(KStringProduct) - 2, sizeof(KStringProduct) - 2));
sl@0
   212
	if (!StringDescProd)
sl@0
   213
		{
sl@0
   214
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for product $ desc failed."));
sl@0
   215
		return KErrGeneral;
sl@0
   216
		}
sl@0
   217
sl@0
   218
	TUsbcStringDescriptor* StringDescSer =
sl@0
   219
		TUsbcStringDescriptor::New(TPtr8(
sl@0
   220
									   const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringSerialNo)),
sl@0
   221
									   sizeof(KStringSerialNo) - 2, sizeof(KStringSerialNo) - 2));
sl@0
   222
	if (!StringDescSer)
sl@0
   223
		{
sl@0
   224
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for serial no $ desc failed."));
sl@0
   225
		return KErrGeneral;
sl@0
   226
		}
sl@0
   227
sl@0
   228
	TUsbcStringDescriptor* StringDescConf =
sl@0
   229
		TUsbcStringDescriptor::New(TPtr8(
sl@0
   230
									   const_cast<TUint8*>(reinterpret_cast<const TUint8*>(KStringConfig)),
sl@0
   231
									   sizeof(KStringConfig) - 2, sizeof(KStringConfig) - 2));
sl@0
   232
	if (!StringDescConf)
sl@0
   233
		{
sl@0
   234
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for config $ desc failed."));
sl@0
   235
		return KErrGeneral;
sl@0
   236
		}
sl@0
   237
sl@0
   238
	const TBool r =	InitialiseBaseClass(DeviceDesc,
sl@0
   239
										ConfigDesc,
sl@0
   240
										StringDescLang,
sl@0
   241
										StringDescManu,
sl@0
   242
										StringDescProd,
sl@0
   243
										StringDescSer,
sl@0
   244
										StringDescConf);
sl@0
   245
	if (!r)
sl@0
   246
		{
sl@0
   247
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: UsbClientController::InitialiseBaseClass failed."));
sl@0
   248
		return KErrGeneral;
sl@0
   249
		}
sl@0
   250
sl@0
   251
	return KErrNone;
sl@0
   252
	}
sl@0
   253
sl@0
   254
sl@0
   255
TTemplateAsspUsbcc::~TTemplateAsspUsbcc()
sl@0
   256
//
sl@0
   257
// Destructor.
sl@0
   258
//
sl@0
   259
	{
sl@0
   260
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::~TTemplateAsspUsbcc"));
sl@0
   261
sl@0
   262
	// Unregister our callback for detecting USB cable insertion/removal
sl@0
   263
	if (iCableDetectable)
sl@0
   264
		{
sl@0
   265
		iAssp->UnregisterUsbClientConnectorCallback();
sl@0
   266
		}
sl@0
   267
	if (iInitialized)
sl@0
   268
		{
sl@0
   269
		// (The explicit scope operator is used against Lint warning #1506.)
sl@0
   270
		TTemplateAsspUsbcc::StopUdc();
sl@0
   271
		}
sl@0
   272
	}
sl@0
   273
sl@0
   274
sl@0
   275
TBool TTemplateAsspUsbcc::DeviceStateChangeCaps() const
sl@0
   276
//
sl@0
   277
// Returns capability of hardware to accurately track the device state (Chapter 9 state).
sl@0
   278
//
sl@0
   279
	{
sl@0
   280
	// TO DO: Return EFalse or ETrue here, depending on whether the UDC supports exact device state tracking
sl@0
   281
	// (most don't).
sl@0
   282
	return EFalse;
sl@0
   283
	}
sl@0
   284
sl@0
   285
sl@0
   286
TInt TTemplateAsspUsbcc::SignalRemoteWakeup()
sl@0
   287
//
sl@0
   288
// Forces the UDC into a non-idle state to perform a remote wakeup operation.
sl@0
   289
//
sl@0
   290
	{
sl@0
   291
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SignalRemoteWakeup"));
sl@0
   292
sl@0
   293
	// TO DO: Do here whatever is necessary for the UDC to signal remote wakeup.
sl@0
   294
	
sl@0
   295
	return KErrNone;
sl@0
   296
	}
sl@0
   297
sl@0
   298
sl@0
   299
void TTemplateAsspUsbcc::DumpRegisters()
sl@0
   300
//
sl@0
   301
// Dumps the contents of a number of UDC registers to the screen (using Kern::Printf()).
sl@0
   302
// Rarely used, but might prove helpful when needed.
sl@0
   303
//
sl@0
   304
	{
sl@0
   305
	Kern::Printf("TCotullaUsbcc::DumpRegisters:");
sl@0
   306
sl@0
   307
	// TO DO: Print the contents of some (or all) UDC registers here.
sl@0
   308
	}
sl@0
   309
sl@0
   310
sl@0
   311
TDfcQue* TTemplateAsspUsbcc::DfcQ(TInt /* aUnit */)
sl@0
   312
//
sl@0
   313
// Returns a pointer to the kernel DFC queue to be used buy the USB LDD.
sl@0
   314
//
sl@0
   315
	{
sl@0
   316
	return Kern::DfcQue0();
sl@0
   317
	}
sl@0
   318
sl@0
   319
sl@0
   320
// --- TTemplateAsspUsbcc private virtual ------------------------------------------
sl@0
   321
sl@0
   322
TInt TTemplateAsspUsbcc::SetDeviceAddress(TInt aAddress)
sl@0
   323
//
sl@0
   324
// Sets the PIL-provided device address manually (if possible - otherwise do nothing).
sl@0
   325
//
sl@0
   326
	{
sl@0
   327
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetDeviceAddress: %d", aAddress));
sl@0
   328
sl@0
   329
	// TO DO (optional): Set device address here.
sl@0
   330
sl@0
   331
	if (aAddress)
sl@0
   332
		{
sl@0
   333
		// Address can be zero.
sl@0
   334
		MoveToAddressState();
sl@0
   335
		}
sl@0
   336
sl@0
   337
	return KErrNone;
sl@0
   338
	}
sl@0
   339
sl@0
   340
sl@0
   341
TInt TTemplateAsspUsbcc::ConfigureEndpoint(TInt aRealEndpoint, const TUsbcEndpointInfo& aEndpointInfo)
sl@0
   342
//
sl@0
   343
// Prepares (enables) an endpoint (incl. Ep0) for data transmission or reception.
sl@0
   344
//
sl@0
   345
	{
sl@0
   346
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ConfigureEndpoint(%d)", aRealEndpoint));
sl@0
   347
sl@0
   348
	const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
sl@0
   349
	if (n < 0)
sl@0
   350
		return KErrArgument;
sl@0
   351
sl@0
   352
	TEndpoint* const ep = &iEndpoints[aRealEndpoint];
sl@0
   353
	if (ep->iDisabled == EFalse)
sl@0
   354
		{
sl@0
   355
		EnableEndpointInterrupt(n);
sl@0
   356
		}
sl@0
   357
	ep->iNoBuffer = EFalse;
sl@0
   358
	if (n == 0)
sl@0
   359
		iEp0Configured = ETrue;
sl@0
   360
sl@0
   361
	return KErrNone;
sl@0
   362
	}
sl@0
   363
sl@0
   364
sl@0
   365
TInt TTemplateAsspUsbcc::DeConfigureEndpoint(TInt aRealEndpoint)
sl@0
   366
//
sl@0
   367
// Disables an endpoint (incl. Ep0).
sl@0
   368
//
sl@0
   369
	{
sl@0
   370
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeConfigureEndpoint(%d)", aRealEndpoint));
sl@0
   371
sl@0
   372
	const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
sl@0
   373
	if (n < 0)
sl@0
   374
		return KErrArgument;
sl@0
   375
sl@0
   376
	DisableEndpointInterrupt(n);
sl@0
   377
	if (n == 0)
sl@0
   378
		iEp0Configured = EFalse;
sl@0
   379
sl@0
   380
	return KErrNone;
sl@0
   381
	}
sl@0
   382
sl@0
   383
sl@0
   384
TInt TTemplateAsspUsbcc::AllocateEndpointResource(TInt aRealEndpoint, TUsbcEndpointResource aResource)
sl@0
   385
//
sl@0
   386
// Puts the requested endpoint resource to use, if possible.
sl@0
   387
//
sl@0
   388
	{
sl@0
   389
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::AllocateEndpointResource(%d): %d",
sl@0
   390
									aRealEndpoint, aResource));
sl@0
   391
sl@0
   392
	// TO DO: Allocate endpoint resource here.
sl@0
   393
sl@0
   394
	return KErrNone;
sl@0
   395
	}
sl@0
   396
sl@0
   397
sl@0
   398
TInt TTemplateAsspUsbcc::DeAllocateEndpointResource(TInt aRealEndpoint, TUsbcEndpointResource aResource)
sl@0
   399
//
sl@0
   400
// Stops the use of the indicated endpoint resource, if beneficial.
sl@0
   401
//
sl@0
   402
	{
sl@0
   403
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeAllocateEndpointResource(%d): %d",
sl@0
   404
									aRealEndpoint, aResource));
sl@0
   405
sl@0
   406
	// TO DO: Deallocate endpoint resource here.
sl@0
   407
sl@0
   408
	return KErrNone;
sl@0
   409
	}
sl@0
   410
sl@0
   411
sl@0
   412
TBool TTemplateAsspUsbcc::QueryEndpointResource(TInt aRealEndpoint, TUsbcEndpointResource aResource) const
sl@0
   413
//
sl@0
   414
// Returns the status of the indicated resource and endpoint.
sl@0
   415
//
sl@0
   416
	{
sl@0
   417
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::QueryEndpointResource(%d): %d",
sl@0
   418
									aRealEndpoint, aResource));
sl@0
   419
sl@0
   420
	// TO DO: Query endpoint resource here. The return value should reflect the actual state.
sl@0
   421
	return ETrue;
sl@0
   422
	}
sl@0
   423
sl@0
   424
sl@0
   425
TInt TTemplateAsspUsbcc::OpenDmaChannel(TInt aRealEndpoint)
sl@0
   426
//
sl@0
   427
// Opens a DMA channel for this endpoint. This function is always called during the creation of an endpoint
sl@0
   428
// in the PIL. If DMA channels are a scarce resource, it's possible to do nothing here and wait for an
sl@0
   429
// AllocateEndpointResource call instead.
sl@0
   430
//
sl@0
   431
	{
sl@0
   432
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::OpenDmaChannel(%d)", aRealEndpoint));
sl@0
   433
sl@0
   434
	// TO DO (optional): Open DMA channel here.
sl@0
   435
sl@0
   436
	// An error should only  be returned in case of an actual DMA problem.
sl@0
   437
	return KErrNone;
sl@0
   438
	}
sl@0
   439
sl@0
   440
sl@0
   441
void TTemplateAsspUsbcc::CloseDmaChannel(TInt aRealEndpoint)
sl@0
   442
//
sl@0
   443
// Closes a DMA channel for this endpoint. This function is always called during the destruction of an
sl@0
   444
// endpoint in the PIL.
sl@0
   445
//
sl@0
   446
	{
sl@0
   447
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::CloseDmaChannel(%d)", aRealEndpoint));
sl@0
   448
sl@0
   449
	// TO DO (optional): Close DMA channel here (only if it was opened via OpenDmaChannel).
sl@0
   450
	}
sl@0
   451
sl@0
   452
sl@0
   453
TInt TTemplateAsspUsbcc::SetupEndpointRead(TInt aRealEndpoint, TUsbcRequestCallback& aCallback)
sl@0
   454
//
sl@0
   455
// Sets up a read request for an endpoint on behalf of the LDD.
sl@0
   456
//
sl@0
   457
	{
sl@0
   458
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointRead(%d)", aRealEndpoint));
sl@0
   459
sl@0
   460
	if (!IS_OUT_ENDPOINT(aRealEndpoint))
sl@0
   461
		{
sl@0
   462
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !IS_OUT_ENDPOINT(%d)", aRealEndpoint));
sl@0
   463
		return KErrArgument;
sl@0
   464
		}
sl@0
   465
	TEndpoint* const ep = &iEndpoints[aRealEndpoint];
sl@0
   466
	if (ep->iRxBuf != NULL)
sl@0
   467
		{
sl@0
   468
		__KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iRxBuf != NULL", aRealEndpoint));
sl@0
   469
		return KErrGeneral;
sl@0
   470
		}
sl@0
   471
	ep->iRxBuf = aCallback.iBufferStart;
sl@0
   472
	ep->iReceived = 0;
sl@0
   473
	ep->iLength = aCallback.iLength;
sl@0
   474
	// For Bulk reads we start out with the assumption of 1 packet (see BulkReceive for why):
sl@0
   475
	ep->iPackets = IS_BULK_OUT_ENDPOINT(aRealEndpoint) ? 1 : 0;
sl@0
   476
	ep->iRequest = &aCallback;
sl@0
   477
	ep->iPacketIndex = aCallback.iPacketIndex;
sl@0
   478
	if (IS_BULK_OUT_ENDPOINT(aRealEndpoint))
sl@0
   479
		*ep->iPacketIndex = 0;								// a one-off optimization
sl@0
   480
	ep->iPacketSize = aCallback.iPacketSize;
sl@0
   481
sl@0
   482
	const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
sl@0
   483
	if (ep->iDisabled)
sl@0
   484
		{
sl@0
   485
		ep->iDisabled = EFalse;
sl@0
   486
		EnableEndpointInterrupt(n);
sl@0
   487
		}
sl@0
   488
	else if (ep->iNoBuffer)
sl@0
   489
		{
sl@0
   490
		__KTRACE_OPT(KUSB, Kern::Printf(" > There had been no Rx buffer available: reading Rx FIFO now"));
sl@0
   491
		ep->iNoBuffer = EFalse;
sl@0
   492
		if (IS_BULK_OUT_ENDPOINT(aRealEndpoint))
sl@0
   493
			{
sl@0
   494
			BulkReadRxFifo(n);
sl@0
   495
			}
sl@0
   496
		else if (IS_ISO_OUT_ENDPOINT(aRealEndpoint))
sl@0
   497
			{
sl@0
   498
			IsoReadRxFifo(n);
sl@0
   499
			}
sl@0
   500
		else
sl@0
   501
			{
sl@0
   502
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint not found"));
sl@0
   503
			}
sl@0
   504
		}
sl@0
   505
sl@0
   506
	return KErrNone;
sl@0
   507
	}
sl@0
   508
sl@0
   509
sl@0
   510
TInt TTemplateAsspUsbcc::SetupEndpointWrite(TInt aRealEndpoint, TUsbcRequestCallback& aCallback)
sl@0
   511
//
sl@0
   512
// Sets up a write request for an endpoint on behalf of the LDD.
sl@0
   513
//
sl@0
   514
	{
sl@0
   515
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointWrite(%d)", aRealEndpoint));
sl@0
   516
sl@0
   517
	if (!IS_IN_ENDPOINT(aRealEndpoint))
sl@0
   518
		{
sl@0
   519
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !IS_IN_ENDPOINT(%d)", aRealEndpoint));
sl@0
   520
		return KErrArgument;
sl@0
   521
		}
sl@0
   522
	TEndpoint* const ep = &iEndpoints[aRealEndpoint];
sl@0
   523
	if (ep->iTxBuf != NULL)
sl@0
   524
		{
sl@0
   525
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: iEndpoints[%d].iTxBuf != NULL", aRealEndpoint));
sl@0
   526
		return KErrGeneral;
sl@0
   527
		}
sl@0
   528
	ep->iTxBuf = aCallback.iBufferStart;
sl@0
   529
	ep->iTransmitted = 0;
sl@0
   530
	ep->iLength = aCallback.iLength;
sl@0
   531
	ep->iPackets = 0;
sl@0
   532
	ep->iZlpReqd = aCallback.iZlpReqd;
sl@0
   533
	ep->iRequest = &aCallback;
sl@0
   534
sl@0
   535
	const TInt n = ArrayIdx2TemplateEp(aRealEndpoint);
sl@0
   536
	if (IS_BULK_IN_ENDPOINT(aRealEndpoint))
sl@0
   537
		{
sl@0
   538
		if (ep->iDisabled)
sl@0
   539
			{
sl@0
   540
			ep->iDisabled = EFalse;
sl@0
   541
			EnableEndpointInterrupt(n);
sl@0
   542
			}
sl@0
   543
		BulkTransmit(n);
sl@0
   544
		}
sl@0
   545
	else if (IS_ISO_IN_ENDPOINT(aRealEndpoint))
sl@0
   546
		{
sl@0
   547
		IsoTransmit(n);
sl@0
   548
		}
sl@0
   549
	else if (IS_INT_IN_ENDPOINT(aRealEndpoint))
sl@0
   550
		{
sl@0
   551
		IntTransmit(n);
sl@0
   552
		}
sl@0
   553
	else
sl@0
   554
		{
sl@0
   555
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint not found"));
sl@0
   556
		}
sl@0
   557
sl@0
   558
	return KErrNone;
sl@0
   559
	}
sl@0
   560
sl@0
   561
sl@0
   562
TInt TTemplateAsspUsbcc::CancelEndpointRead(TInt aRealEndpoint)
sl@0
   563
//
sl@0
   564
// Cancels a read request for an endpoint on behalf of the LDD.
sl@0
   565
// No completion to the PIL occurs.
sl@0
   566
//
sl@0
   567
	{
sl@0
   568
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::CancelEndpointRead(%d)", aRealEndpoint));
sl@0
   569
sl@0
   570
	if (!IS_OUT_ENDPOINT(aRealEndpoint))
sl@0
   571
		{
sl@0
   572
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !IS_OUT_ENDPOINT(%d)", aRealEndpoint));
sl@0
   573
		return KErrArgument;
sl@0
   574
		}
sl@0
   575
	TEndpoint* const ep = &iEndpoints[aRealEndpoint];
sl@0
   576
	if (ep->iRxBuf == NULL)
sl@0
   577
		{
sl@0
   578
		__KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iRxBuf == NULL", aRealEndpoint));
sl@0
   579
		return KErrNone;
sl@0
   580
		}
sl@0
   581
	ep->iRxBuf = NULL;
sl@0
   582
	ep->iReceived = 0;
sl@0
   583
	ep->iNoBuffer = EFalse;
sl@0
   584
sl@0
   585
	return KErrNone;
sl@0
   586
	}
sl@0
   587
sl@0
   588
sl@0
   589
TInt TTemplateAsspUsbcc::CancelEndpointWrite(TInt aRealEndpoint)
sl@0
   590
//
sl@0
   591
// Cancels a write request for an endpoint on behalf of the LDD.
sl@0
   592
// No completion to the PIL occurs.
sl@0
   593
//
sl@0
   594
	{
sl@0
   595
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::CancelEndpointWrite(%d)", aRealEndpoint));
sl@0
   596
sl@0
   597
	if (!IS_IN_ENDPOINT(aRealEndpoint))
sl@0
   598
		{
sl@0
   599
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !IS_IN_ENDPOINT(%d)", aRealEndpoint));
sl@0
   600
		return KErrArgument;
sl@0
   601
		}
sl@0
   602
	TEndpoint* const ep = &iEndpoints[aRealEndpoint];
sl@0
   603
	if (ep->iTxBuf == NULL)
sl@0
   604
		{
sl@0
   605
		__KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iTxBuf == NULL", aRealEndpoint));
sl@0
   606
		return KErrNone;
sl@0
   607
		}
sl@0
   608
sl@0
   609
	// TO DO (optional): Flush the Ep's Tx FIFO here, if possible.
sl@0
   610
sl@0
   611
	ep->iTxBuf = NULL;
sl@0
   612
	ep->iTransmitted = 0;
sl@0
   613
	ep->iNoBuffer = EFalse;
sl@0
   614
sl@0
   615
	return KErrNone;
sl@0
   616
	}
sl@0
   617
sl@0
   618
sl@0
   619
TInt TTemplateAsspUsbcc::SetupEndpointZeroRead()
sl@0
   620
//
sl@0
   621
// Sets up an Ep0 read request (own function due to Ep0's special status).
sl@0
   622
//
sl@0
   623
	{
sl@0
   624
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointZeroRead"));
sl@0
   625
sl@0
   626
	TEndpoint* const ep = &iEndpoints[KEp0_Out];
sl@0
   627
	if (ep->iRxBuf != NULL)
sl@0
   628
		{
sl@0
   629
		__KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: iEndpoints[%d].iRxBuf != NULL", KEp0_Out));
sl@0
   630
		return KErrGeneral;
sl@0
   631
		}
sl@0
   632
	ep->iRxBuf = iEp0_RxBuf;
sl@0
   633
	ep->iReceived = 0;
sl@0
   634
sl@0
   635
	return KErrNone;
sl@0
   636
	}
sl@0
   637
sl@0
   638
sl@0
   639
TInt TTemplateAsspUsbcc::SetupEndpointZeroWrite(const TUint8* aBuffer, TInt aLength, TBool aZlpReqd)
sl@0
   640
//
sl@0
   641
// Sets up an Ep0 write request (own function due to Ep0's special status).
sl@0
   642
//
sl@0
   643
	{
sl@0
   644
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupEndpointZeroWrite"));
sl@0
   645
sl@0
   646
	TEndpoint* const ep = &iEndpoints[KEp0_In];
sl@0
   647
	if (ep->iTxBuf != NULL)
sl@0
   648
		{
sl@0
   649
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: iEndpoints[%d].iTxBuf != NULL", KEp0_In));
sl@0
   650
		return KErrGeneral;
sl@0
   651
		}
sl@0
   652
	ep->iTxBuf = aBuffer;
sl@0
   653
	ep->iTransmitted = 0;
sl@0
   654
	ep->iLength = aLength;
sl@0
   655
	ep->iZlpReqd = aZlpReqd;
sl@0
   656
	ep->iRequest = NULL;
sl@0
   657
	Ep0Transmit();
sl@0
   658
sl@0
   659
	return KErrNone;
sl@0
   660
	}
sl@0
   661
sl@0
   662
sl@0
   663
TInt TTemplateAsspUsbcc::SendEp0ZeroByteStatusPacket()
sl@0
   664
//
sl@0
   665
// Sets up an Ep0 write request for zero bytes.
sl@0
   666
// This is a separate function because no data transfer is involved here.
sl@0
   667
//
sl@0
   668
	{
sl@0
   669
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SendEp0ZeroByteStatusPacket"));
sl@0
   670
sl@0
   671
	// This is possibly a bit tricky. When this function is called it just means that the higher layer wants a
sl@0
   672
	// ZLP to be sent. Whether we actually send one manually here depends on a number of factors, as the
sl@0
   673
	// current Ep0 state (i.e. the stage of the Ep0 Control transfer), and, in case the hardware handles some
sl@0
   674
	// ZLPs itself, whether it might already handle this one.
sl@0
   675
sl@0
   676
	// Here is an example of what the checking of the conditions might look like:
sl@0
   677
sl@0
   678
#ifndef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
sl@0
   679
	if ((!iEp0ReceivedNonStdRequest && iEp0State == EP0_IN_DATA_PHASE) ||
sl@0
   680
#else
sl@0
   681
	if ((!iEp0ReceivedNonStdRequest && iEp0State != EP0_IDLE) ||
sl@0
   682
#endif
sl@0
   683
#ifdef USB_SUPPORTS_PREMATURE_STATUS_IN
sl@0
   684
		(iEp0ReceivedNonStdRequest && iEp0State != EP0_OUT_DATA_PHASE))
sl@0
   685
#else
sl@0
   686
		(iEp0ReceivedNonStdRequest))
sl@0
   687
#endif
sl@0
   688
		{
sl@0
   689
		// TO DO: Arrange for the sending of a ZLP here.
sl@0
   690
		}
sl@0
   691
sl@0
   692
	return KErrNone;
sl@0
   693
	}
sl@0
   694
sl@0
   695
sl@0
   696
TInt TTemplateAsspUsbcc::StallEndpoint(TInt aRealEndpoint)
sl@0
   697
//
sl@0
   698
// Stalls an endpoint.
sl@0
   699
//
sl@0
   700
	{
sl@0
   701
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StallEndpoint(%d)", aRealEndpoint));
sl@0
   702
sl@0
   703
	if (IS_ISO_ENDPOINT(aRealEndpoint))
sl@0
   704
		{
sl@0
   705
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Iso endpoint cannot be stalled"));
sl@0
   706
		return KErrArgument;
sl@0
   707
		}
sl@0
   708
sl@0
   709
	// TO DO: Stall the endpoint here.
sl@0
   710
sl@0
   711
	return KErrNone;
sl@0
   712
	}
sl@0
   713
sl@0
   714
sl@0
   715
TInt TTemplateAsspUsbcc::ClearStallEndpoint(TInt aRealEndpoint)
sl@0
   716
//
sl@0
   717
// Clears the stall condition of an endpoint.
sl@0
   718
//
sl@0
   719
	{
sl@0
   720
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ClearStallEndpoint(%d)", aRealEndpoint));
sl@0
   721
sl@0
   722
	if (IS_ISO_ENDPOINT(aRealEndpoint))
sl@0
   723
		{
sl@0
   724
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Iso endpoint cannot be unstalled"));
sl@0
   725
		return KErrArgument;
sl@0
   726
		}
sl@0
   727
sl@0
   728
	// TO DO: De-stall the endpoint here.
sl@0
   729
sl@0
   730
	return KErrNone;
sl@0
   731
	}
sl@0
   732
sl@0
   733
sl@0
   734
TInt TTemplateAsspUsbcc::EndpointStallStatus(TInt aRealEndpoint) const
sl@0
   735
//
sl@0
   736
// Reports the stall status of an endpoint.
sl@0
   737
//
sl@0
   738
	{
sl@0
   739
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EndpointStallStatus(%d)", aRealEndpoint));
sl@0
   740
sl@0
   741
	if (IS_ISO_ENDPOINT(aRealEndpoint))
sl@0
   742
		{
sl@0
   743
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Iso endpoint has no stall status"));
sl@0
   744
		return KErrArgument;
sl@0
   745
		}
sl@0
   746
sl@0
   747
	// TO DO: Query endpoint stall status here. The return value should reflect the actual state.
sl@0
   748
	return ETrue;
sl@0
   749
	}
sl@0
   750
sl@0
   751
sl@0
   752
TInt TTemplateAsspUsbcc::EndpointErrorStatus(TInt aRealEndpoint) const
sl@0
   753
//
sl@0
   754
// Reports the error status of an endpoint.
sl@0
   755
//
sl@0
   756
	{
sl@0
   757
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EndpointErrorStatus(%d)", aRealEndpoint));
sl@0
   758
sl@0
   759
	if (!IS_VALID_ENDPOINT(aRealEndpoint))
sl@0
   760
		{
sl@0
   761
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: !IS_VALID_ENDPOINT(%d)", aRealEndpoint));
sl@0
   762
		return KErrArgument;
sl@0
   763
		}
sl@0
   764
sl@0
   765
	// TO DO: Query endpoint error status here. The return value should reflect the actual state.
sl@0
   766
	// With some UDCs there is no way of inquiring the endpoint error status; say 'ETrue' in that case.
sl@0
   767
	return KErrNone;
sl@0
   768
	}
sl@0
   769
sl@0
   770
sl@0
   771
TInt TTemplateAsspUsbcc::ResetDataToggle(TInt aRealEndpoint)
sl@0
   772
//
sl@0
   773
// Resets to zero the data toggle bit of an endpoint.
sl@0
   774
//
sl@0
   775
	{
sl@0
   776
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ResetDataToggle(%d)", aRealEndpoint));
sl@0
   777
sl@0
   778
	// TO DO: Reset the endpoint's data toggle bit here.
sl@0
   779
	// With some UDCs there is no way to individually reset the endpoint's toggle bits; just return KErrNone
sl@0
   780
	// in that case.
sl@0
   781
sl@0
   782
	return KErrNone;
sl@0
   783
	}
sl@0
   784
sl@0
   785
sl@0
   786
TInt TTemplateAsspUsbcc::SynchFrameNumber() const
sl@0
   787
//
sl@0
   788
// For use with isochronous endpoints only. Causes the SOF frame number to be returned.
sl@0
   789
//
sl@0
   790
	{
sl@0
   791
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SynchFrameNumber"));
sl@0
   792
sl@0
   793
	// TO DO: Query and return the SOF frame number here.
sl@0
   794
	return 0;
sl@0
   795
	}
sl@0
   796
sl@0
   797
sl@0
   798
void TTemplateAsspUsbcc::SetSynchFrameNumber(TInt aFrameNumber)
sl@0
   799
//
sl@0
   800
// For use with isochronous endpoints only. Causes the SOF frame number to be stored.
sl@0
   801
//
sl@0
   802
	{
sl@0
   803
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetSynchFrameNumber(%d)", aFrameNumber));
sl@0
   804
sl@0
   805
	// We should actually store this number somewhere. But the PIL always sends '0x00'
sl@0
   806
	// in response to a SYNCH_FRAME request...
sl@0
   807
	// TO DO: Store the frame number. Alternatively (until SYNCH_FRAME request specification changes): Do
sl@0
   808
	// nothing.
sl@0
   809
	}
sl@0
   810
sl@0
   811
sl@0
   812
TInt TTemplateAsspUsbcc::StartUdc()
sl@0
   813
//
sl@0
   814
// Called to initialize the device controller hardware before any operation can be performed.
sl@0
   815
//
sl@0
   816
	{
sl@0
   817
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StartUdc"));
sl@0
   818
sl@0
   819
	if (iInitialized)
sl@0
   820
		{
sl@0
   821
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: UDC already initialised"));
sl@0
   822
		return KErrNone;
sl@0
   823
		}
sl@0
   824
sl@0
   825
	// Disable UDC (might also reset the entire design):
sl@0
   826
	UdcDisable();
sl@0
   827
sl@0
   828
	// Enable UDC's clock:
sl@0
   829
	// TO DO: Enable UDC's clock here.
sl@0
   830
sl@0
   831
	// Even if only one USB feature has been enabled, we later need to undo it:
sl@0
   832
	iInitialized = ETrue;
sl@0
   833
sl@0
   834
	// Bind & enable the UDC interrupt
sl@0
   835
	if (SetupUdcInterrupt() != KErrNone)
sl@0
   836
		{
sl@0
   837
		return KErrGeneral;
sl@0
   838
		}
sl@0
   839
sl@0
   840
	// Write meaningful values to some registers:
sl@0
   841
	InitialiseUdcRegisters();
sl@0
   842
sl@0
   843
	// Finally, turn on the UDC:
sl@0
   844
	UdcEnable();
sl@0
   845
sl@0
   846
	return KErrNone;
sl@0
   847
	}
sl@0
   848
sl@0
   849
sl@0
   850
TInt TTemplateAsspUsbcc::StopUdc()
sl@0
   851
//
sl@0
   852
// Basically, makes undone what happened in StartUdc.
sl@0
   853
//
sl@0
   854
	{
sl@0
   855
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StopUdc"));
sl@0
   856
sl@0
   857
	if (!iInitialized)
sl@0
   858
		{
sl@0
   859
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: UDC not initialized"));
sl@0
   860
		return KErrNone;
sl@0
   861
		}
sl@0
   862
sl@0
   863
	// Disable UDC:
sl@0
   864
	UdcDisable();
sl@0
   865
sl@0
   866
	// Mask (disable) Reset interrupt:
sl@0
   867
	// TO DO: Mask (disable) the USB Reset interrupt here.
sl@0
   868
sl@0
   869
	// Disable & unbind the UDC interrupt:
sl@0
   870
	ReleaseUdcInterrupt();
sl@0
   871
sl@0
   872
	// Finally turn off UDC's clock:
sl@0
   873
	// TO DO: Disable UDC's clock here.
sl@0
   874
sl@0
   875
	// Only when all USB features have been disabled we'll call it a day:
sl@0
   876
	iInitialized = EFalse;
sl@0
   877
sl@0
   878
	return KErrNone;
sl@0
   879
	}
sl@0
   880
sl@0
   881
sl@0
   882
TInt TTemplateAsspUsbcc::UdcConnect()
sl@0
   883
//
sl@0
   884
// Connects the UDC to the bus under software control. How this is achieved depends on the UDC; the
sl@0
   885
// functionality might also be part of the Variant component (instead of the ASSP).
sl@0
   886
//
sl@0
   887
	{
sl@0
   888
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcConnect"));
sl@0
   889
sl@0
   890
	// Here: A call into the Variant-provided function.
sl@0
   891
	return iAssp->UsbConnect();
sl@0
   892
	}
sl@0
   893
sl@0
   894
sl@0
   895
TInt TTemplateAsspUsbcc::UdcDisconnect()
sl@0
   896
//
sl@0
   897
// Disconnects the UDC from the bus under software control. How this is achieved depends on the UDC; the
sl@0
   898
// functionality might also be part of the Variant component (instead of the ASSP).
sl@0
   899
//
sl@0
   900
	{
sl@0
   901
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcDisconnect"));
sl@0
   902
sl@0
   903
	// Here: A call into the Variant-provided function.
sl@0
   904
	return iAssp->UsbDisconnect();
sl@0
   905
	}
sl@0
   906
sl@0
   907
sl@0
   908
TBool TTemplateAsspUsbcc::UsbConnectionStatus() const
sl@0
   909
//
sl@0
   910
// Returns a value showing the USB cable connection status of the device.
sl@0
   911
//
sl@0
   912
	{
sl@0
   913
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UsbConnectionStatus"));
sl@0
   914
sl@0
   915
	return iCableConnected;
sl@0
   916
	}
sl@0
   917
sl@0
   918
sl@0
   919
TBool TTemplateAsspUsbcc::UsbPowerStatus() const
sl@0
   920
//
sl@0
   921
// Returns a truth value showing whether VBUS is currently powered or not.
sl@0
   922
//
sl@0
   923
	{
sl@0
   924
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UsbPowerStatus"));
sl@0
   925
sl@0
   926
	return iBusIsPowered;
sl@0
   927
	}
sl@0
   928
sl@0
   929
sl@0
   930
TBool TTemplateAsspUsbcc::DeviceSelfPowered() const
sl@0
   931
//
sl@0
   932
// Returns a truth value showing whether the device is currently self-powered or not.
sl@0
   933
//
sl@0
   934
	{
sl@0
   935
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeviceSelfPowered"));
sl@0
   936
sl@0
   937
	// TO DO: Query and return self powered status here. The return value should reflect the actual state.
sl@0
   938
	// (This can be always 'ETrue' if the UDC does not support bus-powered devices.)
sl@0
   939
	return ETrue;
sl@0
   940
	}
sl@0
   941
sl@0
   942
sl@0
   943
const TUsbcEndpointCaps* TTemplateAsspUsbcc::DeviceEndpointCaps() const
sl@0
   944
//
sl@0
   945
// Returns a pointer to an array of elements, each of which describes the capabilities of one endpoint.
sl@0
   946
//
sl@0
   947
	{
sl@0
   948
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeviceEndpointCaps"));
sl@0
   949
	__KTRACE_OPT(KUSB, Kern::Printf(" > Ep: Sizes Mask, Types Mask"));
sl@0
   950
	__KTRACE_OPT(KUSB, Kern::Printf(" > --------------------------"));
sl@0
   951
	for (TInt i = 0; i < KUsbTotalEndpoints; ++i)
sl@0
   952
		{
sl@0
   953
		__KTRACE_OPT(KUSB, Kern::Printf(" > %02d: 0x%08x, 0x%08x",
sl@0
   954
										i, DeviceEndpoints[i].iSizes, DeviceEndpoints[i].iTypesAndDir));
sl@0
   955
		}
sl@0
   956
	return DeviceEndpoints;
sl@0
   957
	}
sl@0
   958
sl@0
   959
sl@0
   960
TInt TTemplateAsspUsbcc::DeviceTotalEndpoints() const
sl@0
   961
//
sl@0
   962
// Returns the element number of the endpoints array a pointer to which is returned by DeviceEndpointCaps.
sl@0
   963
//
sl@0
   964
	{
sl@0
   965
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DeviceTotalEndpoints"));
sl@0
   966
sl@0
   967
	return KUsbTotalEndpoints;
sl@0
   968
	}
sl@0
   969
sl@0
   970
sl@0
   971
TBool TTemplateAsspUsbcc::SoftConnectCaps() const
sl@0
   972
//
sl@0
   973
// Returns a truth value showing whether or not there is the capability to disconnect and re-connect the D+
sl@0
   974
// line under software control.
sl@0
   975
//
sl@0
   976
	{
sl@0
   977
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SoftConnectCaps"));
sl@0
   978
sl@0
   979
	return iSoftwareConnectable;
sl@0
   980
	}
sl@0
   981
sl@0
   982
sl@0
   983
void TTemplateAsspUsbcc::Suspend()
sl@0
   984
//
sl@0
   985
// Called by the PIL after a Suspend event has been reported (by us).
sl@0
   986
//
sl@0
   987
	{
sl@0
   988
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Suspend"));
sl@0
   989
sl@0
   990
	// TO DO (optional): Implement here anything the device might require after bus SUSPEND signalling.
sl@0
   991
	}
sl@0
   992
sl@0
   993
sl@0
   994
void TTemplateAsspUsbcc::Resume()
sl@0
   995
//
sl@0
   996
// Called by the PIL after a Resume event has been reported (by us).
sl@0
   997
//
sl@0
   998
	{
sl@0
   999
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Resume"));
sl@0
  1000
sl@0
  1001
	// TO DO (optional): Implement here anything the device might require after bus RESUME signalling.
sl@0
  1002
	}
sl@0
  1003
sl@0
  1004
sl@0
  1005
void TTemplateAsspUsbcc::Reset()
sl@0
  1006
//
sl@0
  1007
// Called by the PIL after a Reset event has been reported (by us).
sl@0
  1008
//
sl@0
  1009
	{
sl@0
  1010
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Reset"));
sl@0
  1011
sl@0
  1012
	// This does not really belong here, but has to do with the way the PIL sets
sl@0
  1013
	// up Ep0 reads and writes.
sl@0
  1014
	TEndpoint* ep = &iEndpoints[0];
sl@0
  1015
	ep->iRxBuf = NULL;
sl@0
  1016
	++ep;
sl@0
  1017
	ep->iTxBuf = NULL;
sl@0
  1018
	// Idle
sl@0
  1019
	Ep0NextState(EP0_IDLE);
sl@0
  1020
sl@0
  1021
	// TO DO (optional): Implement here anything the device might require after bus RESET signalling.
sl@0
  1022
sl@0
  1023
	// Write meaningful values to some registers
sl@0
  1024
	InitialiseUdcRegisters();
sl@0
  1025
	UdcEnable();
sl@0
  1026
	if (iEp0Configured)
sl@0
  1027
		EnableEndpointInterrupt(0);
sl@0
  1028
	}
sl@0
  1029
sl@0
  1030
sl@0
  1031
// --- TTemplateAsspUsbcc private --------------------------------------------------
sl@0
  1032
sl@0
  1033
void TTemplateAsspUsbcc::InitialiseUdcRegisters()
sl@0
  1034
//
sl@0
  1035
// Called after every USB Reset etc.
sl@0
  1036
//
sl@0
  1037
	{
sl@0
  1038
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::InitialiseUdcRegisters"));
sl@0
  1039
sl@0
  1040
	// Unmask Suspend interrupt
sl@0
  1041
	// TO DO: Unmask Suspend interrupt here.
sl@0
  1042
sl@0
  1043
	// Unmask Resume interrupt
sl@0
  1044
	// TO DO: Unmask Resume interrupt here.
sl@0
  1045
sl@0
  1046
	// Unmask Start-of-Frame (SOF) interrupt
sl@0
  1047
	// TO DO (optional): Unmask SOF interrupt here.
sl@0
  1048
sl@0
  1049
	// Disable interrupt requests for all endpoints
sl@0
  1050
	// TO DO: Disable interrupt requests for all endpoints here.
sl@0
  1051
	}
sl@0
  1052
sl@0
  1053
sl@0
  1054
void TTemplateAsspUsbcc::UdcEnable()
sl@0
  1055
//
sl@0
  1056
// Enables the UDC for USB transmission or reception.
sl@0
  1057
//
sl@0
  1058
	{
sl@0
  1059
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcEnable"));
sl@0
  1060
sl@0
  1061
	// TO DO: Do whatever is necessary to enable the UDC here. This might include enabling (unmasking)
sl@0
  1062
	// the USB Reset interrupt, setting a UDC enable bit, etc.
sl@0
  1063
	}
sl@0
  1064
sl@0
  1065
sl@0
  1066
void TTemplateAsspUsbcc::UdcDisable()
sl@0
  1067
//
sl@0
  1068
// Disables the UDC.
sl@0
  1069
//
sl@0
  1070
	{
sl@0
  1071
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcDisable"));
sl@0
  1072
sl@0
  1073
	// TO DO: Do whatever is necessary to disable the UDC here. This might include disabling (masking)
sl@0
  1074
	// the USB Reset interrupt, clearing a UDC enable bit, etc.
sl@0
  1075
	}
sl@0
  1076
sl@0
  1077
sl@0
  1078
void TTemplateAsspUsbcc::EnableEndpointInterrupt(TInt aEndpoint)
sl@0
  1079
//
sl@0
  1080
// Enables interrupt requests for an endpoint.
sl@0
  1081
//
sl@0
  1082
	{
sl@0
  1083
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EnableEndpointInterrupt(%d)", aEndpoint));
sl@0
  1084
sl@0
  1085
	// Enable (unmask) interrupt requests for this endpoint:
sl@0
  1086
	// TO DO: Enable interrupt requests for aEndpoint here.
sl@0
  1087
	}
sl@0
  1088
sl@0
  1089
sl@0
  1090
void TTemplateAsspUsbcc::DisableEndpointInterrupt(TInt aEndpoint)
sl@0
  1091
//
sl@0
  1092
// Disables interrupt requests for an endpoint.
sl@0
  1093
//
sl@0
  1094
	{
sl@0
  1095
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::DisableEndpointInterrupt(%d)", aEndpoint));
sl@0
  1096
sl@0
  1097
	// Disable (mask) interrupt requests for this endpoint:
sl@0
  1098
	// TO DO: Disable interrupt requests for aEndpoint here.
sl@0
  1099
	}
sl@0
  1100
sl@0
  1101
sl@0
  1102
void TTemplateAsspUsbcc::ClearEndpointInterrupt(TInt aEndpoint)
sl@0
  1103
//
sl@0
  1104
// Clears a pending interrupt request for an endpoint.
sl@0
  1105
//
sl@0
  1106
	{
sl@0
  1107
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ClearEndpointInterrupt(%d)", aEndpoint));
sl@0
  1108
sl@0
  1109
	// Clear (reset) pending interrupt request for this endpoint:
sl@0
  1110
	// TO DO: Clear interrupt request for aEndpoint here.
sl@0
  1111
	}
sl@0
  1112
sl@0
  1113
sl@0
  1114
void TTemplateAsspUsbcc::Ep0IntService()
sl@0
  1115
//
sl@0
  1116
// ISR for endpoint zero interrupt.
sl@0
  1117
//
sl@0
  1118
	{
sl@0
  1119
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0IntService"));
sl@0
  1120
sl@0
  1121
	// TO DO: Enquire about Ep0 status & the interrupt cause here. Depending on the event and the Ep0 state,
sl@0
  1122
	// one or more of the following functions might then be called:
sl@0
  1123
	Ep0Cancel();
sl@0
  1124
	Ep0ReadSetupPkt();
sl@0
  1125
	Ep0EndXfer();
sl@0
  1126
	Ep0PrematureStatusOut();
sl@0
  1127
	Ep0Transmit();
sl@0
  1128
	Ep0StatusIn();
sl@0
  1129
	Ep0Receive();
sl@0
  1130
	ClearStallEndpoint(0);
sl@0
  1131
sl@0
  1132
	ClearEndpointInterrupt(0);
sl@0
  1133
	return;
sl@0
  1134
	}
sl@0
  1135
sl@0
  1136
sl@0
  1137
void TTemplateAsspUsbcc::Ep0ReadSetupPkt()
sl@0
  1138
//
sl@0
  1139
// Called from the Ep0 ISR when a new Setup packet has been received.
sl@0
  1140
//
sl@0
  1141
	{
sl@0
  1142
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0ReadSetupPkt"));
sl@0
  1143
sl@0
  1144
	TEndpoint* const ep = &iEndpoints[KEp0_Out];
sl@0
  1145
	TUint8* buf = ep->iRxBuf;
sl@0
  1146
	if (!buf)
sl@0
  1147
		{
sl@0
  1148
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: No Ep0 Rx buffer available (1)"));
sl@0
  1149
		StallEndpoint(KEp0_Out);
sl@0
  1150
		return;
sl@0
  1151
		}
sl@0
  1152
sl@0
  1153
	// TO DO: Read Setup packet data from Rx FIFO into 'buf' here.
sl@0
  1154
	// (In this function we don't need to use "ep->iReceived" since Setup packets
sl@0
  1155
	// are always 8 bytes long.)
sl@0
  1156
sl@0
  1157
	// Upcall into PIL to determine next Ep0 state:
sl@0
  1158
	TUsbcEp0State state = EnquireEp0NextState(ep->iRxBuf);
sl@0
  1159
sl@0
  1160
	if (state == EEp0StateStatusIn)
sl@0
  1161
		{
sl@0
  1162
		Ep0NextState(EP0_IDLE);								// Ep0 No Data
sl@0
  1163
		}
sl@0
  1164
	else if (state == EEp0StateDataIn)
sl@0
  1165
		{
sl@0
  1166
		Ep0NextState(EP0_IN_DATA_PHASE);					// Ep0 Control Read
sl@0
  1167
		}
sl@0
  1168
	else
sl@0
  1169
		{
sl@0
  1170
		Ep0NextState(EP0_OUT_DATA_PHASE);					// Ep0 Control Write
sl@0
  1171
		}
sl@0
  1172
sl@0
  1173
	ep->iRxBuf = NULL;
sl@0
  1174
	const TInt r = Ep0RequestComplete(KEp0_Out, 8, KErrNone);
sl@0
  1175
sl@0
  1176
	// Don't finish (proceed) if request completion returned 'KErrNotFound'!
sl@0
  1177
	if (!(r == KErrNone || r == KErrGeneral))
sl@0
  1178
		{
sl@0
  1179
		DisableEndpointInterrupt(0);
sl@0
  1180
		}
sl@0
  1181
sl@0
  1182
	// TO DO (optional): Clear Ep0 Setup condition flags here.
sl@0
  1183
sl@0
  1184
#ifdef USB_SUPPORTS_PREMATURE_STATUS_IN
sl@0
  1185
	if (iEp0State == EP0_OUT_DATA_PHASE)
sl@0
  1186
		{
sl@0
  1187
		// Allow for a premature STATUS IN
sl@0
  1188
		// TO DO: Arrange for the sending of a ZLP here.
sl@0
  1189
		}
sl@0
  1190
#endif
sl@0
  1191
	}
sl@0
  1192
sl@0
  1193
sl@0
  1194
void TTemplateAsspUsbcc::Ep0ReadSetupPktProceed()
sl@0
  1195
//
sl@0
  1196
// Called by the PIL to signal that it has finished processing a received Setup packet and that the PSL can
sl@0
  1197
// now prepare itself for the next Ep0 reception (for instance by re-enabling the Ep0 interrupt).
sl@0
  1198
//
sl@0
  1199
	{
sl@0
  1200
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0ReadSetupPktProceed"));
sl@0
  1201
sl@0
  1202
	EnableEndpointInterrupt(0);
sl@0
  1203
	}
sl@0
  1204
sl@0
  1205
sl@0
  1206
void TTemplateAsspUsbcc::Ep0Receive()
sl@0
  1207
//
sl@0
  1208
// Called from the Ep0 ISR when a data packet has been received.
sl@0
  1209
//
sl@0
  1210
	{
sl@0
  1211
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0Receive"));
sl@0
  1212
sl@0
  1213
	TEndpoint* const ep = &iEndpoints[KEp0_Out];
sl@0
  1214
	TUint8* buf = ep->iRxBuf;
sl@0
  1215
	if (!buf)
sl@0
  1216
		{
sl@0
  1217
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: No Ep0 Rx buffer available (2)"));
sl@0
  1218
		StallEndpoint(KEp0_Out);
sl@0
  1219
		return;
sl@0
  1220
		}
sl@0
  1221
sl@0
  1222
	TInt n = 0;
sl@0
  1223
	// TO DO: Read packet data from Rx FIFO into 'buf' and update 'n' (# of received bytes) here.
sl@0
  1224
sl@0
  1225
	ep->iReceived = n;
sl@0
  1226
	ep->iRxBuf = NULL;
sl@0
  1227
	const TInt r = Ep0RequestComplete(KEp0_Out, n, KErrNone);
sl@0
  1228
sl@0
  1229
	// Don't finish (proceed) if request was 'KErrNotFound'!
sl@0
  1230
	if (!(r == KErrNone || r == KErrGeneral))
sl@0
  1231
		{
sl@0
  1232
		DisableEndpointInterrupt(0);
sl@0
  1233
		}
sl@0
  1234
sl@0
  1235
	// TO DO (optional): Clear Ep0 Rx condition flags here.
sl@0
  1236
sl@0
  1237
#ifdef USB_SUPPORTS_PREMATURE_STATUS_IN
sl@0
  1238
	// Allow for a premature STATUS IN
sl@0
  1239
	// TO DO: Arrange for the sending of a ZLP here.
sl@0
  1240
#endif
sl@0
  1241
	}
sl@0
  1242
sl@0
  1243
sl@0
  1244
void TTemplateAsspUsbcc::Ep0ReceiveProceed()
sl@0
  1245
//
sl@0
  1246
// Called by the PIL to signal that it has finished processing a received Ep0 data packet and that the PSL can
sl@0
  1247
// now prepare itself for the next Ep0 reception (for instance by re-enabling the Ep0 interrupt).
sl@0
  1248
//
sl@0
  1249
	{
sl@0
  1250
	Ep0ReadSetupPktProceed();
sl@0
  1251
	}
sl@0
  1252
sl@0
  1253
sl@0
  1254
void TTemplateAsspUsbcc::Ep0Transmit()
sl@0
  1255
//
sl@0
  1256
// Called from either the Ep0 ISR or the PIL when a data packet has been or is to be transmitted.
sl@0
  1257
//
sl@0
  1258
	{
sl@0
  1259
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0Transmit"));
sl@0
  1260
sl@0
  1261
	if (iEp0State != EP0_IN_DATA_PHASE)
sl@0
  1262
		{
sl@0
  1263
		__KTRACE_OPT(KUSB, Kern::Printf(" > WARNING: Invalid Ep0 state when trying to handle EP0 IN"));
sl@0
  1264
		// TO DO (optional): Do something about this warning.
sl@0
  1265
		}
sl@0
  1266
sl@0
  1267
	TEndpoint* const ep = &iEndpoints[KEp0_In];
sl@0
  1268
	const TUint8* buf = ep->iTxBuf;
sl@0
  1269
	if (!buf)
sl@0
  1270
		{
sl@0
  1271
		__KTRACE_OPT(KUSB, Kern::Printf(" > No Tx buffer available: returning"));
sl@0
  1272
		return;
sl@0
  1273
		}
sl@0
  1274
	const TInt t = ep->iTransmitted;						// already transmitted
sl@0
  1275
	buf += t;
sl@0
  1276
	TInt n = 0;												// now transmitted
sl@0
  1277
sl@0
  1278
	// TO DO: Write packet data (if any) into Tx FIFO from 'buf' and update 'n' (# of tx'ed bytes) here.
sl@0
  1279
sl@0
  1280
	ep->iTransmitted += n;
sl@0
  1281
	
sl@0
  1282
	// coverity[dead_error_condition]
sl@0
  1283
	// The next line should be reachable when this template file is edited for use
sl@0
  1284
	if (n == KEp0MaxPktSz)
sl@0
  1285
		{
sl@0
  1286
		if (ep->iTransmitted == ep->iLength && !(ep->iZlpReqd))
sl@0
  1287
			Ep0NextState(EP0_END_XFER);
sl@0
  1288
		}
sl@0
  1289
	else if (n && n != KEp0MaxPktSz)
sl@0
  1290
		{
sl@0
  1291
		// Send off the data
sl@0
  1292
		__ASSERT_DEBUG((ep->iTransmitted == ep->iLength),
sl@0
  1293
					   Kern::Printf(" > ERROR: Short packet in mid-transfer"));
sl@0
  1294
		Ep0NextState(EP0_END_XFER);
sl@0
  1295
		// TO DO: Send off the data here.
sl@0
  1296
		}
sl@0
  1297
	else // if (n == 0)
sl@0
  1298
		{
sl@0
  1299
		__ASSERT_DEBUG((ep->iTransmitted == ep->iLength),
sl@0
  1300
					   Kern::Printf(" > ERROR: Nothing transmitted but still not finished"));
sl@0
  1301
		if (ep->iZlpReqd)
sl@0
  1302
			{
sl@0
  1303
			// Send a zero length packet
sl@0
  1304
			ep->iZlpReqd = EFalse;
sl@0
  1305
			Ep0NextState(EP0_END_XFER);
sl@0
  1306
			// TO DO: Arrange for the sending of a ZLP here.
sl@0
  1307
			}
sl@0
  1308
		else
sl@0
  1309
			{
sl@0
  1310
			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: nothing transmitted & no ZLP req'd"));
sl@0
  1311
			}
sl@0
  1312
		}
sl@0
  1313
	}
sl@0
  1314
sl@0
  1315
sl@0
  1316
void TTemplateAsspUsbcc::Ep0EndXfer()
sl@0
  1317
//
sl@0
  1318
// Called at the end of a Ep0 Control transfer.
sl@0
  1319
//
sl@0
  1320
	{
sl@0
  1321
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0EndXfer"));
sl@0
  1322
sl@0
  1323
	// TO DO (optional): Clear Ep0 Rx condition flags here.
sl@0
  1324
sl@0
  1325
	Ep0NextState(EP0_IDLE);
sl@0
  1326
	TEndpoint* const ep = &iEndpoints[KEp0_In];
sl@0
  1327
	ep->iTxBuf = NULL;
sl@0
  1328
	(void) Ep0RequestComplete(KEp0_In, ep->iTransmitted, KErrNone);
sl@0
  1329
	}
sl@0
  1330
sl@0
  1331
sl@0
  1332
void TTemplateAsspUsbcc::Ep0Cancel()
sl@0
  1333
//
sl@0
  1334
// Called when an ongoing Ep0 Control transfer has to be aborted prematurely (for instance when receiving a
sl@0
  1335
// new Setup packet before the processing of the old one has completed).
sl@0
  1336
//
sl@0
  1337
	{
sl@0
  1338
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0Cancel"));
sl@0
  1339
sl@0
  1340
	Ep0NextState(EP0_IDLE);
sl@0
  1341
	TEndpoint* const ep = &iEndpoints[KEp0_In];
sl@0
  1342
	if (ep->iTxBuf)
sl@0
  1343
		{
sl@0
  1344
		ep->iTxBuf = NULL;
sl@0
  1345
		const TInt err = (ep->iTransmitted == ep->iLength) ? KErrNone : KErrCancel;
sl@0
  1346
		(void) Ep0RequestComplete(KEp0_In, ep->iTransmitted, err);
sl@0
  1347
		}
sl@0
  1348
	}
sl@0
  1349
sl@0
  1350
sl@0
  1351
void TTemplateAsspUsbcc::Ep0PrematureStatusOut()
sl@0
  1352
//
sl@0
  1353
// Called when an ongoing Ep0 Control transfer encounters a premature Status OUT condition.
sl@0
  1354
//
sl@0
  1355
	{
sl@0
  1356
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0PrematureStatusOut"));
sl@0
  1357
sl@0
  1358
	// TO DO (optional): Clear Ep0 Rx condition flags here.
sl@0
  1359
sl@0
  1360
	Ep0NextState(EP0_IDLE);
sl@0
  1361
sl@0
  1362
	// TO DO (optional): Flush the Ep0 Tx FIFO here, if possible.
sl@0
  1363
sl@0
  1364
	TEndpoint* const ep = &iEndpoints[KEp0_In];
sl@0
  1365
	if (ep->iTxBuf)
sl@0
  1366
		{
sl@0
  1367
		ep->iTxBuf = NULL;
sl@0
  1368
		(void) Ep0RequestComplete(KEp0_In, ep->iTransmitted, KErrPrematureEnd);
sl@0
  1369
		}
sl@0
  1370
	}
sl@0
  1371
sl@0
  1372
sl@0
  1373
void TTemplateAsspUsbcc::Ep0StatusIn()
sl@0
  1374
//
sl@0
  1375
// Called when an ongoing Ep0 Control transfer moves to a Status IN stage.
sl@0
  1376
//
sl@0
  1377
	{
sl@0
  1378
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0StatusIn"));
sl@0
  1379
sl@0
  1380
	Ep0NextState(EP0_IDLE);
sl@0
  1381
	}
sl@0
  1382
sl@0
  1383
sl@0
  1384
void TTemplateAsspUsbcc::BulkTransmit(TInt aEndpoint)
sl@0
  1385
//
sl@0
  1386
// Endpoint 1 (BULK IN).
sl@0
  1387
// Called from either the Ep ISR or the PIL when a data packet has been or is to be transmitted.
sl@0
  1388
//
sl@0
  1389
	{
sl@0
  1390
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::BulkTransmit(%d)", aEndpoint));
sl@0
  1391
sl@0
  1392
	// TO DO: Enquire about Ep status here.
sl@0
  1393
sl@0
  1394
	const TInt idx = 3;										// only in our special case of course!
sl@0
  1395
	TEndpoint* const ep = &iEndpoints[idx];
sl@0
  1396
	const TUint8* buf = ep->iTxBuf;
sl@0
  1397
	if (!buf)
sl@0
  1398
		{
sl@0
  1399
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: No Tx buffer has been set up"));
sl@0
  1400
		DisableEndpointInterrupt(aEndpoint);
sl@0
  1401
		ep->iDisabled = ETrue;
sl@0
  1402
		ClearEndpointInterrupt(aEndpoint);
sl@0
  1403
		return;
sl@0
  1404
		}
sl@0
  1405
	const TInt t = ep->iTransmitted;						// already transmitted
sl@0
  1406
	const TInt len = ep->iLength;							// to be sent in total
sl@0
  1407
	// (len || ep->iPackets): Don't complete for a zero bytes request straight away.
sl@0
  1408
	if (t >= len && (len || ep->iPackets))
sl@0
  1409
		{
sl@0
  1410
		if (ep->iZlpReqd)
sl@0
  1411
			{
sl@0
  1412
			__KTRACE_OPT(KUSB, Kern::Printf(" > 'Transmit Short Packet' explicitly"));
sl@0
  1413
			// TO DO: Arrange for the sending of a ZLP here.
sl@0
  1414
			ep->iZlpReqd = EFalse;
sl@0
  1415
			}
sl@0
  1416
		else
sl@0
  1417
			{
sl@0
  1418
			__KTRACE_OPT(KUSB, Kern::Printf(" > All data sent: %d --> completing", len));
sl@0
  1419
			ep->iTxBuf = NULL;
sl@0
  1420
			ep->iRequest->iTxBytes = ep->iTransmitted;
sl@0
  1421
			ep->iRequest->iError = KErrNone;
sl@0
  1422
			EndpointRequestComplete(ep->iRequest);
sl@0
  1423
			ep->iRequest = NULL;
sl@0
  1424
			}
sl@0
  1425
		}
sl@0
  1426
	else
sl@0
  1427
		{
sl@0
  1428
		buf += t;
sl@0
  1429
		TInt left = len - t;								// left in total
sl@0
  1430
		TInt n = (left >= KBlkMaxPktSz) ? KBlkMaxPktSz : left; // now to be transmitted
sl@0
  1431
		__KTRACE_OPT(KUSB, Kern::Printf(" > About to send %d bytes (%d bytes left in total)", n, left));
sl@0
  1432
sl@0
  1433
		// TO DO: Write data into Tx FIFO from 'buf' here.
sl@0
  1434
sl@0
  1435
		ep->iTransmitted += n;
sl@0
  1436
		ep->iPackets++;										// only used for (len == 0) case
sl@0
  1437
		left -= n;											// (still) left in total
sl@0
  1438
		if (n < KBlkMaxPktSz)
sl@0
  1439
			{
sl@0
  1440
			__KTRACE_OPT(KUSB, Kern::Printf(" > 'Transmit Short Packet' implicitly"));
sl@0
  1441
			// TO DO: Arrange for the sending of a ZLP here.
sl@0
  1442
			ep->iZlpReqd = EFalse;
sl@0
  1443
			}
sl@0
  1444
		// If double-buffering is available, it might be possible to stick a second packet
sl@0
  1445
		// into the FIFO here.
sl@0
  1446
sl@0
  1447
		// TO DO (optional): Send another packet if possible (& available) here.
sl@0
  1448
		}
sl@0
  1449
sl@0
  1450
	ClearEndpointInterrupt(aEndpoint);
sl@0
  1451
	}
sl@0
  1452
sl@0
  1453
sl@0
  1454
sl@0
  1455
void TTemplateAsspUsbcc::BulkReceive(TInt aEndpoint)
sl@0
  1456
//
sl@0
  1457
// Endpoint 2 (BULK OUT) (This one is called in an ISR.)
sl@0
  1458
//
sl@0
  1459
	{
sl@0
  1460
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::BulkReceive(%d)", aEndpoint));
sl@0
  1461
sl@0
  1462
	// TO DO: Enquire about Ep status here.
sl@0
  1463
	const TUint32 status = *(TUint32*)0xdefaced;			// bogus
sl@0
  1464
sl@0
  1465
	const TInt idx = 4;										// only in our special case of course!
sl@0
  1466
	TEndpoint* const ep = &iEndpoints[idx];
sl@0
  1467
	TUint8* buf = ep->iRxBuf;
sl@0
  1468
	if (!buf)
sl@0
  1469
		{
sl@0
  1470
		__KTRACE_OPT(KUSB, Kern::Printf(" > No Rx buffer available: setting iNoBuffer"));
sl@0
  1471
		ep->iNoBuffer = ETrue;
sl@0
  1472
		DisableEndpointInterrupt(aEndpoint);
sl@0
  1473
		ep->iDisabled = ETrue;
sl@0
  1474
		ClearEndpointInterrupt(aEndpoint);
sl@0
  1475
		return;
sl@0
  1476
		}
sl@0
  1477
	TInt bytes = 0;
sl@0
  1478
	const TInt r = ep->iReceived;							// already received
sl@0
  1479
	// TO DO: Check whether a ZLP was received here:
sl@0
  1480
	if (status & 1)											// some condition
sl@0
  1481
		{
sl@0
  1482
		__KTRACE_OPT(KUSB, Kern::Printf(" > received zero-length packet"));
sl@0
  1483
		}
sl@0
  1484
	else if (status & 2)									// some other condition
sl@0
  1485
		{
sl@0
  1486
		// TO DO: Get number of bytes received here.
sl@0
  1487
		bytes = *(TUint32*)0xdadadada;						// bogus
sl@0
  1488
		__KTRACE_OPT(KUSB, Kern::Printf(" > Bulk received: %d bytes", bytes));
sl@0
  1489
		if (r + bytes > ep->iLength)
sl@0
  1490
			{
sl@0
  1491
			__KTRACE_OPT(KUSB, Kern::Printf(" > not enough space in rx buffer: setting iNoBuffer"));
sl@0
  1492
			ep->iNoBuffer = ETrue;
sl@0
  1493
			StopRxTimer(ep);
sl@0
  1494
			*ep->iPacketSize = ep->iReceived;
sl@0
  1495
			RxComplete(ep);
sl@0
  1496
sl@0
  1497
			// TO DO (optional): Clear Ep Rx condition flags here.
sl@0
  1498
sl@0
  1499
			ClearEndpointInterrupt(aEndpoint);
sl@0
  1500
			return;
sl@0
  1501
			}
sl@0
  1502
		buf += r;											// set buffer pointer
sl@0
  1503
sl@0
  1504
		// TO DO: Read 'bytes' bytes from Rx FIFO into 'buf' here.
sl@0
  1505
sl@0
  1506
		ep->iReceived += bytes;
sl@0
  1507
		}
sl@0
  1508
	else
sl@0
  1509
		{
sl@0
  1510
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Inconsistent Ep%d state", aEndpoint));
sl@0
  1511
sl@0
  1512
		// TO DO (optional): Clear Ep Rx condition flags here.
sl@0
  1513
sl@0
  1514
		ClearEndpointInterrupt(aEndpoint);
sl@0
  1515
		return;
sl@0
  1516
		}
sl@0
  1517
sl@0
  1518
	if (bytes == 0)
sl@0
  1519
		{
sl@0
  1520
		// ZLPs must be recorded separately
sl@0
  1521
		const TInt i = ep->iReceived ? 1 : 0;
sl@0
  1522
		ep->iPacketIndex[i] = r;
sl@0
  1523
		ep->iPacketSize[i] = 0;
sl@0
  1524
		// If there were data packets before: total packets reported 1 -> 2
sl@0
  1525
		ep->iPackets += i;
sl@0
  1526
		}
sl@0
  1527
sl@0
  1528
	if ((bytes < KBlkMaxPktSz) ||
sl@0
  1529
		(ep->iReceived == ep->iLength))
sl@0
  1530
		{
sl@0
  1531
		StopRxTimer(ep);
sl@0
  1532
		*ep->iPacketSize = ep->iReceived;
sl@0
  1533
		RxComplete(ep);
sl@0
  1534
		// since we have no buffer any longer we disable interrupts:
sl@0
  1535
		DisableEndpointInterrupt(aEndpoint);
sl@0
  1536
		ep->iDisabled = ETrue;
sl@0
  1537
		}
sl@0
  1538
	else
sl@0
  1539
		{
sl@0
  1540
		if (!ep->iRxTimerSet)
sl@0
  1541
			{
sl@0
  1542
			__KTRACE_OPT(KUSB, Kern::Printf(" > setting rx timer"));
sl@0
  1543
			ep->iRxTimerSet = ETrue;
sl@0
  1544
			ep->iRxTimer.OneShot(KRxTimerTimeout);
sl@0
  1545
			}
sl@0
  1546
		else
sl@0
  1547
			{
sl@0
  1548
			ep->iRxMoreDataRcvd = ETrue;
sl@0
  1549
			}
sl@0
  1550
		}
sl@0
  1551
sl@0
  1552
	// TO DO (optional): Clear Ep Rx condition flags here.
sl@0
  1553
sl@0
  1554
	ClearEndpointInterrupt(aEndpoint);
sl@0
  1555
	}
sl@0
  1556
sl@0
  1557
sl@0
  1558
void TTemplateAsspUsbcc::BulkReadRxFifo(TInt aEndpoint)
sl@0
  1559
//
sl@0
  1560
// Endpoint 2 (BULK OUT) (This one is called w/o interrupt to be served.)
sl@0
  1561
//
sl@0
  1562
	{
sl@0
  1563
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::BulkReadRxFifo(%d)", aEndpoint));
sl@0
  1564
sl@0
  1565
	// TO DO: Enquire about Ep status here.
sl@0
  1566
	const TUint32 status = *(TUint32*)0xdefaced;			// bogus
sl@0
  1567
sl@0
  1568
	const TInt idx = 4;										// only in our special case of course!
sl@0
  1569
	TEndpoint* const ep = &iEndpoints[idx];
sl@0
  1570
	TUint8* buf = ep->iRxBuf;
sl@0
  1571
	if (!buf)
sl@0
  1572
		{
sl@0
  1573
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: No Rx buffer has been set up"));
sl@0
  1574
		return;
sl@0
  1575
		}
sl@0
  1576
	TInt bytes = 0;
sl@0
  1577
	const TInt r = ep->iReceived;							// already received
sl@0
  1578
	// TO DO: Check whether a ZLP was received here:
sl@0
  1579
	if (status & 1)											// some condition
sl@0
  1580
		{
sl@0
  1581
		__KTRACE_OPT(KUSB, Kern::Printf(" > received zero-length packet"));
sl@0
  1582
		}
sl@0
  1583
	else if (status & 2)									// some other condition
sl@0
  1584
		{
sl@0
  1585
		// TO DO: Get number of bytes received here.
sl@0
  1586
		bytes = *(TUint32*)0xdadadada;						// bogus
sl@0
  1587
		__KTRACE_OPT(KUSB, Kern::Printf(" > Bulk received: %d bytes", bytes));
sl@0
  1588
		if (r + bytes > ep->iLength)
sl@0
  1589
			{
sl@0
  1590
			__KTRACE_OPT(KUSB, Kern::Printf(" > not enough space in rx buffer: setting iNoBuffer"));
sl@0
  1591
			ep->iNoBuffer = ETrue;
sl@0
  1592
			*ep->iPacketSize = ep->iReceived;
sl@0
  1593
			RxComplete(ep);
sl@0
  1594
			return;
sl@0
  1595
			}
sl@0
  1596
		buf += r;											// set buffer pointer
sl@0
  1597
sl@0
  1598
		// TO DO: Read 'bytes' bytes from Rx FIFO into 'buf' here.
sl@0
  1599
sl@0
  1600
		ep->iReceived += bytes;
sl@0
  1601
		}
sl@0
  1602
	else
sl@0
  1603
		{
sl@0
  1604
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Inconsistent Ep%d state", aEndpoint));
sl@0
  1605
		return;
sl@0
  1606
		}
sl@0
  1607
sl@0
  1608
	if (bytes == 0)
sl@0
  1609
		{
sl@0
  1610
		// ZLPs must be recorded separately
sl@0
  1611
		const TInt i = ep->iReceived ? 1 : 0;
sl@0
  1612
		ep->iPacketIndex[i] = r;
sl@0
  1613
		ep->iPacketSize[i] = 0;
sl@0
  1614
		// If there were data packets before: total packets reported 1 -> 2
sl@0
  1615
		ep->iPackets += i;
sl@0
  1616
		}
sl@0
  1617
sl@0
  1618
	if ((bytes < KBlkMaxPktSz) ||
sl@0
  1619
		(ep->iReceived == ep->iLength))
sl@0
  1620
		{
sl@0
  1621
		*ep->iPacketSize = ep->iReceived;
sl@0
  1622
		RxComplete(ep);
sl@0
  1623
		}
sl@0
  1624
	else
sl@0
  1625
		{
sl@0
  1626
		if (!ep->iRxTimerSet)
sl@0
  1627
			{
sl@0
  1628
			__KTRACE_OPT(KUSB, Kern::Printf(" > setting rx timer"));
sl@0
  1629
			ep->iRxTimerSet = ETrue;
sl@0
  1630
			ep->iRxTimer.OneShot(KRxTimerTimeout);
sl@0
  1631
			}
sl@0
  1632
		else
sl@0
  1633
			{
sl@0
  1634
			ep->iRxMoreDataRcvd = ETrue;
sl@0
  1635
			}
sl@0
  1636
		}
sl@0
  1637
sl@0
  1638
	// TO DO (optional): Clear Ep Rx condition flags here.
sl@0
  1639
sl@0
  1640
	}
sl@0
  1641
sl@0
  1642
sl@0
  1643
void TTemplateAsspUsbcc::IsoTransmit(TInt aEndpoint)
sl@0
  1644
//
sl@0
  1645
// Endpoint 3 (ISOCHRONOUS IN).
sl@0
  1646
//
sl@0
  1647
	{
sl@0
  1648
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IsoTransmit(%d)", aEndpoint));
sl@0
  1649
sl@0
  1650
	// TO DO: Write data to endpoint FIFO. Might be similar to BulkTransmit.
sl@0
  1651
sl@0
  1652
	}
sl@0
  1653
sl@0
  1654
sl@0
  1655
void TTemplateAsspUsbcc::IsoReceive(TInt aEndpoint)
sl@0
  1656
//
sl@0
  1657
// Endpoint 4 (ISOCHRONOUS OUT) (This one is called in an ISR.)
sl@0
  1658
//
sl@0
  1659
	{
sl@0
  1660
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IsoReceive(%d)", aEndpoint));
sl@0
  1661
sl@0
  1662
	// TO DO: Read data from endpoint FIFO. Might be similar to BulkReceive.
sl@0
  1663
	}
sl@0
  1664
sl@0
  1665
sl@0
  1666
void TTemplateAsspUsbcc::IsoReadRxFifo(TInt aEndpoint)
sl@0
  1667
//
sl@0
  1668
// Endpoint 4 (ISOCHRONOUS OUT) (This one is called w/o interrupt to be served.)
sl@0
  1669
//
sl@0
  1670
	{
sl@0
  1671
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IsoReadRxFifo(%d)", aEndpoint));
sl@0
  1672
sl@0
  1673
	// TO DO: Read data from endpoint FIFO. Might be similar to BulkReadRxFifo.
sl@0
  1674
	}
sl@0
  1675
sl@0
  1676
sl@0
  1677
void TTemplateAsspUsbcc::IntTransmit(TInt aEndpoint)
sl@0
  1678
//
sl@0
  1679
// Endpoint 5 (INTERRUPT IN).
sl@0
  1680
//
sl@0
  1681
	{
sl@0
  1682
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::IntTransmit(%d)", aEndpoint));
sl@0
  1683
sl@0
  1684
	// TO DO: Write data to endpoint FIFO. Might be similar to BulkTransmit.
sl@0
  1685
	}
sl@0
  1686
sl@0
  1687
sl@0
  1688
void TTemplateAsspUsbcc::RxComplete(TEndpoint* aEndpoint)
sl@0
  1689
//
sl@0
  1690
// Called at the end of an Rx (OUT) transfer to complete to the PIL.
sl@0
  1691
//
sl@0
  1692
	{
sl@0
  1693
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::RxComplete"));
sl@0
  1694
sl@0
  1695
	TUsbcRequestCallback* const req = aEndpoint->iRequest;
sl@0
  1696
sl@0
  1697
	__ASSERT_DEBUG((req != NULL), Kern::Fault(KUsbPanicCat, __LINE__));
sl@0
  1698
sl@0
  1699
	aEndpoint->iRxBuf = NULL;
sl@0
  1700
	aEndpoint->iRxTimerSet = EFalse;
sl@0
  1701
	aEndpoint->iRxMoreDataRcvd = EFalse;
sl@0
  1702
	req->iRxPackets = aEndpoint->iPackets;
sl@0
  1703
	req->iError = aEndpoint->iLastError;
sl@0
  1704
	EndpointRequestComplete(req);
sl@0
  1705
	aEndpoint->iRequest = NULL;
sl@0
  1706
	}
sl@0
  1707
sl@0
  1708
sl@0
  1709
void TTemplateAsspUsbcc::StopRxTimer(TEndpoint* aEndpoint)
sl@0
  1710
//
sl@0
  1711
// Stops (cancels) the Rx timer for an endpoint.
sl@0
  1712
//
sl@0
  1713
	{
sl@0
  1714
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::StopRxTimer"));
sl@0
  1715
sl@0
  1716
	if (aEndpoint->iRxTimerSet)
sl@0
  1717
		{
sl@0
  1718
		__KTRACE_OPT(KUSB, Kern::Printf(" > stopping rx timer"));
sl@0
  1719
		aEndpoint->iRxTimer.Cancel();
sl@0
  1720
		aEndpoint->iRxTimerSet = EFalse;
sl@0
  1721
		}
sl@0
  1722
	}
sl@0
  1723
sl@0
  1724
sl@0
  1725
void TTemplateAsspUsbcc::EndpointIntService(TInt aEndpoint)
sl@0
  1726
//
sl@0
  1727
// ISR for endpoint interrupts.
sl@0
  1728
// Note: the aEndpoint here is a "hardware endpoint", not a aRealEndpoint.
sl@0
  1729
//
sl@0
  1730
	{
sl@0
  1731
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::EndpointIntService(%d)", aEndpoint));
sl@0
  1732
sl@0
  1733
	switch (aEndpoint)
sl@0
  1734
		{
sl@0
  1735
	case 0:
sl@0
  1736
		Ep0IntService();
sl@0
  1737
		break;
sl@0
  1738
	case 1:
sl@0
  1739
		BulkTransmit(aEndpoint);
sl@0
  1740
		break;
sl@0
  1741
	case 2:
sl@0
  1742
		BulkReceive(aEndpoint);
sl@0
  1743
		break;
sl@0
  1744
	case 3:
sl@0
  1745
		IsoTransmit(aEndpoint);
sl@0
  1746
		break;
sl@0
  1747
	case 4:
sl@0
  1748
		IsoReceive(aEndpoint);
sl@0
  1749
		break;
sl@0
  1750
	case 5:
sl@0
  1751
		IntTransmit(aEndpoint);
sl@0
  1752
		break;
sl@0
  1753
	default:
sl@0
  1754
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Endpoint not found"));
sl@0
  1755
		break;
sl@0
  1756
		}
sl@0
  1757
	}
sl@0
  1758
sl@0
  1759
sl@0
  1760
TInt TTemplateAsspUsbcc::ResetIntService()
sl@0
  1761
//
sl@0
  1762
// ISR for a USB Reset event interrupt.
sl@0
  1763
// This function returns a value which can be used on the calling end to decide how to proceed.
sl@0
  1764
//
sl@0
  1765
	{
sl@0
  1766
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ResetIntService"));
sl@0
  1767
sl@0
  1768
	// Clear an interrupt:
sl@0
  1769
	// TO DO: Clear reset interrupt flag here.
sl@0
  1770
sl@0
  1771
	// TO DO (optional): Enquire about special conditions and possibly return here.
sl@0
  1772
sl@0
  1773
	DeviceEventNotification(EUsbEventReset);
sl@0
  1774
sl@0
  1775
	return KErrNone;
sl@0
  1776
	}
sl@0
  1777
sl@0
  1778
sl@0
  1779
void TTemplateAsspUsbcc::SuspendIntService()
sl@0
  1780
//
sl@0
  1781
// ISR for a USB Suspend event interrupt.
sl@0
  1782
//
sl@0
  1783
	{
sl@0
  1784
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SuspendIntService"));
sl@0
  1785
sl@0
  1786
	// Clear an interrupt:
sl@0
  1787
	// TO DO: Clear suspend interrupt flag here.
sl@0
  1788
sl@0
  1789
	DeviceEventNotification(EUsbEventSuspend);
sl@0
  1790
	}
sl@0
  1791
sl@0
  1792
sl@0
  1793
void TTemplateAsspUsbcc::ResumeIntService()
sl@0
  1794
//
sl@0
  1795
// ISR for a USB Resume event interrupt.
sl@0
  1796
//
sl@0
  1797
	{
sl@0
  1798
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ResumeIntService"));
sl@0
  1799
sl@0
  1800
	// Clear an interrupt:
sl@0
  1801
	// TO DO: Clear resume interrupt flag here.
sl@0
  1802
sl@0
  1803
	DeviceEventNotification(EUsbEventResume);
sl@0
  1804
	}
sl@0
  1805
sl@0
  1806
sl@0
  1807
void TTemplateAsspUsbcc::SofIntService()
sl@0
  1808
//
sl@0
  1809
// ISR for a USB Start-of-Frame event interrupt.
sl@0
  1810
//
sl@0
  1811
	{
sl@0
  1812
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SofIntService"));
sl@0
  1813
sl@0
  1814
	// Clear an interrupt:
sl@0
  1815
	// TO DO: Clear SOF interrupt flag here.
sl@0
  1816
sl@0
  1817
	// TO DO (optional): Do something about the SOF condition.
sl@0
  1818
	}
sl@0
  1819
sl@0
  1820
sl@0
  1821
void TTemplateAsspUsbcc::UdcInterruptService()
sl@0
  1822
//
sl@0
  1823
// Main UDC ISR - determines the cause of the interrupt, clears the condition, dispatches further for service.
sl@0
  1824
//
sl@0
  1825
	{
sl@0
  1826
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::InterruptService"));
sl@0
  1827
sl@0
  1828
	// TO DO: Find the cause of the interrupt (possibly querying a number of status registers) here.
sl@0
  1829
sl@0
  1830
	// Determine the type of UDC interrupt & then serve it:
sl@0
  1831
	// (The following operations are of course EXAMPLES only.)
sl@0
  1832
	volatile const TUint32* const status_reg = (TUint32*) 0xdefaced;
sl@0
  1833
	const TUint32 status = *status_reg;
sl@0
  1834
	enum {reset_interrupt, suspend_interrupt, resume_interrupt, sof_interrupt, ep_interrupt};
sl@0
  1835
sl@0
  1836
	// Reset interrupt
sl@0
  1837
	if (status & reset_interrupt)
sl@0
  1838
		{
sl@0
  1839
		ResetIntService();
sl@0
  1840
		}
sl@0
  1841
sl@0
  1842
	// Suspend interrupt
sl@0
  1843
	if (status & suspend_interrupt)
sl@0
  1844
		{
sl@0
  1845
		SuspendIntService();
sl@0
  1846
		}
sl@0
  1847
sl@0
  1848
	// Resume interrupt
sl@0
  1849
	if (status & resume_interrupt)
sl@0
  1850
		{
sl@0
  1851
		ResumeIntService();
sl@0
  1852
		}
sl@0
  1853
sl@0
  1854
	// Start-of-Frame interrupt
sl@0
  1855
	if (status & sof_interrupt)
sl@0
  1856
		{
sl@0
  1857
		SofIntService();
sl@0
  1858
		}
sl@0
  1859
sl@0
  1860
	// Endpoint interrupt
sl@0
  1861
	if (status & ep_interrupt)
sl@0
  1862
		{
sl@0
  1863
		const TInt ep = status & 0xffff0000;
sl@0
  1864
			{
sl@0
  1865
			EndpointIntService(ep);
sl@0
  1866
			}
sl@0
  1867
		}
sl@0
  1868
	}
sl@0
  1869
sl@0
  1870
sl@0
  1871
void TTemplateAsspUsbcc::Ep0NextState(TEp0State aNextState)
sl@0
  1872
//
sl@0
  1873
// Moves the Ep0 state to aNextState.
sl@0
  1874
//
sl@0
  1875
	{
sl@0
  1876
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::Ep0NextState"));
sl@0
  1877
sl@0
  1878
	iEp0State = aNextState;
sl@0
  1879
	}
sl@0
  1880
sl@0
  1881
sl@0
  1882
void TTemplateAsspUsbcc::UdcIsr(TAny* aPtr)
sl@0
  1883
//
sl@0
  1884
// This is the static ASSP first-level UDC interrupt service routine. It dispatches the call to the
sl@0
  1885
// actual controller's ISR.
sl@0
  1886
//
sl@0
  1887
	{
sl@0
  1888
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UdcIsr"));
sl@0
  1889
sl@0
  1890
	static_cast<TTemplateAsspUsbcc*>(aPtr)->UdcInterruptService();
sl@0
  1891
	}
sl@0
  1892
sl@0
  1893
sl@0
  1894
TInt TTemplateAsspUsbcc::UsbClientConnectorCallback(TAny* aPtr)
sl@0
  1895
//
sl@0
  1896
// This function is called in ISR context by the Variant's UsbClientConnectorInterruptService.
sl@0
  1897
// (This function is static.)
sl@0
  1898
//
sl@0
  1899
	{
sl@0
  1900
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::UsbClientConnectorCallback"));
sl@0
  1901
sl@0
  1902
	TTemplateAsspUsbcc* const ptr = static_cast<TTemplateAsspUsbcc*>(aPtr);
sl@0
  1903
	ptr->iCableConnected = ptr->iAssp->UsbClientConnectorInserted();
sl@0
  1904
#ifdef _DEBUG
sl@0
  1905
	_LIT(KIns, "inserted");
sl@0
  1906
	_LIT(KRem, "removed");
sl@0
  1907
	__KTRACE_OPT(KUSB, Kern::Printf(" > USB cable now %lS", ptr->iCableConnected ? &KIns : &KRem));
sl@0
  1908
#endif
sl@0
  1909
	if (ptr->iCableConnected)
sl@0
  1910
		{
sl@0
  1911
		ptr->DeviceEventNotification(EUsbEventCableInserted);
sl@0
  1912
		}
sl@0
  1913
	else
sl@0
  1914
		{
sl@0
  1915
		ptr->DeviceEventNotification(EUsbEventCableRemoved);
sl@0
  1916
		}
sl@0
  1917
sl@0
  1918
	return KErrNone;
sl@0
  1919
	}
sl@0
  1920
sl@0
  1921
sl@0
  1922
TInt TTemplateAsspUsbcc::SetupUdcInterrupt()
sl@0
  1923
//
sl@0
  1924
// Registers and enables the UDC interrupt (ASSP first level interrupt).
sl@0
  1925
//
sl@0
  1926
	{
sl@0
  1927
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::SetupUdcInterrupt"));
sl@0
  1928
sl@0
  1929
	// Register UDC interrupt:
sl@0
  1930
	const TInt error = Interrupt::Bind(EAsspIntIdUsb, UdcIsr, this);
sl@0
  1931
	if (error != KErrNone)
sl@0
  1932
		{
sl@0
  1933
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Binding UDC interrupt failed"));
sl@0
  1934
		return error;
sl@0
  1935
		}
sl@0
  1936
sl@0
  1937
	// Enable UDC interrupt:
sl@0
  1938
	Interrupt::Enable(EAsspIntIdUsb);
sl@0
  1939
sl@0
  1940
	return KErrNone;
sl@0
  1941
	}
sl@0
  1942
sl@0
  1943
sl@0
  1944
void TTemplateAsspUsbcc::ReleaseUdcInterrupt()
sl@0
  1945
//
sl@0
  1946
// Disables and unbinds the UDC interrupt.
sl@0
  1947
//
sl@0
  1948
	{
sl@0
  1949
	__KTRACE_OPT(KUSB, Kern::Printf("TTemplateAsspUsbcc::ReleaseUdcInterrupt"));
sl@0
  1950
sl@0
  1951
	// Disable UDC interrupt:
sl@0
  1952
	Interrupt::Disable(EAsspIntIdUsb);
sl@0
  1953
sl@0
  1954
	// Unregister UDC interrupt:
sl@0
  1955
	Interrupt::Unbind(EAsspIntIdUsb);
sl@0
  1956
	}
sl@0
  1957
sl@0
  1958
sl@0
  1959
//
sl@0
  1960
// --- DLL Exported Function --------------------------------------------------
sl@0
  1961
//
sl@0
  1962
sl@0
  1963
DECLARE_STANDARD_EXTENSION()
sl@0
  1964
//
sl@0
  1965
// Creates and initializes a new USB client controller object on the kernel heap.
sl@0
  1966
//
sl@0
  1967
	{
sl@0
  1968
	__KTRACE_OPT(KUSB, Kern::Printf(" > Initializing USB client support (Udcc)..."));
sl@0
  1969
sl@0
  1970
	TTemplateAsspUsbcc* const usbcc = new TTemplateAsspUsbcc();
sl@0
  1971
	if (!usbcc)
sl@0
  1972
		{
sl@0
  1973
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for TTemplateAsspUsbcc failed"));
sl@0
  1974
		return KErrNoMemory;
sl@0
  1975
		}
sl@0
  1976
sl@0
  1977
	TInt r;
sl@0
  1978
	if ((r = usbcc->Construct()) != KErrNone)
sl@0
  1979
		{
sl@0
  1980
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Construction of TTemplateAsspUsbcc failed (%d)", r));
sl@0
  1981
		delete usbcc;
sl@0
  1982
		return r;
sl@0
  1983
		}
sl@0
  1984
sl@0
  1985
	if (usbcc->RegisterUdc(0) == NULL)
sl@0
  1986
		{
sl@0
  1987
		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: PIL registration of PSL failed"));
sl@0
  1988
		delete usbcc;
sl@0
  1989
		return KErrGeneral;
sl@0
  1990
		}
sl@0
  1991
sl@0
  1992
	__KTRACE_OPT(KUSB, Kern::Printf(" > Initializing USB client support: Done"));
sl@0
  1993
sl@0
  1994
	return KErrNone;
sl@0
  1995
	}
sl@0
  1996
sl@0
  1997
sl@0
  1998
// --- EOF --------------------------------------------------------------------