From 278e7af5e509cbfeda9cc5d93215f46c009ab938 Mon Sep 17 00:00:00 2001 From: Matias N Date: Thu, 29 Oct 2020 21:59:29 -0300 Subject: [PATCH] Add LCD character driver: allows interacting with LCD directly from userspace --- drivers/lcd/Kconfig | 8 ++ drivers/lcd/Make.defs | 4 + drivers/lcd/lcd_dev.c | 273 ++++++++++++++++++++++++++++++++++++++++++ drivers/lcd/lcd_dev.h | 105 ++++++++++++++++ 4 files changed, 390 insertions(+) create mode 100644 drivers/lcd/lcd_dev.c create mode 100644 drivers/lcd/lcd_dev.h diff --git a/drivers/lcd/Kconfig b/drivers/lcd/Kconfig index 72e9dddfab..ea939c62cb 100644 --- a/drivers/lcd/Kconfig +++ b/drivers/lcd/Kconfig @@ -24,6 +24,14 @@ config LCD_PACKEDMSFIRST comment "Common Graphic LCD Settings" +config LCD_DEV + bool "LCD character device" + default n + ---help--- + This option enables support for a character driver which exposes + LCD operations to userspace via ioctl() commands. This is useful when + not using NXGraphics but an alternative graphics library such as LVGL. + config LCD_FRAMEBUFFER bool "LCD framebuffer front end" default n diff --git a/drivers/lcd/Make.defs b/drivers/lcd/Make.defs index 919dfb60d0..e5d667d81a 100644 --- a/drivers/lcd/Make.defs +++ b/drivers/lcd/Make.defs @@ -41,6 +41,10 @@ ifeq ($(CONFIG_LCD_FRAMEBUFFER),y) CSRCS += lcd_framebuffer.c endif +ifeq ($(CONFIG_LCD_DEV),y) + CSRCS += lcd_dev.c +endif + # Include support for Graphics LCD drivers ifeq ($(CONFIG_LCD_FT80X),y) diff --git a/drivers/lcd/lcd_dev.c b/drivers/lcd/lcd_dev.c new file mode 100644 index 0000000000..43d0ca8d8f --- /dev/null +++ b/drivers/lcd/lcd_dev.c @@ -0,0 +1,273 @@ +/**************************************************************************** + * drivers/lcd/lcd_dev.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "lcd_dev.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the state of the lcd_dev driver */ + +struct lcddev_dev_s +{ + FAR struct lcd_dev_s *lcd_ptr; + struct lcd_planeinfo_s planeinfo; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Character driver methods */ + +static int lcddev_open(FAR struct file *filep); +static int lcddev_close(FAR struct file *filep); +static int lcddev_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations lcddev_fops = +{ + lcddev_open, /* open */ + lcddev_close, /* close */ + NULL, /* read */ + NULL, /* write */ + NULL, /* seek */ + lcddev_ioctl, /* ioctl */ + NULL /* poll */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lcddev_open + ****************************************************************************/ + +static int lcddev_open(FAR struct file *filep) +{ + /* Nothing to do */ + + return OK; +} + +/**************************************************************************** + * Name: lcddev_close + ****************************************************************************/ + +static int lcddev_close(FAR struct file *filep) +{ + /* Nothing to do */ + + return OK; +} + +/**************************************************************************** + * Name: lcddev_ioctl + ****************************************************************************/ + +static int lcddev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct lcddev_dev_s *priv; + int ret = OK; + + priv = (FAR struct lcddev_dev_s *)filep->f_inode->i_private; + + switch (cmd) + { + case LCDDEVIO_GETRUN: + { + FAR struct lcddev_run_s *lcd_putrun = + (const FAR struct lcddev_run_s *)arg; + + ret = priv->planeinfo.getrun(lcd_putrun->row, lcd_putrun->col, + lcd_putrun->data, lcd_putrun->npixels); + } + break; + case LCDDEVIO_PUTRUN: + { + const FAR struct lcddev_run_s *lcd_putrun = + (FAR struct lcddev_run_s *)arg; + + ret = priv->planeinfo.putrun(lcd_putrun->row, lcd_putrun->col, + lcd_putrun->data, lcd_putrun->npixels); + } + break; + case LCDDEVIO_GETPOWER: + { + *((FAR int *)arg) = priv->lcd_ptr->getpower(priv->lcd_ptr); + } + break; + case LCDDEVIO_SETPOWER: + { + ret = priv->lcd_ptr->setpower(priv->lcd_ptr, (int)arg); + } + break; + case LCDDEVIO_GETCONTRAST: + { + *((FAR int *)arg) = priv->lcd_ptr->getcontrast(priv->lcd_ptr); + } + break; + case LCDDEVIO_SETCONTRAST: + { + ret = priv->lcd_ptr->setcontrast(priv->lcd_ptr, (unsigned int)arg); + } + break; + case LCDDEVIO_GETPLANEINFO: + { + *((FAR struct lcd_planeinfo_s *)arg) = priv->planeinfo; + } + break; + case LCDDEVIO_GETVIDEOINFO: + { + ret = priv->lcd_ptr->getvideoinfo(priv->lcd_ptr, + (FAR struct fb_videoinfo_s *)arg); + } + break; + case LCDDEVIO_SETPLANENO: + { + ret = priv->lcd_ptr->getplaneinfo(priv->lcd_ptr, (int)arg, + &priv->planeinfo); + } + break; +#ifdef CONFIG_FB_CMAP + case LCDDEVIO_GETCMAP: + { + FAR struct fb_cmap_s *cmap = (FAR struct fb_cmap_s *)arg; + + ret = priv->lcd_ptr->getcmap(priv->lcd_ptr, cmap); + } + break; + case LCDDEVIO_PUTCMAP: + { + FAR const struct fb_cmap_s *cmap = (FAR const struct fb_cmap_s *)arg; + + ret = priv->lcd_ptr->putcmap(priv->lcd_ptr, cmap); + } + break; +#endif +#ifdef CONFIG_FB_HWCURSOR + case LCDDEVIO_GETCURSOR: + { + FAR struct fb_cursorattrib_s *attrib = + (FAR struct fb_cursorattrib_s *)arg; + + ret = priv->lcd_ptr->getcursor(priv->lcd_ptr, attrib); + } + break; + case LCDDEVIO_SETCURSOR: + { + FAR struct fb_setcursor_s *settings = + (FAR struct fb_setcursor_s *)arg; + + ret = priv->lcd_ptr->setcursor(priv->lcd_ptr, settings); + } + break; +#endif + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lcddev_register + * + * Description: + * Register the LCD character driver as /dev/lcdN. + * + * Input Parameters: + * devno - The LCD device number. + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int lcddev_register(int devno) +{ + FAR struct lcddev_dev_s *priv; + int ret = OK; + char devname[16]; + + /* Allocate a new lcd_dev driver instance */ + + priv = (FAR struct lcddev_dev_s *)kmm_zalloc(sizeof(struct lcddev_dev_s)); + + if (!priv) + { + return -ENOMEM; + } + + priv->lcd_ptr = board_lcd_getdev(devno); + ret = priv->lcd_ptr->getplaneinfo(priv->lcd_ptr, 0, &priv->planeinfo); + if (ret < 0) + { + goto err; + } + + snprintf(devname, sizeof(devname), "/dev/lcd%i", devno); + ret = register_driver(devname, &lcddev_fops, 0666, priv); + if (ret < 0) + { + goto err; + } + + return ret; +err: + kmm_free(priv); + return ret; +} diff --git a/drivers/lcd/lcd_dev.h b/drivers/lcd/lcd_dev.h new file mode 100644 index 0000000000..85fa67b852 --- /dev/null +++ b/drivers/lcd/lcd_dev.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * drivers/lcd/lcd_dev.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_LCD_LCD_DEV_H +#define __DRIVERS_LCD_LCD_DEV_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +#define LCDDEVIO_PUTRUN _LCDIOC(0) /* Arg: const struct lcddev_putrun_s* */ +#define LCDDEVIO_GETRUN _LCDIOC(1) /* Arg: struct lcddev_putrun_s* */ +#define LCDDEVIO_GETPOWER _LCDIOC(2) /* Arg: int* */ +#define LCDDEVIO_SETPOWER _LCDIOC(3) /* Arg: int */ +#define LCDDEVIO_GETCONTRAST _LCDIOC(4) /* Arg: int* */ +#define LCDDEVIO_SETCONTRAST _LCDIOC(5) /* Arg: unsigned int */ +#define LCDDEVIO_GETPLANEINFO _LCDIOC(6) /* Arg: struct lcd_planeinfo_s* */ +#define LCDDEVIO_GETVIDEOINFO _LCDIOC(7) /* Arg: struct fb_videoinfo_s* */ +#define LCDDEVIO_SETPLANENO _LCDIOC(8) /* Arg: int */ + +#ifdef CONFIG_FB_CMAP +#define LCDDEVIO_GETCMAP _LCDIOC(9) /* Arg: struct fb_cmap_s* */ +#define LCDDEVIO_PUTCMAP _LCDIOC(10) /* Arg: const struct fb_cmap_s* */ +#endif + +#ifdef CONFIG_FB_HWCURSOR +#define LCDDEVIO_GETCURSOR _LCDIOC(11) /* Arg: struct fb_cursorattrib_s* */ +#define LCDDEVIO_SETCURSOR _LCDIOC(12) /* Arg: struct fb_setcursor_s* */ +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +struct lcddev_run_s +{ + fb_coord_t row, col; + FAR uint8_t *data; + size_t npixels; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: lcddev_register + * + * Description: + * Register the lcd_dev character driver as the specified device. + * + * Input Parameters: + * devno - The LCD device number. + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int lcddev_register(int devno); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_LCD_LCD_DEV_H */