diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 2e6e5f93399..0f5fd0d8571 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -69,6 +69,8 @@ struct fb_chardev_s #ifdef CONFIG_FB_OVERLAY int overlay; /* Overlay number */ #endif + mutex_t lock; /* Mutual exclusion */ + int16_t crefs; /* Number of open references */ }; struct fb_panelinfo_s @@ -82,6 +84,8 @@ struct fb_panelinfo_s * Private Function Prototypes ****************************************************************************/ +static int fb_open(FAR struct file *filep); +static int fb_close(FAR struct file *filep); static ssize_t fb_read(FAR struct file *filep, FAR char *buffer, size_t buflen); static ssize_t fb_write(FAR struct file *filep, FAR const char *buffer, @@ -101,8 +105,8 @@ static int fb_get_panelinfo(FAR struct fb_chardev_s *fb, static const struct file_operations g_fb_fops = { - NULL, /* open */ - NULL, /* close */ + fb_open, /* open */ + fb_close, /* close */ fb_read, /* read */ fb_write, /* write */ fb_seek, /* seek */ @@ -116,6 +120,86 @@ static const struct file_operations g_fb_fops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: fb_open + ****************************************************************************/ + +static int fb_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct fb_chardev_s *fb; + int ret; + + DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + inode = filep->f_inode; + fb = inode->i_private; + + DEBUGASSERT(fb->vtable != NULL); + + ret = nxmutex_lock(&fb->lock); + if (ret < 0) + { + return ret; + } + + if (fb->crefs == 0) + { + if (fb->vtable->open != NULL) + { + ret = fb->vtable->open(fb->vtable); + } + } + + if (ret >= 0) + { + fb->crefs++; + DEBUGASSERT(fb->crefs > 0); + } + + nxmutex_unlock(&fb->lock); + return ret; +} + +/**************************************************************************** + * Name: fb_close + ****************************************************************************/ + +static int fb_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct fb_chardev_s *fb; + int ret; + + DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + inode = filep->f_inode; + fb = inode->i_private; + + DEBUGASSERT(fb->vtable != NULL); + + ret = nxmutex_lock(&fb->lock); + if (ret < 0) + { + return ret; + } + + if (fb->crefs == 1) + { + if (fb->vtable->close != NULL) + { + ret = fb->vtable->close(fb->vtable); + } + } + + if (ret >= 0) + { + DEBUGASSERT(fb->crefs > 0); + fb->crefs--; + } + + nxmutex_unlock(&fb->lock); + return ret; +} + /**************************************************************************** * Name: fb_read ****************************************************************************/ @@ -1058,6 +1142,8 @@ int fb_register(int display, int plane) snprintf(devname, 16, "/dev/fb%d.%d", display, plane); } + nxmutex_init(&fb->lock); + ret = register_driver(devname, &g_fb_fops, 0666, (FAR void *)fb); if (ret < 0) { @@ -1068,6 +1154,7 @@ int fb_register(int display, int plane) return OK; errout_with_fb: + nxmutex_destroy(&fb->lock); kmm_free(fb); return ret; } diff --git a/include/nuttx/video/fb.h b/include/nuttx/video/fb.h index 9e12383d0b2..770e2c90697 100644 --- a/include/nuttx/video/fb.h +++ b/include/nuttx/video/fb.h @@ -673,6 +673,11 @@ struct fb_vtable_s int (*getplaneinfo)(FAR struct fb_vtable_s *vtable, int planeno, FAR struct fb_planeinfo_s *pinfo); + /* open/close window. */ + + int (*open)(FAR struct fb_vtable_s *vtable); + int (*close)(FAR struct fb_vtable_s *vtable); + #ifdef CONFIG_FB_CMAP /* The following are provided only if the video hardware supports RGB * color mapping