/* poll the keyboard this every second */ #define INPUT_POLL_TIME (HZ / 50) /* a key starts to repeat after this times INPUT_POLL_TIME */ #define KEYPAD_REP_START (10) /* a key repeats this times INPUT_POLL_TIME */ #define KEYPAD_REP_DELAY (2)
/* converts an r_str() input to an active high, bits string : 000BAOSE */ #define PNL_PINPUT(a) ((((unsignedchar)(a)) ^ 0x7F) >> 3)
#define PNL_PBUSY 0x80 /* inverted input, active low */ #define PNL_PACK 0x40 /* direct input, active low */ #define PNL_POUTPA 0x20 /* direct input, active high */ #define PNL_PSELECD 0x10 /* direct input, active high */ #define PNL_PERRORP 0x08 /* direct input, active low */
#define PNL_PBIDIR 0x20 /* bi-directional ports */ /* high to read data in or-ed with data out */ #define PNL_PINTEN 0x10 #define PNL_PSELECP 0x08 /* inverted output, active low */ #define PNL_PINITP 0x04 /* direct output, active low */ #define PNL_PAUTOLF 0x02 /* inverted output, active low */ #define PNL_PSTROBE 0x01 /* inverted output */
/* macros to simplify use of the parallel port */ #define r_ctr(x) (parport_read_control((x)->port)) #define r_dtr(x) (parport_read_data((x)->port)) #define r_str(x) (parport_read_status((x)->port)) #define w_ctr(x, y) (parport_write_control((x)->port, (y))) #define w_dtr(x, y) (parport_write_data((x)->port, (y)))
/* this defines which bits are to be used and which ones to be ignored */ /* logical or of the output bits involved in the scan matrix */ static __u8 scan_mask_o; /* logical or of the input bits involved in the scan matrix */ static __u8 scan_mask_i;
/* what has just been read from the I/O ports */ static __u64 phys_read; /* previous phys_read */ static __u64 phys_read_prev; /* stabilized phys_read (phys_read|phys_read_prev) */ static __u64 phys_curr; /* previous phys_curr */ static __u64 phys_prev; /* 0 means that at least one logical signal needs be computed */ staticchar inputs_stable;
/* these variables are specific to the keypad */ staticstruct { bool enabled;
} keypad;
staticint 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)");
staticint 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)");
staticint 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)");
staticint 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)");
staticint 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)");
staticint 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)");
/* Deprecated module parameters - consider not using them anymore */
panel_set_bits();
udelay(2); /* maintain the data during 2 us before CLK up */
set_bit(LCD_BIT_CL, bits); /* CLK high */
panel_set_bits();
udelay(1); /* maintain the strobe during 1 us */
byte >>= 1;
}
}
/* turn the backlight on or off */ staticvoid lcd_backlight(struct charlcd *charlcd, enum charlcd_onoff on)
{ if (lcd.pins.bl == PIN_NONE) return;
/* The backlight is activated by setting the AUTOFEED line to +5V */
spin_lock_irq(&pprt_lock); if (on)
set_bit(LCD_BIT_BL, bits); else
clear_bit(LCD_BIT_BL, bits);
panel_set_bits();
spin_unlock_irq(&pprt_lock);
}
/* send a command to the LCD panel in serial mode */ staticvoid lcd_write_cmd_s(struct hd44780_common *hdc, int cmd)
{
spin_lock_irq(&pprt_lock);
lcd_send_serial(0x1F); /* R/W=W, RS=0 */
lcd_send_serial(cmd & 0x0F);
lcd_send_serial((cmd >> 4) & 0x0F);
udelay(40); /* the shortest command takes at least 40 us */
spin_unlock_irq(&pprt_lock);
}
/* send data to the LCD panel in serial mode */ staticvoid lcd_write_data_s(struct hd44780_common *hdc, int data)
{
spin_lock_irq(&pprt_lock);
lcd_send_serial(0x5F); /* R/W=W, RS=1 */
lcd_send_serial(data & 0x0F);
lcd_send_serial((data >> 4) & 0x0F);
udelay(40); /* the shortest data takes at least 40 us */
spin_unlock_irq(&pprt_lock);
}
/* send a command to the LCD panel in 8 bits parallel mode */ staticvoid lcd_write_cmd_p8(struct hd44780_common *hdc, int cmd)
{
spin_lock_irq(&pprt_lock); /* present the data to the data port */
w_dtr(pprt, cmd);
udelay(20); /* maintain the data during 20 us before the strobe */
udelay(40); /* maintain the strobe during 40 us */
clear_bit(LCD_BIT_E, bits);
set_ctrl_bits();
udelay(120); /* the shortest command takes at least 120 us */
spin_unlock_irq(&pprt_lock);
}
/* send data to the LCD panel in 8 bits parallel mode */ staticvoid lcd_write_data_p8(struct hd44780_common *hdc, int data)
{
spin_lock_irq(&pprt_lock); /* present the data to the data port */
w_dtr(pprt, data);
udelay(20); /* maintain the data during 20 us before the strobe */
udelay(40); /* maintain the strobe during 40 us */
clear_bit(LCD_BIT_E, bits);
set_ctrl_bits();
udelay(45); /* the shortest data takes at least 45 us */
spin_unlock_irq(&pprt_lock);
}
/* send a command to the TI LCD panel */ staticvoid lcd_write_cmd_tilcd(struct hd44780_common *hdc, int cmd)
{
spin_lock_irq(&pprt_lock); /* present the data to the control port */
w_ctr(pprt, cmd);
udelay(60);
spin_unlock_irq(&pprt_lock);
}
/* send data to the TI LCD panel */ staticvoid lcd_write_data_tilcd(struct hd44780_common *hdc, int data)
{
spin_lock_irq(&pprt_lock); /* present the data to the data port */
w_dtr(pprt, data);
udelay(60);
spin_unlock_irq(&pprt_lock);
}
/* Overwrite with module params set on loading */ if (lcd_height != NOT_SET)
charlcd->height = lcd_height; if (lcd_width != NOT_SET)
charlcd->width = lcd_width; if (lcd_bwidth != NOT_SET)
hdc->bwidth = lcd_bwidth; if (lcd_hwidth != NOT_SET)
hdc->hwidth = lcd_hwidth; if (lcd_charset != NOT_SET)
lcd.charset = lcd_charset; if (lcd_proto != NOT_SET)
lcd.proto = lcd_proto; if (lcd_e_pin != PIN_NOT_SET)
lcd.pins.e = lcd_e_pin; if (lcd_rs_pin != PIN_NOT_SET)
lcd.pins.rs = lcd_rs_pin; if (lcd_rw_pin != PIN_NOT_SET)
lcd.pins.rw = lcd_rw_pin; if (lcd_cl_pin != PIN_NOT_SET)
lcd.pins.cl = lcd_cl_pin; if (lcd_da_pin != PIN_NOT_SET)
lcd.pins.da = lcd_da_pin; if (lcd_bl_pin != PIN_NOT_SET)
lcd.pins.bl = lcd_bl_pin;
/* this is used to catch wrong and default values */ if (charlcd->width <= 0)
charlcd->width = DEFAULT_LCD_WIDTH; if (hdc->bwidth <= 0)
hdc->bwidth = DEFAULT_LCD_BWIDTH; if (hdc->hwidth <= 0)
hdc->hwidth = DEFAULT_LCD_HWIDTH; if (charlcd->height <= 0)
charlcd->height = DEFAULT_LCD_HEIGHT;
if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */
charlcd->ops = &charlcd_ops;
hdc->write_data = lcd_write_data_s;
hdc->write_cmd = lcd_write_cmd_s;
if (lcd.pins.cl == PIN_NOT_SET)
lcd.pins.cl = DEFAULT_LCD_PIN_SCL; if (lcd.pins.da == PIN_NOT_SET)
lcd.pins.da = DEFAULT_LCD_PIN_SDA;
staticvoid keypad_send_key(constchar *string, int max_len)
{ /* send the key to the device only if a process is attached to it. */ if (!atomic_read(&keypad_available)) { while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) {
keypad_buffer[(keypad_start + keypad_buflen++) %
KEYPAD_BUFFER] = *string++;
}
wake_up_interruptible(&keypad_read_wait);
}
}
/* this function scans all the bits involving at least one logical signal, *andputstheresultsinthebitfield"phys_read"(onebitperestablished *contact),andsets"phys_read_prev"to"phys_read". * *Note:todebounceinputsignals,wewillonlyconsiderasswitchedasignal *whichisstableacross2measures.Signalswhicharedifferentbetweentwo *readswillbekeptastheypreviouslywereintheirlogicalform(phys_prev). *Asignalwhichhasjustswitchedwillhavea1in *(phys_read^phys_read_prev).
*/ staticvoid phys_scan_contacts(void)
{ int bit, bitval; char oldval; char bitmask; char gndmask;
/* converts a name of the form "({BbAaPpSsEe}{01234567-})*" to a series of bits. *if<omask>or<imask>arenon-null,theywillbeor'edwiththebits *correspondingtooutandinbitsrespectively. *returns1ifok,0iferror(inwhichcase,nothingiswritten).
*/ static u8 input_name2mask(constchar *name, __u64 *mask, __u64 *value,
u8 *imask, u8 *omask)
{ constchar sigtab[] = "EeSsPpAaBb";
u8 im, om;
__u64 m, v;
om = 0;
im = 0;
m = 0ULL;
v = 0ULL; while (*name) { int in, out, bit, neg; constchar *idx;
idx = strchr(sigtab, *name); if (!idx) return0; /* input name not found */
in = idx - sigtab;
neg = (in & 1); /* odd (lower) names are negated */
in >>= 1;
im |= BIT(in);
name++; if (*name >= '0' && *name <= '7') {
out = *name - '0';
om |= BIT(out);
} elseif (*name == '-') {
out = 8;
} else { return0; /* unknown bit name */
}
bit = (out * 5) + in;
m |= 1ULL << bit; if (!neg)
v |= 1ULL << bit;
name++;
}
*mask = m;
*value = v; if (imask)
*imask |= im; if (omask)
*omask |= om; return1;
}
/* tries to bind a key to the signal name <name>. The key will send the *strings<press>,<repeat>,<release>fortheserespectiveevents. *Returnsthepointertothenewkeyifok,NULLifthekeycouldnotbebound.
*/ staticstruct logical_input *panel_bind_key(constchar *name, constchar *press, constchar *repeat, constchar *release)
{ struct logical_input *key;
key = kzalloc(sizeof(*key), GFP_KERNEL); if (!key) return NULL;
#if0 /* tries to bind a callback function to the signal name <name>. The function *<press_fct>willbecalledwiththe<press_data>argwhenthesignalis *activated,andsoonfor<release_fct>/<release_data> *Returnsthepointertothenewsignalifok,NULLifthesignalcouldnot *bebound.
*/ staticstruct logical_input *panel_bind_callback(char *name, void (*press_fct)(int), int press_data, void (*release_fct)(int), int release_data)
{ struct logical_input *callback;
callback = kmalloc(sizeof(*callback), GFP_KERNEL); if (!callback) return NULL;
if (parport_claim(pprt)) {
pr_err("could not claim access to parport%d. Aborting.\n",
parport); goto err_unreg_device;
}
/* must init LCD first, just in case an IRQ from the keypad is *generatedatkeypadinit
*/ if (lcd.enabled) {
lcd_init(); if (!lcd.charlcd || charlcd_register(lcd.charlcd)) goto err_unreg_device;
}
if (keypad.enabled) {
keypad_init(); if (misc_register(&keypad_dev)) goto err_lcd_unreg;
} return;
err_lcd_unreg: if (scan_timer.function)
timer_delete_sync(&scan_timer); if (lcd.enabled)
charlcd_unregister(lcd.charlcd);
err_unreg_device:
hd44780_common_free(lcd.charlcd);
lcd.charlcd = NULL;
parport_unregister_device(pprt);
pprt = NULL;
}
staticvoid panel_detach(struct parport *port)
{ if (port->number != parport) return;
if (!pprt) {
pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n",
__func__, port->number, parport); return;
} if (scan_timer.function)
timer_delete_sync(&scan_timer);
if (keypad.enabled) {
misc_deregister(&keypad_dev);
keypad_initialized = 0;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.43Bemerkung:
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.