drivers/lcd: Add unlink support to the FT80x driver.

This commit is contained in:
Gregory Nutt 2018-02-17 13:01:06 -06:00
parent 5ec2b9d6fe
commit e4292dced8
3 changed files with 112 additions and 9 deletions

View File

@ -361,7 +361,10 @@ struct ft80x_dev_s
FAR const struct ft80x_config_s *lower; /* Cached lower half instance */
uint32_t frequency; /* Effective frequency */
sem_t exclsem; /* Mutual exclusion semaphore */
uint8_t crefs; /* Open count */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
uint8_t crefs; /* Number of open references */
bool unlinked; /* True if the driver has been unlinked */
#endif
};
/****************************************************************************

View File

@ -90,6 +90,10 @@
* Private Function Prototypes
****************************************************************************/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static void ft80x_destroy(FAR struct ft80x_dev_s *priv);
#endif
/* Character driver methods */
static int ft80x_open(FAR struct file *filep);
@ -104,6 +108,9 @@ static int ft80x_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static int ft80x_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static int ft80x_unlink(FAR struct inode *inode);
#endif
/* Initialization */
@ -125,7 +132,7 @@ static const struct file_operations g_ft80x_fops =
, ft80x_poll /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
, NULL /* unlink */
, ft80x_unlink /* unlink */
#endif
};
@ -133,6 +140,35 @@ static const struct file_operations g_ft80x_fops =
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: ft80x_destroy
*
* Description:
* The driver has been unlinked... clean up as best we can.
*
****************************************************************************/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static void ft80x_destroy(FAR struct ft80x_dev_s *priv)
{
/* If the lower half driver provided a destroy method, then call that
* method now in order order to clean up resources used by the lower-half
* driver.
*/
DEBUGASSERT(priv != NULL && priv->lower != NULL);
if (priv->lower->destroy != NULL)
{
priv->lower->destroy(priv->lower);
}
/* Then free our container */
sem_destroy(&priv->exclsem);
kmm_free(priv);
}
#endif
/****************************************************************************
* Name: ft80x_open
*
@ -143,6 +179,7 @@ static const struct file_operations g_ft80x_fops =
static int ft80x_open(FAR struct file *filep)
{
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
FAR struct inode *inode;
FAR struct ft80x_dev_s *priv;
uint8_t tmp;
@ -184,6 +221,9 @@ errout_with_sem:
errout:
return ret;
#else
return OK;
#endif
}
/****************************************************************************
@ -196,6 +236,7 @@ errout:
static int ft80x_close(FAR struct file *filep)
{
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
FAR struct inode *inode;
FAR struct ft80x_dev_s *priv;
int ret;
@ -215,10 +256,25 @@ static int ft80x_close(FAR struct file *filep)
goto errout;
}
/* Decrement the references to the driver. */
/* Will the count decrement to zero? */
if (priv->crefs > 1)
if (priv->crefs <= 1)
{
/* Yes.. if the driver has been unlinked, then we need to destroy the
* driver instance.
*/
priv->crefs = 0;
if (priv->unlinked)
{
ft80x_destroy(priv);
return OK;
}
}
else
{
/* NO.. decrement the number of references to the driver. */
priv->crefs--;
}
@ -227,6 +283,9 @@ static int ft80x_close(FAR struct file *filep)
errout:
return ret;
#else
return OK;
#endif
}
/****************************************************************************
@ -276,6 +335,10 @@ static ssize_t ft80x_write(FAR struct file *filep, FAR const char *buffer,
return ret;
}
/* Note that there is no check if the driver was opened read-only. That
* would be a silly thing to do.
*/
/* The write method is functionally equivalent to the FT80XIOC_PUTDISPLAYLIST
* IOCTL command: It simply copies the display list in the user buffer to
* the FT80x display list memory.
@ -424,6 +487,39 @@ static int ft80x_poll(FAR struct file *filep, FAR struct pollfd *fds,
}
#endif
/****************************************************************************
* Name: ft80x_unlink
****************************************************************************/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static int ft80x_unlink(FAR struct inode *inode)
{
FAR struct ft80x_dev_s *priv;
/* Get the reference to our internal state structure from the inode
* structure.
*/
DEBUGASSERT(inode && inode->i_private);
priv = inode->i_private;
/* Indicate that the driver has been unlinked */
priv->unlinked = true;
/* If there are no further open references to the driver, then commit
* Hara-Kiri now.
*/
if (priv->crefs == 0)
{
ft80x_destroy(priv);
}
return OK;
}
#endif
/****************************************************************************
* Name: ft80x_initialize
*

View File

@ -470,13 +470,17 @@ struct ft80x_config_s
* enable - Enable or disable the GPIO interrupt
* clear - Acknowledge/clear any pending GPIO interrupt
* pwrdown - Power down the FT80X
* destroy - The driver has been unlinked. Cleanup as necessary.
*/
int (*attach)(FAR const struct ft80x_config_s *state, xcpt_t isr,
FAR void *arg);
void (*enable)(FAR const struct ft80x_config_s *state, bool enable);
void (*clear)(FAR const struct ft80x_config_s *state);
bool (*pwrdown)(FAR const struct ft80x_config_s *state, bool pwrdown);
CODE int (*attach)(FAR const struct ft80x_config_s *state, xcpt_t isr,
FAR void *arg);
CODE void (*enable)(FAR const struct ft80x_config_s *state, bool enable);
CODE void (*clear)(FAR const struct ft80x_config_s *state);
CODE bool (*pwrdown)(FAR const struct ft80x_config_s *state, bool pwrdown);
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
CODE void (*destroy)(FAR const struct ft80x_config_s *state);
#endif
};
/* This structure describes one generic display list command */