aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/thinkpad_acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
-rw-r--r--drivers/misc/thinkpad_acpi.c108
1 files changed, 104 insertions, 4 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 4427c994bc7d..5c1bea1a6c37 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -730,7 +730,31 @@ static struct ibm_struct thinkpad_acpi_driver_data = {
730static int hotkey_orig_status; 730static int hotkey_orig_status;
731static u32 hotkey_orig_mask; 731static u32 hotkey_orig_mask;
732static u32 hotkey_all_mask; 732static u32 hotkey_all_mask;
733static u32 hotkey_reserved_mask = 0x00778000; 733static u32 hotkey_reserved_mask;
734
735static u16 hotkey_keycode_map[] = {
736 /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */
737 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
738 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
739 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
740 /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */
741 KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */
742 KEY_UNKNOWN, /* 0x0D: FN+INSERT */
743 KEY_UNKNOWN, /* 0x0E: FN+DELETE */
744 KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */
745 /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */
746 KEY_RESERVED, /* 0x10: FN+END (brightness down) */
747 KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */
748 KEY_UNKNOWN, /* 0x12: FN+PGDOWN */
749 KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */
750 KEY_RESERVED, /* 0x14: VOLUME UP */
751 KEY_RESERVED, /* 0x15: VOLUME DOWN */
752 KEY_RESERVED, /* 0x16: MUTE */
753 KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */
754 /* (assignments unknown, please report if found) */
755 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
756 KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
757};
734 758
735static struct attribute_set *hotkey_dev_attributes; 759static struct attribute_set *hotkey_dev_attributes;
736 760
@@ -889,11 +913,13 @@ static struct attribute *hotkey_mask_attributes[] = {
889 913
890static int __init hotkey_init(struct ibm_init_struct *iibm) 914static int __init hotkey_init(struct ibm_init_struct *iibm)
891{ 915{
892 int res; 916 int res, i;
893 int status; 917 int status;
894 918
895 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 919 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
896 920
921 BUG_ON(!tpacpi_inputdev);
922
897 IBM_ACPIHANDLE_INIT(hkey); 923 IBM_ACPIHANDLE_INIT(hkey);
898 mutex_init(&hotkey_mutex); 924 mutex_init(&hotkey_mutex);
899 925
@@ -950,6 +976,23 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
950 &tpacpi_pdev->dev.kobj); 976 &tpacpi_pdev->dev.kobj);
951 if (res) 977 if (res)
952 return res; 978 return res;
979
980 set_bit(EV_KEY, tpacpi_inputdev->evbit);
981 set_bit(EV_MSC, tpacpi_inputdev->evbit);
982 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
983 tpacpi_inputdev->keycodesize = sizeof(hotkey_keycode_map[0]);
984 tpacpi_inputdev->keycodemax = ARRAY_SIZE(hotkey_keycode_map);
985 tpacpi_inputdev->keycode = &hotkey_keycode_map;
986 for (i = 0; i < ARRAY_SIZE(hotkey_keycode_map); i++) {
987 if (hotkey_keycode_map[i] != KEY_RESERVED) {
988 set_bit(hotkey_keycode_map[i],
989 tpacpi_inputdev->keybit);
990 } else {
991 if (i < sizeof(hotkey_reserved_mask)*8)
992 hotkey_reserved_mask |= 1 << i;
993 }
994 }
995
953 } 996 }
954 997
955 return (tp_features.hotkey)? 0 : 1; 998 return (tp_features.hotkey)? 0 : 1;
@@ -972,12 +1015,69 @@ static void hotkey_exit(void)
972 } 1015 }
973} 1016}
974 1017
1018static void tpacpi_input_send_key(unsigned int scancode,
1019 unsigned int keycode)
1020{
1021 if (keycode != KEY_RESERVED) {
1022 input_report_key(tpacpi_inputdev, keycode, 1);
1023 if (keycode == KEY_UNKNOWN)
1024 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1025 scancode);
1026 input_sync(tpacpi_inputdev);
1027
1028 input_report_key(tpacpi_inputdev, keycode, 0);
1029 if (keycode == KEY_UNKNOWN)
1030 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1031 scancode);
1032 input_sync(tpacpi_inputdev);
1033 }
1034}
1035
975static void hotkey_notify(struct ibm_struct *ibm, u32 event) 1036static void hotkey_notify(struct ibm_struct *ibm, u32 event)
976{ 1037{
977 int hkey; 1038 u32 hkey;
1039 unsigned int keycode, scancode;
1040 int sendacpi = 1;
978 1041
979 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { 1042 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
980 acpi_bus_generate_event(ibm->acpi->device, event, hkey); 1043 if (tpacpi_inputdev->users > 0) {
1044 switch (hkey >> 12) {
1045 case 1:
1046 /* 0x1000-0x1FFF: key presses */
1047 scancode = hkey & 0xfff;
1048 if (scancode > 0 && scancode < 0x21) {
1049 scancode--;
1050 keycode = hotkey_keycode_map[scancode];
1051 tpacpi_input_send_key(scancode, keycode);
1052 sendacpi = (keycode == KEY_RESERVED
1053 || keycode == KEY_UNKNOWN);
1054 } else {
1055 printk(IBM_ERR
1056 "hotkey 0x%04x out of range for keyboard map\n",
1057 hkey);
1058 }
1059 break;
1060 case 5:
1061 /* 0x5000-0x5FFF: LID */
1062 /* we don't handle it through this path, just
1063 * eat up known LID events */
1064 if (hkey != 0x5001 && hkey != 0x5002) {
1065 printk(IBM_ERR
1066 "unknown LID-related hotkey event: 0x%04x\n",
1067 hkey);
1068 }
1069 break;
1070 default:
1071 /* case 2: dock-related */
1072 /* 0x2305 - T43 waking up due to bay lever eject while aslept */
1073 /* case 3: ultra-bay related. maybe bay in dock? */
1074 /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */
1075 printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey);
1076 }
1077 }
1078
1079 if (sendacpi)
1080 acpi_bus_generate_event(ibm->acpi->device, event, hkey);
981 } else { 1081 } else {
982 printk(IBM_ERR "unknown hotkey notification event %d\n", event); 1082 printk(IBM_ERR "unknown hotkey notification event %d\n", event);
983 acpi_bus_generate_event(ibm->acpi->device, event, 0); 1083 acpi_bus_generate_event(ibm->acpi->device, event, 0);