/* * Parses a movement command of the form "(.*);", where the group can be * any number of subcommands of the form "(x|y)[0-9]+". * * Returns whether the command is valid. The position arguments are * only written if the parsing was successful. * * For instance: * - ";" returns (<original x>, <original y>). * - "x1;" returns (1, <original y>). * - "y2x1;" returns (1, 2). * - "x12y34x56;" returns (56, 34). * - "" fails. * - "x" fails. * - "x;" fails. * - "x1" fails. * - "xy12;" fails. * - "x12yy12;" fails. * - "xx" fails.
*/ staticbool parse_xy(constchar *s, unsignedlong *x, unsignedlong *y)
{ unsignedlong new_x = *x; unsignedlong new_y = *y; char *p;
for (;;) { if (!*s) returnfalse;
if (*s == ';') break;
if (*s == 'x') {
new_x = simple_strtoul(s + 1, &p, 10); if (p == s + 1) returnfalse;
s = p;
} elseif (*s == 'y') {
new_y = simple_strtoul(s + 1, &p, 10); if (p == s + 1) returnfalse;
s = p;
} else { returnfalse;
}
}
*x = new_x;
*y = new_y; returntrue;
}
/* * These are the file operation function for user access to /dev/lcd * This function can also be called from inside the kernel, by * setting file and ppos to NULL. *
*/
/* first, we'll test if we're in escape mode */ if ((c != '\n') && priv->esc_seq.len >= 0) { /* yes, let's add this char to the buffer */
priv->esc_seq.buf[priv->esc_seq.len++] = c;
priv->esc_seq.buf[priv->esc_seq.len] = '\0';
} else { /* aborts any previous escape sequence */
priv->esc_seq.len = -1;
switch (c) { case LCD_ESCAPE_CHAR: /* start of an escape sequence */
priv->esc_seq.len = 0;
priv->esc_seq.buf[priv->esc_seq.len] = '\0'; break; case'\b': /* go back one char and clear it */ if (lcd->addr.x > 0) { /* back one char */ if (!lcd->ops->shift_cursor(lcd,
CHARLCD_SHIFT_LEFT))
lcd->addr.x--;
} /* replace with a space */
charlcd_print(lcd, ' '); /* back one char again */ if (!lcd->ops->shift_cursor(lcd, CHARLCD_SHIFT_LEFT))
lcd->addr.x--;
break; case'\f': /* quickly clear the display */
charlcd_clear_display(lcd); break; case'\n': /* * flush the remainder of the current line and * go to the beginning of the next line
*/ for (; lcd->addr.x < lcd->width; lcd->addr.x++)
lcd->ops->print(lcd, ' ');
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y); break; case'\r': /* go to the beginning of the same line */
lcd->addr.x = 0;
lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y); break; case'\t': /* print a space instead of the tab */
charlcd_print(lcd, ' '); break; default: /* simply print this char */
charlcd_print(lcd, c); break;
}
}
/* * now we'll see if we're in an escape mode and if the current * escape sequence can be understood.
*/ if (priv->esc_seq.len >= 2) { int processed = 0;
/* LCD special escape codes */ /* * flush the escape sequence if it's been processed * or if it is getting too long.
*/ if (processed || (priv->esc_seq.len >= LCD_ESCAPE_LEN))
priv->esc_seq.len = -1;
} /* escape codes */
}
for (; count-- > 0; (*ppos)++, tmp++) { if (((count + 1) & 0x1f) == 0) { /* * charlcd_write() is invoked as a VFS->write() callback * and as such it is always invoked from preemptible * context and may sleep.
*/
cond_resched();
}
/* * before this line, we must NOT send anything to the display. * Since charlcd_init_display() needs to write data, we have to * enable mark the LCD initialized just before.
*/ if (WARN_ON(!lcd->ops->init_display)) return -EINVAL;
ret = lcd->ops->init_display(lcd); if (ret) return ret;
/* display a short message */
charlcd_puts(lcd, "\x1b[Lc\x1b[Lb" LCD_INIT_BL LCD_INIT_TEXT);
/* clear the display on the next device opening */
priv->must_clear = true;
charlcd_home(lcd); return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.