@@ -40,7 +40,9 @@ MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>");
4040MODULE_DESCRIPTION ("Asus HID Keyboard and TouchPad" );
4141
4242#define T100_TPAD_INTF 2
43+ #define MEDION_E1239T_TPAD_INTF 1
4344
45+ #define E1239T_TP_TOGGLE_REPORT_ID 0x05
4446#define T100CHI_MOUSE_REPORT_ID 0x06
4547#define FEATURE_REPORT_ID 0x0d
4648#define INPUT_REPORT_ID 0x5d
@@ -77,6 +79,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
7779#define QUIRK_G752_KEYBOARD BIT(8)
7880#define QUIRK_T101HA_DOCK BIT(9)
7981#define QUIRK_T90CHI BIT(10)
82+ #define QUIRK_MEDION_E1239T BIT(11)
8083
8184#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
8285 QUIRK_NO_INIT_REPORTS | \
@@ -102,12 +105,14 @@ struct asus_touchpad_info {
102105 int res_y ;
103106 int contact_size ;
104107 int max_contacts ;
108+ int report_size ;
105109};
106110
107111struct asus_drvdata {
108112 unsigned long quirks ;
109113 struct hid_device * hdev ;
110114 struct input_dev * input ;
115+ struct input_dev * tp_kbd_input ;
111116 struct asus_kbd_leds * kbd_backlight ;
112117 const struct asus_touchpad_info * tp ;
113118 bool enable_backlight ;
@@ -126,6 +131,7 @@ static const struct asus_touchpad_info asus_i2c_tp = {
126131 .max_y = 1758 ,
127132 .contact_size = 5 ,
128133 .max_contacts = 5 ,
134+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */ ,
129135};
130136
131137static const struct asus_touchpad_info asus_t100ta_tp = {
@@ -135,6 +141,7 @@ static const struct asus_touchpad_info asus_t100ta_tp = {
135141 .res_y = 27 , /* units/mm */
136142 .contact_size = 5 ,
137143 .max_contacts = 5 ,
144+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */ ,
138145};
139146
140147static const struct asus_touchpad_info asus_t100ha_tp = {
@@ -144,6 +151,7 @@ static const struct asus_touchpad_info asus_t100ha_tp = {
144151 .res_y = 29 , /* units/mm */
145152 .contact_size = 5 ,
146153 .max_contacts = 5 ,
154+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */ ,
147155};
148156
149157static const struct asus_touchpad_info asus_t200ta_tp = {
@@ -153,6 +161,7 @@ static const struct asus_touchpad_info asus_t200ta_tp = {
153161 .res_y = 28 , /* units/mm */
154162 .contact_size = 5 ,
155163 .max_contacts = 5 ,
164+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */ ,
156165};
157166
158167static const struct asus_touchpad_info asus_t100chi_tp = {
@@ -162,6 +171,17 @@ static const struct asus_touchpad_info asus_t100chi_tp = {
162171 .res_y = 29 , /* units/mm */
163172 .contact_size = 3 ,
164173 .max_contacts = 4 ,
174+ .report_size = 15 /* 2 byte header + 3 * 4 + 1 byte footer */ ,
175+ };
176+
177+ static const struct asus_touchpad_info medion_e1239t_tp = {
178+ .max_x = 2640 ,
179+ .max_y = 1380 ,
180+ .res_x = 29 , /* units/mm */
181+ .res_y = 28 , /* units/mm */
182+ .contact_size = 5 ,
183+ .max_contacts = 5 ,
184+ .report_size = 32 /* 2 byte header + 5 * 5 + 5 byte footer */ ,
165185};
166186
167187static void asus_report_contact_down (struct asus_drvdata * drvdat ,
@@ -229,7 +249,7 @@ static int asus_report_input(struct asus_drvdata *drvdat, u8 *data, int size)
229249 int i , toolType = MT_TOOL_FINGER ;
230250 u8 * contactData = data + 2 ;
231251
232- if (size != 3 + drvdat -> tp -> contact_size * drvdat -> tp -> max_contacts )
252+ if (size != drvdat -> tp -> report_size )
233253 return 0 ;
234254
235255 for (i = 0 ; i < drvdat -> tp -> max_contacts ; i ++ ) {
@@ -257,6 +277,34 @@ static int asus_report_input(struct asus_drvdata *drvdat, u8 *data, int size)
257277 return 1 ;
258278}
259279
280+ static int asus_e1239t_event (struct asus_drvdata * drvdat , u8 * data , int size )
281+ {
282+ if (size != 3 )
283+ return 0 ;
284+
285+ /* Handle broken mute key which only sends press events */
286+ if (!drvdat -> tp &&
287+ data [0 ] == 0x02 && data [1 ] == 0xe2 && data [2 ] == 0x00 ) {
288+ input_report_key (drvdat -> input , KEY_MUTE , 1 );
289+ input_sync (drvdat -> input );
290+ input_report_key (drvdat -> input , KEY_MUTE , 0 );
291+ input_sync (drvdat -> input );
292+ return 1 ;
293+ }
294+
295+ /* Handle custom touchpad toggle key which only sends press events */
296+ if (drvdat -> tp_kbd_input &&
297+ data [0 ] == 0x05 && data [1 ] == 0x02 && data [2 ] == 0x28 ) {
298+ input_report_key (drvdat -> tp_kbd_input , KEY_F21 , 1 );
299+ input_sync (drvdat -> tp_kbd_input );
300+ input_report_key (drvdat -> tp_kbd_input , KEY_F21 , 0 );
301+ input_sync (drvdat -> tp_kbd_input );
302+ return 1 ;
303+ }
304+
305+ return 0 ;
306+ }
307+
260308static int asus_event (struct hid_device * hdev , struct hid_field * field ,
261309 struct hid_usage * usage , __s32 value )
262310{
@@ -281,6 +329,9 @@ static int asus_raw_event(struct hid_device *hdev,
281329 if (drvdata -> tp && data [0 ] == INPUT_REPORT_ID )
282330 return asus_report_input (drvdata , data , size );
283331
332+ if (drvdata -> quirks & QUIRK_MEDION_E1239T )
333+ return asus_e1239t_event (drvdata , data , size );
334+
284335 return 0 ;
285336}
286337
@@ -615,6 +666,21 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
615666 hi -> report -> id != T100CHI_MOUSE_REPORT_ID )
616667 return 0 ;
617668
669+ /* Handle MULTI_INPUT on E1239T mouse/touchpad USB interface */
670+ if (drvdata -> tp && (drvdata -> quirks & QUIRK_MEDION_E1239T )) {
671+ switch (hi -> report -> id ) {
672+ case E1239T_TP_TOGGLE_REPORT_ID :
673+ input_set_capability (input , EV_KEY , KEY_F21 );
674+ input -> name = "Asus Touchpad Keys" ;
675+ drvdata -> tp_kbd_input = input ;
676+ return 0 ;
677+ case INPUT_REPORT_ID :
678+ break ; /* Touchpad report, handled below */
679+ default :
680+ return 0 ; /* Ignore other reports */
681+ }
682+ }
683+
618684 if (drvdata -> tp ) {
619685 int ret ;
620686
@@ -677,24 +743,16 @@ static int asus_input_mapping(struct hid_device *hdev,
677743 * This avoids a bunch of non-functional hid_input devices getting
678744 * created because of the T100CHI using HID_QUIRK_MULTI_INPUT.
679745 */
680- if (drvdata -> quirks & (QUIRK_T100CHI | QUIRK_T90CHI )) {
681- if (field -> application == (HID_UP_GENDESK | 0x0080 ) ||
682- usage -> hid == (HID_UP_GENDEVCTRLS | 0x0024 ) ||
683- usage -> hid == (HID_UP_GENDEVCTRLS | 0x0025 ) ||
684- usage -> hid == (HID_UP_GENDEVCTRLS | 0x0026 ))
685- return -1 ;
686- /*
687- * We use the hid_input for the mouse report for the touchpad,
688- * keep the left button, to avoid the core removing it.
689- */
690- if (field -> application == HID_GD_MOUSE &&
691- usage -> hid != (HID_UP_BUTTON | 1 ))
692- return -1 ;
693- }
746+ if ((drvdata -> quirks & (QUIRK_T100CHI | QUIRK_T90CHI )) &&
747+ (field -> application == (HID_UP_GENDESK | 0x0080 ) ||
748+ field -> application == HID_GD_MOUSE ||
749+ usage -> hid == (HID_UP_GENDEVCTRLS | 0x0024 ) ||
750+ usage -> hid == (HID_UP_GENDEVCTRLS | 0x0025 ) ||
751+ usage -> hid == (HID_UP_GENDEVCTRLS | 0x0026 )))
752+ return -1 ;
694753
695754 /* ASUS-specific keyboard hotkeys */
696755 if ((usage -> hid & HID_USAGE_PAGE ) == 0xff310000 ) {
697- set_bit (EV_REP , hi -> input -> evbit );
698756 switch (usage -> hid & HID_USAGE ) {
699757 case 0x10 : asus_map_key_clear (KEY_BRIGHTNESSDOWN ); break ;
700758 case 0x20 : asus_map_key_clear (KEY_BRIGHTNESSUP ); break ;
@@ -737,11 +795,11 @@ static int asus_input_mapping(struct hid_device *hdev,
737795 if (drvdata -> quirks & QUIRK_USE_KBD_BACKLIGHT )
738796 drvdata -> enable_backlight = true;
739797
798+ set_bit (EV_REP , hi -> input -> evbit );
740799 return 1 ;
741800 }
742801
743802 if ((usage -> hid & HID_USAGE_PAGE ) == HID_UP_MSVENDOR ) {
744- set_bit (EV_REP , hi -> input -> evbit );
745803 switch (usage -> hid & HID_USAGE ) {
746804 case 0xff01 : asus_map_key_clear (BTN_1 ); break ;
747805 case 0xff02 : asus_map_key_clear (BTN_2 ); break ;
@@ -764,6 +822,7 @@ static int asus_input_mapping(struct hid_device *hdev,
764822 return 0 ;
765823 }
766824
825+ set_bit (EV_REP , hi -> input -> evbit );
767826 return 1 ;
768827 }
769828
@@ -782,6 +841,16 @@ static int asus_input_mapping(struct hid_device *hdev,
782841 }
783842 }
784843
844+ /*
845+ * The mute button is broken and only sends press events, we
846+ * deal with this in our raw_event handler, so do not map it.
847+ */
848+ if ((drvdata -> quirks & QUIRK_MEDION_E1239T ) &&
849+ usage -> hid == (HID_UP_CONSUMER | 0xe2 )) {
850+ input_set_capability (hi -> input , EV_KEY , KEY_MUTE );
851+ return -1 ;
852+ }
853+
785854 return 0 ;
786855}
787856
@@ -849,7 +918,8 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
849918 if (drvdata -> quirks & QUIRK_IS_MULTITOUCH )
850919 drvdata -> tp = & asus_i2c_tp ;
851920
852- if (drvdata -> quirks & QUIRK_T100_KEYBOARD ) {
921+ if ((drvdata -> quirks & QUIRK_T100_KEYBOARD ) &&
922+ hid_is_using_ll_driver (hdev , & usb_hid_driver )) {
853923 struct usb_interface * intf = to_usb_interface (hdev -> dev .parent );
854924
855925 if (intf -> altsetting -> desc .bInterfaceNumber == T100_TPAD_INTF ) {
@@ -877,6 +947,19 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
877947 drvdata -> tp = & asus_t100chi_tp ;
878948 }
879949
950+ if ((drvdata -> quirks & QUIRK_MEDION_E1239T ) &&
951+ hid_is_using_ll_driver (hdev , & usb_hid_driver )) {
952+ struct usb_host_interface * alt =
953+ to_usb_interface (hdev -> dev .parent )-> altsetting ;
954+
955+ if (alt -> desc .bInterfaceNumber == MEDION_E1239T_TPAD_INTF ) {
956+ /* For separate input-devs for tp and tp toggle key */
957+ hdev -> quirks |= HID_QUIRK_MULTI_INPUT ;
958+ drvdata -> quirks |= QUIRK_SKIP_INPUT_MAPPING ;
959+ drvdata -> tp = & medion_e1239t_tp ;
960+ }
961+ }
962+
880963 if (drvdata -> quirks & QUIRK_NO_INIT_REPORTS )
881964 hdev -> quirks |= HID_QUIRK_NO_INIT_REPORTS ;
882965
@@ -1056,7 +1139,8 @@ static const struct hid_device_id asus_devices[] = {
10561139 { HID_USB_DEVICE (USB_VENDOR_ID_JESS , USB_DEVICE_ID_ASUS_MD_5112 ) },
10571140 { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_ASUSTEK ,
10581141 USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD ), QUIRK_T100CHI },
1059-
1142+ { HID_USB_DEVICE (USB_VENDOR_ID_ITE , USB_DEVICE_ID_ITE_MEDION_E1239T ),
1143+ QUIRK_MEDION_E1239T },
10601144 { }
10611145};
10621146MODULE_DEVICE_TABLE (hid , asus_devices );
0 commit comments