New input patches
cover New input patches
Hi Vojtech,
I have some more input patches that I would like you to review:
01-libps2.patch
- move common code from atkbd and psmouse into one place, create ps2dev structure that should be used to build drivers for hardware attached to a PS/2 port.
I think that command processing is now race free - instead of using bit operations on flags the ps2_command and ps2_send_byte simply take serio->lock (via serio_pause/continue_rx). Since serio->lock is also taken by interrupt handler anyway it gives us desired serialization. As wakeup routines take a spinlock as well and spinlock is guaranteed to be a barrier we should not miss wake up events either.
02-serio-pin-driver.patch
- Add drv_sem to serio structure and implement serio_[un]pin_driver() functions. The main purpose is to pin a driver bound to serio port when accessing driver's data from sysfs attribute handler; otherwise other thread could unbind/unload driver in a middle of processing.
03-atkbd-sysfs-attr.patch
- Export extra, scroll, set, softrepeat and softraw atkbd properties via sysfs and allow them to be controlled at run time, independently for each keyboard.
Now that Linus pulled all pending changes the patches should apply cleanly to all trees (his, yours and Andrew's).
Please let me know if they are ok and I will push them into my bkbits tree.
Thanks!
Signature · 1 line
Dmitry
PATCH 1/3 libps2.patch
===================================================================
[email protected], 2004-09-01 01:00:06-05:00, [email protected]
Input: pull common code from psmouse and atkbd into libps2 module
drivers/input/keyboard/Kconfig | 1 drivers/input/keyboard/atkbd.c | 290 ++++++------------------------------- drivers/input/mouse/Kconfig | 1 drivers/input/mouse/logips2pp.c | 41 ++--- drivers/input/mouse/psmouse-base.c | 230 +++++------------------------ drivers/input/mouse/psmouse.h | 16 -- drivers/input/mouse/synaptics.c | 28 +-- drivers/input/serio/Kconfig | 10 + drivers/input/serio/Makefile | 1 drivers/input/serio/libps2.c | 273 ++++++++++++++++++++++++++++++++++ include/linux/libps2.h | 50 ++++++ 11 files changed, 474 insertions(+), 467 deletions(-)
===================================================================
drivers/input/keyboard/Kconfig +1 -0
@@ -16,6 +16,7 @@ default y depends on INPUT && INPUT_KEYBOARD select SERIO + select SERIO_LIBPS2 select SERIO_I8042 if PC select SERIO_GSCPS2 if GSC help
drivers/input/keyboard/atkbd.c +52 -238
495 lines not on this page · raw message
drivers/input/mouse/Kconfig +1 -0
@@ -16,6 +16,7 @@ default y depends on INPUT && INPUT_MOUSE select SERIO + select SERIO_LIBPS2 select SERIO_I8042 if PC select SERIO_GSCPS2 if GSC ---help---
drivers/input/mouse/logips2pp.c +23 -18
100 lines not on this page · raw message
drivers/input/mouse/psmouse-base.c +47 -183
384 lines not on this page · raw message
drivers/input/mouse/psmouse.h +1 -15
@@ -18,11 +18,6 @@#define PSMOUSE_RET_ACK 0xfa#define PSMOUSE_RET_NAK 0xfe -#define PSMOUSE_FLAG_ACK 0/* Waiting for ACK/NAK */ -#define PSMOUSE_FLAG_CMD 1/* Waiting for command to finish */ -#define PSMOUSE_FLAG_CMD1 2/* Waiting for the first byte of command response */ -#define PSMOUSE_FLAG_WAITID 3/* Command execiting is GET ID */ -enum psmouse_state {PSMOUSE_IGNORE ,PSMOUSE_INITIALIZING ,
@@ -40,26 +35,18 @@struct psmouse {void *private;struct input_dev dev; -struct serio *serio; +struct ps2dev ps2dev;char *vendor;char *name; -unsigned char cmdbuf[8 ];unsigned char packet[8 ]; -unsigned char cmdcnt;unsigned char pktcnt;unsigned char type;unsigned char model;unsigned long last;unsigned long out_of_sync;enum psmouse_state state; -unsigned char nak; -char error;char devname[64 ];char phys[32 ]; -unsigned long flags; - -/* Used to signal completion from interrupt handler */ -wait_queue_head_t wait;psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse,struct pt_regs *regs);int (*reconnect)(struct psmouse *psmouse);
@@ -77,7 +64,6 @@#define PSMOUSE_IMEX 6#define PSMOUSE_SYNAPTICS 7 -int psmouse_command (struct psmouse *psmouse,unsigned char *param,int command);int psmouse_sliced_command (struct psmouse *psmouse,unsigned char command);int psmouse_reset (struct psmouse *psmouse);
drivers/input/mouse/synaptics.c +15 -13
@@ -26,6 +26,7 @@#include <linux/module.h> #include <linux/input.h> #include <linux/serio.h> +#include <linux/libps2.h> #include "psmouse.h" #include "synaptics.h"
@@ -50,7 +51,7 @@ {if (psmouse_sliced_command (psmouse, c))return -1 ; -if (psmouse_command (psmouse, param,PSMOUSE_CMD_GETINFO )) +if (ps2_command (&psmouse->ps2dev, param,PSMOUSE_CMD_GETINFO ))return -1 ;return 0 ; }
@@ -65,7 +66,7 @@if (psmouse_sliced_command (psmouse, mode))return -1 ; param[0 ] =SYN_PS_SET_MODE2 ; -if (psmouse_command (psmouse, param,PSMOUSE_CMD_SETRATE )) +if (ps2_command (&psmouse->ps2dev, param,PSMOUSE_CMD_SETRATE ))return -1 ;return 0 ; }
@@ -219,7 +220,7 @@if (psmouse_sliced_command (parent, c))return -1 ; -if (psmouse_command (parent, &rate_param,PSMOUSE_CMD_SETRATE )) +if (ps2_command (&parent->ps2dev, &rate_param,PSMOUSE_CMD_SETRATE ))return -1 ;return 0 ; }
@@ -245,7 +246,7 @@static void synaptics_pt_activate (struct psmouse *psmouse) { -struct psmouse *child = psmouse->serio->child->private; +struct psmouse *child = psmouse->ps2dev.serio->child->private;/* adjust the touchpad to child's choice of protocol */ if (child && child->type >=PSMOUSE_GENPS ) {
@@ -270,11 +271,11 @@strlcpy (serio->name,"Synaptics pass-through" ,sizeof (serio->name));strlcpy (serio->phys,"synaptics-pt/serio0" ,sizeof (serio->name)); serio->write = synaptics_pt_write; - serio->parent = psmouse->serio; + serio->parent = psmouse->ps2dev.serio; psmouse->pt_activate = synaptics_pt_activate; - psmouse->serio->child = serio; + psmouse->ps2dev.serio->child = serio; }/*****************************************************************************
@@ -470,8 +471,8 @@ priv->pkt_type =synaptics_detect_pkt_type (psmouse);if (SYN_CAP_PASS_THROUGH (priv->capabilities) &&synaptics_is_pt_packet (psmouse->packet)) { -if (psmouse->serio->child) -synaptics_pass_pt_packet (psmouse->serio->child, psmouse->packet); +if (psmouse->ps2dev.serio->child) +synaptics_pass_pt_packet (psmouse->ps2dev.serio->child, psmouse->packet); }else synaptics_process_packet (psmouse);
@@ -561,15 +562,16 @@int synaptics_detect (struct psmouse *psmouse) { +struct ps2dev *ps2dev = &psmouse->ps2dev;unsigned char param[4 ]; param[0 ] =0 ; -psmouse_command (psmouse, param,PSMOUSE_CMD_SETRES ); -psmouse_command (psmouse, param,PSMOUSE_CMD_SETRES ); -psmouse_command (psmouse, param,PSMOUSE_CMD_SETRES ); -psmouse_command (psmouse, param,PSMOUSE_CMD_SETRES ); -psmouse_command (psmouse, param,PSMOUSE_CMD_GETINFO ); +ps2_command (ps2dev, param,PSMOUSE_CMD_SETRES ); +ps2_command (ps2dev, param,PSMOUSE_CMD_SETRES ); +ps2_command (ps2dev, param,PSMOUSE_CMD_SETRES ); +ps2_command (ps2dev, param,PSMOUSE_CMD_SETRES ); +ps2_command (ps2dev, param,PSMOUSE_CMD_GETINFO );return param[1 ] ==0x47 ; }
drivers/input/serio/Kconfig +10 -0
@@ -131,6 +131,16 @@ To compile this driver as a module, choose M here: the module will be called maceps2. +config SERIO_LIBPS2 + tristate "PS/2 driver library" + depends on SERIO + help + Say Y here if you are using a driver for device connected + to a PS/2 port, such as PS/2 mouse or standard AT keyboard. + + To compile this driver as a module, choose M here: the + module will be called libps2. + config SERIO_RAW tristate "Raw access to serio ports" depends on SERIO
drivers/input/serio/Makefile +1 -0
@@ -17,4 +17,5 @@ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o +obj-$(CONFIG_SERIO_LIBPS2) += libps2.o obj-$(CONFIG_SERIO_RAW) += serio_raw.o
drivers/input/serio/libps2.c new file +273 -0
273 lines not on this page · raw message
include/linux/libps2.h new file +50 -0
50 lines not on this page · raw message
PATCH 2/3 serio-pin-driver.patch
===================================================================
[email protected], 2004-09-16 23:06:29-05:00, [email protected]
Input: add serio_[un]pin_driver() functions so attribute handlers
can safely access driver bound to a serio port.
drivers/input/serio/serio.c | 20 ++++++++++++-------- include/linux/serio.h | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 9 deletions(-)
===================================================================
drivers/input/serio/serio.c +12 -8
@@ -326,6 +326,7 @@try_module_get (THIS_MODULE );spin_lock_init (&serio->lock); +init_MUTEX (&serio->drv_sem);list_add_tail (&serio->node, &serio_list);snprintf (serio->dev.bus_id,sizeof (serio->dev.bus_id),"serio%d" , serio_no++); serio->dev.bus = &serio_bus;
@@ -595,17 +596,22 @@up (&serio_sem); } -/* called from serio_driver->connect/disconnect methods under serio_sem */ -int serio_open (struct serio *serio,struct serio_driver *drv) +static void serio_set_drv (struct serio *serio,struct serio_driver *drv) { +down (&serio->drv_sem);serio_pause_rx (serio); serio->drv = drv;serio_continue_rx (serio); +up (&serio->drv_sem); +} + +/* called from serio_driver->connect/disconnect methods under serio_sem */ +int serio_open (struct serio *serio,struct serio_driver *drv) +{ +serio_set_drv (serio, drv);if (serio->open && serio->open (serio)) { -serio_pause_rx (serio); - serio->drv =NULL ; -serio_continue_rx (serio); +serio_set_drv (serio,NULL );return -1 ; }return 0 ;
@@ -617,9 +623,7 @@if (serio->close) serio->close (serio); -serio_pause_rx (serio); - serio->drv =NULL ; -serio_continue_rx (serio); +serio_set_drv (serio,NULL ); } irqreturn_t serio_interrupt(struct serio *serio,
include/linux/serio.h +15 -1
@@ -45,7 +45,8 @@struct serio *parent, *child; -struct serio_driver *drv;/* accessed from interrupt, must be protected by serio->lock */ +struct serio_driver *drv;/* accessed from interrupt, must be protected by serio->lock and serio->sem */ +struct semaphore drv_sem;/* protects serio->drv so attributes can pin driver */ struct device dev;
@@ -120,6 +121,19 @@static __inline__void serio_continue_rx (struct serio *serio) {spin_unlock_irq (&serio->lock); +} + +/* +* Use the following fucntions to pin serio's driver in process context +*/ +static __inline__int serio_pin_driver (struct serio *serio) +{ +return down_interruptible (&serio->drv_sem); +} + +static __inline__void serio_unpin_driver (struct serio *serio) +{ +up (&serio->drv_sem); }
PATCH 3/3 atkbd-sysfs-attr.patch
===================================================================
[email protected], 2004-09-16 23:24:30-05:00, [email protected]
Input: atkbd - export extra, scroll, set, softrepeat and softraw as individual
keyboard attributes (sysfs) and allow them to be set/changed independently for each keyboard:
echo -n "2" > /sys/bus/serio/devices/serio1/set echo -n "1" > /sys/bus/serio/devices/serio1/softrepeat
atkbd.c | 444 ++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 367 insertions(+), 77 deletions(-)
===================================================================
drivers/input/keyboard/atkbd.c +367 -77
@@ -184,13 +184,15 @@char phys[32 ];struct input_dev dev; -unsigned char set;unsigned short id;unsigned char keycode[512 ]; +unsigned char set;unsigned char translated;unsigned char extra;unsigned char write; - +unsigned char softrepeat; +unsigned char softraw; +unsigned char scroll;unsigned char enabled;/* Accessed only from interrupt */
@@ -202,6 +204,31 @@unsigned long time; }; +static ssize_t atkbd_attr_show_helper (struct device *dev,char *buf, +ssize_t (*handler)(struct atkbd *,char *)); +static ssize_t atkbd_attr_set_helper (struct device *dev,const char *buf,size_t count, +int (*handler)(struct atkbd *,const char *,size_t )); +#define ATKBD_DEFINE_ATTR (_name) \ +static ssize_t atkbd_show_##_name(struct atkbd *, char *); \ +static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \ +static ssize_t atkbd_do_show_##_name(struct device *d, char *b) \ +{ \ + return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \ +} \ +static ssize_t atkbd_do_set_##_name(struct device *d, const char *b, size_t s) \ +{ \ + return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ +} \ +static struct device_attribute atkbd_attr_##_name = \ + __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); + +ATKBD_DEFINE_ATTR (extra); +ATKBD_DEFINE_ATTR (scroll); +ATKBD_DEFINE_ATTR (set); +ATKBD_DEFINE_ATTR (softrepeat); +ATKBD_DEFINE_ATTR (softraw); + +static void atkbd_report_key (struct input_dev *dev,struct pt_regs *regs,int code,int value) {input_regs (dev, regs);
@@ -253,7 +280,8 @@if (!atkbd->enabled) goto out; -input_event (&atkbd->dev,EV_MSC ,MSC_RAW , code); +if (atkbd->softraw) +input_event (&atkbd->dev,EV_MSC ,MSC_RAW , code);if (atkbd->translated) {
@@ -343,7 +371,7 @@break ;default : value = atkbd->release ?0 : - (1 + (!atkbd_softrepeat &&test_bit (atkbd->keycode[code], atkbd->dev.key))); + (1 + (!atkbd->softrepeat &&test_bit (atkbd->keycode[code], atkbd->dev.key)));switch (value) {/* Workaround Toshiba laptop multiple keypress */ case 0 :
@@ -418,7 +446,7 @@case EV_REP : -if (atkbd_softrepeat)return 0 ; +if (atkbd->softrepeat)return 0 ; i = j =0 ;while (i <32 && period[i] < dev->rep[REP_PERIOD ]) i++;
@@ -435,6 +463,30 @@ }/* +* atkbd_enable() signals that interrupt handler is allowed to +* generate input events. +*/ + +static inline void atkbd_enable (struct atkbd *atkbd) +{ +serio_pause_rx (atkbd->ps2dev.serio); + atkbd->enabled =1 ; +serio_continue_rx (atkbd->ps2dev.serio); +} + +/* +* atkbd_disable() tells input handler that all incoming data except +* for ACKs and command response should be dropped. +*/ + +static inline void atkbd_disable (struct atkbd *atkbd) +{ +serio_pause_rx (atkbd->ps2dev.serio); + atkbd->enabled =0 ; +serio_continue_rx (atkbd->ps2dev.serio); +} + +/* * atkbd_probe() probes for an AT keyboard on a serio port. */
@@ -489,16 +541,17 @@ }/* -* atkbd_set_3 checks if a keyboard has a working Set 3 support, and +* atkbd_select_set checks if a keyboard has a working Set 3 support, and * sets it into that. Unfortunately there are keyboards that can be switched * to Set 3, but don't work well in that (BTC Multimedia ...) */ -static int atkbd_set_3 (struct atkbd *atkbd) +static int atkbd_select_set (struct atkbd *atkbd,int target_set,int allow_extra) {struct ps2dev *ps2dev = &atkbd->ps2dev;unsigned char param[2 ]; + atkbd->extra =0 ;/* * For known special keyboards we can go ahead and set the correct set. * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and
@@ -514,7 +567,7 @@return 3 ; } -if (atkbd_extra) { +if (allow_extra) { param[0 ] =0x71 ;if (!ps2_command (ps2dev, param,ATKBD_CMD_EX_ENABLE )) { atkbd->extra =1 ;
@@ -522,7 +575,7 @@ } } -if (atkbd_set !=3 ) +if (target_set !=3 )return 2 ;if (!ps2_command (ps2dev, param,ATKBD_CMD_OK_GETID )) {
@@ -549,7 +602,7 @@return 3 ; } -static int atkbd_enable (struct atkbd *atkbd) +static int atkbd_activate (struct atkbd *atkbd) {struct ps2dev *ps2dev = &atkbd->ps2dev;unsigned char param[1 ];
@@ -594,6 +647,7 @@ps2_command (&atkbd->ps2dev,NULL ,ATKBD_CMD_RESET_BAT ); } +/* * atkbd_disconnect() closes and frees. */
@@ -602,19 +656,108 @@ {struct atkbd *atkbd = serio->private; -serio_pause_rx (serio); - atkbd->enabled =0 ; -serio_continue_rx (serio); +atkbd_disable (atkbd);/* make sure we don't have a command in flight */ synchronize_kernel ();flush_scheduled_work (); +device_remove_file (&serio->dev, &atkbd_attr_extra); +device_remove_file (&serio->dev, &atkbd_attr_scroll); +device_remove_file (&serio->dev, &atkbd_attr_set); +device_remove_file (&serio->dev, &atkbd_attr_softrepeat); +device_remove_file (&serio->dev, &atkbd_attr_softraw); +input_unregister_device (&atkbd->dev);serio_close (serio);kfree (atkbd); } + +/* +* atkbd_set_device_attrs() initializes keyboard's keycode table +* according to the selected scancode set +*/ + +static void atkbd_set_keycode_table (struct atkbd *atkbd) +{ +int i, j; + +memset (atkbd->keycode,0 ,sizeof (atkbd->keycode)); + +if (atkbd->translated) { +for (i =0 ; i <128 ; i++) { + atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; + atkbd->keycode[i |0x80 ] = atkbd_set2_keycode[atkbd_unxlate_table[i] |0x80 ]; +if (atkbd->scroll) +for (j =0 ; i <5 ; i++) { +if (atkbd_unxlate_table[i] == atkbd_scroll_keys[j][1 ]) + atkbd->keycode[i] = atkbd_scroll_keys[j][0 ]; +if ((atkbd_unxlate_table[i] |0x80 ) == atkbd_scroll_keys[j][1 ]) + atkbd->keycode[i |0x80 ] = atkbd_scroll_keys[j][0 ]; + } + } + }else if (atkbd->set ==3 ) { +memcpy (atkbd->keycode, atkbd_set3_keycode,sizeof (atkbd->keycode)); + }else { +memcpy (atkbd->keycode, atkbd_set2_keycode,sizeof (atkbd->keycode)); + +if (atkbd->scroll) +for (i =0 ; i <5 ; i++) + atkbd->keycode[atkbd_scroll_keys[i][1 ]] = atkbd_scroll_keys[i][0 ]; + } +} + +/* +* atkbd_set_device_attrs() sets up keyboard's input device structure +*/ + +static void atkbd_set_device_attrs (struct atkbd *atkbd) +{ +int i; + +memset (&atkbd->dev,0 ,sizeof (struct input_dev )); + +init_input_dev (&atkbd->dev); + + atkbd->dev.name = atkbd->name; + atkbd->dev.phys = atkbd->phys; + atkbd->dev.id.bustype =BUS_I8042 ; + atkbd->dev.id.vendor =0x0001 ; + atkbd->dev.id.product = atkbd->translated ?1 : atkbd->set; + atkbd->dev.id.version = atkbd->id; + atkbd->dev.event = atkbd_event; + atkbd->dev.private = atkbd; + + atkbd->dev.evbit[0 ] =BIT (EV_KEY ) |BIT (EV_REP ) |BIT (EV_MSC ); + +if (atkbd->write) { + atkbd->dev.evbit[0 ] |=BIT (EV_LED ); + atkbd->dev.ledbit[0 ] =BIT (LED_NUML ) |BIT (LED_CAPSL ) |BIT (LED_SCROLLL ); + } + +if (atkbd->extra) + atkbd->dev.ledbit[0 ] |=BIT (LED_COMPOSE ) |BIT (LED_SUSPEND ) | +BIT (LED_SLEEP ) |BIT (LED_MUTE ) |BIT (LED_MISC ); + +if (!atkbd->softrepeat) { + atkbd->dev.rep[REP_DELAY ] =250 ; + atkbd->dev.rep[REP_PERIOD ] =33 ; + } + + atkbd->dev.mscbit[0 ] = atkbd->softraw ?BIT (MSC_SCAN ) :BIT (MSC_RAW ) |BIT (MSC_SCAN ); + +if (atkbd->scroll) { + atkbd->dev.evbit[0 ] |=BIT (EV_REL ); + atkbd->dev.relbit[0 ] =BIT (REL_WHEEL ); +set_bit (BTN_MIDDLE , atkbd->dev.keybit); + } + +for (i =0 ; i <512 ; i++) +if (atkbd->keycode[i] && atkbd->keycode[i] <ATKBD_SPECIAL ) +set_bit (atkbd->keycode[i], atkbd->dev.keybit); +} +/* * atkbd_connect() is called when the serio module finds and interface * that isn't handled yet by an appropriate device driver. We check if
@@ -625,7 +768,6 @@static void atkbd_connect (struct serio *serio,struct serio_driver *drv) {struct atkbd *atkbd; -int i;if (!(atkbd =kmalloc (sizeof (struct atkbd ),GFP_KERNEL )))return ;
@@ -649,29 +791,19 @@return ; } -if (!atkbd->write) - atkbd_softrepeat =1 ; -if (atkbd_softrepeat) - atkbd_softraw =1 ; - -if (atkbd->write) { - atkbd->dev.evbit[0 ] =BIT (EV_KEY ) |BIT (EV_LED ) |BIT (EV_REP ) |BIT (EV_MSC ); - atkbd->dev.ledbit[0 ] =BIT (LED_NUML ) |BIT (LED_CAPSL ) |BIT (LED_SCROLLL ); - }else atkbd->dev.evbit[0 ] =BIT (EV_KEY ) |BIT (EV_REP ) |BIT (EV_MSC ); - atkbd->dev.mscbit[0 ] = atkbd_softraw ?BIT (MSC_SCAN ) :BIT (MSC_RAW ) |BIT (MSC_SCAN ); + atkbd->softraw = atkbd_softraw; + atkbd->softrepeat = atkbd_softrepeat; + atkbd->scroll = atkbd_scroll; -if (!atkbd_softrepeat) { - atkbd->dev.rep[REP_DELAY ] =250 ; - atkbd->dev.rep[REP_PERIOD ] =33 ; - }else atkbd_softraw =1 ; +if (!atkbd->write) + atkbd->softrepeat =1 ; -init_input_dev (&atkbd->dev); +if (atkbd->softrepeat) + atkbd->softraw =1 ; atkbd->dev.keycode = atkbd->keycode; atkbd->dev.keycodesize =sizeof (unsigned char ); atkbd->dev.keycodemax =ARRAY_SIZE (atkbd_set2_keycode); - atkbd->dev.event = atkbd_event; - atkbd->dev.private = atkbd; serio->private = atkbd;
@@ -689,58 +821,34 @@return ; } - atkbd->set =atkbd_set_3 (atkbd); -atkbd_enable (atkbd); + atkbd->set =atkbd_select_set (atkbd, atkbd_set, atkbd_extra); +atkbd_activate (atkbd); }else { atkbd->set =2 ; atkbd->id =0xab00 ; } -if (atkbd->extra) { - atkbd->dev.ledbit[0 ] |=BIT (LED_COMPOSE ) |BIT (LED_SUSPEND ) |BIT (LED_SLEEP ) |BIT (LED_MUTE ) |BIT (LED_MISC ); +if (atkbd->extra)sprintf (atkbd->name,"AT Set 2 Extra keyboard" ); - }else +else sprintf (atkbd->name,"AT %s Set %d keyboard" , atkbd->translated ?"Translated" :"Raw" , atkbd->set);sprintf (atkbd->phys,"%s/input0" , serio->phys); -if (atkbd_scroll) { -for (i =0 ; i <5 ; i++) - atkbd_set2_keycode[atkbd_scroll_keys[i][1 ]] = atkbd_scroll_keys[i][0 ]; - atkbd->dev.evbit[0 ] |=BIT (EV_REL ); - atkbd->dev.relbit[0 ] =BIT (REL_WHEEL ); -set_bit (BTN_MIDDLE , atkbd->dev.keybit); - } - -if (atkbd->translated) { -for (i =0 ; i <128 ; i++) { - atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; - atkbd->keycode[i |0x80 ] = atkbd_set2_keycode[atkbd_unxlate_table[i] |0x80 ]; - } - }else if (atkbd->set ==3 ) { -memcpy (atkbd->keycode, atkbd_set3_keycode,sizeof (atkbd->keycode)); - }else { -memcpy (atkbd->keycode, atkbd_set2_keycode,sizeof (atkbd->keycode)); - } - - atkbd->dev.name = atkbd->name; - atkbd->dev.phys = atkbd->phys; - atkbd->dev.id.bustype =BUS_I8042 ; - atkbd->dev.id.vendor =0x0001 ; - atkbd->dev.id.product = atkbd->translated ?1 : atkbd->set; - atkbd->dev.id.version = atkbd->id; - -for (i =0 ; i <512 ; i++) -if (atkbd->keycode[i] && atkbd->keycode[i] <ATKBD_SPECIAL ) -set_bit (atkbd->keycode[i], atkbd->dev.keybit); +atkbd_set_keycode_table (atkbd); +atkbd_set_device_attrs (atkbd);input_register_device (&atkbd->dev); -serio_pause_rx (serio); - atkbd->enabled =1 ; -serio_continue_rx (serio); +device_create_file (&serio->dev, &atkbd_attr_extra); +device_create_file (&serio->dev, &atkbd_attr_scroll); +device_create_file (&serio->dev, &atkbd_attr_set); +device_create_file (&serio->dev, &atkbd_attr_softrepeat); +device_create_file (&serio->dev, &atkbd_attr_softraw); + +atkbd_enable (atkbd);printk (KERN_INFO "input: %s on %s\n" , atkbd->name, serio->phys); }
@@ -756,14 +864,12 @@struct serio_driver *drv = serio->drv;unsigned char param[1 ]; -if (!drv) { +if (!atkbd || !drv) {printk (KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n" );return -1 ; } -serio_pause_rx (serio); - atkbd->enabled =0 ; -serio_continue_rx (serio); +atkbd_disable (atkbd);if (atkbd->write) { param[0 ] = (test_bit (LED_SCROLLL , atkbd->dev.led) ?1 :0 )
@@ -772,18 +878,16 @@if (atkbd_probe (atkbd))return -1 ; -if (atkbd->set !=atkbd_set_3 (atkbd)) +if (atkbd->set !=atkbd_select_set (atkbd, atkbd->set, atkbd->extra))return -1 ; -atkbd_enable (atkbd); +atkbd_activate (atkbd);if (ps2_command (&atkbd->ps2dev, param,ATKBD_CMD_SETLEDS ))return -1 ; } -serio_pause_rx (serio); - atkbd->enabled =1 ; -serio_continue_rx (serio); +atkbd_enable (atkbd);return 0 ; }
@@ -799,6 +903,192 @@ .disconnect = atkbd_disconnect, .cleanup = atkbd_cleanup, }; + +static ssize_t atkbd_attr_show_helper (struct device *dev,char *buf, +ssize_t (*handler)(struct atkbd *,char *)) +{ +struct serio *serio =to_serio_port (dev); +int retval; + + retval =serio_pin_driver (serio); +if (retval) +return retval; + +if (serio->drv != &atkbd_drv) { + retval = -ENODEV ; + goto out; + } + + retval =handler ((struct atkbd *)serio->private, buf); + +out: +serio_unpin_driver (serio); +return retval; +} + +static ssize_t atkbd_attr_set_helper (struct device *dev,const char *buf,size_t count, +int (*handler)(struct atkbd *,const char *,size_t )) +{ +struct serio *serio =to_serio_port (dev); +struct atkbd *atkbd; +int retval; + + retval =serio_pin_driver (serio); +if (retval) +return retval; + +if (serio->drv != &atkbd_drv) { + retval = -ENODEV ; + goto out; + } + + atkbd = serio->private; +atkbd_disable (atkbd); + retval =handler (atkbd, buf, count); +atkbd_enable (atkbd); + +out: +serio_unpin_driver (serio); +return retval; +} + +static ssize_t atkbd_show_extra (struct atkbd *atkbd,char *buf) +{ +return sprintf (buf,"%d\n" , atkbd->extra ?1 :0 ); +} + +static ssize_t atkbd_set_extra (struct atkbd *atkbd,const char *buf,size_t count) +{ +unsigned long value; +char *rest; + +if (!atkbd->write) +return -EIO ; + + value =simple_strtoul (buf, &rest,10 ); +if (*rest || value >1 ) +return -EINVAL ; + +if (atkbd->extra != value) { +/* unregister device as it's properties will change */ +input_unregister_device (&atkbd->dev); + atkbd->set =atkbd_select_set (atkbd, atkbd->set, value); +atkbd_activate (atkbd); +atkbd_set_device_attrs (atkbd); +input_register_device (&atkbd->dev); + } +return count; +} + +static ssize_t atkbd_show_scroll (struct atkbd *atkbd,char *buf) +{ +return sprintf (buf,"%d\n" , atkbd->scroll ?1 :0 ); +} + +static ssize_t atkbd_set_scroll (struct atkbd *atkbd,const char *buf,size_t count) +{ +unsigned long value; +char *rest; + + value =simple_strtoul (buf, &rest,10 ); +if (*rest || value >1 ) +return -EINVAL ; + +if (atkbd->scroll != value) { +/* unregister device as it's properties will change */ +input_unregister_device (&atkbd->dev); + atkbd->scroll = value; +atkbd_set_keycode_table (atkbd); +atkbd_set_device_attrs (atkbd); +input_register_device (&atkbd->dev); + } +return count; +} + +static ssize_t atkbd_show_set (struct atkbd *atkbd,char *buf) +{ +return sprintf (buf,"%d\n" , atkbd->set); +} + +static ssize_t atkbd_set_set (struct atkbd *atkbd,const char *buf,size_t count) +{ +unsigned long value; +char *rest; + +if (!atkbd->write) +return -EIO ; + + value =simple_strtoul (buf, &rest,10 ); +if (*rest || (value !=2 && value !=3 )) +return -EINVAL ; + +if (atkbd->set != value) { +/* unregister device as it's properties will change */ +input_unregister_device (&atkbd->dev); + atkbd->set =atkbd_select_set (atkbd, value, atkbd->extra); +atkbd_activate (atkbd); +atkbd_set_keycode_table (atkbd); +atkbd_set_device_attrs (atkbd); +input_register_device (&atkbd->dev); + } +return count; +} + +static ssize_t atkbd_show_softrepeat (struct atkbd *atkbd,char *buf) +{ +return sprintf (buf,"%d\n" , atkbd->softrepeat ?1 :0 ); +} + +static ssize_t atkbd_set_softrepeat (struct atkbd *atkbd,const char *buf,size_t count) +{ +unsigned long value; +char *rest; + +if (!atkbd->write) +return -EIO ; + + value =simple_strtoul (buf, &rest,10 ); +if (*rest || value >1 ) +return -EINVAL ; + +if (atkbd->softrepeat != value) { +/* unregister device as it's properties will change */ +input_unregister_device (&atkbd->dev); + atkbd->softrepeat = value; +if (atkbd->softrepeat) + atkbd->softraw =1 ; +atkbd_set_device_attrs (atkbd); +input_register_device (&atkbd->dev); + } + +return count; +} + + +static ssize_t atkbd_show_softraw (struct atkbd *atkbd,char *buf) +{ +return sprintf (buf,"%d\n" , atkbd->softraw ?1 :0 ); +} + +static ssize_t atkbd_set_softraw (struct atkbd *atkbd,const char *buf,size_t count) +{ +unsigned long value; +char *rest; + + value =simple_strtoul (buf, &rest,10 ); +if (*rest || value >1 ) +return -EINVAL ; + +if (atkbd->softraw != value) { +/* unregister device as it's properties will change */ +input_unregister_device (&atkbd->dev); + atkbd->softraw = value; +atkbd_set_device_attrs (atkbd); +input_register_device (&atkbd->dev); + } +return count; +} +int __init atkbd_init (void ) {
Quoted 8 lines · Dmitry Torokhov
Hi Vojtech,
I have some more input patches that I would like you to review:
01-libps2.patch
- move common code from atkbd and psmouse into one place, create ps2dev structure that should be used to build drivers for hardware attached to a PS/2 port.
Very nice.
Quoted 7 lines
I think that command processing is now race free - instead of using bit operations on flags the
ps2_commandandps2_send_bytesimply takeserio->lock(via serio_pause/continue_rx). Sinceserio->lockis also taken by interrupt handler anyway it gives us desired serialization. As wakeup routines take a spinlock as well and spinlock is guaranteed to be a barrier we should not miss wake up events either.
I hope the wait_event* functions also use memory barriers properly, but they probably must, otherwise they won't be useful, because there we're accessing the flags variable without a lock.
Quoted 5 lines
02-serio-pin-driver.patch
- Adddrv_semto serio structure and implement serio_[un]pin_driver() functions. The main purpose is to pin a driver bound to serio port when accessing driver's data from sysfs attribute handler; otherwise other thread could unbind/unload driver in a middle of processing.
This one looks fine.
Quoted 4 lines
03-atkbd-sysfs-attr.patch
- Export extra, scroll, set, softrepeat and softraw atkbd properties via sysfs and allow them to be controlled at run time, independently for each keyboard.
This bit looks wrong in the patch:
- input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
+ if (atkbd->softraw)
+ input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
... we definitely want the RAW codes to be sent when we're not in softraw mode, because that's when they're passed through keyboard.c to the console.
So the condition needs to be inverted. However, it's not necessary at all, since the input layer will not pass the RAW events when the MSC_RAW bit is not set.
Quoted 2 lines
Now that Linus pulled all pending changes the patches should apply cleanly to all trees (his, yours and Andrew's).
Great.
Quoted 1 line
Please let me know if they are ok and I will push them into my bkbits tree.
I think they're fine except for the above minor bug.
Signature · 2 lines
Vojtech Pavlik SuSE Labs, SuSE CR
Quoted 9 lines · Vojtech Pavlik
Quoted 7 lines · Dmitry Torokhov
I think that command processing is now race free - instead of using bit operations on flags the
ps2_commandandps2_send_bytesimply takeserio->lock(via serio_pause/continue_rx). Sinceserio->lockis also taken by interrupt handler anyway it gives us desired serialization. As wakeup routines take a spinlock as well and spinlock is guaranteed to be a barrier we should not miss wake up events either.
Quoted 3 lines
I hope the wait_event* functions also use memory barriers properly, but they probably must, otherwise they won't be useful, because there we're accessing the flags variable without a lock.
prepare_to_wait does spin_lock/spin_unlock on when adding a task to a wait queue and (I hope someone corrects me if I'm wrong) spin lock/unlock are guaranteed to be memory barriers.
Quoted 11 lines
(quoted diff) +2
-1- input_event(&atkbd->dev, EV_MSC, MSC_RAW, code); + if (atkbd->softraw) + input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);... we definitely want the RAW codes to be sent when we're not in softraw mode, because that's when they're passed through
keyboard.cto the console.So the condition needs to be inverted. However, it's not necessary at all, since the input layer will not pass the RAW events when the
MSC_RAWbit is not set.
I see, my bad. I will drop that bit.
Thanks for the comments!
Signature · 1 line
Dmitry
Quoted 10 lines · Dmitry Torokhov
Quoted 3 lines · Vojtech Pavlik
So the condition needs to be inverted. However, it's not necessary at all, since the input layer will not pass the RAW events when the
MSC_RAWbit is not set.I see, my bad. I will drop that bit.
Thanks for the comments!
Vojtech,
I have fixed the aforementioned bug and re-diffed the patches against your latest tree. Please do:
bk pull bk://dtor.bkbits.net/input
Thanks!
Signature · 1 line
Dmitry
Quoted 12 lines · Dmitry Torokhov
Quoted 10 lines · Dmitry Torokhov
Quoted 3 lines · Vojtech Pavlik
So the condition needs to be inverted. However, it's not necessary at all, since the input layer will not pass the RAW events when the
MSC_RAWbit is not set.I see, my bad. I will drop that bit.
Thanks for the comments!
Quoted 8 lines
Vojtech,
I have fixed the aforementioned bug and re-diffed the patches against your latest tree. Please do:
bk pull bk://dtor.bkbits.net/input
Thanks!
Done.
Signature · 2 lines
Vojtech Pavlik SuSE Labs, SuSE CR