hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/auxdisplay/charlcd.c
....@@ -20,9 +20,7 @@
2020
2121 #include <generated/utsrelease.h>
2222
23
-#include <misc/charlcd.h>
24
-
25
-#define LCD_MINOR 156
23
+#include "charlcd.h"
2624
2725 #define DEFAULT_LCD_BWIDTH 40
2826 #define DEFAULT_LCD_HWIDTH 64
....@@ -88,10 +86,10 @@
8886 int len;
8987 } esc_seq;
9088
91
- unsigned long long drvdata[0];
89
+ unsigned long long drvdata[];
9290 };
9391
94
-#define to_priv(p) container_of(p, struct charlcd_priv, lcd)
92
+#define charlcd_to_priv(p) container_of(p, struct charlcd_priv, lcd)
9593
9694 /* Device single-open policy control */
9795 static atomic_t charlcd_available = ATOMIC_INIT(1);
....@@ -105,7 +103,7 @@
105103 /* turn the backlight on or off */
106104 static void charlcd_backlight(struct charlcd *lcd, int on)
107105 {
108
- struct charlcd_priv *priv = to_priv(lcd);
106
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
109107
110108 if (!lcd->ops->backlight)
111109 return;
....@@ -134,7 +132,7 @@
134132 /* turn the backlight on for a little while */
135133 void charlcd_poke(struct charlcd *lcd)
136134 {
137
- struct charlcd_priv *priv = to_priv(lcd);
135
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
138136
139137 if (!lcd->ops->backlight)
140138 return;
....@@ -152,7 +150,7 @@
152150
153151 static void charlcd_gotoxy(struct charlcd *lcd)
154152 {
155
- struct charlcd_priv *priv = to_priv(lcd);
153
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
156154 unsigned int addr;
157155
158156 /*
....@@ -170,7 +168,7 @@
170168
171169 static void charlcd_home(struct charlcd *lcd)
172170 {
173
- struct charlcd_priv *priv = to_priv(lcd);
171
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
174172
175173 priv->addr.x = 0;
176174 priv->addr.y = 0;
....@@ -179,7 +177,7 @@
179177
180178 static void charlcd_print(struct charlcd *lcd, char c)
181179 {
182
- struct charlcd_priv *priv = to_priv(lcd);
180
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
183181
184182 if (priv->addr.x < lcd->bwidth) {
185183 if (lcd->char_conv)
....@@ -211,7 +209,7 @@
211209 /* clears the display and resets X/Y */
212210 static void charlcd_clear_display(struct charlcd *lcd)
213211 {
214
- struct charlcd_priv *priv = to_priv(lcd);
212
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
215213
216214 lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CLEAR);
217215 priv->addr.x = 0;
....@@ -223,7 +221,7 @@
223221 static int charlcd_init_display(struct charlcd *lcd)
224222 {
225223 void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
226
- struct charlcd_priv *priv = to_priv(lcd);
224
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
227225 u8 init;
228226
229227 if (lcd->ifwidth != 4 && lcd->ifwidth != 8)
....@@ -288,31 +286,6 @@
288286 }
289287
290288 /*
291
- * Parses an unsigned integer from a string, until a non-digit character
292
- * is found. The empty string is not accepted. No overflow checks are done.
293
- *
294
- * Returns whether the parsing was successful. Only in that case
295
- * the output parameters are written to.
296
- *
297
- * TODO: If the kernel adds an inplace version of kstrtoul(), this function
298
- * could be easily replaced by that.
299
- */
300
-static bool parse_n(const char *s, unsigned long *res, const char **next_s)
301
-{
302
- if (!isdigit(*s))
303
- return false;
304
-
305
- *res = 0;
306
- while (isdigit(*s)) {
307
- *res = *res * 10 + (*s - '0');
308
- ++s;
309
- }
310
-
311
- *next_s = s;
312
- return true;
313
-}
314
-
315
-/*
316289 * Parses a movement command of the form "(.*);", where the group can be
317290 * any number of subcommands of the form "(x|y)[0-9]+".
318291 *
....@@ -336,6 +309,7 @@
336309 {
337310 unsigned long new_x = *x;
338311 unsigned long new_y = *y;
312
+ char *p;
339313
340314 for (;;) {
341315 if (!*s)
....@@ -345,11 +319,15 @@
345319 break;
346320
347321 if (*s == 'x') {
348
- if (!parse_n(s + 1, &new_x, &s))
322
+ new_x = simple_strtoul(s + 1, &p, 10);
323
+ if (p == s + 1)
349324 return false;
325
+ s = p;
350326 } else if (*s == 'y') {
351
- if (!parse_n(s + 1, &new_y, &s))
327
+ new_y = simple_strtoul(s + 1, &p, 10);
328
+ if (p == s + 1)
352329 return false;
330
+ s = p;
353331 } else {
354332 return false;
355333 }
....@@ -369,7 +347,7 @@
369347
370348 static inline int handle_lcd_special_code(struct charlcd *lcd)
371349 {
372
- struct charlcd_priv *priv = to_priv(lcd);
350
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
373351
374352 /* LCD special codes */
375353
....@@ -507,24 +485,19 @@
507485 shift = 0;
508486 value = 0;
509487 while (*esc && cgoffset < 8) {
510
- shift ^= 4;
511
- if (*esc >= '0' && *esc <= '9') {
512
- value |= (*esc - '0') << shift;
513
- } else if (*esc >= 'A' && *esc <= 'F') {
514
- value |= (*esc - 'A' + 10) << shift;
515
- } else if (*esc >= 'a' && *esc <= 'f') {
516
- value |= (*esc - 'a' + 10) << shift;
517
- } else {
518
- esc++;
519
- continue;
520
- }
488
+ int half;
521489
490
+ shift ^= 4;
491
+
492
+ half = hex_to_bin(*esc++);
493
+ if (half < 0)
494
+ continue;
495
+
496
+ value |= half << shift;
522497 if (shift == 0) {
523498 cgbytes[cgoffset++] = value;
524499 value = 0;
525500 }
526
-
527
- esc++;
528501 }
529502
530503 lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
....@@ -580,7 +553,7 @@
580553
581554 static void charlcd_write_char(struct charlcd *lcd, char c)
582555 {
583
- struct charlcd_priv *priv = to_priv(lcd);
556
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
584557
585558 /* first, we'll test if we're in escape mode */
586559 if ((c != '\n') && priv->esc_seq.len >= 0) {
....@@ -705,7 +678,7 @@
705678
706679 static int charlcd_open(struct inode *inode, struct file *file)
707680 {
708
- struct charlcd_priv *priv = to_priv(the_charlcd);
681
+ struct charlcd_priv *priv = charlcd_to_priv(the_charlcd);
709682 int ret;
710683
711684 ret = -EBUSY;
....@@ -763,10 +736,24 @@
763736 }
764737 }
765738
739
+#ifdef CONFIG_PANEL_BOOT_MESSAGE
740
+#define LCD_INIT_TEXT CONFIG_PANEL_BOOT_MESSAGE
741
+#else
742
+#define LCD_INIT_TEXT "Linux-" UTS_RELEASE "\n"
743
+#endif
744
+
745
+#ifdef CONFIG_CHARLCD_BL_ON
746
+#define LCD_INIT_BL "\x1b[L+"
747
+#elif defined(CONFIG_CHARLCD_BL_FLASH)
748
+#define LCD_INIT_BL "\x1b[L*"
749
+#else
750
+#define LCD_INIT_BL "\x1b[L-"
751
+#endif
752
+
766753 /* initialize the LCD driver */
767754 static int charlcd_init(struct charlcd *lcd)
768755 {
769
- struct charlcd_priv *priv = to_priv(lcd);
756
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
770757 int ret;
771758
772759 if (lcd->ops->backlight) {
....@@ -784,13 +771,8 @@
784771 return ret;
785772
786773 /* display a short message */
787
-#ifdef CONFIG_PANEL_CHANGE_MESSAGE
788
-#ifdef CONFIG_PANEL_BOOT_MESSAGE
789
- charlcd_puts(lcd, "\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE);
790
-#endif
791
-#else
792
- charlcd_puts(lcd, "\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\n");
793
-#endif
774
+ charlcd_puts(lcd, "\x1b[Lc\x1b[Lb" LCD_INIT_BL LCD_INIT_TEXT);
775
+
794776 /* clear the display on the next device opening */
795777 priv->must_clear = true;
796778 charlcd_home(lcd);
....@@ -817,6 +799,12 @@
817799 return lcd;
818800 }
819801 EXPORT_SYMBOL_GPL(charlcd_alloc);
802
+
803
+void charlcd_free(struct charlcd *lcd)
804
+{
805
+ kfree(charlcd_to_priv(lcd));
806
+}
807
+EXPORT_SYMBOL_GPL(charlcd_free);
820808
821809 static int panel_notify_sys(struct notifier_block *this, unsigned long code,
822810 void *unused)
....@@ -866,7 +854,7 @@
866854
867855 int charlcd_unregister(struct charlcd *lcd)
868856 {
869
- struct charlcd_priv *priv = to_priv(lcd);
857
+ struct charlcd_priv *priv = charlcd_to_priv(lcd);
870858
871859 unregister_reboot_notifier(&panel_notifier);
872860 charlcd_puts(lcd, "\x0cLCD driver unloaded.\x1b[Lc\x1b[Lb\x1b[L-");