sl@0: /* sl@0: * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: const TInt32 KHwGpioPinMax = 0; // TO DO: max pin number this GPIO chip supports sl@0: const TInt32 KIntIdGpio = 0; // TO DO: need to define which interrupt the GPIO chip is attached to sl@0: sl@0: // sl@0: // TO DO: if the GPIO chip doesn't support specific features sl@0: // such as debouncing or pin modes, then it may be sl@0: // necessary to store them ourselves in an array of GpioPins sl@0: // other features such as pin bias or idle configurations sl@0: // may be left as KErrNotSupported sl@0: // sl@0: class GpioPin sl@0: { sl@0: public: sl@0: TGpioIsr iIsr; // e.g. we may want to remeber the isr attached to a pin sl@0: TAny * iPtr; // argument to pass to isr sl@0: }; sl@0: sl@0: static GpioPin GpioPins[KHwGpioPinMax+1]; sl@0: sl@0: static TInt32 GpioInterruptId; // place to store interrupt handle returned from Interrupt::Bind() sl@0: sl@0: /** sl@0: GPIO interrupt handler sl@0: generic argument (TAny*) is a pointer to the GpioPins array sl@0: */ sl@0: void GpioIsrDispatch(TAny *aPtr) sl@0: { sl@0: // TO DO: work out which pins have interrupts pending sl@0: // and dispatch the appropriate ISR sl@0: GpioPin *pins = (GpioPin *)aPtr; sl@0: TUint32 interrupt = 0xff; // TO DO: read gpio pending interupts sl@0: TUint32 enabled = 0x00; // TO DO: read gpio enabled interupts sl@0: TUint32 masked = interrupt & enabled; // TO DO: read masked interrupts sl@0: sl@0: // check each pin and dispatch ISR if necessary sl@0: for (TInt i = 0; i <= KHwGpioPinMax; i++) sl@0: { sl@0: if ((masked & 0x1) && (pins[i].iIsr != NULL)) sl@0: { sl@0: // we have a pending interrupt and a registered ISR sl@0: (*pins[i].iIsr)(pins[i].iPtr); // dispatch this pin's ISR sl@0: } sl@0: masked >>= 1; sl@0: } sl@0: Interrupt::Clear(GpioInterruptId); sl@0: } sl@0: sl@0: sl@0: EXPORT_C TInt GPIO::SetPinMode sl@0: ( sl@0: TInt aId, sl@0: TGpioMode aMode sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: store pin mode and return sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetPinMode sl@0: ( sl@0: TInt aId, sl@0: TGpioMode & aMode sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set aMode = pin mode sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetPinDirection sl@0: ( sl@0: TInt aId, sl@0: TGpioDirection aDirection sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax || aDirection == ETriStated) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: if we support setting the pin direction then do it here sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetPinDirection sl@0: ( sl@0: TInt aId, sl@0: TGpioDirection & aDirection sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: if we support getting the pin direction then do it here sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetPinBias sl@0: ( sl@0: TInt aId, sl@0: TGpioBias aBias sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: if we support setting the pin bias then do it here sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetPinBias sl@0: ( sl@0: TInt aId, sl@0: TGpioBias & aBias sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: if we support getting the pin bias then do it here sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetPinIdleConfigurationAndState sl@0: ( sl@0: TInt aId, sl@0: TInt /*aConf*/ sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: if we support setting the pin idle config then do it here sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetPinIdleConfigurationAndState sl@0: ( sl@0: TInt aId, sl@0: TInt & aBias sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: if we support getting the pin idle config then do it here sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::BindInterrupt sl@0: ( sl@0: TInt aId, sl@0: TGpioIsr aIsr, sl@0: TAny * aPtr sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax || aIsr == NULL) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (GpioPins[aId].iIsr != NULL) sl@0: { sl@0: // already bound sl@0: return KErrInUse; sl@0: } sl@0: // record isr and arg bound to this pin sl@0: GpioPins[aId].iIsr = aIsr; sl@0: GpioPins[aId].iPtr = aPtr; sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::UnbindInterrupt sl@0: ( sl@0: TInt aId sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (GpioPins[aId].iIsr == NULL) sl@0: { sl@0: // nothing bound sl@0: return KErrGeneral; sl@0: } sl@0: // NULL isr bound to this pin sl@0: GpioPins[aId].iIsr = NULL; sl@0: GpioPins[aId].iPtr = NULL; sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::EnableInterrupt sl@0: ( sl@0: TInt aId sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (GpioPins[aId].iIsr == NULL) sl@0: { sl@0: // nothing bound sl@0: return KErrGeneral; sl@0: } sl@0: // TODO: enable interrupts on this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::DisableInterrupt sl@0: ( sl@0: TInt aId sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (GpioPins[aId].iIsr == NULL) sl@0: { sl@0: // nothing bound sl@0: return KErrGeneral; sl@0: } sl@0: // TODO: disable interrupts on this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::IsInterruptEnabled sl@0: ( sl@0: TInt aId, sl@0: TBool & aEnable sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (GpioPins[aId].iIsr == NULL) sl@0: { sl@0: // nothing bound sl@0: return KErrGeneral; sl@0: } sl@0: // TO DO: are interrupts enabled on this pin ? sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::ClearInterrupt sl@0: ( sl@0: TInt aId sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (GpioPins[aId].iIsr == NULL) sl@0: { sl@0: // nothing bound sl@0: return KErrGeneral; sl@0: } sl@0: // TO DO: clear pin interrupt status sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetMaskedInterruptState sl@0: ( sl@0: TInt aId, sl@0: TBool & aActive sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set aActive to masked interrupt state sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetRawInterruptState sl@0: ( sl@0: TInt aId, sl@0: TBool & aActive sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set aActive to raw (unmasked) interrupt state sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetInterruptTrigger sl@0: ( sl@0: TInt aId, sl@0: TGpioDetectionTrigger aTrigger sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set interrupt trigger on this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::EnableWakeup sl@0: ( sl@0: TInt aId sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: enable wakeup on this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::DisableWakeup sl@0: ( sl@0: TInt aId sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: disable wakeup on this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::IsWakeupEnabled sl@0: ( sl@0: TInt aId, sl@0: TBool & aEnable sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set aEnable wakeup state for this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetWakeupTrigger sl@0: ( sl@0: TInt aId, sl@0: TGpioDetectionTrigger aTrigger sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set wakeup trigger on this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetDebounceTime sl@0: ( sl@0: TInt aId, sl@0: TInt aTime sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set debounce time for this pin sl@0: // it may be necessary to emulate debouncing ourselves sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetDebounceTime sl@0: ( sl@0: TInt aId, sl@0: TInt & aTime sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: get debounce time for this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetInputState sl@0: ( sl@0: TInt aId, sl@0: TGpioState & aState sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: read the input state of this pin sl@0: // if debouncing is handled by the driver here sl@0: // is where we will need to work out what the sl@0: // debounced state is sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetOutputState sl@0: ( sl@0: TInt aId, sl@0: TGpioState aState sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set the output state of this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetOutputState sl@0: ( sl@0: TInt aId, sl@0: TGpioState & aState sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: get the output state of this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::GetInputState sl@0: ( sl@0: TInt aId, sl@0: TGpioCallback * aCb sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: get the input state of this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::SetOutputState sl@0: ( sl@0: TInt aId, sl@0: TGpioState aState, sl@0: TGpioCallback * aCb sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: set the ouput state of this pin sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TInt GPIO::StaticExtension sl@0: ( sl@0: TInt aId, sl@0: TInt aCmd, sl@0: TAny * aArg1, sl@0: TAny * aArg2 sl@0: ) sl@0: { sl@0: if (aId < 0 || aId > KHwGpioPinMax) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: // TO DO: call the appropriate static extension if supported sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: sl@0: // sl@0: // entry point for GPIO setup sl@0: // sl@0: DECLARE_STANDARD_EXTENSION() sl@0: { sl@0: sl@0: // initialise GPIO pins array (if necessary) sl@0: for (TInt32 i = 0; i <= KHwGpioPinMax; i++) sl@0: { sl@0: GpioPins[i].iIsr = NULL; sl@0: GpioPins[i].iPtr = NULL; sl@0: } sl@0: // bind and enable GPIO Isr sl@0: // NB Interrupt::Bind() now returns a handle (-ve value means an error) sl@0: TInt r = Interrupt::Bind(KIntIdGpio, GpioIsrDispatch, &GpioPins[0]); sl@0: if (r < 0) sl@0: { sl@0: return r; sl@0: } sl@0: // store handle sl@0: GpioInterruptId = r; sl@0: // NB Interrupt::Enable() now expects the handle return from Bind sl@0: r = Interrupt::Enable(r); sl@0: return r; sl@0: }