mirror of
https://github.com/apache/nuttx.git
synced 2025-12-10 12:14:36 +08:00
drivers/input/ft5x06: Adapt to touchscreen frame
Calling touch_register() to register touchscreen driver instead of registering generic driver. Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
This commit is contained in:
committed by
Alan C. Assis
parent
ed1384fc81
commit
770d4a6c86
@@ -218,12 +218,6 @@ config FT5X06_POLLMODE
|
||||
in detecting touch related events and (2) it will consume a
|
||||
significant amount of CPU time to perform the polling.
|
||||
|
||||
config FT5X06_SWAPXY
|
||||
bool "Swap X/Y"
|
||||
default n
|
||||
---help---
|
||||
Reverse the meaning of X and Y to handle different LCD orientations.
|
||||
|
||||
config FT5X06_SINGLEPOINT
|
||||
bool "Single point"
|
||||
default n
|
||||
@@ -252,11 +246,11 @@ config FT5X06_THRESHY
|
||||
|
||||
endif # FT5X06_SINGLEPOINT
|
||||
|
||||
config FT5X06_NPOLLWAITERS
|
||||
int "Number FT5336/FT5x06 poll waiters"
|
||||
default 4
|
||||
---help---
|
||||
Maximum number of threads that can be waiting on poll()
|
||||
config FT5X06_SAMPLE_NBUFFER
|
||||
int "Number FT5336/FT5x06 sample buffers"
|
||||
default 4
|
||||
---help---
|
||||
Maximum number of samples buffered.
|
||||
|
||||
endif # INPUT_FT5X06
|
||||
|
||||
|
||||
@@ -97,10 +97,7 @@
|
||||
|
||||
struct ft5x06_dev_s
|
||||
{
|
||||
uint8_t crefs; /* Number of times the device
|
||||
* has been opened */
|
||||
uint8_t nwaiters; /* Number of threads waiting for
|
||||
* FT5x06 data */
|
||||
struct ft5x06_config_s config; /* Board configuration data */
|
||||
volatile bool valid; /* True: New, valid touch data
|
||||
* in touchbuf[] */
|
||||
#ifdef CONFIG_FT5X06_SINGLEPOINT
|
||||
@@ -111,14 +108,11 @@ struct ft5x06_dev_s
|
||||
#endif
|
||||
mutex_t devlock; /* Manages exclusive access to
|
||||
* this structure */
|
||||
sem_t waitsem; /* Used to wait for the
|
||||
* availability of data */
|
||||
uint32_t frequency; /* Current I2C frequency */
|
||||
#ifdef CONFIG_FT5X06_POLLMODE
|
||||
uint32_t delay; /* Current poll delay */
|
||||
#endif
|
||||
|
||||
FAR const struct ft5x06_config_s *config; /* Board configuration data */
|
||||
FAR struct i2c_master_s *i2c; /* Saved I2C driver instance */
|
||||
struct work_s work; /* Supports the interrupt
|
||||
* handling "bottom half" */
|
||||
@@ -126,13 +120,6 @@ struct ft5x06_dev_s
|
||||
struct wdog_s polltimer; /* Poll timer */
|
||||
#endif
|
||||
uint8_t touchbuf[FT5X06_TOUCH_DATA_LEN]; /* Raw touch data */
|
||||
|
||||
/* The following is a list if poll structures of threads waiting for
|
||||
* driver events. The 'struct pollfd' reference for each open is also
|
||||
* retained in the f_priv field of the 'struct file'.
|
||||
*/
|
||||
|
||||
FAR struct pollfd *fds[CONFIG_FT5X06_NPOLLWAITERS];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -148,41 +135,15 @@ static int ft5x06_data_interrupt(int irq, FAR void *context, FAR void *arg);
|
||||
#endif
|
||||
static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer,
|
||||
size_t len);
|
||||
static ssize_t ft5x06_waitsample(FAR struct ft5x06_dev_s *priv,
|
||||
FAR char *buffer, size_t len);
|
||||
static int ft5x06_bringup(FAR struct ft5x06_dev_s *priv);
|
||||
static void ft5x06_shutdown(FAR struct ft5x06_dev_s *priv);
|
||||
|
||||
/* Character driver methods */
|
||||
|
||||
static int ft5x06_open(FAR struct file *filep);
|
||||
static int ft5x06_close(FAR struct file *filep);
|
||||
static ssize_t ft5x06_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t len);
|
||||
static int ft5x06_ioctl(FAR struct file *filep, int cmd,
|
||||
static int ft5x06_bringup(FAR struct touch_lowerhalf_s *lower);
|
||||
static int ft5x06_shutdown(FAR struct touch_lowerhalf_s *lower);
|
||||
static int ft5x06_ioctl(FAR struct touch_lowerhalf_s *lower, int cmd,
|
||||
unsigned long arg);
|
||||
static int ft5x06_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This the vtable that supports the character driver interface */
|
||||
|
||||
static const struct file_operations g_ft5x06_fops =
|
||||
{
|
||||
ft5x06_open, /* open */
|
||||
ft5x06_close, /* close */
|
||||
ft5x06_read, /* read */
|
||||
NULL, /* write */
|
||||
NULL, /* seek */
|
||||
ft5x06_ioctl, /* ioctl */
|
||||
NULL, /* mmap */
|
||||
NULL, /* truncate */
|
||||
ft5x06_poll /* poll */
|
||||
};
|
||||
|
||||
/* Maps FT5x06 touch events into bit encoded representation used by NuttX */
|
||||
|
||||
static const uint8_t g_event_map[4] =
|
||||
@@ -203,25 +164,12 @@ static const uint8_t g_event_map[4] =
|
||||
|
||||
static void ft5x06_notify(FAR struct ft5x06_dev_s *priv)
|
||||
{
|
||||
/* If there are threads waiting on poll() for FT5x06 data to become
|
||||
* available, then wake them up now. NOTE: we wake up all waiting threads
|
||||
* because we do not know that they are going to do. If they all try to
|
||||
* read the data, then some make end up blocking after all.
|
||||
*/
|
||||
struct touch_sample_s sample;
|
||||
|
||||
poll_notify(priv->fds, CONFIG_FT5X06_NPOLLWAITERS, POLLIN);
|
||||
|
||||
/* If there are threads waiting for read data, then signal one of them
|
||||
* that the read data is available.
|
||||
*/
|
||||
|
||||
if (priv->nwaiters > 0)
|
||||
memset(&sample, 0, sizeof(sample));
|
||||
if (ft5x06_sample(priv, (FAR char *)&sample, sizeof(sample)) > 0)
|
||||
{
|
||||
/* After posting this semaphore, we need to exit because the FT5x06
|
||||
* is no longer available.
|
||||
*/
|
||||
|
||||
nxsem_post(&priv->waitsem);
|
||||
touch_event(priv->config.lower.priv, &sample);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,8 +188,8 @@ static void ft5x06_data_worker(FAR void *arg)
|
||||
|
||||
/* Get a pointer the callbacks for convenience */
|
||||
|
||||
DEBUGASSERT(priv != NULL && priv->config != NULL);
|
||||
config = priv->config;
|
||||
DEBUGASSERT(priv != NULL);
|
||||
config = &priv->config;
|
||||
|
||||
/* We need to have exclusive access to the touchbuf so that we do not
|
||||
* corrupt any read operation that is in place.
|
||||
@@ -374,7 +322,7 @@ static int ft5x06_data_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
* ugly).
|
||||
*/
|
||||
|
||||
config = priv->config;
|
||||
config = &priv->config;
|
||||
DEBUGASSERT(config != NULL);
|
||||
|
||||
/* Disable further interrupts */
|
||||
@@ -429,13 +377,8 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer,
|
||||
|
||||
/* Get the reported X and Y positions */
|
||||
|
||||
#ifdef CONFIG_FT5X06_SWAPXY
|
||||
y = TOUCH_POINT_GET_X(touch[0]);
|
||||
x = TOUCH_POINT_GET_Y(touch[0]);
|
||||
#else
|
||||
x = TOUCH_POINT_GET_X(touch[0]);
|
||||
y = TOUCH_POINT_GET_Y(touch[0]);
|
||||
#endif
|
||||
|
||||
/* Get the touch point ID and event */
|
||||
|
||||
@@ -582,13 +525,8 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer,
|
||||
|
||||
point[i].id = TOUCH_POINT_GET_ID(touch[i]);
|
||||
point[i].flags = g_event_map[event];
|
||||
#ifdef CONFIG_FT5X06_SWAPXY
|
||||
point[i].y = TOUCH_POINT_GET_X(touch[i]);
|
||||
point[i].x = TOUCH_POINT_GET_Y(touch[i]);
|
||||
#else
|
||||
point[i].x = TOUCH_POINT_GET_X(touch[i]);
|
||||
point[i].y = TOUCH_POINT_GET_Y(touch[i]);
|
||||
#endif
|
||||
point[i].h = 0;
|
||||
point[i].w = 0;
|
||||
point[i].pressure = 0;
|
||||
@@ -599,71 +537,13 @@ static ssize_t ft5x06_sample(FAR struct ft5x06_dev_s *priv, FAR char *buffer,
|
||||
}
|
||||
#endif /* CONFIG_FT5X06_SINGLEPOINT */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ft5x06_waitsample
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t ft5x06_waitsample(FAR struct ft5x06_dev_s *priv,
|
||||
FAR char *buffer, size_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Now release the semaphore that manages mutually exclusive access to
|
||||
* the device structure. This may cause other tasks to become ready to
|
||||
* run, but they cannot run yet because pre-emption is disabled.
|
||||
*/
|
||||
|
||||
nxmutex_unlock(&priv->devlock);
|
||||
|
||||
/* Try to get the a sample... if we cannot, then wait on the semaphore
|
||||
* that is posted when new sample data is available.
|
||||
*/
|
||||
|
||||
while (!priv->valid)
|
||||
{
|
||||
/* Increment the count of waiters */
|
||||
|
||||
priv->nwaiters++;
|
||||
|
||||
/* Wait for a change in the FT5x06 state */
|
||||
|
||||
ret = nxsem_wait(&priv->waitsem);
|
||||
priv->nwaiters--;
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ierr("ERROR: nxsem_wait failed: %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* Re-acquire the semaphore that manages mutually exclusive access to
|
||||
* the device structure. We may have to wait here. But we have our
|
||||
* sample. Interrupts and pre-emption will be re-enabled while we wait.
|
||||
*/
|
||||
|
||||
ret = nxmutex_lock(&priv->devlock);
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Now sample the data.
|
||||
*
|
||||
* REVISIT: Is it safe to assume that priv->valid will always be
|
||||
* true? I think that sched_lock() would protect the setting.
|
||||
*/
|
||||
|
||||
ret = ft5x06_sample(priv, buffer, len);
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ft5x06_bringup
|
||||
****************************************************************************/
|
||||
|
||||
static int ft5x06_bringup(FAR struct ft5x06_dev_s *priv)
|
||||
static int ft5x06_bringup(FAR struct touch_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct ft5x06_dev_s *priv = (FAR struct ft5x06_dev_s *)lower;
|
||||
FAR const struct ft5x06_config_s *config;
|
||||
struct i2c_msg_s msg;
|
||||
uint8_t data[2];
|
||||
@@ -673,7 +553,7 @@ static int ft5x06_bringup(FAR struct ft5x06_dev_s *priv)
|
||||
* ugly).
|
||||
*/
|
||||
|
||||
config = priv->config;
|
||||
config = &priv->config;
|
||||
DEBUGASSERT(config != NULL);
|
||||
|
||||
/* Set device mode to normal operation */
|
||||
@@ -706,215 +586,38 @@ static int ft5x06_bringup(FAR struct ft5x06_dev_s *priv)
|
||||
* Name: ft5x06_shutdown
|
||||
****************************************************************************/
|
||||
|
||||
static void ft5x06_shutdown(FAR struct ft5x06_dev_s *priv)
|
||||
static int ft5x06_shutdown(FAR struct touch_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct ft5x06_dev_s *priv = (FAR struct ft5x06_dev_s *)lower;
|
||||
|
||||
#ifdef CONFIG_FT5X06_POLLMODE
|
||||
/* Stop the poll timer */
|
||||
|
||||
wd_cancel(&priv->polltimer);
|
||||
|
||||
#else
|
||||
FAR const struct ft5x06_config_s *config = priv->config;
|
||||
FAR const struct ft5x06_config_s *config = &priv->config;
|
||||
|
||||
/* Make sure that the FT5x06 interrupt is disabled */
|
||||
|
||||
config->clear(config);
|
||||
config->enable(config, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ft5x06_open
|
||||
****************************************************************************/
|
||||
|
||||
static int ft5x06_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct ft5x06_dev_s *priv;
|
||||
uint8_t tmp;
|
||||
int ret;
|
||||
|
||||
inode = filep->f_inode;
|
||||
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = inode->i_private;
|
||||
|
||||
/* Get exclusive access to the driver data structure */
|
||||
|
||||
ret = nxmutex_lock(&priv->devlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
ierr("ERROR: nxmutex_lock failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Increment the reference count */
|
||||
|
||||
tmp = priv->crefs + 1;
|
||||
if (tmp == 0)
|
||||
{
|
||||
/* More than 255 opens; uint8_t overflows to zero */
|
||||
|
||||
ret = -EMFILE;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
/* When the reference increments to 1, this is the first open event
|
||||
* on the driver.. and the time when we must initialize the driver.
|
||||
*/
|
||||
|
||||
if (tmp == 1)
|
||||
{
|
||||
ret = ft5x06_bringup(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
ierr("ERROR: ft5x06_bringup failed: %d\n", ret);
|
||||
goto errout_with_lock;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the new open count on success */
|
||||
|
||||
priv->crefs = tmp;
|
||||
|
||||
errout_with_lock:
|
||||
nxmutex_unlock(&priv->devlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ft5x06_close
|
||||
****************************************************************************/
|
||||
|
||||
static int ft5x06_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct ft5x06_dev_s *priv;
|
||||
int ret;
|
||||
|
||||
inode = filep->f_inode;
|
||||
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = inode->i_private;
|
||||
|
||||
/* Get exclusive access to the driver data structure */
|
||||
|
||||
ret = nxmutex_lock(&priv->devlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
ierr("ERROR: nxmutex_lock failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Decrement the reference count unless it would decrement a negative
|
||||
* value.
|
||||
*/
|
||||
|
||||
if (priv->crefs >= 1)
|
||||
{
|
||||
priv->crefs--;
|
||||
}
|
||||
|
||||
/* When the count decrements to zero, there are no further open references
|
||||
* to the driver and it can be uninitialized.
|
||||
*/
|
||||
|
||||
if (priv->crefs == 0)
|
||||
{
|
||||
ft5x06_shutdown(priv);
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->devlock);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ft5x06_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t ft5x06_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct ft5x06_dev_s *priv;
|
||||
int ret;
|
||||
|
||||
inode = filep->f_inode;
|
||||
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = inode->i_private;
|
||||
|
||||
/* Verify that the caller has provided a buffer large enough to receive
|
||||
* the touch data.
|
||||
*/
|
||||
|
||||
if (len < SIZEOF_TOUCH_SAMPLE_S(1))
|
||||
{
|
||||
/* We could provide logic to break up a touch report into segments and
|
||||
* handle smaller reads... but why?
|
||||
*/
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* Get exclusive access to the driver data structure */
|
||||
|
||||
ret = nxmutex_lock(&priv->devlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
ierr("ERROR: nxmutex_lock failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Try to read sample data. */
|
||||
|
||||
ret = ft5x06_sample(priv, buffer, len);
|
||||
while (ret == 0)
|
||||
{
|
||||
/* Sample data is not available now. We would have to wait to receive
|
||||
* sample data. If the user has specified the O_NONBLOCK option, then
|
||||
* just return an error.
|
||||
*/
|
||||
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Wait for sample data */
|
||||
|
||||
ret = ft5x06_waitsample(priv, buffer, len);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* We might have been awakened by a signal */
|
||||
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
ret = SIZEOF_TOUCH_SAMPLE_S(1);
|
||||
|
||||
errout:
|
||||
nxmutex_unlock(&priv->devlock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ft5x06_ioctl
|
||||
****************************************************************************/
|
||||
|
||||
static int ft5x06_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
static int ft5x06_ioctl(FAR struct touch_lowerhalf_s *lower, int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct ft5x06_dev_s *priv;
|
||||
FAR struct ft5x06_dev_s *priv = (FAR struct ft5x06_dev_s *)lower;
|
||||
int ret;
|
||||
|
||||
iinfo("cmd: %d arg: %ld\n", cmd, arg);
|
||||
inode = filep->f_inode;
|
||||
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = inode->i_private;
|
||||
|
||||
/* Get exclusive access to the driver data structure */
|
||||
|
||||
@@ -932,7 +635,7 @@ static int ft5x06_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
case TSIOC_SETFREQUENCY: /* arg: Pointer to uint32_t frequency value */
|
||||
{
|
||||
FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
|
||||
DEBUGASSERT(priv->config != NULL && ptr != NULL);
|
||||
DEBUGASSERT(ptr != NULL);
|
||||
priv->frequency = *ptr;
|
||||
}
|
||||
break;
|
||||
@@ -940,7 +643,7 @@ static int ft5x06_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
case TSIOC_GETFREQUENCY: /* arg: Pointer to uint32_t frequency value */
|
||||
{
|
||||
FAR uint32_t *ptr = (FAR uint32_t *)((uintptr_t)arg);
|
||||
DEBUGASSERT(priv->config != NULL && ptr != NULL);
|
||||
DEBUGASSERT(ptr != NULL);
|
||||
*ptr = priv->frequency;
|
||||
}
|
||||
break;
|
||||
@@ -954,101 +657,6 @@ static int ft5x06_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ft5x06_poll
|
||||
****************************************************************************/
|
||||
|
||||
static int ft5x06_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup)
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct ft5x06_dev_s *priv;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
iinfo("setup: %d\n", (int)setup);
|
||||
DEBUGASSERT(fds);
|
||||
inode = filep->f_inode;
|
||||
|
||||
DEBUGASSERT(inode->i_private);
|
||||
priv = inode->i_private;
|
||||
|
||||
/* Are we setting up the poll? Or tearing it down? */
|
||||
|
||||
ret = nxmutex_lock(&priv->devlock);
|
||||
if (ret < 0)
|
||||
{
|
||||
ierr("ERROR: nxmutex_lock failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (setup)
|
||||
{
|
||||
/* Ignore waits that do not include POLLIN */
|
||||
|
||||
if ((fds->events & POLLIN) == 0)
|
||||
{
|
||||
ierr("ERROR: Missing POLLIN: revents: %08" PRIx32 "\n",
|
||||
fds->revents);
|
||||
ret = -EDEADLK;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* This is a request to set up the poll. Find an available
|
||||
* slot for the poll structure reference
|
||||
*/
|
||||
|
||||
for (i = 0; i < CONFIG_FT5X06_NPOLLWAITERS; i++)
|
||||
{
|
||||
/* Find an available slot */
|
||||
|
||||
if (!priv->fds[i])
|
||||
{
|
||||
/* Bind the poll structure and this slot */
|
||||
|
||||
priv->fds[i] = fds;
|
||||
fds->priv = &priv->fds[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= CONFIG_FT5X06_NPOLLWAITERS)
|
||||
{
|
||||
ierr("ERROR: No available slot found: %d\n", i);
|
||||
fds->priv = NULL;
|
||||
ret = -EBUSY;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Should we immediately notify on any of the requested events? */
|
||||
|
||||
if (priv->valid)
|
||||
{
|
||||
poll_notify(&fds, 1, POLLIN);
|
||||
}
|
||||
}
|
||||
else if (fds->priv)
|
||||
{
|
||||
/* This is a request to tear down the poll. */
|
||||
|
||||
FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
|
||||
DEBUGASSERT(slot != NULL);
|
||||
|
||||
/* Remove all memory of the poll setup */
|
||||
|
||||
*slot = NULL;
|
||||
fds->priv = NULL;
|
||||
}
|
||||
|
||||
errout:
|
||||
nxmutex_unlock(&priv->devlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -1101,11 +709,13 @@ int ft5x06_register(FAR struct i2c_master_s *i2c,
|
||||
/* Initialize the FT5x06 device driver instance */
|
||||
|
||||
priv->i2c = i2c; /* Save the I2C device handle */
|
||||
priv->config = config; /* Save the board configuration */
|
||||
priv->frequency = config->frequency; /* Set the current I2C frequency */
|
||||
|
||||
/* Save the board configuration */
|
||||
|
||||
memcpy(&priv->config, config, sizeof(priv->config));
|
||||
|
||||
nxmutex_init(&priv->devlock); /* Initialize device structure mutex */
|
||||
nxsem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */
|
||||
|
||||
#ifdef CONFIG_FT5X06_POLLMODE
|
||||
/* Allocate a timer for polling the FT5x06 */
|
||||
@@ -1130,10 +740,14 @@ int ft5x06_register(FAR struct i2c_master_s *i2c,
|
||||
|
||||
/* Register the device as an input device */
|
||||
|
||||
priv->config.lower.open = ft5x06_bringup;
|
||||
priv->config.lower.close = ft5x06_shutdown;
|
||||
priv->config.lower.control = ft5x06_ioctl;
|
||||
snprintf(devname, sizeof(devname), DEV_FORMAT, minor);
|
||||
iinfo("Registering %s\n", devname);
|
||||
|
||||
ret = register_driver(devname, &g_ft5x06_fops, 0666, priv);
|
||||
ret = touch_register(&priv->config.lower, devname,
|
||||
CONFIG_FT5X06_SAMPLE_NBUFFER);
|
||||
if (ret < 0)
|
||||
{
|
||||
ierr("ERROR: register_driver() failed: %d\n", ret);
|
||||
@@ -1157,7 +771,6 @@ int ft5x06_register(FAR struct i2c_master_s *i2c,
|
||||
|
||||
errout_with_priv:
|
||||
nxmutex_destroy(&priv->devlock);
|
||||
nxsem_destroy(&priv->waitsem);
|
||||
kmm_free(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/input/touchscreen.h>
|
||||
|
||||
#ifdef CONFIG_INPUT_FT5X06
|
||||
|
||||
@@ -81,6 +82,7 @@ struct ft5x06_config_s
|
||||
{
|
||||
/* Device characterization */
|
||||
|
||||
struct touch_lowerhalf_s lower;
|
||||
uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */
|
||||
uint32_t frequency; /* Default I2C frequency */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user