diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/mouse/psmouse-base.c | 164 |
1 files changed, 86 insertions, 78 deletions
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 131bbc1bd446..316105e30064 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -767,6 +767,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
767 | .type = PSMOUSE_LIFEBOOK, | 767 | .type = PSMOUSE_LIFEBOOK, |
768 | .name = "LBPS/2", | 768 | .name = "LBPS/2", |
769 | .alias = "lifebook", | 769 | .alias = "lifebook", |
770 | .detect = lifebook_detect, | ||
770 | .init = lifebook_init, | 771 | .init = lifebook_init, |
771 | }, | 772 | }, |
772 | #endif | 773 | #endif |
@@ -844,7 +845,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
844 | }, | 845 | }, |
845 | }; | 846 | }; |
846 | 847 | ||
847 | static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) | 848 | static const struct psmouse_protocol *__psmouse_protocol_by_type(enum psmouse_type type) |
848 | { | 849 | { |
849 | int i; | 850 | int i; |
850 | 851 | ||
@@ -852,6 +853,17 @@ static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type | |||
852 | if (psmouse_protocols[i].type == type) | 853 | if (psmouse_protocols[i].type == type) |
853 | return &psmouse_protocols[i]; | 854 | return &psmouse_protocols[i]; |
854 | 855 | ||
856 | return NULL; | ||
857 | } | ||
858 | |||
859 | static const struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) | ||
860 | { | ||
861 | const struct psmouse_protocol *proto; | ||
862 | |||
863 | proto = __psmouse_protocol_by_type(type); | ||
864 | if (proto) | ||
865 | return proto; | ||
866 | |||
855 | WARN_ON(1); | 867 | WARN_ON(1); |
856 | return &psmouse_protocols[0]; | 868 | return &psmouse_protocols[0]; |
857 | } | 869 | } |
@@ -910,18 +922,37 @@ static void psmouse_apply_defaults(struct psmouse *psmouse) | |||
910 | psmouse->pt_deactivate = NULL; | 922 | psmouse->pt_deactivate = NULL; |
911 | } | 923 | } |
912 | 924 | ||
913 | /* | 925 | static bool psmouse_try_protocol(struct psmouse *psmouse, |
914 | * Apply default settings to the psmouse structure and call specified | 926 | enum psmouse_type type, |
915 | * protocol detection or initialization routine. | 927 | unsigned int *max_proto, |
916 | */ | 928 | bool set_properties, bool init_allowed) |
917 | static int psmouse_do_detect(int (*detect)(struct psmouse *psmouse, | ||
918 | bool set_properties), | ||
919 | struct psmouse *psmouse, bool set_properties) | ||
920 | { | 929 | { |
930 | const struct psmouse_protocol *proto; | ||
931 | |||
932 | proto = __psmouse_protocol_by_type(type); | ||
933 | if (!proto) | ||
934 | return false; | ||
935 | |||
921 | if (set_properties) | 936 | if (set_properties) |
922 | psmouse_apply_defaults(psmouse); | 937 | psmouse_apply_defaults(psmouse); |
923 | 938 | ||
924 | return detect(psmouse, set_properties); | 939 | if (proto->detect(psmouse, set_properties) != 0) |
940 | return false; | ||
941 | |||
942 | if (set_properties && proto->init && init_allowed) { | ||
943 | if (proto->init(psmouse) != 0) { | ||
944 | /* | ||
945 | * We detected device, but init failed. Adjust | ||
946 | * max_proto so we only try standard protocols. | ||
947 | */ | ||
948 | if (*max_proto > PSMOUSE_IMEX) | ||
949 | *max_proto = PSMOUSE_IMEX; | ||
950 | |||
951 | return false; | ||
952 | } | ||
953 | } | ||
954 | |||
955 | return true; | ||
925 | } | 956 | } |
926 | 957 | ||
927 | /* | 958 | /* |
@@ -937,12 +968,12 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
937 | * Always check for focaltech, this is safe as it uses pnp-id | 968 | * Always check for focaltech, this is safe as it uses pnp-id |
938 | * matching. | 969 | * matching. |
939 | */ | 970 | */ |
940 | if (psmouse_do_detect(focaltech_detect, psmouse, set_properties) == 0) { | 971 | if (psmouse_try_protocol(psmouse, PSMOUSE_FOCALTECH, |
941 | if (max_proto > PSMOUSE_IMEX) { | 972 | &max_proto, set_properties, false)) { |
942 | if (IS_ENABLED(CONFIG_MOUSE_PS2_FOCALTECH) && | 973 | if (max_proto > PSMOUSE_IMEX && |
943 | (!set_properties || focaltech_init(psmouse) == 0)) { | 974 | IS_ENABLED(CONFIG_MOUSE_PS2_FOCALTECH) && |
944 | return PSMOUSE_FOCALTECH; | 975 | (!set_properties || focaltech_init(psmouse) == 0)) { |
945 | } | 976 | return PSMOUSE_FOCALTECH; |
946 | } | 977 | } |
947 | /* | 978 | /* |
948 | * Restrict psmouse_max_proto so that psmouse_initialize() | 979 | * Restrict psmouse_max_proto so that psmouse_initialize() |
@@ -959,26 +990,21 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
959 | * We always check for LifeBook because it does not disturb mouse | 990 | * We always check for LifeBook because it does not disturb mouse |
960 | * (it only checks DMI information). | 991 | * (it only checks DMI information). |
961 | */ | 992 | */ |
962 | if (psmouse_do_detect(lifebook_detect, psmouse, set_properties) == 0) { | 993 | if (psmouse_try_protocol(psmouse, PSMOUSE_LIFEBOOK, &max_proto, |
963 | if (max_proto > PSMOUSE_IMEX) { | 994 | set_properties, max_proto > PSMOUSE_IMEX)) |
964 | if (!set_properties || lifebook_init(psmouse) == 0) | 995 | return PSMOUSE_LIFEBOOK; |
965 | return PSMOUSE_LIFEBOOK; | ||
966 | } | ||
967 | } | ||
968 | 996 | ||
969 | if (psmouse_do_detect(vmmouse_detect, psmouse, set_properties) == 0) { | 997 | if (psmouse_try_protocol(psmouse, PSMOUSE_VMMOUSE, &max_proto, |
970 | if (max_proto > PSMOUSE_IMEX) { | 998 | set_properties, max_proto > PSMOUSE_IMEX)) |
971 | if (!set_properties || vmmouse_init(psmouse) == 0) | 999 | return PSMOUSE_VMMOUSE; |
972 | return PSMOUSE_VMMOUSE; | ||
973 | } | ||
974 | } | ||
975 | 1000 | ||
976 | /* | 1001 | /* |
977 | * Try Kensington ThinkingMouse (we try first, because Synaptics | 1002 | * Try Kensington ThinkingMouse (we try first, because Synaptics |
978 | * probe upsets the ThinkingMouse). | 1003 | * probe upsets the ThinkingMouse). |
979 | */ | 1004 | */ |
980 | if (max_proto > PSMOUSE_IMEX && | 1005 | if (max_proto > PSMOUSE_IMEX && |
981 | psmouse_do_detect(thinking_detect, psmouse, set_properties) == 0) { | 1006 | psmouse_try_protocol(psmouse, PSMOUSE_THINKPS, &max_proto, |
1007 | set_properties, true)) { | ||
982 | return PSMOUSE_THINKPS; | 1008 | return PSMOUSE_THINKPS; |
983 | } | 1009 | } |
984 | 1010 | ||
@@ -989,7 +1015,8 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
989 | * probing for IntelliMouse. | 1015 | * probing for IntelliMouse. |
990 | */ | 1016 | */ |
991 | if (max_proto > PSMOUSE_PS2 && | 1017 | if (max_proto > PSMOUSE_PS2 && |
992 | psmouse_do_detect(synaptics_detect, psmouse, set_properties) == 0) { | 1018 | psmouse_try_protocol(psmouse, PSMOUSE_SYNAPTICS, &max_proto, |
1019 | set_properties, false)) { | ||
993 | synaptics_hardware = true; | 1020 | synaptics_hardware = true; |
994 | 1021 | ||
995 | if (max_proto > PSMOUSE_IMEX) { | 1022 | if (max_proto > PSMOUSE_IMEX) { |
@@ -1025,64 +1052,48 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
1025 | * Trackpads. | 1052 | * Trackpads. |
1026 | */ | 1053 | */ |
1027 | if (max_proto > PSMOUSE_IMEX && | 1054 | if (max_proto > PSMOUSE_IMEX && |
1028 | psmouse_do_detect(cypress_detect, psmouse, set_properties) == 0) { | 1055 | psmouse_try_protocol(psmouse, PSMOUSE_CYPRESS, &max_proto, |
1029 | if (!set_properties || cypress_init(psmouse) == 0) | 1056 | set_properties, true)) { |
1030 | return PSMOUSE_CYPRESS; | 1057 | return PSMOUSE_CYPRESS; |
1031 | |||
1032 | /* | ||
1033 | * Finger Sensing Pad probe upsets some modules of | ||
1034 | * Cypress Trackpad, must avoid Finger Sensing Pad | ||
1035 | * probe if Cypress Trackpad device detected. | ||
1036 | */ | ||
1037 | max_proto = PSMOUSE_IMEX; | ||
1038 | } | 1058 | } |
1039 | 1059 | ||
1040 | /* Try ALPS TouchPad */ | 1060 | /* Try ALPS TouchPad */ |
1041 | if (max_proto > PSMOUSE_IMEX) { | 1061 | if (max_proto > PSMOUSE_IMEX) { |
1042 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); | 1062 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); |
1043 | if (psmouse_do_detect(alps_detect, | 1063 | if (psmouse_try_protocol(psmouse, PSMOUSE_ALPS, |
1044 | psmouse, set_properties) == 0) { | 1064 | &max_proto, set_properties, true)) |
1045 | if (!set_properties || alps_init(psmouse) == 0) | 1065 | return PSMOUSE_ALPS; |
1046 | return PSMOUSE_ALPS; | ||
1047 | |||
1048 | /* Init failed, try basic relative protocols */ | ||
1049 | max_proto = PSMOUSE_IMEX; | ||
1050 | } | ||
1051 | } | 1066 | } |
1052 | 1067 | ||
1053 | /* Try OLPC HGPK touchpad */ | 1068 | /* Try OLPC HGPK touchpad */ |
1054 | if (max_proto > PSMOUSE_IMEX && | 1069 | if (max_proto > PSMOUSE_IMEX && |
1055 | psmouse_do_detect(hgpk_detect, psmouse, set_properties) == 0) { | 1070 | psmouse_try_protocol(psmouse, PSMOUSE_HGPK, &max_proto, |
1056 | if (!set_properties || hgpk_init(psmouse) == 0) | 1071 | set_properties, true)) { |
1057 | return PSMOUSE_HGPK; | 1072 | return PSMOUSE_HGPK; |
1058 | /* Init failed, try basic relative protocols */ | ||
1059 | max_proto = PSMOUSE_IMEX; | ||
1060 | } | 1073 | } |
1061 | 1074 | ||
1062 | /* Try Elantech touchpad */ | 1075 | /* Try Elantech touchpad */ |
1063 | if (max_proto > PSMOUSE_IMEX && | 1076 | if (max_proto > PSMOUSE_IMEX && |
1064 | psmouse_do_detect(elantech_detect, psmouse, set_properties) == 0) { | 1077 | psmouse_try_protocol(psmouse, PSMOUSE_ELANTECH, |
1065 | if (!set_properties || elantech_init(psmouse) == 0) | 1078 | &max_proto, set_properties, true)) { |
1066 | return PSMOUSE_ELANTECH; | 1079 | return PSMOUSE_ELANTECH; |
1067 | /* Init failed, try basic relative protocols */ | ||
1068 | max_proto = PSMOUSE_IMEX; | ||
1069 | } | 1080 | } |
1070 | 1081 | ||
1071 | if (max_proto > PSMOUSE_IMEX) { | 1082 | if (max_proto > PSMOUSE_IMEX) { |
1072 | if (psmouse_do_detect(genius_detect, | 1083 | if (psmouse_try_protocol(psmouse, PSMOUSE_GENPS, |
1073 | psmouse, set_properties) == 0) | 1084 | &max_proto, set_properties, true)) |
1074 | return PSMOUSE_GENPS; | 1085 | return PSMOUSE_GENPS; |
1075 | 1086 | ||
1076 | if (psmouse_do_detect(ps2pp_init, | 1087 | if (psmouse_try_protocol(psmouse, PSMOUSE_PS2PP, |
1077 | psmouse, set_properties) == 0) | 1088 | &max_proto, set_properties, true)) |
1078 | return PSMOUSE_PS2PP; | 1089 | return PSMOUSE_PS2PP; |
1079 | 1090 | ||
1080 | if (psmouse_do_detect(trackpoint_detect, | 1091 | if (psmouse_try_protocol(psmouse, PSMOUSE_TRACKPOINT, |
1081 | psmouse, set_properties) == 0) | 1092 | &max_proto, set_properties, true)) |
1082 | return PSMOUSE_TRACKPOINT; | 1093 | return PSMOUSE_TRACKPOINT; |
1083 | 1094 | ||
1084 | if (psmouse_do_detect(touchkit_ps2_detect, | 1095 | if (psmouse_try_protocol(psmouse, PSMOUSE_TOUCHKIT_PS2, |
1085 | psmouse, set_properties) == 0) | 1096 | &max_proto, set_properties, true)) |
1086 | return PSMOUSE_TOUCHKIT_PS2; | 1097 | return PSMOUSE_TOUCHKIT_PS2; |
1087 | } | 1098 | } |
1088 | 1099 | ||
@@ -1090,14 +1101,10 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
1090 | * Try Finger Sensing Pad. We do it here because its probe upsets | 1101 | * Try Finger Sensing Pad. We do it here because its probe upsets |
1091 | * Trackpoint devices (causing TP_READ_ID command to time out). | 1102 | * Trackpoint devices (causing TP_READ_ID command to time out). |
1092 | */ | 1103 | */ |
1093 | if (max_proto > PSMOUSE_IMEX) { | 1104 | if (max_proto > PSMOUSE_IMEX && |
1094 | if (psmouse_do_detect(fsp_detect, | 1105 | psmouse_try_protocol(psmouse, PSMOUSE_FSP, |
1095 | psmouse, set_properties) == 0) { | 1106 | &max_proto, set_properties, true)) { |
1096 | if (!set_properties || fsp_init(psmouse) == 0) | 1107 | return PSMOUSE_FSP; |
1097 | return PSMOUSE_FSP; | ||
1098 | /* Init failed, try basic relative protocols */ | ||
1099 | max_proto = PSMOUSE_IMEX; | ||
1100 | } | ||
1101 | } | 1108 | } |
1102 | 1109 | ||
1103 | /* | 1110 | /* |
@@ -1109,14 +1116,14 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
1109 | psmouse_reset(psmouse); | 1116 | psmouse_reset(psmouse); |
1110 | 1117 | ||
1111 | if (max_proto >= PSMOUSE_IMEX && | 1118 | if (max_proto >= PSMOUSE_IMEX && |
1112 | psmouse_do_detect(im_explorer_detect, | 1119 | psmouse_try_protocol(psmouse, PSMOUSE_IMEX, |
1113 | psmouse, set_properties) == 0) { | 1120 | &max_proto, set_properties, true)) { |
1114 | return PSMOUSE_IMEX; | 1121 | return PSMOUSE_IMEX; |
1115 | } | 1122 | } |
1116 | 1123 | ||
1117 | if (max_proto >= PSMOUSE_IMPS && | 1124 | if (max_proto >= PSMOUSE_IMPS && |
1118 | psmouse_do_detect(intellimouse_detect, | 1125 | psmouse_try_protocol(psmouse, PSMOUSE_IMPS, |
1119 | psmouse, set_properties) == 0) { | 1126 | &max_proto, set_properties, true)) { |
1120 | return PSMOUSE_IMPS; | 1127 | return PSMOUSE_IMPS; |
1121 | } | 1128 | } |
1122 | 1129 | ||
@@ -1124,7 +1131,8 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
1124 | * Okay, all failed, we have a standard mouse here. The number of | 1131 | * Okay, all failed, we have a standard mouse here. The number of |
1125 | * the buttons is still a question, though. We assume 3. | 1132 | * the buttons is still a question, though. We assume 3. |
1126 | */ | 1133 | */ |
1127 | psmouse_do_detect(ps2bare_detect, psmouse, set_properties); | 1134 | psmouse_try_protocol(psmouse, PSMOUSE_PS2, |
1135 | &max_proto, set_properties, true); | ||
1128 | 1136 | ||
1129 | if (synaptics_hardware) { | 1137 | if (synaptics_hardware) { |
1130 | /* | 1138 | /* |