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