From 91b1006d4299ab3f6beb74360c8efae0796144b5 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 1 Aug 2016 07:26:04 -0600 Subject: [PATCH] I/O Expander Interface: Add argument to interrupt callback. Add a method to detach the interrupt. --- drivers/ioexpander/pca9555.c | 61 ++++++++++++++++++++++----- drivers/ioexpander/pca9555.h | 1 + drivers/ioexpander/tca64xx.c | 59 +++++++++++++++++++++----- drivers/ioexpander/tca64xx.h | 1 + include/nuttx/ioexpander/ioexpander.h | 36 +++++++++++++--- 5 files changed, 130 insertions(+), 28 deletions(-) diff --git a/drivers/ioexpander/pca9555.c b/drivers/ioexpander/pca9555.c index ad0c19d5af..c473dfed3e 100644 --- a/drivers/ioexpander/pca9555.c +++ b/drivers/ioexpander/pca9555.c @@ -93,8 +93,10 @@ static int pca9555_multireadbuf(FAR struct ioexpander_dev_s *dev, FAR uint8_t *pins, FAR bool *values, int count); #endif #ifdef CONFIG_IOEXPANDER_INT_ENABLE -static int pca9555_attach(FAR struct ioexpander_dev_s *dev, - ioe_pinset_t pinset, ioe_callback_t callback); +static FAR void *pca9555_attach(FAR struct ioexpander_dev_s *dev, + ioe_pinset_t pinset, ioe_callback_t callback, FAR void *arg); +static int pca9555_detach(FAR struct ioexpander_dev_s *dev, + FAR void *handle); #endif /**************************************************************************** @@ -130,6 +132,7 @@ static const struct ioexpander_ops_s g_pca9555_ops = #endif #ifdef CONFIG_IOEXPANDER_INT_ENABLE , pca9555_attach + , pca9555_detach #endif }; @@ -701,24 +704,27 @@ static int pca9555_multireadbuf(FAR struct ioexpander_dev_s *dev, * Name: pca9555_attach * * Description: - * Attach a pin interrupt callback function. + * Attach and enable a pin interrupt callback function. * * Input Parameters: * dev - Device-specific state data * pinset - The set of pin events that will generate the callback * callback - The pointer to callback function. NULL will detach the * callback. + * arg - User-provided callback argument * * Returned Value: - * 0 on success, else a negative error code + * A non-NULL handle value is returned on success. This handle may be + * used later to detach and disable the pin interrupt. * ****************************************************************************/ -static int pca9555_attach(FAR struct ioexpander_dev_s *dev, - ioe_pinset_t pinset, ioe_callback_t callback) +static FAR void *pca9555_attach(FAR struct ioexpander_dev_s *dev, + ioe_pinset_t pinset, ioe_callback_t callback, + FAR void *arg) { FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s *)dev; - int ret; + FAR void *handle = NULL; int i; /* Get exclusive access to the PCA555 */ @@ -727,7 +733,6 @@ static int pca9555_attach(FAR struct ioexpander_dev_s *dev, /* Find and available in entry in the callback table */ - ret = -ENOSPC; for (i = 0; i < CONFIG_PCA9555_INT_NCALLBACKS; i++) { /* Is this entry available (i.e., no callback attached) */ @@ -738,14 +743,47 @@ static int pca9555_attach(FAR struct ioexpander_dev_s *dev, pca->cb[i].pinset = pinset; pca->cb[i].cbfunc = callback; - ret = OK; + pca->cb[i].cbarg = arg; + handle = &pca->cb[i]; + break; } } /* Add this callback to the table */ pca9555_unlock(pca); - return ret; + return handle; +} + +/**************************************************************************** + * Name: pca9555_detach + * + * Description: + * Detach and disable a pin interrupt callback function. + * + * Input Parameters: + * dev - Device-specific state data + * handle - The non-NULL opaque value return by pca9555_attch() + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int pca9555_detach(FAR struct ioexpander_dev_s *dev, FAR void *handle) +{ + FAR struct pca9555_dev_s *pca = (FAR struct pca9555_dev_s *)dev; + FAR struct pca9555_callback_s *cb = (FAR struct pca9555_callback_s *)handle; + + DEBUGASSERT(pca != NULL && cb != NULL); + DEBUGASSERT((uintptr_t)cb >= (uintptr_t)&pca->cb[0] && + (uintptr_t)cb <= (uintptr_t)&pca->cb[CONFIG_TCA64XX_INT_NCALLBACKS-1]); + UNUSED(pca); + + cb->pinset = 0; + cb->cbfunc = NULL; + cb->cbarg = NULL; + return OK; } /**************************************************************************** @@ -798,7 +836,8 @@ static void pca9555_irqworker(void *arg) { /* Yes.. perform the callback */ - (void)pca->cb[i].cbfunc(&pca->dev, match); + (void)pca->cb[i].cbfunc(&pca->dev, match, + pca->cb[i].cbarg); } } } diff --git a/drivers/ioexpander/pca9555.h b/drivers/ioexpander/pca9555.h index 77e276de5d..1782222592 100644 --- a/drivers/ioexpander/pca9555.h +++ b/drivers/ioexpander/pca9555.h @@ -134,6 +134,7 @@ struct pca9555_callback_s ioe_pinset_t pinset; /* Set of pin interrupts that will generate * the callback. */ ioe_callback_t cbfunc; /* The saved callback function pointer */ + FAR void *cbarg; /* Callback argument */ }; #endif diff --git a/drivers/ioexpander/tca64xx.c b/drivers/ioexpander/tca64xx.c index 3a9922721b..1cde899b45 100644 --- a/drivers/ioexpander/tca64xx.c +++ b/drivers/ioexpander/tca64xx.c @@ -105,8 +105,9 @@ static int tca64_multireadpin(FAR struct ioexpander_dev_s *dev, FAR uint8_t *pins, FAR bool *values, int count); #endif #ifdef CONFIG_IOEXPANDER_INT_ENABLE -static int tca64_attach(FAR struct ioexpander_dev_s *dev, - ioe_pinset_t pinset, ioe_callback_t callback); +static FAR void *tca64_attach(FAR struct ioexpander_dev_s *dev, + ioe_pinset_t pinset, ioe_callback_t callback, FAR void *arg); +static int tca64_detach(FAR struct ioexpander_dev_s *dev, FAR void *handle); #endif #ifdef CONFIG_TCA64XX_INT_ENABLE @@ -148,6 +149,7 @@ static const struct ioexpander_ops_s g_tca64_ops = #endif #ifdef CONFIG_IOEXPANDER_INT_ENABLE , tca64_attach + , tca64_detach #endif }; @@ -932,25 +934,28 @@ errout_with_lock: * Name: tca64_attach * * Description: - * Attach a pin interrupt callback function. + * Attach and enable a pin interrupt callback function. * * Input Parameters: * dev - Device-specific state data * pinset - The set of pin events that will generate the callback * callback - The pointer to callback function. NULL will detach the * callback. + * arg - User-provided callback argument * * Returned Value: - * 0 on success, else a negative error code + * A non-NULL handle value is returned on success. This handle may be + * used later to detach and disable the pin interrupt. * ****************************************************************************/ #ifdef CONFIG_TCA64XX_INT_ENABLE -static int tca64_attach(FAR struct ioexpander_dev_s *dev, ioe_pinset_t pinset, - ioe_callback_t callback) +static FAR void *tca64_attach(FAR struct ioexpander_dev_s *dev, + ioe_pinset_t pinset, ioe_callback_t callback, + FAR void *arg) { FAR struct tca64_dev_s *priv = (FAR struct tca64_dev_s *)dev; - int ret; + FAR void *handle = NULL; int i; /* Get exclusive access to the I/O Expander */ @@ -959,7 +964,6 @@ static int tca64_attach(FAR struct ioexpander_dev_s *dev, ioe_pinset_t pinset, /* Find and available in entry in the callback table */ - ret = -ENOSPC; for (i = 0; i < CONFIG_TCA64XX_INT_NCALLBACKS; i++) { /* Is this entry available (i.e., no callback attached) */ @@ -970,16 +974,48 @@ static int tca64_attach(FAR struct ioexpander_dev_s *dev, ioe_pinset_t pinset, priv->cb[i].pinset = pinset; priv->cb[i].cbfunc = callback; - ret = OK; + priv->cb[i].cbarg = arg; + handle = &priv->cb[i]; break; } } tca64_unlock(priv); - return ret; + return handle; } #endif +/**************************************************************************** + * Name: tca64_detach + * + * Description: + * Detach and disable a pin interrupt callback function. + * + * Input Parameters: + * dev - Device-specific state data + * handle - The non-NULL opaque value return by tca64_attch() + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int tca64_detach(FAR struct ioexpander_dev_s *dev, FAR void *handle) +{ + FAR struct tca64_dev_s *priv = (FAR struct tca64_dev_s *)dev; + FAR struct tca64_callback_s *cb = (FAR struct tca64_callback_s *)handle; + + DEBUGASSERT(priv != NULL && cb != NULL); + DEBUGASSERT((uintptr_t)cb >= (uintptr_t)&priv->cb[0] && + (uintptr_t)cb <= (uintptr_t)&priv->cb[CONFIG_TCA64XX_INT_NCALLBACKS-1]); + UNUSED(priv); + + cb->pinset = 0; + cb->cbfunc = NULL; + cb->cbarg = NULL; + return OK; +} + /**************************************************************************** * Name: tca64_int_update * @@ -1170,7 +1206,8 @@ static void tca64_irqworker(void *arg) { /* Yes.. perform the callback */ - (void)priv->cb[i].cbfunc(&priv->dev, match); + (void)priv->cb[i].cbfunc(&priv->dev, match, + priv->cb[i].cbarg); } } } diff --git a/drivers/ioexpander/tca64xx.h b/drivers/ioexpander/tca64xx.h index 704fbc8c81..24d036a1e8 100644 --- a/drivers/ioexpander/tca64xx.h +++ b/drivers/ioexpander/tca64xx.h @@ -231,6 +231,7 @@ struct tca64_callback_s ioe_pinset_t pinset; /* Set of pin interrupts that will generate * the callback. */ ioe_callback_t cbfunc; /* The saved callback function pointer */ + FAR void *cbarg; /* Callback argument */ }; #endif diff --git a/include/nuttx/ioexpander/ioexpander.h b/include/nuttx/ioexpander/ioexpander.h index 6557f9f7be..d1615aac1b 100644 --- a/include/nuttx/ioexpander/ioexpander.h +++ b/include/nuttx/ioexpander/ioexpander.h @@ -247,13 +247,35 @@ * Name: IOEP_ATTACH * * Description: - * Attach a pin interrupt callback function. + * Attach and enable a pin interrupt callback function. * * Input Parameters: * dev - Device-specific state data * pinset - The set of pin events that will generate the callback * callback - The pointer to callback function. NULL will detach the * callback. + * arg - User-provided callback argument + * + * Returned Value: + * A non-NULL handle value is returned on success. This handle may be + * used later to detach and disable the pin interrupt. + * + ****************************************************************************/ + +#ifdef CONFIG_IOEXPANDER_INT_ENABLE +#define IOEP_ATTACH(dev,pinset,callback,arg) \ + ((dev)->ops->ioe_attach(dev,pins,callback,arg)) +#endif + +/**************************************************************************** + * Name: IOEP_DETACH + * + * Description: + * Detach and disable a pin interrupt callback function. + * + * Input Parameters: + * dev - Device-specific state data + * handle - The non-NULL opaque value return by IOEP_ATTACH * * Returned Value: * 0 on success, else a negative error code @@ -261,8 +283,7 @@ ****************************************************************************/ #ifdef CONFIG_IOEXPANDER_INT_ENABLE -#define IOEP_ATTACH(dev,pinset,callback) \ - ((dev)->ops->ioe_attach(dev,pins,callback)) +#define IOEP_DETACH(dev,handle) (dev)->ops->ioe_detach(dev,handle)) #endif /**************************************************************************** @@ -286,7 +307,7 @@ typedef uint64_t ioe_pinset_t; struct ioexpander_dev_s; typedef int (*ioe_callback_t)(FAR struct ioexpander_dev_s *dev, - ioe_pinset_t pinset); + ioe_pinset_t pinset, FAR void *arg); #endif /* CONFIG_IOEXPANDER_INT_ENABLE */ /* I/O expander interface methods */ @@ -313,8 +334,11 @@ struct ioexpander_ops_s uint8_t *pins, bool *values, int count); #endif #ifdef CONFIG_IOEXPANDER_INT_ENABLE - CODE int (*ioe_attach)(FAR struct ioexpander_dev_s *dev, - ioe_pinset_t pinset, ioe_callback_t callback); + CODE FAR void *(*ioe_attach)(FAR struct ioexpander_dev_s *dev, + ioe_pinset_t pinset, + ioe_callback_t callback, FAR void *arg); + CODE int (*ioe_detach)(FAR struct ioexpander_dev_s *dev, + FAR void *handle); #endif };