1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
38
39#include <linux/module.h>
40
41#include <linux/types.h>
42#include <linux/errno.h>
43#include <linux/signal.h>
44#include <linux/sched.h>
45#include <linux/spinlock.h>
46#include <linux/interrupt.h>
47#include <linux/miscdevice.h>
48#include <linux/slab.h>
49#include <linux/ioport.h>
50#include <linux/fcntl.h>
51#include <linux/init.h>
52#include <linux/delay.h>
53#include <linux/kernel.h>
54#include <linux/ctype.h>
55#include <linux/parport.h>
56#include <linux/list.h>
57#include <linux/notifier.h>
58#include <linux/reboot.h>
59#include <generated/utsrelease.h>
60
61#include <linux/io.h>
62#include <linux/uaccess.h>
63
64#define LCD_MINOR 156
65#define KEYPAD_MINOR 185
66
67#define PANEL_VERSION "0.9.5"
68
69#define LCD_MAXBYTES 256
70
71#define KEYPAD_BUFFER 64
72
73
74#define INPUT_POLL_TIME (HZ/50)
75
76#define KEYPAD_REP_START (10)
77
78#define KEYPAD_REP_DELAY (2)
79
80
81#define FLASH_LIGHT_TEMPO (200)
82
83
84#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3)
85
86#define PNL_PBUSY 0x80
87#define PNL_PACK 0x40
88#define PNL_POUTPA 0x20
89#define PNL_PSELECD 0x10
90#define PNL_PERRORP 0x08
91
92#define PNL_PBIDIR 0x20
93
94#define PNL_PINTEN 0x10
95#define PNL_PSELECP 0x08
96#define PNL_PINITP 0x04
97#define PNL_PAUTOLF 0x02
98#define PNL_PSTROBE 0x01
99
100#define PNL_PD0 0x01
101#define PNL_PD1 0x02
102#define PNL_PD2 0x04
103#define PNL_PD3 0x08
104#define PNL_PD4 0x10
105#define PNL_PD5 0x20
106#define PNL_PD6 0x40
107#define PNL_PD7 0x80
108
109#define PIN_NONE 0
110#define PIN_STROBE 1
111#define PIN_D0 2
112#define PIN_D1 3
113#define PIN_D2 4
114#define PIN_D3 5
115#define PIN_D4 6
116#define PIN_D5 7
117#define PIN_D6 8
118#define PIN_D7 9
119#define PIN_AUTOLF 14
120#define PIN_INITP 16
121#define PIN_SELECP 17
122#define PIN_NOT_SET 127
123
124#define LCD_FLAG_S 0x0001
125#define LCD_FLAG_ID 0x0002
126#define LCD_FLAG_B 0x0004
127#define LCD_FLAG_C 0x0008
128#define LCD_FLAG_D 0x0010
129#define LCD_FLAG_F 0x0020
130#define LCD_FLAG_N 0x0040
131#define LCD_FLAG_L 0x0080
132
133#define LCD_ESCAPE_LEN 24
134#define LCD_ESCAPE_CHAR 27
135
136
137#define r_ctr(x) (parport_read_control((x)->port))
138#define r_dtr(x) (parport_read_data((x)->port))
139#define r_str(x) (parport_read_status((x)->port))
140#define w_ctr(x, y) (parport_write_control((x)->port, (y)))
141#define w_dtr(x, y) (parport_write_data((x)->port, (y)))
142
143
144
145static __u8 scan_mask_o;
146
147static __u8 scan_mask_i;
148
149typedef __u64 pmask_t;
150
151enum input_type {
152 INPUT_TYPE_STD,
153 INPUT_TYPE_KBD,
154};
155
156enum input_state {
157 INPUT_ST_LOW,
158 INPUT_ST_RISING,
159 INPUT_ST_HIGH,
160 INPUT_ST_FALLING,
161};
162
163struct logical_input {
164 struct list_head list;
165 pmask_t mask;
166 pmask_t value;
167 enum input_type type;
168 enum input_state state;
169 __u8 rise_time, fall_time;
170 __u8 rise_timer, fall_timer, high_timer;
171
172 union {
173 struct {
174 void (*press_fct) (int);
175 void (*release_fct) (int);
176 int press_data;
177 int release_data;
178 } std;
179 struct {
180
181 char press_str[sizeof(void *) + sizeof(int)];
182 char repeat_str[sizeof(void *) + sizeof(int)];
183 char release_str[sizeof(void *) + sizeof(int)];
184 } kbd;
185 } u;
186};
187
188static LIST_HEAD(logical_inputs);
189
190
191
192
193
194
195
196
197
198
199
200
201
202static pmask_t phys_read;
203
204static pmask_t phys_read_prev;
205
206static pmask_t phys_curr;
207
208static pmask_t phys_prev;
209
210static char inputs_stable;
211
212
213static char keypad_buffer[KEYPAD_BUFFER];
214static int keypad_buflen;
215static int keypad_start;
216static char keypressed;
217static wait_queue_head_t keypad_read_wait;
218
219
220
221
222static unsigned long int lcd_flags;
223
224static unsigned long int lcd_addr_x;
225
226static unsigned long int lcd_addr_y;
227
228static char lcd_escape[LCD_ESCAPE_LEN + 1];
229
230static int lcd_escape_len = -1;
231
232
233
234
235
236
237#define BIT_CLR 0
238#define BIT_SET 1
239#define BIT_MSK 2
240#define BIT_STATES 3
241
242
243
244#define LCD_BIT_E 0
245#define LCD_BIT_RS 1
246#define LCD_BIT_RW 2
247#define LCD_BIT_BL 3
248#define LCD_BIT_CL 4
249#define LCD_BIT_DA 5
250#define LCD_BITS 6
251
252
253
254
255#define LCD_PORT_C 0
256#define LCD_PORT_D 1
257#define LCD_PORTS 2
258
259static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
260
261
262
263
264#define LCD_PROTO_PARALLEL 0
265#define LCD_PROTO_SERIAL 1
266#define LCD_PROTO_TI_DA8XX_LCD 2
267
268
269
270
271#define LCD_CHARSET_NORMAL 0
272#define LCD_CHARSET_KS0074 1
273
274
275
276
277#define LCD_TYPE_NONE 0
278#define LCD_TYPE_OLD 1
279#define LCD_TYPE_KS0074 2
280#define LCD_TYPE_HANTRONIX 3
281#define LCD_TYPE_NEXCOM 4
282#define LCD_TYPE_CUSTOM 5
283
284
285
286
287#define KEYPAD_TYPE_NONE 0
288#define KEYPAD_TYPE_OLD 1
289#define KEYPAD_TYPE_NEW 2
290#define KEYPAD_TYPE_NEXCOM 3
291
292
293
294
295#define PANEL_PROFILE_CUSTOM 0
296#define PANEL_PROFILE_OLD 1
297#define PANEL_PROFILE_NEW 2
298#define PANEL_PROFILE_HANTRONIX 3
299#define PANEL_PROFILE_NEXCOM 4
300#define PANEL_PROFILE_LARGE 5
301
302
303
304
305#define DEFAULT_PROFILE PANEL_PROFILE_LARGE
306#define DEFAULT_PARPORT 0
307#define DEFAULT_LCD LCD_TYPE_OLD
308#define DEFAULT_KEYPAD KEYPAD_TYPE_OLD
309#define DEFAULT_LCD_WIDTH 40
310#define DEFAULT_LCD_BWIDTH 40
311#define DEFAULT_LCD_HWIDTH 64
312#define DEFAULT_LCD_HEIGHT 2
313#define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL
314
315#define DEFAULT_LCD_PIN_E PIN_AUTOLF
316#define DEFAULT_LCD_PIN_RS PIN_SELECP
317#define DEFAULT_LCD_PIN_RW PIN_INITP
318#define DEFAULT_LCD_PIN_SCL PIN_STROBE
319#define DEFAULT_LCD_PIN_SDA PIN_D0
320#define DEFAULT_LCD_PIN_BL PIN_NOT_SET
321#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL
322
323#ifdef CONFIG_PANEL_PROFILE
324#undef DEFAULT_PROFILE
325#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE
326#endif
327
328#ifdef CONFIG_PANEL_PARPORT
329#undef DEFAULT_PARPORT
330#define DEFAULT_PARPORT CONFIG_PANEL_PARPORT
331#endif
332
333#if DEFAULT_PROFILE == 0
334#ifdef CONFIG_PANEL_KEYPAD
335#undef DEFAULT_KEYPAD
336#define DEFAULT_KEYPAD CONFIG_PANEL_KEYPAD
337#endif
338
339#ifdef CONFIG_PANEL_LCD
340#undef DEFAULT_LCD
341#define DEFAULT_LCD CONFIG_PANEL_LCD
342#endif
343
344#ifdef CONFIG_PANEL_LCD_WIDTH
345#undef DEFAULT_LCD_WIDTH
346#define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH
347#endif
348
349#ifdef CONFIG_PANEL_LCD_BWIDTH
350#undef DEFAULT_LCD_BWIDTH
351#define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH
352#endif
353
354#ifdef CONFIG_PANEL_LCD_HWIDTH
355#undef DEFAULT_LCD_HWIDTH
356#define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH
357#endif
358
359#ifdef CONFIG_PANEL_LCD_HEIGHT
360#undef DEFAULT_LCD_HEIGHT
361#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT
362#endif
363
364#ifdef CONFIG_PANEL_LCD_PROTO
365#undef DEFAULT_LCD_PROTO
366#define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO
367#endif
368
369#ifdef CONFIG_PANEL_LCD_PIN_E
370#undef DEFAULT_LCD_PIN_E
371#define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E
372#endif
373
374#ifdef CONFIG_PANEL_LCD_PIN_RS
375#undef DEFAULT_LCD_PIN_RS
376#define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS
377#endif
378
379#ifdef CONFIG_PANEL_LCD_PIN_RW
380#undef DEFAULT_LCD_PIN_RW
381#define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW
382#endif
383
384#ifdef CONFIG_PANEL_LCD_PIN_SCL
385#undef DEFAULT_LCD_PIN_SCL
386#define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL
387#endif
388
389#ifdef CONFIG_PANEL_LCD_PIN_SDA
390#undef DEFAULT_LCD_PIN_SDA
391#define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA
392#endif
393
394#ifdef CONFIG_PANEL_LCD_PIN_BL
395#undef DEFAULT_LCD_PIN_BL
396#define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL
397#endif
398
399#ifdef CONFIG_PANEL_LCD_CHARSET
400#undef DEFAULT_LCD_CHARSET
401#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET
402#endif
403
404#endif
405
406
407static int keypad_open_cnt;
408static int lcd_open_cnt;
409static struct pardevice *pprt;
410
411static int lcd_initialized;
412static int keypad_initialized;
413
414static int light_tempo;
415
416static char lcd_must_clear;
417static char lcd_left_shift;
418static char init_in_progress;
419
420static void (*lcd_write_cmd) (int);
421static void (*lcd_write_data) (int);
422static void (*lcd_clear_fast) (void);
423
424static DEFINE_SPINLOCK(pprt_lock);
425static struct timer_list scan_timer;
426
427MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver");
428
429static int parport = -1;
430module_param(parport, int, 0000);
431MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)");
432
433static int lcd_height = -1;
434module_param(lcd_height, int, 0000);
435MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD");
436
437static int lcd_width = -1;
438module_param(lcd_width, int, 0000);
439MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD");
440
441static int lcd_bwidth = -1;
442module_param(lcd_bwidth, int, 0000);
443MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)");
444
445static int lcd_hwidth = -1;
446module_param(lcd_hwidth, int, 0000);
447MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)");
448
449static int lcd_enabled = -1;
450module_param(lcd_enabled, int, 0000);
451MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead");
452
453static int keypad_enabled = -1;
454module_param(keypad_enabled, int, 0000);
455MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
456
457static int lcd_type = -1;
458module_param(lcd_type, int, 0000);
459MODULE_PARM_DESC(lcd_type,
460 "LCD type: 0=none, 1=old //, 2=serial ks0074, "
461 "3=hantronix //, 4=nexcom //, 5=compiled-in");
462
463static int lcd_proto = -1;
464module_param(lcd_proto, int, 0000);
465MODULE_PARM_DESC(lcd_proto,
466 "LCD communication: 0=parallel (//), 1=serial,"
467 "2=TI LCD Interface");
468
469static int lcd_charset = -1;
470module_param(lcd_charset, int, 0000);
471MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074");
472
473static int keypad_type = -1;
474module_param(keypad_type, int, 0000);
475MODULE_PARM_DESC(keypad_type,
476 "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, "
477 "3=nexcom 4 keys");
478
479static int profile = DEFAULT_PROFILE;
480module_param(profile, int, 0000);
481MODULE_PARM_DESC(profile,
482 "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; "
483 "4=16x2 nexcom; default=40x2, old kp");
484
485
486
487
488
489
490
491
492
493
494static int lcd_e_pin = PIN_NOT_SET;
495module_param(lcd_e_pin, int, 0000);
496MODULE_PARM_DESC(lcd_e_pin,
497 "# of the // port pin connected to LCD 'E' signal, "
498 "with polarity (-17..17)");
499
500static int lcd_rs_pin = PIN_NOT_SET;
501module_param(lcd_rs_pin, int, 0000);
502MODULE_PARM_DESC(lcd_rs_pin,
503 "# of the // port pin connected to LCD 'RS' signal, "
504 "with polarity (-17..17)");
505
506static int lcd_rw_pin = PIN_NOT_SET;
507module_param(lcd_rw_pin, int, 0000);
508MODULE_PARM_DESC(lcd_rw_pin,
509 "# of the // port pin connected to LCD 'RW' signal, "
510 "with polarity (-17..17)");
511
512static int lcd_bl_pin = PIN_NOT_SET;
513module_param(lcd_bl_pin, int, 0000);
514MODULE_PARM_DESC(lcd_bl_pin,
515 "# of the // port pin connected to LCD backlight, "
516 "with polarity (-17..17)");
517
518static int lcd_da_pin = PIN_NOT_SET;
519module_param(lcd_da_pin, int, 0000);
520MODULE_PARM_DESC(lcd_da_pin,
521 "# of the // port pin connected to serial LCD 'SDA' "
522 "signal, with polarity (-17..17)");
523
524static int lcd_cl_pin = PIN_NOT_SET;
525module_param(lcd_cl_pin, int, 0000);
526MODULE_PARM_DESC(lcd_cl_pin,
527 "# of the // port pin connected to serial LCD 'SCL' "
528 "signal, with polarity (-17..17)");
529
530static const unsigned char *lcd_char_conv;
531
532
533static const unsigned char lcd_char_conv_ks0074[256] = {
534
535 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
536 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
537 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
538 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
539 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27,
540 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
541 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
542 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
543 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
544 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
545 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
546 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4,
547 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
548 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
549 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
550 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20,
551 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
552 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
553 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
554 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
555 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f,
556 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96,
557 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd,
558 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60,
559 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9,
560 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3,
561 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78,
562 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe,
563 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8,
564 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69,
565 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25,
566 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79,
567};
568
569static const char old_keypad_profile[][4][9] = {
570 {"S0", "Left\n", "Left\n", ""},
571 {"S1", "Down\n", "Down\n", ""},
572 {"S2", "Up\n", "Up\n", ""},
573 {"S3", "Right\n", "Right\n", ""},
574 {"S4", "Esc\n", "Esc\n", ""},
575 {"S5", "Ret\n", "Ret\n", ""},
576 {"", "", "", ""}
577};
578
579
580static const char new_keypad_profile[][4][9] = {
581 {"S0", "Left\n", "Left\n", ""},
582 {"S1", "Down\n", "Down\n", ""},
583 {"S2", "Up\n", "Up\n", ""},
584 {"S3", "Right\n", "Right\n", ""},
585 {"S4s5", "", "Esc\n", "Esc\n"},
586 {"s4S5", "", "Ret\n", "Ret\n"},
587 {"S4S5", "Help\n", "", ""},
588
589 {"", "", "", ""}
590};
591
592
593static const char nexcom_keypad_profile[][4][9] = {
594 {"a-p-e-", "Down\n", "Down\n", ""},
595 {"a-p-E-", "Ret\n", "Ret\n", ""},
596 {"a-P-E-", "Esc\n", "Esc\n", ""},
597 {"a-P-e-", "Up\n", "Up\n", ""},
598
599 {"", "", "", ""}
600};
601
602static const char (*keypad_profile)[4][9] = old_keypad_profile;
603
604
605static struct {
606 unsigned char e;
607 unsigned char rs;
608 unsigned char rw;
609 unsigned char bl;
610 unsigned char cl;
611 unsigned char da;
612} bits;
613
614static void init_scan_timer(void);
615
616
617static int set_data_bits(void)
618{
619 int val, bit;
620
621 val = r_dtr(pprt);
622 for (bit = 0; bit < LCD_BITS; bit++)
623 val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK];
624
625 val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e]
626 | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs]
627 | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw]
628 | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl]
629 | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl]
630 | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da];
631
632 w_dtr(pprt, val);
633 return val;
634}
635
636
637static int set_ctrl_bits(void)
638{
639 int val, bit;
640
641 val = r_ctr(pprt);
642 for (bit = 0; bit < LCD_BITS; bit++)
643 val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK];
644
645 val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e]
646 | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs]
647 | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw]
648 | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl]
649 | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl]
650 | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da];
651
652 w_ctr(pprt, val);
653 return val;
654}
655
656
657static void panel_set_bits(void)
658{
659 set_data_bits();
660 set_ctrl_bits();
661}
662
663
664
665
666
667
668
669
670
671
672static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
673{
674 int d_bit, c_bit, inv;
675
676 d_val[0] = c_val[0] = d_val[1] = c_val[1] = 0;
677 d_val[2] = c_val[2] = 0xFF;
678
679 if (pin == 0)
680 return;
681
682 inv = (pin < 0);
683 if (inv)
684 pin = -pin;
685
686 d_bit = c_bit = 0;
687
688 switch (pin) {
689 case PIN_STROBE:
690 c_bit = PNL_PSTROBE;
691 inv = !inv;
692 break;
693 case PIN_D0...PIN_D7:
694 d_bit = 1 << (pin - 2);
695 break;
696 case PIN_AUTOLF:
697 c_bit = PNL_PAUTOLF;
698 inv = !inv;
699 break;
700 case PIN_INITP:
701 c_bit = PNL_PINITP;
702 break;
703 case PIN_SELECP:
704 c_bit = PNL_PSELECP;
705 inv = !inv;
706 break;
707 default:
708 break;
709 }
710
711 if (c_bit) {
712 c_val[2] &= ~c_bit;
713 c_val[!inv] = c_bit;
714 } else if (d_bit) {
715 d_val[2] &= ~d_bit;
716 d_val[!inv] = d_bit;
717 }
718}
719
720
721static void long_sleep(int ms)
722{
723
724 if (in_interrupt())
725 mdelay(ms);
726 else {
727 current->state = TASK_INTERRUPTIBLE;
728 schedule_timeout((ms * HZ + 999) / 1000);
729 }
730}
731
732
733
734static void lcd_send_serial(int byte)
735{
736 int bit;
737
738
739
740 for (bit = 0; bit < 8; bit++) {
741 bits.cl = BIT_CLR;
742 panel_set_bits();
743 bits.da = byte & 1;
744 panel_set_bits();
745 udelay(2);
746 bits.cl = BIT_SET;
747 panel_set_bits();
748 udelay(1);
749 byte >>= 1;
750 }
751}
752
753
754static void lcd_backlight(int on)
755{
756 if (lcd_bl_pin == PIN_NONE)
757 return;
758
759
760 spin_lock_irq(&pprt_lock);
761 bits.bl = on;
762 panel_set_bits();
763 spin_unlock_irq(&pprt_lock);
764}
765
766
767static void lcd_write_cmd_s(int cmd)
768{
769 spin_lock_irq(&pprt_lock);
770 lcd_send_serial(0x1F);
771 lcd_send_serial(cmd & 0x0F);
772 lcd_send_serial((cmd >> 4) & 0x0F);
773 udelay(40);
774 spin_unlock_irq(&pprt_lock);
775}
776
777
778static void lcd_write_data_s(int data)
779{
780 spin_lock_irq(&pprt_lock);
781 lcd_send_serial(0x5F);
782 lcd_send_serial(data & 0x0F);
783 lcd_send_serial((data >> 4) & 0x0F);
784 udelay(40);
785 spin_unlock_irq(&pprt_lock);
786}
787
788
789static void lcd_write_cmd_p8(int cmd)
790{
791 spin_lock_irq(&pprt_lock);
792
793 w_dtr(pprt, cmd);
794 udelay(20);
795
796 bits.e = BIT_SET;
797 bits.rs = BIT_CLR;
798 bits.rw = BIT_CLR;
799 set_ctrl_bits();
800
801 udelay(40);
802
803 bits.e = BIT_CLR;
804 set_ctrl_bits();
805
806 udelay(120);
807 spin_unlock_irq(&pprt_lock);
808}
809
810
811static void lcd_write_data_p8(int data)
812{
813 spin_lock_irq(&pprt_lock);
814
815 w_dtr(pprt, data);
816 udelay(20);
817
818 bits.e = BIT_SET;
819 bits.rs = BIT_SET;
820 bits.rw = BIT_CLR;
821 set_ctrl_bits();
822
823 udelay(40);
824
825 bits.e = BIT_CLR;
826 set_ctrl_bits();
827
828 udelay(45);
829 spin_unlock_irq(&pprt_lock);
830}
831
832
833static void lcd_write_cmd_tilcd(int cmd)
834{
835 spin_lock_irq(&pprt_lock);
836
837 w_ctr(pprt, cmd);
838 udelay(60);
839 spin_unlock_irq(&pprt_lock);
840}
841
842
843static void lcd_write_data_tilcd(int data)
844{
845 spin_lock_irq(&pprt_lock);
846
847 w_dtr(pprt, data);
848 udelay(60);
849 spin_unlock_irq(&pprt_lock);
850}
851
852static void lcd_gotoxy(void)
853{
854 lcd_write_cmd(0x80
855 | (lcd_addr_y ? lcd_hwidth : 0)
856
857
858 | ((lcd_addr_x < lcd_bwidth) ? lcd_addr_x &
859 (lcd_hwidth - 1) : lcd_bwidth - 1));
860}
861
862static void lcd_print(char c)
863{
864 if (lcd_addr_x < lcd_bwidth) {
865 if (lcd_char_conv != NULL)
866 c = lcd_char_conv[(unsigned char)c];
867 lcd_write_data(c);
868 lcd_addr_x++;
869 }
870
871 if (lcd_addr_x == lcd_bwidth)
872 lcd_gotoxy();
873}
874
875
876static void lcd_clear_fast_s(void)
877{
878 int pos;
879 lcd_addr_x = lcd_addr_y = 0;
880 lcd_gotoxy();
881
882 spin_lock_irq(&pprt_lock);
883 for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) {
884 lcd_send_serial(0x5F);
885 lcd_send_serial(' ' & 0x0F);
886 lcd_send_serial((' ' >> 4) & 0x0F);
887 udelay(40);
888 }
889 spin_unlock_irq(&pprt_lock);
890
891 lcd_addr_x = lcd_addr_y = 0;
892 lcd_gotoxy();
893}
894
895
896static void lcd_clear_fast_p8(void)
897{
898 int pos;
899 lcd_addr_x = lcd_addr_y = 0;
900 lcd_gotoxy();
901
902 spin_lock_irq(&pprt_lock);
903 for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) {
904
905 w_dtr(pprt, ' ');
906
907
908 udelay(20);
909
910 bits.e = BIT_SET;
911 bits.rs = BIT_SET;
912 bits.rw = BIT_CLR;
913 set_ctrl_bits();
914
915
916 udelay(40);
917
918 bits.e = BIT_CLR;
919 set_ctrl_bits();
920
921
922 udelay(45);
923 }
924 spin_unlock_irq(&pprt_lock);
925
926 lcd_addr_x = lcd_addr_y = 0;
927 lcd_gotoxy();
928}
929
930
931static void lcd_clear_fast_tilcd(void)
932{
933 int pos;
934 lcd_addr_x = lcd_addr_y = 0;
935 lcd_gotoxy();
936
937 spin_lock_irq(&pprt_lock);
938 for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) {
939
940 w_dtr(pprt, ' ');
941 udelay(60);
942 }
943
944 spin_unlock_irq(&pprt_lock);
945
946 lcd_addr_x = lcd_addr_y = 0;
947 lcd_gotoxy();
948}
949
950
951static void lcd_clear_display(void)
952{
953 lcd_write_cmd(0x01);
954 lcd_addr_x = lcd_addr_y = 0;
955
956 long_sleep(15);
957}
958
959static void lcd_init_display(void)
960{
961
962 lcd_flags = ((lcd_height > 1) ? LCD_FLAG_N : 0)
963 | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B;
964
965 long_sleep(20);
966
967 lcd_write_cmd(0x30);
968 long_sleep(10);
969 lcd_write_cmd(0x30);
970 long_sleep(10);
971 lcd_write_cmd(0x30);
972 long_sleep(10);
973
974 lcd_write_cmd(0x30
975 | ((lcd_flags & LCD_FLAG_F) ? 4 : 0)
976 | ((lcd_flags & LCD_FLAG_N) ? 8 : 0)
977 );
978 long_sleep(10);
979
980 lcd_write_cmd(0x08);
981 long_sleep(10);
982
983 lcd_write_cmd(0x08
984 | ((lcd_flags & LCD_FLAG_D) ? 4 : 0)
985 | ((lcd_flags & LCD_FLAG_C) ? 2 : 0)
986 | ((lcd_flags & LCD_FLAG_B) ? 1 : 0)
987 );
988
989 lcd_backlight((lcd_flags & LCD_FLAG_L) ? 1 : 0);
990
991 long_sleep(10);
992
993
994 lcd_write_cmd(0x06);
995
996 lcd_clear_display();
997}
998
999
1000
1001
1002
1003
1004
1005
1006static inline int handle_lcd_special_code(void)
1007{
1008
1009
1010 int processed = 0;
1011
1012 char *esc = lcd_escape + 2;
1013 int oldflags = lcd_flags;
1014
1015
1016 switch (*esc) {
1017 case 'D':
1018 lcd_flags |= LCD_FLAG_D;
1019 processed = 1;
1020 break;
1021 case 'd':
1022 lcd_flags &= ~LCD_FLAG_D;
1023 processed = 1;
1024 break;
1025 case 'C':
1026 lcd_flags |= LCD_FLAG_C;
1027 processed = 1;
1028 break;
1029 case 'c':
1030 lcd_flags &= ~LCD_FLAG_C;
1031 processed = 1;
1032 break;
1033 case 'B':
1034 lcd_flags |= LCD_FLAG_B;
1035 processed = 1;
1036 break;
1037 case 'b':
1038 lcd_flags &= ~LCD_FLAG_B;
1039 processed = 1;
1040 break;
1041 case '+':
1042 lcd_flags |= LCD_FLAG_L;
1043 processed = 1;
1044 break;
1045 case '-':
1046 lcd_flags &= ~LCD_FLAG_L;
1047 processed = 1;
1048 break;
1049 case '*':
1050
1051 if (scan_timer.function != NULL) {
1052 if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0))
1053 lcd_backlight(1);
1054 light_tempo = FLASH_LIGHT_TEMPO;
1055 }
1056 processed = 1;
1057 break;
1058 case 'f':
1059 lcd_flags &= ~LCD_FLAG_F;
1060 processed = 1;
1061 break;
1062 case 'F':
1063 lcd_flags |= LCD_FLAG_F;
1064 processed = 1;
1065 break;
1066 case 'n':
1067 lcd_flags &= ~LCD_FLAG_N;
1068 processed = 1;
1069 break;
1070 case 'N':
1071 lcd_flags |= LCD_FLAG_N;
1072 break;
1073 case 'l':
1074 if (lcd_addr_x > 0) {
1075
1076 if (lcd_addr_x < lcd_bwidth)
1077 lcd_write_cmd(0x10);
1078 lcd_addr_x--;
1079 }
1080 processed = 1;
1081 break;
1082 case 'r':
1083 if (lcd_addr_x < lcd_width) {
1084
1085 if (lcd_addr_x <
1086 (lcd_bwidth - 1))
1087 lcd_write_cmd(0x14);
1088 lcd_addr_x++;
1089 }
1090 processed = 1;
1091 break;
1092 case 'L':
1093 lcd_left_shift++;
1094 lcd_write_cmd(0x18);
1095 processed = 1;
1096 break;
1097 case 'R':
1098 lcd_left_shift--;
1099 lcd_write_cmd(0x1C);
1100 processed = 1;
1101 break;
1102 case 'k': {
1103 int x;
1104 for (x = lcd_addr_x; x < lcd_bwidth; x++)
1105 lcd_write_data(' ');
1106
1107
1108 lcd_gotoxy();
1109 processed = 1;
1110 break;
1111 }
1112 case 'I':
1113 lcd_init_display();
1114 lcd_left_shift = 0;
1115 processed = 1;
1116 break;
1117 case 'G': {
1118
1119
1120
1121
1122
1123
1124
1125
1126 unsigned char cgbytes[8];
1127 unsigned char cgaddr;
1128 int cgoffset;
1129 int shift;
1130 char value;
1131 int addr;
1132
1133 if (strchr(esc, ';') == NULL)
1134 break;
1135
1136 esc++;
1137
1138 cgaddr = *(esc++) - '0';
1139 if (cgaddr > 7) {
1140 processed = 1;
1141 break;
1142 }
1143
1144 cgoffset = 0;
1145 shift = 0;
1146 value = 0;
1147 while (*esc && cgoffset < 8) {
1148 shift ^= 4;
1149 if (*esc >= '0' && *esc <= '9')
1150 value |= (*esc - '0') << shift;
1151 else if (*esc >= 'A' && *esc <= 'Z')
1152 value |= (*esc - 'A' + 10) << shift;
1153 else if (*esc >= 'a' && *esc <= 'z')
1154 value |= (*esc - 'a' + 10) << shift;
1155 else {
1156 esc++;
1157 continue;
1158 }
1159
1160 if (shift == 0) {
1161 cgbytes[cgoffset++] = value;
1162 value = 0;
1163 }
1164
1165 esc++;
1166 }
1167
1168 lcd_write_cmd(0x40 | (cgaddr * 8));
1169 for (addr = 0; addr < cgoffset; addr++)
1170 lcd_write_data(cgbytes[addr]);
1171
1172
1173 lcd_gotoxy();
1174 processed = 1;
1175 break;
1176 }
1177 case 'x':
1178 case 'y':
1179 if (strchr(esc, ';') == NULL)
1180 break;
1181
1182 while (*esc) {
1183 if (*esc == 'x') {
1184 esc++;
1185 if (kstrtoul(esc, 10, &lcd_addr_x) < 0)
1186 break;
1187 } else if (*esc == 'y') {
1188 esc++;
1189 if (kstrtoul(esc, 10, &lcd_addr_y) < 0)
1190 break;
1191 } else
1192 break;
1193 }
1194
1195 lcd_gotoxy();
1196 processed = 1;
1197 break;
1198 }
1199
1200
1201 if (oldflags != lcd_flags) {
1202
1203 if ((oldflags ^ lcd_flags) &
1204 (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
1205
1206 lcd_write_cmd(0x08
1207 | ((lcd_flags & LCD_FLAG_D) ? 4 : 0)
1208 | ((lcd_flags & LCD_FLAG_C) ? 2 : 0)
1209 | ((lcd_flags & LCD_FLAG_B) ? 1 : 0));
1210
1211 else if ((oldflags ^ lcd_flags) & (LCD_FLAG_F | LCD_FLAG_N))
1212 lcd_write_cmd(0x30
1213 | ((lcd_flags & LCD_FLAG_F) ? 4 : 0)
1214 | ((lcd_flags & LCD_FLAG_N) ? 8 : 0));
1215
1216 else if ((oldflags ^ lcd_flags) & (LCD_FLAG_L)) {
1217 if (lcd_flags & (LCD_FLAG_L))
1218 lcd_backlight(1);
1219 else if (light_tempo == 0)
1220
1221
1222 lcd_backlight(0);
1223 }
1224 }
1225
1226 return processed;
1227}
1228
1229static ssize_t lcd_write(struct file *file,
1230 const char *buf, size_t count, loff_t *ppos)
1231{
1232 const char *tmp = buf;
1233 char c;
1234
1235 for (; count-- > 0; (ppos ? (*ppos)++ : 0), ++tmp) {
1236 if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
1237
1238
1239 schedule();
1240
1241 if (ppos == NULL && file == NULL)
1242
1243 c = *tmp;
1244 else if (get_user(c, tmp))
1245 return -EFAULT;
1246
1247
1248 if ((c != '\n') && lcd_escape_len >= 0) {
1249
1250 lcd_escape[lcd_escape_len++] = c;
1251 lcd_escape[lcd_escape_len] = 0;
1252 } else {
1253
1254 lcd_escape_len = -1;
1255
1256 switch (c) {
1257 case LCD_ESCAPE_CHAR:
1258
1259 lcd_escape_len = 0;
1260 lcd_escape[lcd_escape_len] = 0;
1261 break;
1262 case '\b':
1263
1264 if (lcd_addr_x > 0) {
1265
1266
1267 if (lcd_addr_x < lcd_bwidth)
1268
1269 lcd_write_cmd(0x10);
1270 lcd_addr_x--;
1271 }
1272
1273 lcd_write_data(' ');
1274
1275 lcd_write_cmd(0x10);
1276 break;
1277 case '\014':
1278
1279 lcd_clear_fast();
1280 break;
1281 case '\n':
1282
1283
1284 for (; lcd_addr_x < lcd_bwidth; lcd_addr_x++)
1285 lcd_write_data(' ');
1286 lcd_addr_x = 0;
1287 lcd_addr_y = (lcd_addr_y + 1) % lcd_height;
1288 lcd_gotoxy();
1289 break;
1290 case '\r':
1291
1292 lcd_addr_x = 0;
1293 lcd_gotoxy();
1294 break;
1295 case '\t':
1296
1297 lcd_print(' ');
1298 break;
1299 default:
1300
1301 lcd_print(c);
1302 break;
1303 }
1304 }
1305
1306
1307
1308 if (lcd_escape_len >= 2) {
1309 int processed = 0;
1310
1311 if (!strcmp(lcd_escape, "[2J")) {
1312
1313 lcd_clear_fast();
1314 processed = 1;
1315 } else if (!strcmp(lcd_escape, "[H")) {
1316
1317 lcd_addr_x = lcd_addr_y = 0;
1318 lcd_gotoxy();
1319 processed = 1;
1320 }
1321
1322 else if ((lcd_escape_len >= 3) &&
1323 (lcd_escape[0] == '[') &&
1324 (lcd_escape[1] == 'L')) {
1325 processed = handle_lcd_special_code();
1326 }
1327
1328
1329
1330
1331 if (processed || (lcd_escape_len >= LCD_ESCAPE_LEN))
1332 lcd_escape_len = -1;
1333 }
1334 }
1335
1336 return tmp - buf;
1337}
1338
1339static int lcd_open(struct inode *inode, struct file *file)
1340{
1341 if (lcd_open_cnt)
1342 return -EBUSY;
1343
1344 if (file->f_mode & FMODE_READ)
1345 return -EPERM;
1346
1347 if (lcd_must_clear) {
1348 lcd_clear_display();
1349 lcd_must_clear = 0;
1350 }
1351 lcd_open_cnt++;
1352 return nonseekable_open(inode, file);
1353}
1354
1355static int lcd_release(struct inode *inode, struct file *file)
1356{
1357 lcd_open_cnt--;
1358 return 0;
1359}
1360
1361static const struct file_operations lcd_fops = {
1362 .write = lcd_write,
1363 .open = lcd_open,
1364 .release = lcd_release,
1365 .llseek = no_llseek,
1366};
1367
1368static struct miscdevice lcd_dev = {
1369 LCD_MINOR,
1370 "lcd",
1371 &lcd_fops
1372};
1373
1374
1375static void panel_lcd_print(const char *s)
1376{
1377 if (lcd_enabled && lcd_initialized)
1378 lcd_write(NULL, s, strlen(s), NULL);
1379}
1380
1381
1382static void lcd_init(void)
1383{
1384 switch (lcd_type) {
1385 case LCD_TYPE_OLD:
1386
1387 if (lcd_proto < 0)
1388 lcd_proto = LCD_PROTO_PARALLEL;
1389 if (lcd_charset < 0)
1390 lcd_charset = LCD_CHARSET_NORMAL;
1391 if (lcd_e_pin == PIN_NOT_SET)
1392 lcd_e_pin = PIN_STROBE;
1393 if (lcd_rs_pin == PIN_NOT_SET)
1394 lcd_rs_pin = PIN_AUTOLF;
1395
1396 if (lcd_width < 0)
1397 lcd_width = 40;
1398 if (lcd_bwidth < 0)
1399 lcd_bwidth = 40;
1400 if (lcd_hwidth < 0)
1401 lcd_hwidth = 64;
1402 if (lcd_height < 0)
1403 lcd_height = 2;
1404 break;
1405 case LCD_TYPE_KS0074:
1406
1407 if (lcd_proto < 0)
1408 lcd_proto = LCD_PROTO_SERIAL;
1409 if (lcd_charset < 0)
1410 lcd_charset = LCD_CHARSET_KS0074;
1411 if (lcd_bl_pin == PIN_NOT_SET)
1412 lcd_bl_pin = PIN_AUTOLF;
1413 if (lcd_cl_pin == PIN_NOT_SET)
1414 lcd_cl_pin = PIN_STROBE;
1415 if (lcd_da_pin == PIN_NOT_SET)
1416 lcd_da_pin = PIN_D0;
1417
1418 if (lcd_width < 0)
1419 lcd_width = 16;
1420 if (lcd_bwidth < 0)
1421 lcd_bwidth = 40;
1422 if (lcd_hwidth < 0)
1423 lcd_hwidth = 16;
1424 if (lcd_height < 0)
1425 lcd_height = 2;
1426 break;
1427 case LCD_TYPE_NEXCOM:
1428
1429 if (lcd_proto < 0)
1430 lcd_proto = LCD_PROTO_PARALLEL;
1431 if (lcd_charset < 0)
1432 lcd_charset = LCD_CHARSET_NORMAL;
1433 if (lcd_e_pin == PIN_NOT_SET)
1434 lcd_e_pin = PIN_AUTOLF;
1435 if (lcd_rs_pin == PIN_NOT_SET)
1436 lcd_rs_pin = PIN_SELECP;
1437 if (lcd_rw_pin == PIN_NOT_SET)
1438 lcd_rw_pin = PIN_INITP;
1439
1440 if (lcd_width < 0)
1441 lcd_width = 16;
1442 if (lcd_bwidth < 0)
1443 lcd_bwidth = 40;
1444 if (lcd_hwidth < 0)
1445 lcd_hwidth = 64;
1446 if (lcd_height < 0)
1447 lcd_height = 2;
1448 break;
1449 case LCD_TYPE_CUSTOM:
1450
1451 if (lcd_proto < 0)
1452 lcd_proto = DEFAULT_LCD_PROTO;
1453 if (lcd_charset < 0)
1454 lcd_charset = DEFAULT_LCD_CHARSET;
1455
1456 break;
1457 case LCD_TYPE_HANTRONIX:
1458
1459 default:
1460 if (lcd_proto < 0)
1461 lcd_proto = LCD_PROTO_PARALLEL;
1462 if (lcd_charset < 0)
1463 lcd_charset = LCD_CHARSET_NORMAL;
1464 if (lcd_e_pin == PIN_NOT_SET)
1465 lcd_e_pin = PIN_STROBE;
1466 if (lcd_rs_pin == PIN_NOT_SET)
1467 lcd_rs_pin = PIN_SELECP;
1468
1469 if (lcd_width < 0)
1470 lcd_width = 16;
1471 if (lcd_bwidth < 0)
1472 lcd_bwidth = 40;
1473 if (lcd_hwidth < 0)
1474 lcd_hwidth = 64;
1475 if (lcd_height < 0)
1476 lcd_height = 2;
1477 break;
1478 }
1479
1480
1481 if (lcd_width <= 0)
1482 lcd_width = DEFAULT_LCD_WIDTH;
1483 if (lcd_bwidth <= 0)
1484 lcd_bwidth = DEFAULT_LCD_BWIDTH;
1485 if (lcd_hwidth <= 0)
1486 lcd_hwidth = DEFAULT_LCD_HWIDTH;
1487 if (lcd_height <= 0)
1488 lcd_height = DEFAULT_LCD_HEIGHT;
1489
1490 if (lcd_proto == LCD_PROTO_SERIAL) {
1491 lcd_write_cmd = lcd_write_cmd_s;
1492 lcd_write_data = lcd_write_data_s;
1493 lcd_clear_fast = lcd_clear_fast_s;
1494
1495 if (lcd_cl_pin == PIN_NOT_SET)
1496 lcd_cl_pin = DEFAULT_LCD_PIN_SCL;
1497 if (lcd_da_pin == PIN_NOT_SET)
1498 lcd_da_pin = DEFAULT_LCD_PIN_SDA;
1499
1500 } else if (lcd_proto == LCD_PROTO_PARALLEL) {
1501 lcd_write_cmd = lcd_write_cmd_p8;
1502 lcd_write_data = lcd_write_data_p8;
1503 lcd_clear_fast = lcd_clear_fast_p8;
1504
1505 if (lcd_e_pin == PIN_NOT_SET)
1506 lcd_e_pin = DEFAULT_LCD_PIN_E;
1507 if (lcd_rs_pin == PIN_NOT_SET)
1508 lcd_rs_pin = DEFAULT_LCD_PIN_RS;
1509 if (lcd_rw_pin == PIN_NOT_SET)
1510 lcd_rw_pin = DEFAULT_LCD_PIN_RW;
1511 } else {
1512 lcd_write_cmd = lcd_write_cmd_tilcd;
1513 lcd_write_data = lcd_write_data_tilcd;
1514 lcd_clear_fast = lcd_clear_fast_tilcd;
1515 }
1516
1517 if (lcd_bl_pin == PIN_NOT_SET)
1518 lcd_bl_pin = DEFAULT_LCD_PIN_BL;
1519
1520 if (lcd_e_pin == PIN_NOT_SET)
1521 lcd_e_pin = PIN_NONE;
1522 if (lcd_rs_pin == PIN_NOT_SET)
1523 lcd_rs_pin = PIN_NONE;
1524 if (lcd_rw_pin == PIN_NOT_SET)
1525 lcd_rw_pin = PIN_NONE;
1526 if (lcd_bl_pin == PIN_NOT_SET)
1527 lcd_bl_pin = PIN_NONE;
1528 if (lcd_cl_pin == PIN_NOT_SET)
1529 lcd_cl_pin = PIN_NONE;
1530 if (lcd_da_pin == PIN_NOT_SET)
1531 lcd_da_pin = PIN_NONE;
1532
1533 if (lcd_charset < 0)
1534 lcd_charset = DEFAULT_LCD_CHARSET;
1535
1536 if (lcd_charset == LCD_CHARSET_KS0074)
1537 lcd_char_conv = lcd_char_conv_ks0074;
1538 else
1539 lcd_char_conv = NULL;
1540
1541 if (lcd_bl_pin != PIN_NONE)
1542 init_scan_timer();
1543
1544 pin_to_bits(lcd_e_pin, lcd_bits[LCD_PORT_D][LCD_BIT_E],
1545 lcd_bits[LCD_PORT_C][LCD_BIT_E]);
1546 pin_to_bits(lcd_rs_pin, lcd_bits[LCD_PORT_D][LCD_BIT_RS],
1547 lcd_bits[LCD_PORT_C][LCD_BIT_RS]);
1548 pin_to_bits(lcd_rw_pin, lcd_bits[LCD_PORT_D][LCD_BIT_RW],
1549 lcd_bits[LCD_PORT_C][LCD_BIT_RW]);
1550 pin_to_bits(lcd_bl_pin, lcd_bits[LCD_PORT_D][LCD_BIT_BL],
1551 lcd_bits[LCD_PORT_C][LCD_BIT_BL]);
1552 pin_to_bits(lcd_cl_pin, lcd_bits[LCD_PORT_D][LCD_BIT_CL],
1553 lcd_bits[LCD_PORT_C][LCD_BIT_CL]);
1554 pin_to_bits(lcd_da_pin, lcd_bits[LCD_PORT_D][LCD_BIT_DA],
1555 lcd_bits[LCD_PORT_C][LCD_BIT_DA]);
1556
1557
1558
1559
1560 lcd_initialized = 1;
1561 lcd_init_display();
1562
1563
1564#ifdef CONFIG_PANEL_CHANGE_MESSAGE
1565#ifdef CONFIG_PANEL_BOOT_MESSAGE
1566 panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE);
1567#endif
1568#else
1569 panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-"
1570 PANEL_VERSION);
1571#endif
1572 lcd_addr_x = lcd_addr_y = 0;
1573
1574 lcd_must_clear = 1;
1575 lcd_gotoxy();
1576}
1577
1578
1579
1580
1581
1582static ssize_t keypad_read(struct file *file,
1583 char *buf, size_t count, loff_t *ppos)
1584{
1585
1586 unsigned i = *ppos;
1587 char *tmp = buf;
1588
1589 if (keypad_buflen == 0) {
1590 if (file->f_flags & O_NONBLOCK)
1591 return -EAGAIN;
1592
1593 interruptible_sleep_on(&keypad_read_wait);
1594 if (signal_pending(current))
1595 return -EINTR;
1596 }
1597
1598 for (; count-- > 0 && (keypad_buflen > 0);
1599 ++i, ++tmp, --keypad_buflen) {
1600 put_user(keypad_buffer[keypad_start], tmp);
1601 keypad_start = (keypad_start + 1) % KEYPAD_BUFFER;
1602 }
1603 *ppos = i;
1604
1605 return tmp - buf;
1606}
1607
1608static int keypad_open(struct inode *inode, struct file *file)
1609{
1610
1611 if (keypad_open_cnt)
1612 return -EBUSY;
1613
1614 if (file->f_mode & FMODE_WRITE)
1615 return -EPERM;
1616
1617 keypad_buflen = 0;
1618 keypad_open_cnt++;
1619 return 0;
1620}
1621
1622static int keypad_release(struct inode *inode, struct file *file)
1623{
1624 keypad_open_cnt--;
1625 return 0;
1626}
1627
1628static const struct file_operations keypad_fops = {
1629 .read = keypad_read,
1630 .open = keypad_open,
1631 .release = keypad_release,
1632 .llseek = default_llseek,
1633};
1634
1635static struct miscdevice keypad_dev = {
1636 KEYPAD_MINOR,
1637 "keypad",
1638 &keypad_fops
1639};
1640
1641static void keypad_send_key(const char *string, int max_len)
1642{
1643 if (init_in_progress)
1644 return;
1645
1646
1647 if (keypad_open_cnt > 0) {
1648 while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) {
1649 keypad_buffer[(keypad_start + keypad_buflen++) %
1650 KEYPAD_BUFFER] = *string++;
1651 }
1652 wake_up_interruptible(&keypad_read_wait);
1653 }
1654}
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666static void phys_scan_contacts(void)
1667{
1668 int bit, bitval;
1669 char oldval;
1670 char bitmask;
1671 char gndmask;
1672
1673 phys_prev = phys_curr;
1674 phys_read_prev = phys_read;
1675 phys_read = 0;
1676
1677
1678 oldval = r_dtr(pprt) | scan_mask_o;
1679
1680 w_dtr(pprt, oldval & ~scan_mask_o);
1681
1682
1683 bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i;
1684
1685 w_dtr(pprt, oldval);
1686
1687
1688
1689
1690
1691
1692 gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i;
1693
1694
1695 phys_read |= (pmask_t) gndmask << 40;
1696
1697 if (bitmask != gndmask) {
1698
1699
1700
1701
1702 for (bit = 0; bit < 8; bit++) {
1703 bitval = 1 << bit;
1704
1705 if (!(scan_mask_o & bitval))
1706 continue;
1707
1708 w_dtr(pprt, oldval & ~bitval);
1709 bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask;
1710 phys_read |= (pmask_t) bitmask << (5 * bit);
1711 }
1712 w_dtr(pprt, oldval);
1713 }
1714
1715
1716 phys_curr = (phys_prev & (phys_read ^ phys_read_prev)) |
1717 (phys_read & ~(phys_read ^ phys_read_prev));
1718}
1719
1720static inline int input_state_high(struct logical_input *input)
1721{
1722#if 0
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740 if (((phys_prev & input->mask) == input->value)
1741 && ((phys_curr & input->mask) > input->value)) {
1742 input->state = INPUT_ST_LOW;
1743 return 1;
1744 }
1745#endif
1746
1747 if ((phys_curr & input->mask) == input->value) {
1748 if ((input->type == INPUT_TYPE_STD) &&
1749 (input->high_timer == 0)) {
1750 input->high_timer++;
1751 if (input->u.std.press_fct != NULL)
1752 input->u.std.press_fct(input->u.std.press_data);
1753 } else if (input->type == INPUT_TYPE_KBD) {
1754
1755 keypressed = 1;
1756
1757 if (input->high_timer == 0) {
1758 char *press_str = input->u.kbd.press_str;
1759 if (press_str[0])
1760 keypad_send_key(press_str,
1761 sizeof(input->u.kbd.press_str));
1762 }
1763
1764 if (input->u.kbd.repeat_str[0]) {
1765 char *repeat_str = input->u.kbd.repeat_str;
1766 if (input->high_timer >= KEYPAD_REP_START) {
1767 input->high_timer -= KEYPAD_REP_DELAY;
1768 keypad_send_key(repeat_str,
1769 sizeof(input->u.kbd.repeat_str));
1770 }
1771
1772 inputs_stable = 0;
1773 }
1774
1775 if (input->high_timer < 255)
1776 input->high_timer++;
1777 }
1778 return 1;
1779 } else {
1780
1781 input->state = INPUT_ST_FALLING;
1782 input->fall_timer = 0;
1783 }
1784 return 0;
1785}
1786
1787static inline void input_state_falling(struct logical_input *input)
1788{
1789#if 0
1790
1791 if (((phys_prev & input->mask) == input->value)
1792 && ((phys_curr & input->mask) > input->value)) {
1793 input->state = INPUT_ST_LOW;
1794 return;
1795 }
1796#endif
1797
1798 if ((phys_curr & input->mask) == input->value) {
1799 if (input->type == INPUT_TYPE_KBD) {
1800
1801 keypressed = 1;
1802
1803 if (input->u.kbd.repeat_str[0]) {
1804 char *repeat_str = input->u.kbd.repeat_str;
1805 if (input->high_timer >= KEYPAD_REP_START)
1806 input->high_timer -= KEYPAD_REP_DELAY;
1807 keypad_send_key(repeat_str,
1808 sizeof(input->u.kbd.repeat_str));
1809
1810 inputs_stable = 0;
1811 }
1812
1813 if (input->high_timer < 255)
1814 input->high_timer++;
1815 }
1816 input->state = INPUT_ST_HIGH;
1817 } else if (input->fall_timer >= input->fall_time) {
1818
1819 if (input->type == INPUT_TYPE_STD) {
1820 void (*release_fct)(int) = input->u.std.release_fct;
1821 if (release_fct != NULL)
1822 release_fct(input->u.std.release_data);
1823 } else if (input->type == INPUT_TYPE_KBD) {
1824 char *release_str = input->u.kbd.release_str;
1825 if (release_str[0])
1826 keypad_send_key(release_str,
1827 sizeof(input->u.kbd.release_str));
1828 }
1829
1830 input->state = INPUT_ST_LOW;
1831 } else {
1832 input->fall_timer++;
1833 inputs_stable = 0;
1834 }
1835}
1836
1837static void panel_process_inputs(void)
1838{
1839 struct list_head *item;
1840 struct logical_input *input;
1841
1842 keypressed = 0;
1843 inputs_stable = 1;
1844 list_for_each(item, &logical_inputs) {
1845 input = list_entry(item, struct logical_input, list);
1846
1847 switch (input->state) {
1848 case INPUT_ST_LOW:
1849 if ((phys_curr & input->mask) != input->value)
1850 break;
1851
1852
1853
1854
1855
1856
1857
1858 if ((phys_prev & input->mask) == input->value)
1859 break;
1860 input->rise_timer = 0;
1861 input->state = INPUT_ST_RISING;
1862
1863 case INPUT_ST_RISING:
1864 if ((phys_curr & input->mask) != input->value) {
1865 input->state = INPUT_ST_LOW;
1866 break;
1867 }
1868 if (input->rise_timer < input->rise_time) {
1869 inputs_stable = 0;
1870 input->rise_timer++;
1871 break;
1872 }
1873 input->high_timer = 0;
1874 input->state = INPUT_ST_HIGH;
1875
1876 case INPUT_ST_HIGH:
1877 if (input_state_high(input))
1878 break;
1879
1880 case INPUT_ST_FALLING:
1881 input_state_falling(input);
1882 }
1883 }
1884}
1885
1886static void panel_scan_timer(void)
1887{
1888 if (keypad_enabled && keypad_initialized) {
1889 if (spin_trylock_irq(&pprt_lock)) {
1890 phys_scan_contacts();
1891
1892
1893 spin_unlock_irq(&pprt_lock);
1894 }
1895
1896 if (!inputs_stable || phys_curr != phys_prev)
1897 panel_process_inputs();
1898 }
1899
1900 if (lcd_enabled && lcd_initialized) {
1901 if (keypressed) {
1902 if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0))
1903 lcd_backlight(1);
1904 light_tempo = FLASH_LIGHT_TEMPO;
1905 } else if (light_tempo > 0) {
1906 light_tempo--;
1907 if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0))
1908 lcd_backlight(0);
1909 }
1910 }
1911
1912 mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
1913}
1914
1915static void init_scan_timer(void)
1916{
1917 if (scan_timer.function != NULL)
1918 return;
1919
1920 init_timer(&scan_timer);
1921 scan_timer.expires = jiffies + INPUT_POLL_TIME;
1922 scan_timer.data = 0;
1923 scan_timer.function = (void *)&panel_scan_timer;
1924 add_timer(&scan_timer);
1925}
1926
1927
1928
1929
1930
1931
1932static int input_name2mask(const char *name, pmask_t *mask, pmask_t *value,
1933 char *imask, char *omask)
1934{
1935 static char sigtab[10] = "EeSsPpAaBb";
1936 char im, om;
1937 pmask_t m, v;
1938
1939 om = im = m = v = 0ULL;
1940 while (*name) {
1941 int in, out, bit, neg;
1942 for (in = 0; (in < sizeof(sigtab)) &&
1943 (sigtab[in] != *name); in++)
1944 ;
1945 if (in >= sizeof(sigtab))
1946 return 0;
1947 neg = (in & 1);
1948 in >>= 1;
1949 im |= (1 << in);
1950
1951 name++;
1952 if (isdigit(*name)) {
1953 out = *name - '0';
1954 om |= (1 << out);
1955 } else if (*name == '-')
1956 out = 8;
1957 else
1958 return 0;
1959
1960 bit = (out * 5) + in;
1961
1962 m |= 1ULL << bit;
1963 if (!neg)
1964 v |= 1ULL << bit;
1965 name++;
1966 }
1967 *mask = m;
1968 *value = v;
1969 if (imask)
1970 *imask |= im;
1971 if (omask)
1972 *omask |= om;
1973 return 1;
1974}
1975
1976
1977
1978
1979
1980static struct logical_input *panel_bind_key(const char *name, const char *press,
1981 const char *repeat,
1982 const char *release)
1983{
1984 struct logical_input *key;
1985
1986 key = kzalloc(sizeof(struct logical_input), GFP_KERNEL);
1987 if (!key)
1988 return NULL;
1989
1990 if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i,
1991 &scan_mask_o)) {
1992 kfree(key);
1993 return NULL;
1994 }
1995
1996 key->type = INPUT_TYPE_KBD;
1997 key->state = INPUT_ST_LOW;
1998 key->rise_time = 1;
1999 key->fall_time = 1;
2000
2001 strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str));
2002 strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str));
2003 strncpy(key->u.kbd.release_str, release,
2004 sizeof(key->u.kbd.release_str));
2005 list_add(&key->list, &logical_inputs);
2006 return key;
2007}
2008
2009#if 0
2010
2011
2012
2013
2014
2015
2016static struct logical_input *panel_bind_callback(char *name,
2017 void (*press_fct) (int),
2018 int press_data,
2019 void (*release_fct) (int),
2020 int release_data)
2021{
2022 struct logical_input *callback;
2023
2024 callback = kmalloc(sizeof(struct logical_input), GFP_KERNEL);
2025 if (!callback)
2026 return NULL;
2027
2028 memset(callback, 0, sizeof(struct logical_input));
2029 if (!input_name2mask(name, &callback->mask, &callback->value,
2030 &scan_mask_i, &scan_mask_o))
2031 return NULL;
2032
2033 callback->type = INPUT_TYPE_STD;
2034 callback->state = INPUT_ST_LOW;
2035 callback->rise_time = 1;
2036 callback->fall_time = 1;
2037 callback->u.std.press_fct = press_fct;
2038 callback->u.std.press_data = press_data;
2039 callback->u.std.release_fct = release_fct;
2040 callback->u.std.release_data = release_data;
2041 list_add(&callback->list, &logical_inputs);
2042 return callback;
2043}
2044#endif
2045
2046static void keypad_init(void)
2047{
2048 int keynum;
2049 init_waitqueue_head(&keypad_read_wait);
2050 keypad_buflen = 0;
2051
2052
2053
2054 for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) {
2055 panel_bind_key(keypad_profile[keynum][0],
2056 keypad_profile[keynum][1],
2057 keypad_profile[keynum][2],
2058 keypad_profile[keynum][3]);
2059 }
2060
2061 init_scan_timer();
2062 keypad_initialized = 1;
2063}
2064
2065
2066
2067
2068
2069static int panel_notify_sys(struct notifier_block *this, unsigned long code,
2070 void *unused)
2071{
2072 if (lcd_enabled && lcd_initialized) {
2073 switch (code) {
2074 case SYS_DOWN:
2075 panel_lcd_print
2076 ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+");
2077 break;
2078 case SYS_HALT:
2079 panel_lcd_print
2080 ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+");
2081 break;
2082 case SYS_POWER_OFF:
2083 panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+");
2084 break;
2085 default:
2086 break;
2087 }
2088 }
2089 return NOTIFY_DONE;
2090}
2091
2092static struct notifier_block panel_notifier = {
2093 panel_notify_sys,
2094 NULL,
2095 0
2096};
2097
2098static void panel_attach(struct parport *port)
2099{
2100 if (port->number != parport)
2101 return;
2102
2103 if (pprt) {
2104 pr_err("%s: port->number=%d parport=%d, already registered!\n",
2105 __func__, port->number, parport);
2106 return;
2107 }
2108
2109 pprt = parport_register_device(port, "panel", NULL, NULL,
2110 NULL,
2111
2112 0, (void *)&pprt);
2113 if (pprt == NULL) {
2114 pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n",
2115 __func__, port->number, parport);
2116 return;
2117 }
2118
2119 if (parport_claim(pprt)) {
2120 pr_err("could not claim access to parport%d. Aborting.\n",
2121 parport);
2122 goto err_unreg_device;
2123 }
2124
2125
2126
2127
2128 if (lcd_enabled) {
2129 lcd_init();
2130 if (misc_register(&lcd_dev))
2131 goto err_unreg_device;
2132 }
2133
2134 if (keypad_enabled) {
2135 keypad_init();
2136 if (misc_register(&keypad_dev))
2137 goto err_lcd_unreg;
2138 }
2139 return;
2140
2141err_lcd_unreg:
2142 if (lcd_enabled)
2143 misc_deregister(&lcd_dev);
2144err_unreg_device:
2145 parport_unregister_device(pprt);
2146 pprt = NULL;
2147}
2148
2149static void panel_detach(struct parport *port)
2150{
2151 if (port->number != parport)
2152 return;
2153
2154 if (!pprt) {
2155 pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n",
2156 __func__, port->number, parport);
2157 return;
2158 }
2159
2160 if (keypad_enabled && keypad_initialized) {
2161 misc_deregister(&keypad_dev);
2162 keypad_initialized = 0;
2163 }
2164
2165 if (lcd_enabled && lcd_initialized) {
2166 misc_deregister(&lcd_dev);
2167 lcd_initialized = 0;
2168 }
2169
2170 parport_release(pprt);
2171 parport_unregister_device(pprt);
2172 pprt = NULL;
2173}
2174
2175static struct parport_driver panel_driver = {
2176 .name = "panel",
2177 .attach = panel_attach,
2178 .detach = panel_detach,
2179};
2180
2181
2182static int panel_init(void)
2183{
2184
2185 if (keypad_type < 0)
2186 keypad_type = keypad_enabled;
2187
2188 if (lcd_type < 0)
2189 lcd_type = lcd_enabled;
2190
2191 if (parport < 0)
2192 parport = DEFAULT_PARPORT;
2193
2194
2195 switch (profile) {
2196 case PANEL_PROFILE_CUSTOM:
2197
2198 if (keypad_type < 0)
2199 keypad_type = DEFAULT_KEYPAD;
2200 if (lcd_type < 0)
2201 lcd_type = DEFAULT_LCD;
2202 break;
2203 case PANEL_PROFILE_OLD:
2204
2205 if (keypad_type < 0)
2206 keypad_type = KEYPAD_TYPE_OLD;
2207 if (lcd_type < 0)
2208 lcd_type = LCD_TYPE_OLD;
2209 if (lcd_width < 0)
2210 lcd_width = 16;
2211 if (lcd_hwidth < 0)
2212 lcd_hwidth = 16;
2213 break;
2214 case PANEL_PROFILE_NEW:
2215
2216 if (keypad_type < 0)
2217 keypad_type = KEYPAD_TYPE_NEW;
2218 if (lcd_type < 0)
2219 lcd_type = LCD_TYPE_KS0074;
2220 break;
2221 case PANEL_PROFILE_HANTRONIX:
2222
2223 if (keypad_type < 0)
2224 keypad_type = KEYPAD_TYPE_NONE;
2225 if (lcd_type < 0)
2226 lcd_type = LCD_TYPE_HANTRONIX;
2227 break;
2228 case PANEL_PROFILE_NEXCOM:
2229
2230 if (keypad_type < 0)
2231 keypad_type = KEYPAD_TYPE_NEXCOM;
2232 if (lcd_type < 0)
2233 lcd_type = LCD_TYPE_NEXCOM;
2234 break;
2235 case PANEL_PROFILE_LARGE:
2236
2237 if (keypad_type < 0)
2238 keypad_type = KEYPAD_TYPE_OLD;
2239 if (lcd_type < 0)
2240 lcd_type = LCD_TYPE_OLD;
2241 break;
2242 }
2243
2244 lcd_enabled = (lcd_type > 0);
2245 keypad_enabled = (keypad_type > 0);
2246
2247 switch (keypad_type) {
2248 case KEYPAD_TYPE_OLD:
2249 keypad_profile = old_keypad_profile;
2250 break;
2251 case KEYPAD_TYPE_NEW:
2252 keypad_profile = new_keypad_profile;
2253 break;
2254 case KEYPAD_TYPE_NEXCOM:
2255 keypad_profile = nexcom_keypad_profile;
2256 break;
2257 default:
2258 keypad_profile = NULL;
2259 break;
2260 }
2261
2262
2263 init_in_progress = 1;
2264
2265 if (parport_register_driver(&panel_driver)) {
2266 pr_err("could not register with parport. Aborting.\n");
2267 return -EIO;
2268 }
2269
2270 if (!lcd_enabled && !keypad_enabled) {
2271
2272 if (pprt) {
2273 parport_release(pprt);
2274 parport_unregister_device(pprt);
2275 pprt = NULL;
2276 }
2277 parport_unregister_driver(&panel_driver);
2278 pr_err("driver version " PANEL_VERSION " disabled.\n");
2279 return -ENODEV;
2280 }
2281
2282 register_reboot_notifier(&panel_notifier);
2283
2284 if (pprt)
2285 pr_info("driver version " PANEL_VERSION
2286 " registered on parport%d (io=0x%lx).\n", parport,
2287 pprt->port->base);
2288 else
2289 pr_info("driver version " PANEL_VERSION
2290 " not yet registered\n");
2291
2292
2293 init_in_progress = 0;
2294 return 0;
2295}
2296
2297static int __init panel_init_module(void)
2298{
2299 return panel_init();
2300}
2301
2302static void __exit panel_cleanup_module(void)
2303{
2304 unregister_reboot_notifier(&panel_notifier);
2305
2306 if (scan_timer.function != NULL)
2307 del_timer(&scan_timer);
2308
2309 if (pprt != NULL) {
2310 if (keypad_enabled) {
2311 misc_deregister(&keypad_dev);
2312 keypad_initialized = 0;
2313 }
2314
2315 if (lcd_enabled) {
2316 panel_lcd_print("\x0cLCD driver " PANEL_VERSION
2317 "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
2318 misc_deregister(&lcd_dev);
2319 lcd_initialized = 0;
2320 }
2321
2322
2323 parport_release(pprt);
2324 parport_unregister_device(pprt);
2325 pprt = NULL;
2326 }
2327 parport_unregister_driver(&panel_driver);
2328}
2329
2330module_init(panel_init_module);
2331module_exit(panel_cleanup_module);
2332MODULE_AUTHOR("Willy Tarreau");
2333MODULE_LICENSE("GPL");
2334
2335
2336
2337
2338
2339
2340
2341