#include <asm/uaccess.h>
#include <asm/system.h>
-/* smartcard length */
-#define SMARTCARD_BYTES 64
#define LCD_MINOR 156
#define KEYPAD_MINOR 185
-#define SMARTCARD_MINOR 186
#define PANEL_VERSION "0.9.5"
#define LCD_MAXBYTES 256 /* max burst write */
-#define SMARTCARD_LOGICAL_DETECTOR "S6" /* D6 wired to SELECT = card inserted */
-
#define KEYPAD_BUFFER 64
#define INPUT_POLL_TIME (HZ/50) /* poll the keyboard this every second */
#define KEYPAD_REP_START (10) /* a key starts to repeat after this times INPUT_POLL_TIME */
#define PIN_SELECP 17
#define PIN_NOT_SET 127
-/* some smartcard-specific signals */
-#define PNL_SC_IO PNL_PD1 /* Warning! inverted output, 0=highZ */
-#define PNL_SC_RST PNL_PD2
-#define PNL_SC_CLK PNL_PD3
-#define PNL_SC_RW PNL_PD4
-#define PNL_SC_ENA PNL_PINITP
-#define PNL_SC_IOR PNL_PACK
-#define PNL_SC_BITS (PNL_SC_IO | PNL_SC_RST | PNL_SC_CLK | PNL_SC_RW)
-
#define LCD_FLAG_S 0x0001
#define LCD_FLAG_ID 0x0002
#define LCD_FLAG_B 0x0004 /* blink on */
static pmask_t phys_prev; /* previous phys_curr */
static char inputs_stable; /* 0 means that at least one logical signal needs be computed */
-/* these variables are specific to the smartcard */
-static __u8 smartcard_data[SMARTCARD_BYTES];
-static int smartcard_ptr; /* pointer to half bytes in smartcard_data */
-
/* these variables are specific to the keypad */
static char keypad_buffer[KEYPAD_BUFFER];
static int keypad_buflen;
static int keypad_start;
static char keypressed;
static wait_queue_head_t keypad_read_wait;
-static wait_queue_head_t smartcard_read_wait;
/* lcd-specific variables */
static unsigned long int lcd_flags; /* contains the LCD config state */
static char lcd_escape[LCD_ESCAPE_LEN + 1]; /* current escape sequence, 0 terminated */
static int lcd_escape_len = -1; /* not in escape state. >=0 = escape cmd len */
-static int lcd_height = -1;
-static int lcd_width = -1;
-static int lcd_hwidth = -1; /* hardware buffer width (usually 64) */
-static int lcd_bwidth = -1; /* internal buffer width (usually 40) */
-
-/*
- * These are the parallel port pins the LCD control signals are connected to.
- * Set this to 0 if the signal is not used. Set it to its opposite value
- * (negative) if the signal is negated. -MAXINT is used to indicate that the
- * pin has not been explicitly specified.
- *
- * WARNING! no check will be performed about collisions with keypad/smartcard !
- */
-static int lcd_e_pin = PIN_NOT_SET;
-static int lcd_rs_pin = PIN_NOT_SET;
-static int lcd_rw_pin = PIN_NOT_SET;
-static int lcd_bl_pin = PIN_NOT_SET;
-static int lcd_cl_pin = PIN_NOT_SET;
-static int lcd_da_pin = PIN_NOT_SET;
-
/*
* Bit masks to convert LCD signals to parallel port outputs.
* _d_ are values for data port, _c_ are for control port.
#define DEFAULT_PARPORT 0
#define DEFAULT_LCD LCD_TYPE_OLD
#define DEFAULT_KEYPAD KEYPAD_TYPE_OLD
-#define DEFAULT_SMARTCARD 0
#define DEFAULT_LCD_WIDTH 40
#define DEFAULT_LCD_BWIDTH 40
#define DEFAULT_LCD_HWIDTH 64
#define DEFAULT_KEYPAD CONFIG_PANEL_KEYPAD
#endif
-#ifdef CONFIG_PANEL_SMARTCARD
-#undef DEFAULT_SMARTCARD
-#define DEFAULT_SMARTCARD 1
-#endif
-
#ifdef CONFIG_PANEL_LCD
#undef DEFAULT_LCD
#define DEFAULT_LCD CONFIG_PANEL_LCD
#endif /* DEFAULT_PROFILE == 0 */
/* global variables */
-static int smartcard_open_cnt; /* #times opened */
static int keypad_open_cnt; /* #times opened */
static int lcd_open_cnt; /* #times opened */
-
-static int profile = DEFAULT_PROFILE;
static struct pardevice *pprt;
-static int parport = -1;
-static int lcd_enabled = -1;
-static int lcd_type = -1;
-static int lcd_proto = -1;
-static int lcd_charset = -1;
-static int keypad_enabled = -1;
-static int keypad_type = -1;
-static int smartcard_enabled = -1;
-static int lcd_initialized, keypad_initialized, smartcard_initialized;
+static int lcd_initialized;
+static int keypad_initialized;
static int light_tempo;
static DEFINE_SPINLOCK(pprt_lock);
static struct timer_list scan_timer;
-#ifdef MODULE
+MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver");
-MODULE_DESCRIPTION("Generic parallel port LCD/Keypad/Smartcard driver");
+static int parport = -1;
module_param(parport, int, 0000);
MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)");
+
+static int lcd_height = -1;
module_param(lcd_height, int, 0000);
MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD");
+
+static int lcd_width = -1;
module_param(lcd_width, int, 0000);
MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD");
+
+static int lcd_bwidth = -1; /* internal buffer width (usually 40) */
module_param(lcd_bwidth, int, 0000);
MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)");
+
+static int lcd_hwidth = -1; /* hardware buffer width (usually 64) */
module_param(lcd_hwidth, int, 0000);
MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)");
+
+static int lcd_enabled = -1;
module_param(lcd_enabled, int, 0000);
MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead");
+
+static int keypad_enabled = -1;
module_param(keypad_enabled, int, 0000);
MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
+
+static int lcd_type = -1;
module_param(lcd_type, int, 0000);
MODULE_PARM_DESC(lcd_type,
"LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in");
+
+static int lcd_proto = -1;
module_param(lcd_proto, int, 0000);
MODULE_PARM_DESC(lcd_proto, "LCD communication: 0=parallel (//), 1=serial");
+
+static int lcd_charset = -1;
module_param(lcd_charset, int, 0000);
MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074");
+
+static int keypad_type = -1;
module_param(keypad_type, int, 0000);
MODULE_PARM_DESC(keypad_type,
"Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys");
-module_param(smartcard_enabled, int, 0000);
-MODULE_PARM_DESC(smartcard_enabled,
- "Smartcard reader: 0=disabled (default), 1=enabled");
+
+static int profile = DEFAULT_PROFILE;
module_param(profile, int, 0000);
MODULE_PARM_DESC(profile,
"1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; 4=16x2 nexcom; default=40x2, old kp");
+/*
+ * These are the parallel port pins the LCD control signals are connected to.
+ * Set this to 0 if the signal is not used. Set it to its opposite value
+ * (negative) if the signal is negated. -MAXINT is used to indicate that the
+ * pin has not been explicitly specified.
+ *
+ * WARNING! no check will be performed about collisions with keypad !
+ */
+
+static int lcd_e_pin = PIN_NOT_SET;
module_param(lcd_e_pin, int, 0000);
MODULE_PARM_DESC(lcd_e_pin,
"# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)");
+
+static int lcd_rs_pin = PIN_NOT_SET;
module_param(lcd_rs_pin, int, 0000);
MODULE_PARM_DESC(lcd_rs_pin,
"# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)");
+
+static int lcd_rw_pin = PIN_NOT_SET;
module_param(lcd_rw_pin, int, 0000);
MODULE_PARM_DESC(lcd_rw_pin,
"# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)");
+
+static int lcd_bl_pin = PIN_NOT_SET;
module_param(lcd_bl_pin, int, 0000);
MODULE_PARM_DESC(lcd_bl_pin,
"# of the // port pin connected to LCD backlight, with polarity (-17..17)");
+
+static int lcd_da_pin = PIN_NOT_SET;
module_param(lcd_da_pin, int, 0000);
MODULE_PARM_DESC(lcd_da_pin,
"# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)");
+
+static int lcd_cl_pin = PIN_NOT_SET;
module_param(lcd_cl_pin, int, 0000);
MODULE_PARM_DESC(lcd_cl_pin,
"# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)");
-#endif
-
static unsigned char *lcd_char_conv;
/* for some LCD drivers (ks0074) we need a charset conversion table. */
}
/* sets ctrl & data port bits according to current signals values */
-static void set_bits(void)
+static void panel_set_bits(void)
{
set_data_bits();
set_ctrl_bits();
*/
for (bit = 0; bit < 8; bit++) {
bits.cl = BIT_CLR; /* CLK low */
- set_bits();
+ panel_set_bits();
bits.da = byte & 1;
- set_bits();
+ panel_set_bits();
udelay(2); /* maintain the data during 2 us before CLK up */
bits.cl = BIT_SET; /* CLK high */
- set_bits();
+ panel_set_bits();
udelay(1); /* maintain the strobe during 1 us */
byte >>= 1;
}
/* The backlight is activated by seting the AUTOFEED line to +5V */
spin_lock(&pprt_lock);
bits.bl = on;
- set_bits();
+ panel_set_bits();
spin_unlock(&pprt_lock);
}
static void panel_scan_timer(void)
{
- if ((keypad_enabled && keypad_initialized)
- || (smartcard_enabled && smartcard_enabled)) {
-
+ if (keypad_enabled && keypad_initialized) {
if (spin_trylock(&pprt_lock)) {
phys_scan_contacts();
spin_unlock(&pprt_lock); /* no need for the parport anymore */
mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
}
-/* send a high / low clock impulse of <duration> microseconds high and low */
-static void smartcard_send_clock(int duration)
-{
- int old;
-
- w_dtr(pprt, (old = r_dtr(pprt)) | PNL_SC_CLK);
- udelay(duration);
- w_dtr(pprt, (old & ~PNL_SC_CLK));
- udelay(duration);
-}
-
-static void smartcard_insert(int dummy)
-{
- int ofs;
-
- spin_lock(&pprt_lock);
- w_dtr(pprt, (r_dtr(pprt) & ~PNL_SC_BITS));
- w_ctr(pprt, (r_ctr(pprt) | PNL_SC_ENA));
-
- udelay(30); /* ensure the rst is low at least 30 us */
-
- smartcard_send_clock(100); /* reset address counter */
-
- w_dtr(pprt, r_dtr(pprt) | PNL_SC_RST);
- udelay(30); /* ensure the rst is high at least 30 us */
-
- for (ofs = 0; ofs < SMARTCARD_BYTES; ofs++) {
- int bit, byte;
- byte = 0;
- for (bit = 128; bit > 0; bit >>= 1) {
- if (!(r_str(pprt) & PNL_SC_IOR))
- byte |= bit;
- smartcard_send_clock(15); /* 15 us are enough for data */
- }
- smartcard_data[ofs] = byte;
- }
-
- w_dtr(pprt, (r_dtr(pprt) & ~PNL_SC_BITS));
- w_ctr(pprt, (r_ctr(pprt) & ~PNL_SC_ENA));
-
- spin_unlock(&pprt_lock);
-
- printk(KERN_INFO "Panel: smart card inserted : %02x%02x%02x%02x%1x\n",
- smartcard_data[2], smartcard_data[3], smartcard_data[4],
- smartcard_data[5], smartcard_data[6] >> 4);
- keypad_send_key("CardIn\n", 7);
-}
-
-static void smartcard_remove(int dummy)
-{
- printk(KERN_INFO "Panel: smart card removed : %02x%02x%02x%02x%1x\n",
- smartcard_data[2], smartcard_data[3], smartcard_data[4],
- smartcard_data[5], smartcard_data[6] >> 4);
- memset(smartcard_data, 0, sizeof(smartcard_data));
- keypad_send_key("CardOut\n", 8);
-}
-
-/*
- * These are the file operation function for user access to /dev/smartcard
- */
-
-static ssize_t smartcard_read(struct file *file,
- char *buf, size_t count, loff_t *ppos)
-{
-
- unsigned i = *ppos;
- char *tmp = buf;
-
- for (; count-- > 0 && (smartcard_ptr < 9); ++i, ++tmp, ++smartcard_ptr) {
- if (smartcard_ptr & 1)
- put_user('0' +
- (smartcard_data[2 + (smartcard_ptr >> 1)] &
- 0xF), tmp);
- else
- put_user('0' +
- (smartcard_data[2 + (smartcard_ptr >> 1)] >>
- 4), tmp);
- }
- *ppos = i;
-
- return tmp - buf;
-}
-
-static int smartcard_open(struct inode *inode, struct file *file)
-{
-
- if (smartcard_open_cnt)
- return -EBUSY; /* open only once at a time */
-
- if (file->f_mode & FMODE_WRITE) /* device is read-only */
- return -EPERM;
-
- smartcard_ptr = 0; /* flush the buffer on opening */
- smartcard_open_cnt++;
- return 0;
-}
-
-static int smartcard_release(struct inode *inode, struct file *file)
-{
- smartcard_open_cnt--;
- return 0;
-}
-
-static struct file_operations smartcard_fops = {
- .read = smartcard_read, /* read */
- .open = smartcard_open, /* open */
- .release = smartcard_release, /* close */
-};
-
-static struct miscdevice smartcard_dev = {
- SMARTCARD_MINOR,
- "smartcard",
- &smartcard_fops
-};
-
static void init_scan_timer(void)
{
if (scan_timer.function != NULL)
return key;
}
+#if 0
/* tries to bind a callback function to the signal name <name>. The function
* <press_fct> will be called with the <press_data> arg when the signal is
* activated, and so on for <release_fct>/<release_data>
list_add(&callback->list, &logical_inputs);
return callback;
}
+#endif
static void keypad_init(void)
{
keypad_initialized = 1;
}
-static void smartcard_init(void)
-{
- init_waitqueue_head(&smartcard_read_wait);
-
- panel_bind_callback(SMARTCARD_LOGICAL_DETECTOR, &smartcard_insert, 0,
- &smartcard_remove, 0);
- init_scan_timer();
- smartcard_enabled = 1;
-}
-
/**************************************************/
/* device initialization */
/**************************************************/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define INIT_FUNC static int __init panel_init_module
-#define CLEANUP_FUNC static void __exit panel_cleanup_module
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-#define INIT_FUNC static int __init panel_init_module
-#define CLEANUP_FUNC static void panel_cleanup_module
-#else
-#define INIT_FUNC int init_module
-#define CLEANUP_FUNC int cleanup_module
-#endif
-
-#ifndef MODULE
-/* called when compiled into the kernel */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-static int __init panel_setup(char *str)
-#else
-__initfunc(void panel_setup(char *str, int *ints))
-#endif
-{
- int dummy;
- int *where;
- int helpdisplayed = 0;
-
- if (!str)
- return 0;
-
- while (*str) {
- where = NULL;
-
- /* let's parse each of the command line parameters of the following form :
- panel=[parport:x],[lcd_height:x],[lcd_width:x],[lcd_bwidth:x],[lcd_hwidth:x]
- */
- if (!strncmp(str, "parport:", 8)) {
- str += 8;
- where = &parport;
- } else if (!strncmp(str, "disabled", 8)) {
- return 0;
- } else if (!strncmp(str, "lcd_height:", 11)) {
- str += 11;
- where = &lcd_height;
- } else if (!strncmp(str, "lcd_width:", 10)) {
- str += 10;
- where = &lcd_width;
- } else if (!strncmp(str, "lcd_bwidth:", 11)) {
- str += 11;
- where = &lcd_bwidth;
- } else if (!strncmp(str, "lcd_hwidth:", 11)) {
- str += 11;
- where = &lcd_hwidth;
- } else if (!strncmp(str, "lcd_enabled:", 12)) {
- str += 12;
- where = &lcd_enabled;
- } else if (!strncmp(str, "keypad_enabled:", 15)) {
- str += 15;
- where = &keypad_enabled;
- } else if (!strncmp(str, "smartcard_enabled:", 18)) {
- str += 18;
- where = &smartcard_enabled;
- } else if (!strncmp(str, "profile:", 8)) {
- str += 8;
- where = &profile;
- } else if (!helpdisplayed) {
- helpdisplayed = 1;
- printk(KERN_ERR "Panel version " PANEL_VERSION
- ": invalid argument. Known arguments are :\n"
- " parport:, lcd_{height,width,bwidth,enabled}:, keypad_enabled:\n");
- }
-
- /* see if we need to read a number */
- if (where != NULL) {
- dummy = 0;
- while (isdigit(*str)) {
- dummy = (dummy * 10) + (*str - '0');
- str++;
- }
- *where = dummy;
- }
-
- /* look for next arg */
- while (*str && (*str != ','))
- str++;
- while (*str == ',')
- str++;
- }
- return 1;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-__setup("panel=", panel_setup);
-#else
-__setup("panel", panel_setup);
-#endif
-
-#endif /* !MODULE */
-
static int panel_notify_sys(struct notifier_block *this, unsigned long code,
void *unused)
{
keypad_init();
misc_register(&keypad_dev);
}
-
- if (smartcard_enabled) {
- smartcard_init();
- misc_register(&smartcard_dev);
- }
}
static void panel_detach(struct parport *port)
return;
}
- if (smartcard_enabled && smartcard_initialized)
- misc_deregister(&smartcard_dev);
-
if (keypad_enabled && keypad_initialized)
misc_deregister(&keypad_dev);
case PANEL_PROFILE_CUSTOM: /* custom profile */
if (keypad_type < 0)
keypad_type = DEFAULT_KEYPAD;
- if (smartcard_enabled < 0)
- smartcard_enabled = DEFAULT_SMARTCARD;
if (lcd_type < 0)
lcd_type = DEFAULT_LCD;
break;
case PANEL_PROFILE_OLD: /* 8 bits, 2*16, old keypad */
if (keypad_type < 0)
keypad_type = KEYPAD_TYPE_OLD;
- if (smartcard_enabled < 0)
- smartcard_enabled = 0;
if (lcd_type < 0)
lcd_type = LCD_TYPE_OLD;
if (lcd_width < 0)
case PANEL_PROFILE_NEW: /* serial, 2*16, new keypad */
if (keypad_type < 0)
keypad_type = KEYPAD_TYPE_NEW;
- if (smartcard_enabled < 0)
- smartcard_enabled = 1;
if (lcd_type < 0)
lcd_type = LCD_TYPE_KS0074;
break;
case PANEL_PROFILE_HANTRONIX: /* 8 bits, 2*16 hantronix-like, no keypad */
if (keypad_type < 0)
keypad_type = KEYPAD_TYPE_NONE;
- if (smartcard_enabled < 0)
- smartcard_enabled = 0;
if (lcd_type < 0)
lcd_type = LCD_TYPE_HANTRONIX;
break;
case PANEL_PROFILE_NEXCOM: /* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */
if (keypad_type < 0)
keypad_type = KEYPAD_TYPE_NEXCOM;
- if (smartcard_enabled < 0)
- smartcard_enabled = 0;
if (lcd_type < 0)
lcd_type = LCD_TYPE_NEXCOM;
break;
case PANEL_PROFILE_LARGE: /* 8 bits, 2*40, old keypad */
if (keypad_type < 0)
keypad_type = KEYPAD_TYPE_OLD;
- if (smartcard_enabled < 0)
- smartcard_enabled = 0;
if (lcd_type < 0)
lcd_type = LCD_TYPE_OLD;
break;
return -EIO;
}
- if (!lcd_enabled && !keypad_enabled && !smartcard_enabled) { /* no device enabled, let's release the parport */
+ if (!lcd_enabled && !keypad_enabled) {
+ /* no device enabled, let's release the parport */
if (pprt) {
parport_release(pprt);
parport_unregister_device(pprt);
return 0;
}
-#if defined(MODULE) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
-INIT_FUNC(void)
+static int __init panel_init_module(void)
{
return panel_init();
}
-CLEANUP_FUNC(void)
+static void __exit panel_cleanup_module(void)
{
unregister_reboot_notifier(&panel_notifier);
if (scan_timer.function != NULL)
del_timer(&scan_timer);
- if (keypad_enabled)
- misc_deregister(&keypad_dev);
+ if (pprt != NULL) {
+ if (keypad_enabled)
+ misc_deregister(&keypad_dev);
- if (smartcard_enabled)
- misc_deregister(&smartcard_dev);
+ if (lcd_enabled) {
+ panel_lcd_print("\x0cLCD driver " PANEL_VERSION
+ "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
+ misc_deregister(&lcd_dev);
+ }
- if (lcd_enabled) {
- panel_lcd_print("\x0cLCD driver " PANEL_VERSION
- "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
- misc_deregister(&lcd_dev);
+ /* TODO: free all input signals */
+ parport_release(pprt);
+ parport_unregister_device(pprt);
}
-
- /* TODO: free all input signals */
-
- parport_release(pprt);
- parport_unregister_device(pprt);
parport_unregister_driver(&panel_driver);
}
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
module_init(panel_init_module);
module_exit(panel_cleanup_module);
MODULE_AUTHOR("Willy Tarreau");
MODULE_LICENSE("GPL");
-#endif
/*
* Local variables: