Input: wistron_btns - switch to using sparse keymap library

The keymap manipulation code was split into a library module,
so let's make us of it.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
Dmitry Torokhov 2009-12-04 10:22:24 -08:00
parent 36203c4f3d
commit e97af4cbbe
2 changed files with 46 additions and 135 deletions

View file

@ -80,6 +80,7 @@ config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface" tristate "x86 Wistron laptop button interface"
depends on X86 && !X86_64 depends on X86 && !X86_64
select INPUT_POLLDEV select INPUT_POLLDEV
select INPUT_SPARSEKMAP
select NEW_LEDS select NEW_LEDS
select LEDS_CLASS select LEDS_CLASS
select CHECK_SIGNATURE select CHECK_SIGNATURE

View file

@ -21,6 +21,7 @@
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/input-polldev.h> #include <linux/input-polldev.h>
#include <linux/input/sparse-keymap.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -224,19 +225,8 @@ static void bios_set_state(u8 subsys, int enable)
/* Hardware database */ /* Hardware database */
struct key_entry { #define KE_WIFI (KE_LAST + 1)
char type; /* See KE_* below */ #define KE_BLUETOOTH (KE_LAST + 2)
u8 code;
union {
u16 keycode; /* For KE_KEY */
struct { /* For KE_SW */
u8 code;
u8 value;
} sw;
};
};
enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
#define FE_MAIL_LED 0x01 #define FE_MAIL_LED 0x01
#define FE_WIFI_LED 0x02 #define FE_WIFI_LED 0x02
@ -1037,21 +1027,6 @@ static unsigned long jiffies_last_press;
static bool wifi_enabled; static bool wifi_enabled;
static bool bluetooth_enabled; static bool bluetooth_enabled;
static void report_key(struct input_dev *dev, unsigned int keycode)
{
input_report_key(dev, keycode, 1);
input_sync(dev);
input_report_key(dev, keycode, 0);
input_sync(dev);
}
static void report_switch(struct input_dev *dev, unsigned int code, int value)
{
input_report_switch(dev, code, value);
input_sync(dev);
}
/* led management */ /* led management */
static void wistron_mail_led_set(struct led_classdev *led_cdev, static void wistron_mail_led_set(struct led_classdev *led_cdev,
enum led_brightness value) enum led_brightness value)
@ -1128,43 +1103,13 @@ static inline void wistron_led_resume(void)
led_classdev_resume(&wistron_wifi_led); led_classdev_resume(&wistron_wifi_led);
} }
static struct key_entry *wistron_get_entry_by_scancode(int code)
{
struct key_entry *key;
for (key = keymap; key->type != KE_END; key++)
if (code == key->code)
return key;
return NULL;
}
static struct key_entry *wistron_get_entry_by_keycode(int keycode)
{
struct key_entry *key;
for (key = keymap; key->type != KE_END; key++)
if (key->type == KE_KEY && keycode == key->keycode)
return key;
return NULL;
}
static void handle_key(u8 code) static void handle_key(u8 code)
{ {
const struct key_entry *key = wistron_get_entry_by_scancode(code); const struct key_entry *key =
sparse_keymap_entry_from_scancode(wistron_idev->input, code);
if (key) { if (key) {
switch (key->type) { switch (key->type) {
case KE_KEY:
report_key(wistron_idev->input, key->keycode);
break;
case KE_SW:
report_switch(wistron_idev->input,
key->sw.code, key->sw.value);
break;
case KE_WIFI: case KE_WIFI:
if (have_wifi) { if (have_wifi) {
wifi_enabled = !wifi_enabled; wifi_enabled = !wifi_enabled;
@ -1180,7 +1125,9 @@ static void handle_key(u8 code)
break; break;
default: default:
BUG(); sparse_keymap_report_entry(wistron_idev->input,
key, 1, true);
break;
} }
jiffies_last_press = jiffies; jiffies_last_press = jiffies;
} else } else
@ -1220,42 +1167,39 @@ static void wistron_poll(struct input_polled_dev *dev)
dev->poll_interval = POLL_INTERVAL_DEFAULT; dev->poll_interval = POLL_INTERVAL_DEFAULT;
} }
static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode) static int __devinit wistron_setup_keymap(struct input_dev *dev,
struct key_entry *entry)
{ {
const struct key_entry *key = wistron_get_entry_by_scancode(scancode); switch (entry->type) {
if (key && key->type == KE_KEY) { /* if wifi or bluetooth are not available, create normal keys */
*keycode = key->keycode; case KE_WIFI:
return 0; if (!have_wifi) {
entry->type = KE_KEY;
entry->keycode = KEY_WLAN;
}
break;
case KE_BLUETOOTH:
if (!have_bluetooth) {
entry->type = KE_KEY;
entry->keycode = KEY_BLUETOOTH;
}
break;
case KE_END:
if (entry->code & FE_UNTESTED)
printk(KERN_WARNING "Untested laptop multimedia keys, "
"please report success or failure to "
"eric.piel@tremplin-utc.net\n");
break;
} }
return -EINVAL; return 0;
}
static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
{
struct key_entry *key;
int old_keycode;
if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;
key = wistron_get_entry_by_scancode(scancode);
if (key && key->type == KE_KEY) {
old_keycode = key->keycode;
key->keycode = keycode;
set_bit(keycode, dev->keybit);
if (!wistron_get_entry_by_keycode(old_keycode))
clear_bit(old_keycode, dev->keybit);
return 0;
}
return -EINVAL;
} }
static int __devinit setup_input_dev(void) static int __devinit setup_input_dev(void)
{ {
struct key_entry *key;
struct input_dev *input_dev; struct input_dev *input_dev;
int error; int error;
@ -1273,56 +1217,21 @@ static int __devinit setup_input_dev(void)
input_dev->id.bustype = BUS_HOST; input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &wistron_device->dev; input_dev->dev.parent = &wistron_device->dev;
input_dev->getkeycode = wistron_getkeycode; error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
input_dev->setkeycode = wistron_setkeycode; if (error)
goto err_free_dev;
for (key = keymap; key->type != KE_END; key++) {
switch (key->type) {
case KE_KEY:
set_bit(EV_KEY, input_dev->evbit);
set_bit(key->keycode, input_dev->keybit);
break;
case KE_SW:
set_bit(EV_SW, input_dev->evbit);
set_bit(key->sw.code, input_dev->swbit);
break;
/* if wifi or bluetooth are not available, create normal keys */
case KE_WIFI:
if (!have_wifi) {
key->type = KE_KEY;
key->keycode = KEY_WLAN;
key--;
}
break;
case KE_BLUETOOTH:
if (!have_bluetooth) {
key->type = KE_KEY;
key->keycode = KEY_BLUETOOTH;
key--;
}
break;
default:
break;
}
}
/* reads information flags on KE_END */
if (key->code & FE_UNTESTED)
printk(KERN_WARNING "Untested laptop multimedia keys, "
"please report success or failure to eric.piel"
"@tremplin-utc.net\n");
error = input_register_polled_device(wistron_idev); error = input_register_polled_device(wistron_idev);
if (error) { if (error)
input_free_polled_device(wistron_idev); goto err_free_keymap;
return error;
}
return 0; return 0;
err_free_keymap:
sparse_keymap_free(input_dev);
err_free_dev:
input_free_polled_device(wistron_idev);
return error;
} }
/* Driver core */ /* Driver core */
@ -1371,6 +1280,7 @@ static int __devexit wistron_remove(struct platform_device *dev)
{ {
wistron_led_remove(); wistron_led_remove();
input_unregister_polled_device(wistron_idev); input_unregister_polled_device(wistron_idev);
sparse_keymap_free(wistron_idev->input);
input_free_polled_device(wistron_idev); input_free_polled_device(wistron_idev);
bios_detach(); bios_detach();