Out of curiosity, have you tested this patch?

On Fri, Apr 18, 2014 at 06:10:57PM +0200, Bastien Armand wrote:
> This patch fixes two sparse warnings related to lcd_write :
> warning: incorrect type in argument 1 (different address spaces)
> warning: incorrect type in initializer (incompatible argument 2 
> (different address spaces))
> 
> lcd_write can be used from kernel space (in panel_lcd_print) or from user
> space. So we introduce the lcd_write_char function that will write a char to
> the device. We modify lcd_write and panel_lcd_print to use it. Finally we add
> __user annotation missing in lcd_write.
> 
> 
> Signed-off-by: Bastien Armand <armand.bast...@laposte.net>
> ---
>  drivers/staging/panel/panel.c |  205 
> ++++++++++++++++++++++-------------------
>  1 file changed, 109 insertions(+), 96 deletions(-)
> 
> diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
> index 1569e26..dc34254 100644
> --- a/drivers/staging/panel/panel.c
> +++ b/drivers/staging/panel/panel.c
> @@ -1217,111 +1217,113 @@ static inline int handle_lcd_special_code(void)
>       return processed;
>  }
> 
> +static void lcd_write_char(char c)
> +{
> +     /* first, we'll test if we're in escape mode */
> +     if ((c != '\n') && lcd_escape_len >= 0) {
> +             /* yes, let's add this char to the buffer */
> +             lcd_escape[lcd_escape_len++] = c;
> +             lcd_escape[lcd_escape_len] = 0;
> +     } else {
> +             /* aborts any previous escape sequence */
> +             lcd_escape_len = -1;
> +
> +             switch (c) {
> +             case LCD_ESCAPE_CHAR:
> +                     /* start of an escape sequence */
> +                     lcd_escape_len = 0;
> +                     lcd_escape[lcd_escape_len] = 0;
> +                     break;
> +             case '\b':
> +                     /* go back one char and clear it */
> +                     if (lcd_addr_x > 0) {
> +                             /* check if we're not at the
> +                                end of the line */
> +                             if (lcd_addr_x < lcd_bwidth)
> +                                     /* back one char */
> +                                     lcd_write_cmd(0x10);
> +                             lcd_addr_x--;
> +                     }
> +                     /* replace with a space */
> +                     lcd_write_data(' ');
> +                     /* back one char again */
> +                     lcd_write_cmd(0x10);
> +                     break;
> +             case '\014':
> +                     /* quickly clear the display */
> +                     lcd_clear_fast();
> +                     break;
> +             case '\n':
> +                     /* flush the remainder of the current line and
> +                        go to the beginning of the next line */
> +                     for (; lcd_addr_x < lcd_bwidth; lcd_addr_x++)
> +                             lcd_write_data(' ');
> +                     lcd_addr_x = 0;
> +                     lcd_addr_y = (lcd_addr_y + 1) % lcd_height;
> +                     lcd_gotoxy();
> +                     break;
> +             case '\r':
> +                     /* go to the beginning of the same line */
> +                     lcd_addr_x = 0;
> +                     lcd_gotoxy();
> +                     break;
> +             case '\t':
> +                     /* print a space instead of the tab */
> +                     lcd_print(' ');
> +                     break;
> +             default:
> +                     /* simply print this char */
> +                     lcd_print(c);
> +                     break;
> +             }
> +     }
> +
> +     /* now we'll see if we're in an escape mode and if the current
> +        escape sequence can be understood. */
> +     if (lcd_escape_len >= 2) {
> +             int processed = 0;
> +
> +             if (!strcmp(lcd_escape, "[2J")) {
> +                     /* clear the display */
> +                     lcd_clear_fast();
> +                     processed = 1;
> +             } else if (!strcmp(lcd_escape, "[H")) {
> +                     /* cursor to home */
> +                     lcd_addr_x = lcd_addr_y = 0;
> +                     lcd_gotoxy();
> +                     processed = 1;
> +             }
> +             /* codes starting with ^[[L */
> +             else if ((lcd_escape_len >= 3) &&
> +                      (lcd_escape[0] == '[') &&
> +                      (lcd_escape[1] == 'L')) {
> +                     processed = handle_lcd_special_code();
> +             }
> +
> +             /* LCD special escape codes */
> +             /* flush the escape sequence if it's been processed
> +                or if it is getting too long. */
> +             if (processed || (lcd_escape_len >= LCD_ESCAPE_LEN))
> +                     lcd_escape_len = -1;
> +     } /* escape codes */
> +}
> +
>  static ssize_t lcd_write(struct file *file,
> -                      const char *buf, size_t count, loff_t *ppos)
> +     const char __user *buf, size_t count, loff_t *ppos)
>  {
> -     const char *tmp = buf;
> +     const char __user *tmp = buf;
>       char c;
> 
> -     for (; count-- > 0; (ppos ? (*ppos)++ : 0), ++tmp) {
> +     for (; count-- > 0; (*ppos)++, tmp++) {
>               if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
>                       /* let's be a little nice with other processes
>                          that need some CPU */
>                       schedule();
> 
> -             if (ppos == NULL && file == NULL)
> -                     /* let's not use get_user() from the kernel ! */
> -                     c = *tmp;
> -             else if (get_user(c, tmp))
> +             if (get_user(c, buf))
>                       return -EFAULT;

This is buggy.  You are getting the first character over and over.  You
should be doing:

                if (get_user(c, tmp))
                        return -EFAULT;

Btw, this whole function is terrible.  It should be reading larger
chunks at once instead of get_user() for each character.


> 
> -             /* first, we'll test if we're in escape mode */
> -             if ((c != '\n') && lcd_escape_len >= 0) {
> -                     /* yes, let's add this char to the buffer */
> -                     lcd_escape[lcd_escape_len++] = c;
> -                     lcd_escape[lcd_escape_len] = 0;
> -             } else {
> -                     /* aborts any previous escape sequence */
> -                     lcd_escape_len = -1;
> -
> -                     switch (c) {
> -                     case LCD_ESCAPE_CHAR:
> -                             /* start of an escape sequence */
> -                             lcd_escape_len = 0;
> -                             lcd_escape[lcd_escape_len] = 0;
> -                             break;
> -                     case '\b':
> -                             /* go back one char and clear it */
> -                             if (lcd_addr_x > 0) {
> -                                     /* check if we're not at the
> -                                        end of the line */
> -                                     if (lcd_addr_x < lcd_bwidth)
> -                                             /* back one char */
> -                                             lcd_write_cmd(0x10);
> -                                     lcd_addr_x--;
> -                             }
> -                             /* replace with a space */
> -                             lcd_write_data(' ');
> -                             /* back one char again */
> -                             lcd_write_cmd(0x10);
> -                             break;
> -                     case '\014':
> -                             /* quickly clear the display */
> -                             lcd_clear_fast();
> -                             break;
> -                     case '\n':
> -                             /* flush the remainder of the current line and
> -                                go to the beginning of the next line */
> -                             for (; lcd_addr_x < lcd_bwidth; lcd_addr_x++)
> -                                     lcd_write_data(' ');
> -                             lcd_addr_x = 0;
> -                             lcd_addr_y = (lcd_addr_y + 1) % lcd_height;
> -                             lcd_gotoxy();
> -                             break;
> -                     case '\r':
> -                             /* go to the beginning of the same line */
> -                             lcd_addr_x = 0;
> -                             lcd_gotoxy();
> -                             break;
> -                     case '\t':
> -                             /* print a space instead of the tab */
> -                             lcd_print(' ');
> -                             break;
> -                     default:
> -                             /* simply print this char */
> -                             lcd_print(c);
> -                             break;
> -                     }
> -             }
> -
> -             /* now we'll see if we're in an escape mode and if the current
> -                escape sequence can be understood. */
> -             if (lcd_escape_len >= 2) {
> -                     int processed = 0;
> -
> -                     if (!strcmp(lcd_escape, "[2J")) {
> -                             /* clear the display */
> -                             lcd_clear_fast();
> -                             processed = 1;
> -                     } else if (!strcmp(lcd_escape, "[H")) {
> -                             /* cursor to home */
> -                             lcd_addr_x = lcd_addr_y = 0;
> -                             lcd_gotoxy();
> -                             processed = 1;
> -                     }
> -                     /* codes starting with ^[[L */
> -                     else if ((lcd_escape_len >= 3) &&
> -                              (lcd_escape[0] == '[') &&
> -                              (lcd_escape[1] == 'L')) {
> -                             processed = handle_lcd_special_code();
> -                     }
> -
> -                     /* LCD special escape codes */
> -                     /* flush the escape sequence if it's been processed
> -                        or if it is getting too long. */
> -                     if (processed || (lcd_escape_len >= LCD_ESCAPE_LEN))
> -                             lcd_escape_len = -1;
> -             } /* escape codes */
> +             lcd_write_char(c);
>       }
> 
>       return tmp - buf;
> @@ -1365,8 +1367,19 @@ static struct miscdevice lcd_dev = {
>  /* public function usable from the kernel for any purpose */
>  static void panel_lcd_print(const char *s)
>  {
> -     if (lcd_enabled && lcd_initialized)
> -             lcd_write(NULL, s, strlen(s), NULL);
> +     const char *tmp = s;
> +     int count = strlen(s);
> +
> +     if (lcd_enabled && lcd_initialized) {
> +             for (; count-- > 0; tmp++) {
> +                     if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
> +                             /* let's be a little nice with other processes
> +                                that need some CPU */
> +                             schedule();

This schedule() isn't needed.  It just prints a line or two at start up
and some other debug output or something.  Small small.

regards,
dan carpenter

> +
> +                     lcd_write_char(*tmp);
> +             }
> +     }
>  }
> 
>  /* initialize the LCD driver */
> --
> 1.7.10.4
> 
> _______________________________________________
> devel mailing list
> de...@linuxdriverproject.org
> http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to