Loading drivers/misc/eeepc-laptop.c +209 −19 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <acpi/acpi_drivers.h> #include <acpi/acpi_bus.h> #include <linux/uaccess.h> #include <linux/input.h> #include <linux/rfkill.h> #define EEEPC_LAPTOP_VERSION "0.1" Loading Loading @@ -125,6 +127,10 @@ struct eeepc_hotk { by this BIOS */ uint init_flag; /* Init flags */ u16 event_count[128]; /* count for each event */ struct input_dev *inputdev; u16 *keycode_map; struct rfkill *eeepc_wlan_rfkill; struct rfkill *eeepc_bluetooth_rfkill; }; /* The actual device the driver binds to */ Loading @@ -140,6 +146,27 @@ static struct platform_driver platform_driver = { static struct platform_device *platform_device; struct key_entry { char type; u8 code; u16 keycode; }; enum { KE_KEY, KE_END }; static struct key_entry eeepc_keymap[] = { /* Sleep already handled via generic ACPI code */ {KE_KEY, 0x10, KEY_WLAN }, {KE_KEY, 0x12, KEY_PROG1 }, {KE_KEY, 0x13, KEY_MUTE }, {KE_KEY, 0x14, KEY_VOLUMEDOWN }, {KE_KEY, 0x15, KEY_VOLUMEUP }, {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, {KE_END, 0}, }; /* * The hotkey driver declaration */ Loading Loading @@ -260,6 +287,44 @@ static int update_bl_status(struct backlight_device *bd) return set_brightness(bd, bd->props.brightness); } /* * Rfkill helpers */ static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state) { if (state == RFKILL_STATE_SOFT_BLOCKED) return set_acpi(CM_ASL_WLAN, 0); else return set_acpi(CM_ASL_WLAN, 1); } static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state) { if (get_acpi(CM_ASL_WLAN) == 1) *state = RFKILL_STATE_UNBLOCKED; else *state = RFKILL_STATE_SOFT_BLOCKED; return 0; } static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state) { if (state == RFKILL_STATE_SOFT_BLOCKED) return set_acpi(CM_ASL_BLUETOOTH, 0); else return set_acpi(CM_ASL_BLUETOOTH, 1); } static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state) { if (get_acpi(CM_ASL_BLUETOOTH) == 1) *state = RFKILL_STATE_UNBLOCKED; else *state = RFKILL_STATE_SOFT_BLOCKED; return 0; } /* * Sys helpers */ Loading Loading @@ -311,13 +376,11 @@ static ssize_t show_sys_acpi(int cm, char *buf) EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN); static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_disp.attr, &dev_attr_wlan.attr, NULL }; Loading @@ -328,8 +391,64 @@ static struct attribute_group platform_attribute_group = { /* * Hotkey functions */ static struct key_entry *eepc_get_entry_by_scancode(int code) { struct key_entry *key; for (key = eeepc_keymap; key->type != KE_END; key++) if (code == key->code) return key; return NULL; } static struct key_entry *eepc_get_entry_by_keycode(int code) { struct key_entry *key; for (key = eeepc_keymap; key->type != KE_END; key++) if (code == key->keycode && key->type == KE_KEY) return key; return NULL; } static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) { struct key_entry *key = eepc_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { *keycode = key->keycode; return 0; } return -EINVAL; } static int eeepc_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 = eepc_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { old_keycode = key->keycode; key->keycode = keycode; set_bit(keycode, dev->keybit); if (!eepc_get_entry_by_keycode(old_keycode)) clear_bit(old_keycode, dev->keybit); return 0; } return -EINVAL; } static int eeepc_hotk_check(void) { const struct key_entry *key; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; int result; Loading @@ -356,6 +475,31 @@ static int eeepc_hotk_check(void) "Get control methods supported: 0x%x\n", ehotk->cm_supported); } ehotk->inputdev = input_allocate_device(); if (!ehotk->inputdev) { printk(EEEPC_INFO "Unable to allocate input device\n"); return 0; } ehotk->inputdev->name = "Asus EeePC extra buttons"; ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; ehotk->inputdev->id.bustype = BUS_HOST; ehotk->inputdev->getkeycode = eeepc_getkeycode; ehotk->inputdev->setkeycode = eeepc_setkeycode; for (key = eeepc_keymap; key->type != KE_END; key++) { switch (key->type) { case KE_KEY: set_bit(EV_KEY, ehotk->inputdev->evbit); set_bit(key->keycode, ehotk->inputdev->keybit); break; } } result = input_register_device(ehotk->inputdev); if (result) { printk(EEEPC_INFO "Unable to register input device\n"); input_free_device(ehotk->inputdev); return 0; } } else { printk(EEEPC_ERR "Hotkey device not present, aborting\n"); return -EINVAL; Loading @@ -363,21 +507,6 @@ static int eeepc_hotk_check(void) return 0; } static void notify_wlan(u32 *event) { /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2 will always be 0x10 */ if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) { const char *method = cm_getv[CM_ASL_WLAN]; int value; if (read_acpi_int(ehotk->handle, method, &value)) printk(EEEPC_WARNING "Error reading %s\n", method); else if (value == 1) *event = 0x11; } } static void notify_brn(void) { struct backlight_device *bd = eeepc_backlight_device; Loading @@ -386,14 +515,28 @@ static void notify_brn(void) static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; if (!ehotk) return; if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) notify_wlan(&event); if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); acpi_bus_generate_proc_event(ehotk->device, event, ehotk->event_count[event % 128]++); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { switch (key->type) { case KE_KEY: input_report_key(ehotk->inputdev, key->keycode, 1); input_sync(ehotk->inputdev); input_report_key(ehotk->inputdev, key->keycode, 0); input_sync(ehotk->inputdev); break; } } } } static int eeepc_hotk_add(struct acpi_device *device) Loading @@ -420,6 +563,47 @@ static int eeepc_hotk_add(struct acpi_device *device) eeepc_hotk_notify, ehotk); if (ACPI_FAILURE(status)) printk(EEEPC_ERR "Error installing notify handler\n"); if (get_acpi(CM_ASL_WLAN) != -1) { ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); if (!ehotk->eeepc_wlan_rfkill) goto end; ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; if (get_acpi(CM_ASL_WLAN) == 1) ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_UNBLOCKED; else ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; rfkill_register(ehotk->eeepc_wlan_rfkill); } if (get_acpi(CM_ASL_BLUETOOTH) != -1) { ehotk->eeepc_bluetooth_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); if (!ehotk->eeepc_bluetooth_rfkill) goto end; ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; ehotk->eeepc_bluetooth_rfkill->toggle_radio = eeepc_bluetooth_rfkill_set; ehotk->eeepc_bluetooth_rfkill->get_state = eeepc_bluetooth_rfkill_state; if (get_acpi(CM_ASL_BLUETOOTH) == 1) ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_UNBLOCKED; else ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; rfkill_register(ehotk->eeepc_bluetooth_rfkill); } end: if (result) { kfree(ehotk); Loading Loading @@ -553,6 +737,12 @@ static void eeepc_backlight_exit(void) { if (eeepc_backlight_device) backlight_device_unregister(eeepc_backlight_device); if (ehotk->inputdev) input_unregister_device(ehotk->inputdev); if (ehotk->eeepc_wlan_rfkill) rfkill_unregister(ehotk->eeepc_wlan_rfkill); if (ehotk->eeepc_bluetooth_rfkill) rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); eeepc_backlight_device = NULL; } Loading Loading
drivers/misc/eeepc-laptop.c +209 −19 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ #include <acpi/acpi_drivers.h> #include <acpi/acpi_bus.h> #include <linux/uaccess.h> #include <linux/input.h> #include <linux/rfkill.h> #define EEEPC_LAPTOP_VERSION "0.1" Loading Loading @@ -125,6 +127,10 @@ struct eeepc_hotk { by this BIOS */ uint init_flag; /* Init flags */ u16 event_count[128]; /* count for each event */ struct input_dev *inputdev; u16 *keycode_map; struct rfkill *eeepc_wlan_rfkill; struct rfkill *eeepc_bluetooth_rfkill; }; /* The actual device the driver binds to */ Loading @@ -140,6 +146,27 @@ static struct platform_driver platform_driver = { static struct platform_device *platform_device; struct key_entry { char type; u8 code; u16 keycode; }; enum { KE_KEY, KE_END }; static struct key_entry eeepc_keymap[] = { /* Sleep already handled via generic ACPI code */ {KE_KEY, 0x10, KEY_WLAN }, {KE_KEY, 0x12, KEY_PROG1 }, {KE_KEY, 0x13, KEY_MUTE }, {KE_KEY, 0x14, KEY_VOLUMEDOWN }, {KE_KEY, 0x15, KEY_VOLUMEUP }, {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, {KE_END, 0}, }; /* * The hotkey driver declaration */ Loading Loading @@ -260,6 +287,44 @@ static int update_bl_status(struct backlight_device *bd) return set_brightness(bd, bd->props.brightness); } /* * Rfkill helpers */ static int eeepc_wlan_rfkill_set(void *data, enum rfkill_state state) { if (state == RFKILL_STATE_SOFT_BLOCKED) return set_acpi(CM_ASL_WLAN, 0); else return set_acpi(CM_ASL_WLAN, 1); } static int eeepc_wlan_rfkill_state(void *data, enum rfkill_state *state) { if (get_acpi(CM_ASL_WLAN) == 1) *state = RFKILL_STATE_UNBLOCKED; else *state = RFKILL_STATE_SOFT_BLOCKED; return 0; } static int eeepc_bluetooth_rfkill_set(void *data, enum rfkill_state state) { if (state == RFKILL_STATE_SOFT_BLOCKED) return set_acpi(CM_ASL_BLUETOOTH, 0); else return set_acpi(CM_ASL_BLUETOOTH, 1); } static int eeepc_bluetooth_rfkill_state(void *data, enum rfkill_state *state) { if (get_acpi(CM_ASL_BLUETOOTH) == 1) *state = RFKILL_STATE_UNBLOCKED; else *state = RFKILL_STATE_SOFT_BLOCKED; return 0; } /* * Sys helpers */ Loading Loading @@ -311,13 +376,11 @@ static ssize_t show_sys_acpi(int cm, char *buf) EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN); static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_disp.attr, &dev_attr_wlan.attr, NULL }; Loading @@ -328,8 +391,64 @@ static struct attribute_group platform_attribute_group = { /* * Hotkey functions */ static struct key_entry *eepc_get_entry_by_scancode(int code) { struct key_entry *key; for (key = eeepc_keymap; key->type != KE_END; key++) if (code == key->code) return key; return NULL; } static struct key_entry *eepc_get_entry_by_keycode(int code) { struct key_entry *key; for (key = eeepc_keymap; key->type != KE_END; key++) if (code == key->keycode && key->type == KE_KEY) return key; return NULL; } static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) { struct key_entry *key = eepc_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { *keycode = key->keycode; return 0; } return -EINVAL; } static int eeepc_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 = eepc_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { old_keycode = key->keycode; key->keycode = keycode; set_bit(keycode, dev->keybit); if (!eepc_get_entry_by_keycode(old_keycode)) clear_bit(old_keycode, dev->keybit); return 0; } return -EINVAL; } static int eeepc_hotk_check(void) { const struct key_entry *key; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; int result; Loading @@ -356,6 +475,31 @@ static int eeepc_hotk_check(void) "Get control methods supported: 0x%x\n", ehotk->cm_supported); } ehotk->inputdev = input_allocate_device(); if (!ehotk->inputdev) { printk(EEEPC_INFO "Unable to allocate input device\n"); return 0; } ehotk->inputdev->name = "Asus EeePC extra buttons"; ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; ehotk->inputdev->id.bustype = BUS_HOST; ehotk->inputdev->getkeycode = eeepc_getkeycode; ehotk->inputdev->setkeycode = eeepc_setkeycode; for (key = eeepc_keymap; key->type != KE_END; key++) { switch (key->type) { case KE_KEY: set_bit(EV_KEY, ehotk->inputdev->evbit); set_bit(key->keycode, ehotk->inputdev->keybit); break; } } result = input_register_device(ehotk->inputdev); if (result) { printk(EEEPC_INFO "Unable to register input device\n"); input_free_device(ehotk->inputdev); return 0; } } else { printk(EEEPC_ERR "Hotkey device not present, aborting\n"); return -EINVAL; Loading @@ -363,21 +507,6 @@ static int eeepc_hotk_check(void) return 0; } static void notify_wlan(u32 *event) { /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2 will always be 0x10 */ if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) { const char *method = cm_getv[CM_ASL_WLAN]; int value; if (read_acpi_int(ehotk->handle, method, &value)) printk(EEEPC_WARNING "Error reading %s\n", method); else if (value == 1) *event = 0x11; } } static void notify_brn(void) { struct backlight_device *bd = eeepc_backlight_device; Loading @@ -386,14 +515,28 @@ static void notify_brn(void) static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; if (!ehotk) return; if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) notify_wlan(&event); if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); acpi_bus_generate_proc_event(ehotk->device, event, ehotk->event_count[event % 128]++); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { switch (key->type) { case KE_KEY: input_report_key(ehotk->inputdev, key->keycode, 1); input_sync(ehotk->inputdev); input_report_key(ehotk->inputdev, key->keycode, 0); input_sync(ehotk->inputdev); break; } } } } static int eeepc_hotk_add(struct acpi_device *device) Loading @@ -420,6 +563,47 @@ static int eeepc_hotk_add(struct acpi_device *device) eeepc_hotk_notify, ehotk); if (ACPI_FAILURE(status)) printk(EEEPC_ERR "Error installing notify handler\n"); if (get_acpi(CM_ASL_WLAN) != -1) { ehotk->eeepc_wlan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); if (!ehotk->eeepc_wlan_rfkill) goto end; ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; if (get_acpi(CM_ASL_WLAN) == 1) ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_UNBLOCKED; else ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; rfkill_register(ehotk->eeepc_wlan_rfkill); } if (get_acpi(CM_ASL_BLUETOOTH) != -1) { ehotk->eeepc_bluetooth_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); if (!ehotk->eeepc_bluetooth_rfkill) goto end; ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; ehotk->eeepc_bluetooth_rfkill->toggle_radio = eeepc_bluetooth_rfkill_set; ehotk->eeepc_bluetooth_rfkill->get_state = eeepc_bluetooth_rfkill_state; if (get_acpi(CM_ASL_BLUETOOTH) == 1) ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_UNBLOCKED; else ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; rfkill_register(ehotk->eeepc_bluetooth_rfkill); } end: if (result) { kfree(ehotk); Loading Loading @@ -553,6 +737,12 @@ static void eeepc_backlight_exit(void) { if (eeepc_backlight_device) backlight_device_unregister(eeepc_backlight_device); if (ehotk->inputdev) input_unregister_device(ehotk->inputdev); if (ehotk->eeepc_wlan_rfkill) rfkill_unregister(ehotk->eeepc_wlan_rfkill); if (ehotk->eeepc_bluetooth_rfkill) rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); eeepc_backlight_device = NULL; } Loading