charlcd.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Character LCD driver for Linux
  4. *
  5. * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
  6. * Copyright (C) 2016-2017 Glider bvba
  7. */
  8. #include <linux/atomic.h>
  9. #include <linux/ctype.h>
  10. #include <linux/delay.h>
  11. #include <linux/fs.h>
  12. #include <linux/miscdevice.h>
  13. #include <linux/module.h>
  14. #include <linux/notifier.h>
  15. #include <linux/reboot.h>
  16. #include <linux/slab.h>
  17. #include <linux/uaccess.h>
  18. #include <linux/workqueue.h>
  19. #include <generated/utsrelease.h>
  20. #include <misc/charlcd.h>
  21. #define LCD_MINOR 156
  22. #define DEFAULT_LCD_BWIDTH 40
  23. #define DEFAULT_LCD_HWIDTH 64
  24. /* Keep the backlight on this many seconds for each flash */
  25. #define LCD_BL_TEMPO_PERIOD 4
  26. #define LCD_FLAG_B 0x0004 /* Blink on */
  27. #define LCD_FLAG_C 0x0008 /* Cursor on */
  28. #define LCD_FLAG_D 0x0010 /* Display on */
  29. #define LCD_FLAG_F 0x0020 /* Large font mode */
  30. #define LCD_FLAG_N 0x0040 /* 2-rows mode */
  31. #define LCD_FLAG_L 0x0080 /* Backlight enabled */
  32. /* LCD commands */
  33. #define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */
  34. #define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */
  35. #define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */
  36. #define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */
  37. #define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */
  38. #define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */
  39. #define LCD_CMD_BLINK_ON 0x01 /* Set blink on */
  40. #define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */
  41. #define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */
  42. #define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */
  43. #define LCD_CMD_FUNCTION_SET 0x20 /* Set function */
  44. #define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */
  45. #define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */
  46. #define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */
  47. #define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */
  48. #define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */
  49. #define LCD_ESCAPE_LEN 24 /* Max chars for LCD escape command */
  50. #define LCD_ESCAPE_CHAR 27 /* Use char 27 for escape command */
  51. struct charlcd_priv {
  52. struct charlcd lcd;
  53. struct delayed_work bl_work;
  54. struct mutex bl_tempo_lock; /* Protects access to bl_tempo */
  55. bool bl_tempo;
  56. bool must_clear;
  57. /* contains the LCD config state */
  58. unsigned long int flags;
  59. /* Contains the LCD X and Y offset */
  60. struct {
  61. unsigned long int x;
  62. unsigned long int y;
  63. } addr;
  64. /* Current escape sequence and it's length or -1 if outside */
  65. struct {
  66. char buf[LCD_ESCAPE_LEN + 1];
  67. int len;
  68. } esc_seq;
  69. unsigned long long drvdata[0];
  70. };
  71. #define to_priv(p) container_of(p, struct charlcd_priv, lcd)
  72. /* Device single-open policy control */
  73. static atomic_t charlcd_available = ATOMIC_INIT(1);
  74. /* sleeps that many milliseconds with a reschedule */
  75. static void long_sleep(int ms)
  76. {
  77. schedule_timeout_interruptible(msecs_to_jiffies(ms));
  78. }
  79. /* turn the backlight on or off */
  80. static void charlcd_backlight(struct charlcd *lcd, int on)
  81. {
  82. struct charlcd_priv *priv = to_priv(lcd);
  83. if (!lcd->ops->backlight)
  84. return;
  85. mutex_lock(&priv->bl_tempo_lock);
  86. if (!priv->bl_tempo)
  87. lcd->ops->backlight(lcd, on);
  88. mutex_unlock(&priv->bl_tempo_lock);
  89. }
  90. static void charlcd_bl_off(struct work_struct *work)
  91. {
  92. struct delayed_work *dwork = to_delayed_work(work);
  93. struct charlcd_priv *priv =
  94. container_of(dwork, struct charlcd_priv, bl_work);
  95. mutex_lock(&priv->bl_tempo_lock);
  96. if (priv->bl_tempo) {
  97. priv->bl_tempo = false;
  98. if (!(priv->flags & LCD_FLAG_L))
  99. priv->lcd.ops->backlight(&priv->lcd, 0);
  100. }
  101. mutex_unlock(&priv->bl_tempo_lock);
  102. }
  103. /* turn the backlight on for a little while */
  104. void charlcd_poke(struct charlcd *lcd)
  105. {
  106. struct charlcd_priv *priv = to_priv(lcd);
  107. if (!lcd->ops->backlight)
  108. return;
  109. cancel_delayed_work_sync(&priv->bl_work);
  110. mutex_lock(&priv->bl_tempo_lock);
  111. if (!priv->bl_tempo && !(priv->flags & LCD_FLAG_L))
  112. lcd->ops->backlight(lcd, 1);
  113. priv->bl_tempo = true;
  114. schedule_delayed_work(&priv->bl_work, LCD_BL_TEMPO_PERIOD * HZ);
  115. mutex_unlock(&priv->bl_tempo_lock);
  116. }
  117. EXPORT_SYMBOL_GPL(charlcd_poke);
  118. static void charlcd_gotoxy(struct charlcd *lcd)
  119. {
  120. struct charlcd_priv *priv = to_priv(lcd);
  121. unsigned int addr;
  122. /*
  123. * we force the cursor to stay at the end of the
  124. * line if it wants to go farther
  125. */
  126. addr = priv->addr.x < lcd->bwidth ? priv->addr.x & (lcd->hwidth - 1)
  127. : lcd->bwidth - 1;
  128. if (priv->addr.y & 1)
  129. addr += lcd->hwidth;
  130. if (priv->addr.y & 2)
  131. addr += lcd->bwidth;
  132. lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
  133. }
  134. static void charlcd_home(struct charlcd *lcd)
  135. {
  136. struct charlcd_priv *priv = to_priv(lcd);
  137. priv->addr.x = 0;
  138. priv->addr.y = 0;
  139. charlcd_gotoxy(lcd);
  140. }
  141. static void charlcd_print(struct charlcd *lcd, char c)
  142. {
  143. struct charlcd_priv *priv = to_priv(lcd);
  144. if (priv->addr.x < lcd->bwidth) {
  145. if (lcd->char_conv)
  146. c = lcd->char_conv[(unsigned char)c];
  147. lcd->ops->write_data(lcd, c);
  148. priv->addr.x++;
  149. /* prevents the cursor from wrapping onto the next line */
  150. if (priv->addr.x == lcd->bwidth)
  151. charlcd_gotoxy(lcd);
  152. }
  153. }
  154. static void charlcd_clear_fast(struct charlcd *lcd)
  155. {
  156. int pos;
  157. charlcd_home(lcd);
  158. if (lcd->ops->clear_fast)
  159. lcd->ops->clear_fast(lcd);
  160. else
  161. for (pos = 0; pos < min(2, lcd->height) * lcd->hwidth; pos++)
  162. lcd->ops->write_data(lcd, ' ');
  163. charlcd_home(lcd);
  164. }
  165. /* clears the display and resets X/Y */
  166. static void charlcd_clear_display(struct charlcd *lcd)
  167. {
  168. struct charlcd_priv *priv = to_priv(lcd);
  169. lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CLEAR);
  170. priv->addr.x = 0;
  171. priv->addr.y = 0;
  172. /* we must wait a few milliseconds (15) */
  173. long_sleep(15);
  174. }
  175. static int charlcd_init_display(struct charlcd *lcd)
  176. {
  177. void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
  178. struct charlcd_priv *priv = to_priv(lcd);
  179. u8 init;
  180. if (lcd->ifwidth != 4 && lcd->ifwidth != 8)
  181. return -EINVAL;
  182. priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
  183. LCD_FLAG_C | LCD_FLAG_B;
  184. long_sleep(20); /* wait 20 ms after power-up for the paranoid */
  185. /*
  186. * 8-bit mode, 1 line, small fonts; let's do it 3 times, to make sure
  187. * the LCD is in 8-bit mode afterwards
  188. */
  189. init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
  190. if (lcd->ifwidth == 4) {
  191. init >>= 4;
  192. write_cmd_raw = lcd->ops->write_cmd_raw4;
  193. } else {
  194. write_cmd_raw = lcd->ops->write_cmd;
  195. }
  196. write_cmd_raw(lcd, init);
  197. long_sleep(10);
  198. write_cmd_raw(lcd, init);
  199. long_sleep(10);
  200. write_cmd_raw(lcd, init);
  201. long_sleep(10);
  202. if (lcd->ifwidth == 4) {
  203. /* Switch to 4-bit mode, 1 line, small fonts */
  204. lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
  205. long_sleep(10);
  206. }
  207. /* set font height and lines number */
  208. lcd->ops->write_cmd(lcd,
  209. LCD_CMD_FUNCTION_SET |
  210. ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
  211. ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
  212. ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
  213. long_sleep(10);
  214. /* display off, cursor off, blink off */
  215. lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CTRL);
  216. long_sleep(10);
  217. lcd->ops->write_cmd(lcd,
  218. LCD_CMD_DISPLAY_CTRL | /* set display mode */
  219. ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
  220. ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
  221. ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
  222. charlcd_backlight(lcd, (priv->flags & LCD_FLAG_L) ? 1 : 0);
  223. long_sleep(10);
  224. /* entry mode set : increment, cursor shifting */
  225. lcd->ops->write_cmd(lcd, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
  226. charlcd_clear_display(lcd);
  227. return 0;
  228. }
  229. /*
  230. * Parses an unsigned integer from a string, until a non-digit character
  231. * is found. The empty string is not accepted. No overflow checks are done.
  232. *
  233. * Returns whether the parsing was successful. Only in that case
  234. * the output parameters are written to.
  235. *
  236. * TODO: If the kernel adds an inplace version of kstrtoul(), this function
  237. * could be easily replaced by that.
  238. */
  239. static bool parse_n(const char *s, unsigned long *res, const char **next_s)
  240. {
  241. if (!isdigit(*s))
  242. return false;
  243. *res = 0;
  244. while (isdigit(*s)) {
  245. *res = *res * 10 + (*s - '0');
  246. ++s;
  247. }
  248. *next_s = s;
  249. return true;
  250. }
  251. /*
  252. * Parses a movement command of the form "(.*);", where the group can be
  253. * any number of subcommands of the form "(x|y)[0-9]+".
  254. *
  255. * Returns whether the command is valid. The position arguments are
  256. * only written if the parsing was successful.
  257. *
  258. * For instance:
  259. * - ";" returns (<original x>, <original y>).
  260. * - "x1;" returns (1, <original y>).
  261. * - "y2x1;" returns (1, 2).
  262. * - "x12y34x56;" returns (56, 34).
  263. * - "" fails.
  264. * - "x" fails.
  265. * - "x;" fails.
  266. * - "x1" fails.
  267. * - "xy12;" fails.
  268. * - "x12yy12;" fails.
  269. * - "xx" fails.
  270. */
  271. static bool parse_xy(const char *s, unsigned long *x, unsigned long *y)
  272. {
  273. unsigned long new_x = *x;
  274. unsigned long new_y = *y;
  275. for (;;) {
  276. if (!*s)
  277. return false;
  278. if (*s == ';')
  279. break;
  280. if (*s == 'x') {
  281. if (!parse_n(s + 1, &new_x, &s))
  282. return false;
  283. } else if (*s == 'y') {
  284. if (!parse_n(s + 1, &new_y, &s))
  285. return false;
  286. } else {
  287. return false;
  288. }
  289. }
  290. *x = new_x;
  291. *y = new_y;
  292. return true;
  293. }
  294. /*
  295. * These are the file operation function for user access to /dev/lcd
  296. * This function can also be called from inside the kernel, by
  297. * setting file and ppos to NULL.
  298. *
  299. */
  300. static inline int handle_lcd_special_code(struct charlcd *lcd)
  301. {
  302. struct charlcd_priv *priv = to_priv(lcd);
  303. /* LCD special codes */
  304. int processed = 0;
  305. char *esc = priv->esc_seq.buf + 2;
  306. int oldflags = priv->flags;
  307. /* check for display mode flags */
  308. switch (*esc) {
  309. case 'D': /* Display ON */
  310. priv->flags |= LCD_FLAG_D;
  311. processed = 1;
  312. break;
  313. case 'd': /* Display OFF */
  314. priv->flags &= ~LCD_FLAG_D;
  315. processed = 1;
  316. break;
  317. case 'C': /* Cursor ON */
  318. priv->flags |= LCD_FLAG_C;
  319. processed = 1;
  320. break;
  321. case 'c': /* Cursor OFF */
  322. priv->flags &= ~LCD_FLAG_C;
  323. processed = 1;
  324. break;
  325. case 'B': /* Blink ON */
  326. priv->flags |= LCD_FLAG_B;
  327. processed = 1;
  328. break;
  329. case 'b': /* Blink OFF */
  330. priv->flags &= ~LCD_FLAG_B;
  331. processed = 1;
  332. break;
  333. case '+': /* Back light ON */
  334. priv->flags |= LCD_FLAG_L;
  335. processed = 1;
  336. break;
  337. case '-': /* Back light OFF */
  338. priv->flags &= ~LCD_FLAG_L;
  339. processed = 1;
  340. break;
  341. case '*': /* Flash back light */
  342. charlcd_poke(lcd);
  343. processed = 1;
  344. break;
  345. case 'f': /* Small Font */
  346. priv->flags &= ~LCD_FLAG_F;
  347. processed = 1;
  348. break;
  349. case 'F': /* Large Font */
  350. priv->flags |= LCD_FLAG_F;
  351. processed = 1;
  352. break;
  353. case 'n': /* One Line */
  354. priv->flags &= ~LCD_FLAG_N;
  355. processed = 1;
  356. break;
  357. case 'N': /* Two Lines */
  358. priv->flags |= LCD_FLAG_N;
  359. processed = 1;
  360. break;
  361. case 'l': /* Shift Cursor Left */
  362. if (priv->addr.x > 0) {
  363. /* back one char if not at end of line */
  364. if (priv->addr.x < lcd->bwidth)
  365. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
  366. priv->addr.x--;
  367. }
  368. processed = 1;
  369. break;
  370. case 'r': /* shift cursor right */
  371. if (priv->addr.x < lcd->width) {
  372. /* allow the cursor to pass the end of the line */
  373. if (priv->addr.x < (lcd->bwidth - 1))
  374. lcd->ops->write_cmd(lcd,
  375. LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
  376. priv->addr.x++;
  377. }
  378. processed = 1;
  379. break;
  380. case 'L': /* shift display left */
  381. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT);
  382. processed = 1;
  383. break;
  384. case 'R': /* shift display right */
  385. lcd->ops->write_cmd(lcd,
  386. LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT |
  387. LCD_CMD_SHIFT_RIGHT);
  388. processed = 1;
  389. break;
  390. case 'k': { /* kill end of line */
  391. int x;
  392. for (x = priv->addr.x; x < lcd->bwidth; x++)
  393. lcd->ops->write_data(lcd, ' ');
  394. /* restore cursor position */
  395. charlcd_gotoxy(lcd);
  396. processed = 1;
  397. break;
  398. }
  399. case 'I': /* reinitialize display */
  400. charlcd_init_display(lcd);
  401. processed = 1;
  402. break;
  403. case 'G': {
  404. /* Generator : LGcxxxxx...xx; must have <c> between '0'
  405. * and '7', representing the numerical ASCII code of the
  406. * redefined character, and <xx...xx> a sequence of 16
  407. * hex digits representing 8 bytes for each character.
  408. * Most LCDs will only use 5 lower bits of the 7 first
  409. * bytes.
  410. */
  411. unsigned char cgbytes[8];
  412. unsigned char cgaddr;
  413. int cgoffset;
  414. int shift;
  415. char value;
  416. int addr;
  417. if (!strchr(esc, ';'))
  418. break;
  419. esc++;
  420. cgaddr = *(esc++) - '0';
  421. if (cgaddr > 7) {
  422. processed = 1;
  423. break;
  424. }
  425. cgoffset = 0;
  426. shift = 0;
  427. value = 0;
  428. while (*esc && cgoffset < 8) {
  429. shift ^= 4;
  430. if (*esc >= '0' && *esc <= '9') {
  431. value |= (*esc - '0') << shift;
  432. } else if (*esc >= 'A' && *esc <= 'F') {
  433. value |= (*esc - 'A' + 10) << shift;
  434. } else if (*esc >= 'a' && *esc <= 'f') {
  435. value |= (*esc - 'a' + 10) << shift;
  436. } else {
  437. esc++;
  438. continue;
  439. }
  440. if (shift == 0) {
  441. cgbytes[cgoffset++] = value;
  442. value = 0;
  443. }
  444. esc++;
  445. }
  446. lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
  447. for (addr = 0; addr < cgoffset; addr++)
  448. lcd->ops->write_data(lcd, cgbytes[addr]);
  449. /* ensures that we stop writing to CGRAM */
  450. charlcd_gotoxy(lcd);
  451. processed = 1;
  452. break;
  453. }
  454. case 'x': /* gotoxy : LxXXX[yYYY]; */
  455. case 'y': /* gotoxy : LyYYY[xXXX]; */
  456. if (priv->esc_seq.buf[priv->esc_seq.len - 1] != ';')
  457. break;
  458. /* If the command is valid, move to the new address */
  459. if (parse_xy(esc, &priv->addr.x, &priv->addr.y))
  460. charlcd_gotoxy(lcd);
  461. /* Regardless of its validity, mark as processed */
  462. processed = 1;
  463. break;
  464. }
  465. /* TODO: This indent party here got ugly, clean it! */
  466. /* Check whether one flag was changed */
  467. if (oldflags == priv->flags)
  468. return processed;
  469. /* check whether one of B,C,D flags were changed */
  470. if ((oldflags ^ priv->flags) &
  471. (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
  472. /* set display mode */
  473. lcd->ops->write_cmd(lcd,
  474. LCD_CMD_DISPLAY_CTRL |
  475. ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
  476. ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
  477. ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
  478. /* check whether one of F,N flags was changed */
  479. else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
  480. lcd->ops->write_cmd(lcd,
  481. LCD_CMD_FUNCTION_SET |
  482. ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
  483. ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
  484. ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
  485. /* check whether L flag was changed */
  486. else if ((oldflags ^ priv->flags) & LCD_FLAG_L)
  487. charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
  488. return processed;
  489. }
  490. static void charlcd_write_char(struct charlcd *lcd, char c)
  491. {
  492. struct charlcd_priv *priv = to_priv(lcd);
  493. /* first, we'll test if we're in escape mode */
  494. if ((c != '\n') && priv->esc_seq.len >= 0) {
  495. /* yes, let's add this char to the buffer */
  496. priv->esc_seq.buf[priv->esc_seq.len++] = c;
  497. priv->esc_seq.buf[priv->esc_seq.len] = '\0';
  498. } else {
  499. /* aborts any previous escape sequence */
  500. priv->esc_seq.len = -1;
  501. switch (c) {
  502. case LCD_ESCAPE_CHAR:
  503. /* start of an escape sequence */
  504. priv->esc_seq.len = 0;
  505. priv->esc_seq.buf[priv->esc_seq.len] = '\0';
  506. break;
  507. case '\b':
  508. /* go back one char and clear it */
  509. if (priv->addr.x > 0) {
  510. /*
  511. * check if we're not at the
  512. * end of the line
  513. */
  514. if (priv->addr.x < lcd->bwidth)
  515. /* back one char */
  516. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
  517. priv->addr.x--;
  518. }
  519. /* replace with a space */
  520. lcd->ops->write_data(lcd, ' ');
  521. /* back one char again */
  522. lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
  523. break;
  524. case '\f':
  525. /* quickly clear the display */
  526. charlcd_clear_fast(lcd);
  527. break;
  528. case '\n':
  529. /*
  530. * flush the remainder of the current line and
  531. * go to the beginning of the next line
  532. */
  533. for (; priv->addr.x < lcd->bwidth; priv->addr.x++)
  534. lcd->ops->write_data(lcd, ' ');
  535. priv->addr.x = 0;
  536. priv->addr.y = (priv->addr.y + 1) % lcd->height;
  537. charlcd_gotoxy(lcd);
  538. break;
  539. case '\r':
  540. /* go to the beginning of the same line */
  541. priv->addr.x = 0;
  542. charlcd_gotoxy(lcd);
  543. break;
  544. case '\t':
  545. /* print a space instead of the tab */
  546. charlcd_print(lcd, ' ');
  547. break;
  548. default:
  549. /* simply print this char */
  550. charlcd_print(lcd, c);
  551. break;
  552. }
  553. }
  554. /*
  555. * now we'll see if we're in an escape mode and if the current
  556. * escape sequence can be understood.
  557. */
  558. if (priv->esc_seq.len >= 2) {
  559. int processed = 0;
  560. if (!strcmp(priv->esc_seq.buf, "[2J")) {
  561. /* clear the display */
  562. charlcd_clear_fast(lcd);
  563. processed = 1;
  564. } else if (!strcmp(priv->esc_seq.buf, "[H")) {
  565. /* cursor to home */
  566. charlcd_home(lcd);
  567. processed = 1;
  568. }
  569. /* codes starting with ^[[L */
  570. else if ((priv->esc_seq.len >= 3) &&
  571. (priv->esc_seq.buf[0] == '[') &&
  572. (priv->esc_seq.buf[1] == 'L')) {
  573. processed = handle_lcd_special_code(lcd);
  574. }
  575. /* LCD special escape codes */
  576. /*
  577. * flush the escape sequence if it's been processed
  578. * or if it is getting too long.
  579. */
  580. if (processed || (priv->esc_seq.len >= LCD_ESCAPE_LEN))
  581. priv->esc_seq.len = -1;
  582. } /* escape codes */
  583. }
  584. static struct charlcd *the_charlcd;
  585. static ssize_t charlcd_write(struct file *file, const char __user *buf,
  586. size_t count, loff_t *ppos)
  587. {
  588. const char __user *tmp = buf;
  589. char c;
  590. for (; count-- > 0; (*ppos)++, tmp++) {
  591. if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
  592. /*
  593. * let's be a little nice with other processes
  594. * that need some CPU
  595. */
  596. schedule();
  597. if (get_user(c, tmp))
  598. return -EFAULT;
  599. charlcd_write_char(the_charlcd, c);
  600. }
  601. return tmp - buf;
  602. }
  603. static int charlcd_open(struct inode *inode, struct file *file)
  604. {
  605. struct charlcd_priv *priv = to_priv(the_charlcd);
  606. int ret;
  607. ret = -EBUSY;
  608. if (!atomic_dec_and_test(&charlcd_available))
  609. goto fail; /* open only once at a time */
  610. ret = -EPERM;
  611. if (file->f_mode & FMODE_READ) /* device is write-only */
  612. goto fail;
  613. if (priv->must_clear) {
  614. charlcd_clear_display(&priv->lcd);
  615. priv->must_clear = false;
  616. }
  617. return nonseekable_open(inode, file);
  618. fail:
  619. atomic_inc(&charlcd_available);
  620. return ret;
  621. }
  622. static int charlcd_release(struct inode *inode, struct file *file)
  623. {
  624. atomic_inc(&charlcd_available);
  625. return 0;
  626. }
  627. static const struct file_operations charlcd_fops = {
  628. .write = charlcd_write,
  629. .open = charlcd_open,
  630. .release = charlcd_release,
  631. .llseek = no_llseek,
  632. };
  633. static struct miscdevice charlcd_dev = {
  634. .minor = LCD_MINOR,
  635. .name = "lcd",
  636. .fops = &charlcd_fops,
  637. };
  638. static void charlcd_puts(struct charlcd *lcd, const char *s)
  639. {
  640. const char *tmp = s;
  641. int count = strlen(s);
  642. for (; count-- > 0; tmp++) {
  643. if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
  644. /*
  645. * let's be a little nice with other processes
  646. * that need some CPU
  647. */
  648. schedule();
  649. charlcd_write_char(lcd, *tmp);
  650. }
  651. }
  652. /* initialize the LCD driver */
  653. static int charlcd_init(struct charlcd *lcd)
  654. {
  655. struct charlcd_priv *priv = to_priv(lcd);
  656. int ret;
  657. if (lcd->ops->backlight) {
  658. mutex_init(&priv->bl_tempo_lock);
  659. INIT_DELAYED_WORK(&priv->bl_work, charlcd_bl_off);
  660. }
  661. /*
  662. * before this line, we must NOT send anything to the display.
  663. * Since charlcd_init_display() needs to write data, we have to
  664. * enable mark the LCD initialized just before.
  665. */
  666. ret = charlcd_init_display(lcd);
  667. if (ret)
  668. return ret;
  669. /* display a short message */
  670. #ifdef CONFIG_PANEL_CHANGE_MESSAGE
  671. #ifdef CONFIG_PANEL_BOOT_MESSAGE
  672. charlcd_puts(lcd, "\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE);
  673. #endif
  674. #else
  675. charlcd_puts(lcd, "\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\n");
  676. #endif
  677. /* clear the display on the next device opening */
  678. priv->must_clear = true;
  679. charlcd_home(lcd);
  680. return 0;
  681. }
  682. struct charlcd *charlcd_alloc(unsigned int drvdata_size)
  683. {
  684. struct charlcd_priv *priv;
  685. struct charlcd *lcd;
  686. priv = kzalloc(sizeof(*priv) + drvdata_size, GFP_KERNEL);
  687. if (!priv)
  688. return NULL;
  689. priv->esc_seq.len = -1;
  690. lcd = &priv->lcd;
  691. lcd->ifwidth = 8;
  692. lcd->bwidth = DEFAULT_LCD_BWIDTH;
  693. lcd->hwidth = DEFAULT_LCD_HWIDTH;
  694. lcd->drvdata = priv->drvdata;
  695. return lcd;
  696. }
  697. EXPORT_SYMBOL_GPL(charlcd_alloc);
  698. static int panel_notify_sys(struct notifier_block *this, unsigned long code,
  699. void *unused)
  700. {
  701. struct charlcd *lcd = the_charlcd;
  702. switch (code) {
  703. case SYS_DOWN:
  704. charlcd_puts(lcd,
  705. "\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+");
  706. break;
  707. case SYS_HALT:
  708. charlcd_puts(lcd, "\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+");
  709. break;
  710. case SYS_POWER_OFF:
  711. charlcd_puts(lcd, "\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+");
  712. break;
  713. default:
  714. break;
  715. }
  716. return NOTIFY_DONE;
  717. }
  718. static struct notifier_block panel_notifier = {
  719. panel_notify_sys,
  720. NULL,
  721. 0
  722. };
  723. int charlcd_register(struct charlcd *lcd)
  724. {
  725. int ret;
  726. ret = charlcd_init(lcd);
  727. if (ret)
  728. return ret;
  729. ret = misc_register(&charlcd_dev);
  730. if (ret)
  731. return ret;
  732. the_charlcd = lcd;
  733. register_reboot_notifier(&panel_notifier);
  734. return 0;
  735. }
  736. EXPORT_SYMBOL_GPL(charlcd_register);
  737. int charlcd_unregister(struct charlcd *lcd)
  738. {
  739. struct charlcd_priv *priv = to_priv(lcd);
  740. unregister_reboot_notifier(&panel_notifier);
  741. charlcd_puts(lcd, "\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-");
  742. misc_deregister(&charlcd_dev);
  743. the_charlcd = NULL;
  744. if (lcd->ops->backlight) {
  745. cancel_delayed_work_sync(&priv->bl_work);
  746. priv->lcd.ops->backlight(&priv->lcd, 0);
  747. }
  748. return 0;
  749. }
  750. EXPORT_SYMBOL_GPL(charlcd_unregister);
  751. MODULE_LICENSE("GPL");