staging: panel: fix sparse warnings in lcd_write

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.bastien@laposte.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Bastien Armand 2014-04-18 18:10:57 +02:00 committed by Greg Kroah-Hartman
parent e112f89bcc
commit 70a8c3eb85
1 changed files with 110 additions and 97 deletions

View File

@ -1217,111 +1217,113 @@ static inline int handle_lcd_special_code(void)
return processed;
}
static ssize_t lcd_write(struct file *file,
const char *buf, size_t count, loff_t *ppos)
static void lcd_write_char(char c)
{
const char *tmp = buf;
/* 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 __user *buf, size_t count, loff_t *ppos)
{
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;
/* 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();
lcd_write_char(*tmp);
}
}
}
/* initialize the LCD driver */