1*9a6a4193SAlexandrov Stansilav /* 2*9a6a4193SAlexandrov Stansilav * HID Driver for ELAN Touchpad 3*9a6a4193SAlexandrov Stansilav * 4*9a6a4193SAlexandrov Stansilav * Currently only supports touchpad found on HP Pavilion X2 10 5*9a6a4193SAlexandrov Stansilav * 6*9a6a4193SAlexandrov Stansilav * Copyright (c) 2016 Alexandrov Stanislav <neko@nya.ai> 7*9a6a4193SAlexandrov Stansilav * 8*9a6a4193SAlexandrov Stansilav * This program is free software; you can redistribute it and/or modify it 9*9a6a4193SAlexandrov Stansilav * under the terms of the GNU General Public License as published by the Free 10*9a6a4193SAlexandrov Stansilav * Software Foundation; either version 2 of the License, or (at your option) 11*9a6a4193SAlexandrov Stansilav * any later version. 12*9a6a4193SAlexandrov Stansilav */ 13*9a6a4193SAlexandrov Stansilav 14*9a6a4193SAlexandrov Stansilav #include <linux/hid.h> 15*9a6a4193SAlexandrov Stansilav #include <linux/input/mt.h> 16*9a6a4193SAlexandrov Stansilav #include <linux/leds.h> 17*9a6a4193SAlexandrov Stansilav #include <linux/module.h> 18*9a6a4193SAlexandrov Stansilav #include <linux/usb.h> 19*9a6a4193SAlexandrov Stansilav 20*9a6a4193SAlexandrov Stansilav #include "hid-ids.h" 21*9a6a4193SAlexandrov Stansilav 22*9a6a4193SAlexandrov Stansilav #define ELAN_SINGLE_FINGER 0x81 23*9a6a4193SAlexandrov Stansilav #define ELAN_MT_FIRST_FINGER 0x82 24*9a6a4193SAlexandrov Stansilav #define ELAN_MT_SECOND_FINGER 0x83 25*9a6a4193SAlexandrov Stansilav #define ELAN_INPUT_REPORT_SIZE 8 26*9a6a4193SAlexandrov Stansilav 27*9a6a4193SAlexandrov Stansilav #define ELAN_MUTE_LED_REPORT 0xBC 28*9a6a4193SAlexandrov Stansilav #define ELAN_LED_REPORT_SIZE 8 29*9a6a4193SAlexandrov Stansilav 30*9a6a4193SAlexandrov Stansilav struct elan_touchpad_settings { 31*9a6a4193SAlexandrov Stansilav u8 max_fingers; 32*9a6a4193SAlexandrov Stansilav u16 max_x; 33*9a6a4193SAlexandrov Stansilav u16 max_y; 34*9a6a4193SAlexandrov Stansilav u8 max_area_x; 35*9a6a4193SAlexandrov Stansilav u8 max_area_y; 36*9a6a4193SAlexandrov Stansilav u8 max_w; 37*9a6a4193SAlexandrov Stansilav int usb_bInterfaceNumber; 38*9a6a4193SAlexandrov Stansilav }; 39*9a6a4193SAlexandrov Stansilav 40*9a6a4193SAlexandrov Stansilav struct elan_drvdata { 41*9a6a4193SAlexandrov Stansilav struct input_dev *input; 42*9a6a4193SAlexandrov Stansilav u8 prev_report[ELAN_INPUT_REPORT_SIZE]; 43*9a6a4193SAlexandrov Stansilav struct led_classdev mute_led; 44*9a6a4193SAlexandrov Stansilav u8 mute_led_state; 45*9a6a4193SAlexandrov Stansilav struct elan_touchpad_settings *settings; 46*9a6a4193SAlexandrov Stansilav }; 47*9a6a4193SAlexandrov Stansilav 48*9a6a4193SAlexandrov Stansilav static int is_not_elan_touchpad(struct hid_device *hdev) 49*9a6a4193SAlexandrov Stansilav { 50*9a6a4193SAlexandrov Stansilav struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 51*9a6a4193SAlexandrov Stansilav struct elan_drvdata *drvdata = hid_get_drvdata(hdev); 52*9a6a4193SAlexandrov Stansilav 53*9a6a4193SAlexandrov Stansilav return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber); 54*9a6a4193SAlexandrov Stansilav } 55*9a6a4193SAlexandrov Stansilav 56*9a6a4193SAlexandrov Stansilav static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi, 57*9a6a4193SAlexandrov Stansilav struct hid_field *field, struct hid_usage *usage, 58*9a6a4193SAlexandrov Stansilav unsigned long **bit, int *max) 59*9a6a4193SAlexandrov Stansilav { 60*9a6a4193SAlexandrov Stansilav if (is_not_elan_touchpad(hdev)) 61*9a6a4193SAlexandrov Stansilav return 0; 62*9a6a4193SAlexandrov Stansilav 63*9a6a4193SAlexandrov Stansilav if (field->report->id == ELAN_SINGLE_FINGER || 64*9a6a4193SAlexandrov Stansilav field->report->id == ELAN_MT_FIRST_FINGER || 65*9a6a4193SAlexandrov Stansilav field->report->id == ELAN_MT_SECOND_FINGER) 66*9a6a4193SAlexandrov Stansilav return -1; 67*9a6a4193SAlexandrov Stansilav 68*9a6a4193SAlexandrov Stansilav return 0; 69*9a6a4193SAlexandrov Stansilav } 70*9a6a4193SAlexandrov Stansilav 71*9a6a4193SAlexandrov Stansilav static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) 72*9a6a4193SAlexandrov Stansilav { 73*9a6a4193SAlexandrov Stansilav int ret; 74*9a6a4193SAlexandrov Stansilav struct input_dev *input; 75*9a6a4193SAlexandrov Stansilav struct elan_drvdata *drvdata = hid_get_drvdata(hdev); 76*9a6a4193SAlexandrov Stansilav 77*9a6a4193SAlexandrov Stansilav if (is_not_elan_touchpad(hdev)) 78*9a6a4193SAlexandrov Stansilav return 0; 79*9a6a4193SAlexandrov Stansilav 80*9a6a4193SAlexandrov Stansilav input = devm_input_allocate_device(&hdev->dev); 81*9a6a4193SAlexandrov Stansilav if (!input) 82*9a6a4193SAlexandrov Stansilav return -ENOMEM; 83*9a6a4193SAlexandrov Stansilav 84*9a6a4193SAlexandrov Stansilav input->name = "Elan Touchpad"; 85*9a6a4193SAlexandrov Stansilav input->phys = hdev->phys; 86*9a6a4193SAlexandrov Stansilav input->uniq = hdev->uniq; 87*9a6a4193SAlexandrov Stansilav input->id.bustype = hdev->bus; 88*9a6a4193SAlexandrov Stansilav input->id.vendor = hdev->vendor; 89*9a6a4193SAlexandrov Stansilav input->id.product = hdev->product; 90*9a6a4193SAlexandrov Stansilav input->id.version = hdev->version; 91*9a6a4193SAlexandrov Stansilav input->dev.parent = &hdev->dev; 92*9a6a4193SAlexandrov Stansilav 93*9a6a4193SAlexandrov Stansilav input_set_abs_params(input, ABS_MT_POSITION_X, 0, 94*9a6a4193SAlexandrov Stansilav drvdata->settings->max_x, 0, 0); 95*9a6a4193SAlexandrov Stansilav input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 96*9a6a4193SAlexandrov Stansilav drvdata->settings->max_y, 0, 0); 97*9a6a4193SAlexandrov Stansilav input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 98*9a6a4193SAlexandrov Stansilav drvdata->settings->max_fingers, 0, 0); 99*9a6a4193SAlexandrov Stansilav input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 100*9a6a4193SAlexandrov Stansilav drvdata->settings->max_w, 0, 0); 101*9a6a4193SAlexandrov Stansilav 102*9a6a4193SAlexandrov Stansilav __set_bit(BTN_LEFT, input->keybit); 103*9a6a4193SAlexandrov Stansilav __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); 104*9a6a4193SAlexandrov Stansilav 105*9a6a4193SAlexandrov Stansilav ret = input_mt_init_slots(input, drvdata->settings->max_fingers, 106*9a6a4193SAlexandrov Stansilav INPUT_MT_POINTER); 107*9a6a4193SAlexandrov Stansilav if (ret) { 108*9a6a4193SAlexandrov Stansilav hid_err(hdev, "Failed to init elan MT slots: %d\n", ret); 109*9a6a4193SAlexandrov Stansilav return ret; 110*9a6a4193SAlexandrov Stansilav } 111*9a6a4193SAlexandrov Stansilav 112*9a6a4193SAlexandrov Stansilav ret = input_register_device(input); 113*9a6a4193SAlexandrov Stansilav if (ret) { 114*9a6a4193SAlexandrov Stansilav hid_err(hdev, "Failed to register elan input device: %d\n", 115*9a6a4193SAlexandrov Stansilav ret); 116*9a6a4193SAlexandrov Stansilav input_free_device(input); 117*9a6a4193SAlexandrov Stansilav return ret; 118*9a6a4193SAlexandrov Stansilav } 119*9a6a4193SAlexandrov Stansilav 120*9a6a4193SAlexandrov Stansilav drvdata->input = input; 121*9a6a4193SAlexandrov Stansilav 122*9a6a4193SAlexandrov Stansilav return 0; 123*9a6a4193SAlexandrov Stansilav } 124*9a6a4193SAlexandrov Stansilav 125*9a6a4193SAlexandrov Stansilav static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data, 126*9a6a4193SAlexandrov Stansilav unsigned int slot_num) 127*9a6a4193SAlexandrov Stansilav { 128*9a6a4193SAlexandrov Stansilav struct input_dev *input = drvdata->input; 129*9a6a4193SAlexandrov Stansilav int x, y, w; 130*9a6a4193SAlexandrov Stansilav 131*9a6a4193SAlexandrov Stansilav bool active = !!data; 132*9a6a4193SAlexandrov Stansilav 133*9a6a4193SAlexandrov Stansilav input_mt_slot(input, slot_num); 134*9a6a4193SAlexandrov Stansilav input_mt_report_slot_state(input, MT_TOOL_FINGER, active); 135*9a6a4193SAlexandrov Stansilav if (active) { 136*9a6a4193SAlexandrov Stansilav x = ((data[0] & 0xF0) << 4) | data[1]; 137*9a6a4193SAlexandrov Stansilav y = drvdata->settings->max_y - 138*9a6a4193SAlexandrov Stansilav (((data[0] & 0x07) << 8) | data[2]); 139*9a6a4193SAlexandrov Stansilav w = data[4]; 140*9a6a4193SAlexandrov Stansilav 141*9a6a4193SAlexandrov Stansilav input_report_abs(input, ABS_MT_POSITION_X, x); 142*9a6a4193SAlexandrov Stansilav input_report_abs(input, ABS_MT_POSITION_Y, y); 143*9a6a4193SAlexandrov Stansilav input_report_abs(input, ABS_TOOL_WIDTH, w); 144*9a6a4193SAlexandrov Stansilav } 145*9a6a4193SAlexandrov Stansilav } 146*9a6a4193SAlexandrov Stansilav 147*9a6a4193SAlexandrov Stansilav static void elan_report_input(struct elan_drvdata *drvdata, u8 *data) 148*9a6a4193SAlexandrov Stansilav { 149*9a6a4193SAlexandrov Stansilav int i; 150*9a6a4193SAlexandrov Stansilav struct input_dev *input = drvdata->input; 151*9a6a4193SAlexandrov Stansilav 152*9a6a4193SAlexandrov Stansilav /* 153*9a6a4193SAlexandrov Stansilav * There is 3 types of reports: for single touch, 154*9a6a4193SAlexandrov Stansilav * for multitouch - first finger and for multitouch - second finger 155*9a6a4193SAlexandrov Stansilav * 156*9a6a4193SAlexandrov Stansilav * packet structure for ELAN_SINGLE_FINGER and ELAN_MT_FIRST_FINGER: 157*9a6a4193SAlexandrov Stansilav * 158*9a6a4193SAlexandrov Stansilav * byte 1: 1 0 0 0 0 0 0 1 // 0x81 or 0x82 159*9a6a4193SAlexandrov Stansilav * byte 2: 0 0 0 0 0 0 0 0 // looks like unused 160*9a6a4193SAlexandrov Stansilav * byte 3: f5 f4 f3 f2 f1 0 0 L 161*9a6a4193SAlexandrov Stansilav * byte 4: x12 x11 x10 x9 0? y11 y10 y9 162*9a6a4193SAlexandrov Stansilav * byte 5: x8 x7 x6 x5 x4 x3 x2 x1 163*9a6a4193SAlexandrov Stansilav * byte 6: y8 y7 y6 y5 y4 y3 y2 y1 164*9a6a4193SAlexandrov Stansilav * byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1 165*9a6a4193SAlexandrov Stansilav * byte 8: w8 w7 w6 w5 w4 w3 w2 w1 166*9a6a4193SAlexandrov Stansilav * 167*9a6a4193SAlexandrov Stansilav * packet structure for ELAN_MT_SECOND_FINGER: 168*9a6a4193SAlexandrov Stansilav * 169*9a6a4193SAlexandrov Stansilav * byte 1: 1 0 0 0 0 0 1 1 // 0x83 170*9a6a4193SAlexandrov Stansilav * byte 2: x12 x11 x10 x9 0 y11 y10 y9 171*9a6a4193SAlexandrov Stansilav * byte 3: x8 x7 x6 x5 x4 x3 x2 x1 172*9a6a4193SAlexandrov Stansilav * byte 4: y8 y7 y6 y5 y4 y3 y2 y1 173*9a6a4193SAlexandrov Stansilav * byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1 174*9a6a4193SAlexandrov Stansilav * byte 6: w8 w7 w6 w5 w4 w3 w2 w1 175*9a6a4193SAlexandrov Stansilav * byte 7: 0 0 0 0 0 0 0 0 176*9a6a4193SAlexandrov Stansilav * byte 8: 0 0 0 0 0 0 0 0 177*9a6a4193SAlexandrov Stansilav * 178*9a6a4193SAlexandrov Stansilav * f5-f1: finger touch bits 179*9a6a4193SAlexandrov Stansilav * L: clickpad button 180*9a6a4193SAlexandrov Stansilav * sy / sx: not sure yet, but this looks like rectangular 181*9a6a4193SAlexandrov Stansilav * area for finger 182*9a6a4193SAlexandrov Stansilav * w: looks like finger width 183*9a6a4193SAlexandrov Stansilav */ 184*9a6a4193SAlexandrov Stansilav 185*9a6a4193SAlexandrov Stansilav if (data[0] == ELAN_SINGLE_FINGER) { 186*9a6a4193SAlexandrov Stansilav for (i = 0; i < drvdata->settings->max_fingers; i++) { 187*9a6a4193SAlexandrov Stansilav if (data[2] & BIT(i + 3)) 188*9a6a4193SAlexandrov Stansilav elan_report_mt_slot(drvdata, data + 3, i); 189*9a6a4193SAlexandrov Stansilav else 190*9a6a4193SAlexandrov Stansilav elan_report_mt_slot(drvdata, NULL, i); 191*9a6a4193SAlexandrov Stansilav } 192*9a6a4193SAlexandrov Stansilav input_report_key(input, BTN_LEFT, data[2] & 0x01); 193*9a6a4193SAlexandrov Stansilav } 194*9a6a4193SAlexandrov Stansilav /* 195*9a6a4193SAlexandrov Stansilav * When touched with two fingers Elan touchpad will emit two HID reports 196*9a6a4193SAlexandrov Stansilav * first is ELAN_MT_FIRST_FINGER and second is ELAN_MT_SECOND_FINGER 197*9a6a4193SAlexandrov Stansilav * we will save ELAN_MT_FIRST_FINGER report and wait for 198*9a6a4193SAlexandrov Stansilav * ELAN_MT_SECOND_FINGER to finish multitouch 199*9a6a4193SAlexandrov Stansilav */ 200*9a6a4193SAlexandrov Stansilav if (data[0] == ELAN_MT_FIRST_FINGER) { 201*9a6a4193SAlexandrov Stansilav memcpy(drvdata->prev_report, data, 202*9a6a4193SAlexandrov Stansilav sizeof(drvdata->prev_report)); 203*9a6a4193SAlexandrov Stansilav return; 204*9a6a4193SAlexandrov Stansilav } 205*9a6a4193SAlexandrov Stansilav 206*9a6a4193SAlexandrov Stansilav if (data[0] == ELAN_MT_SECOND_FINGER) { 207*9a6a4193SAlexandrov Stansilav int first = 0; 208*9a6a4193SAlexandrov Stansilav u8 *prev_report = drvdata->prev_report; 209*9a6a4193SAlexandrov Stansilav 210*9a6a4193SAlexandrov Stansilav if (prev_report[0] != ELAN_MT_FIRST_FINGER) 211*9a6a4193SAlexandrov Stansilav return; 212*9a6a4193SAlexandrov Stansilav 213*9a6a4193SAlexandrov Stansilav for (i = 0; i < drvdata->settings->max_fingers; i++) { 214*9a6a4193SAlexandrov Stansilav if (prev_report[2] & BIT(i + 3)) { 215*9a6a4193SAlexandrov Stansilav if (!first) { 216*9a6a4193SAlexandrov Stansilav first = 1; 217*9a6a4193SAlexandrov Stansilav elan_report_mt_slot(drvdata, prev_report + 3, i); 218*9a6a4193SAlexandrov Stansilav } else { 219*9a6a4193SAlexandrov Stansilav elan_report_mt_slot(drvdata, data + 1, i); 220*9a6a4193SAlexandrov Stansilav } 221*9a6a4193SAlexandrov Stansilav } else { 222*9a6a4193SAlexandrov Stansilav elan_report_mt_slot(drvdata, NULL, i); 223*9a6a4193SAlexandrov Stansilav } 224*9a6a4193SAlexandrov Stansilav } 225*9a6a4193SAlexandrov Stansilav input_report_key(input, BTN_LEFT, prev_report[2] & 0x01); 226*9a6a4193SAlexandrov Stansilav } 227*9a6a4193SAlexandrov Stansilav 228*9a6a4193SAlexandrov Stansilav input_mt_sync_frame(input); 229*9a6a4193SAlexandrov Stansilav input_sync(input); 230*9a6a4193SAlexandrov Stansilav } 231*9a6a4193SAlexandrov Stansilav 232*9a6a4193SAlexandrov Stansilav static int elan_raw_event(struct hid_device *hdev, 233*9a6a4193SAlexandrov Stansilav struct hid_report *report, u8 *data, int size) 234*9a6a4193SAlexandrov Stansilav { 235*9a6a4193SAlexandrov Stansilav struct elan_drvdata *drvdata = hid_get_drvdata(hdev); 236*9a6a4193SAlexandrov Stansilav 237*9a6a4193SAlexandrov Stansilav if (is_not_elan_touchpad(hdev)) 238*9a6a4193SAlexandrov Stansilav return 0; 239*9a6a4193SAlexandrov Stansilav 240*9a6a4193SAlexandrov Stansilav if (data[0] == ELAN_SINGLE_FINGER || 241*9a6a4193SAlexandrov Stansilav data[0] == ELAN_MT_FIRST_FINGER || 242*9a6a4193SAlexandrov Stansilav data[0] == ELAN_MT_SECOND_FINGER) { 243*9a6a4193SAlexandrov Stansilav if (size == ELAN_INPUT_REPORT_SIZE) { 244*9a6a4193SAlexandrov Stansilav elan_report_input(drvdata, data); 245*9a6a4193SAlexandrov Stansilav return 1; 246*9a6a4193SAlexandrov Stansilav } 247*9a6a4193SAlexandrov Stansilav } 248*9a6a4193SAlexandrov Stansilav 249*9a6a4193SAlexandrov Stansilav return 0; 250*9a6a4193SAlexandrov Stansilav } 251*9a6a4193SAlexandrov Stansilav 252*9a6a4193SAlexandrov Stansilav static int elan_start_multitouch(struct hid_device *hdev) 253*9a6a4193SAlexandrov Stansilav { 254*9a6a4193SAlexandrov Stansilav int ret; 255*9a6a4193SAlexandrov Stansilav 256*9a6a4193SAlexandrov Stansilav /* 257*9a6a4193SAlexandrov Stansilav * This byte sequence will enable multitouch mode and disable 258*9a6a4193SAlexandrov Stansilav * mouse emulation 259*9a6a4193SAlexandrov Stansilav */ 260*9a6a4193SAlexandrov Stansilav const unsigned char buf[] = { 0x0D, 0x00, 0x03, 0x21, 0x00 }; 261*9a6a4193SAlexandrov Stansilav unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL); 262*9a6a4193SAlexandrov Stansilav 263*9a6a4193SAlexandrov Stansilav if (!dmabuf) 264*9a6a4193SAlexandrov Stansilav return -ENOMEM; 265*9a6a4193SAlexandrov Stansilav 266*9a6a4193SAlexandrov Stansilav ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf), 267*9a6a4193SAlexandrov Stansilav HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 268*9a6a4193SAlexandrov Stansilav 269*9a6a4193SAlexandrov Stansilav kfree(dmabuf); 270*9a6a4193SAlexandrov Stansilav 271*9a6a4193SAlexandrov Stansilav if (ret != sizeof(buf)) { 272*9a6a4193SAlexandrov Stansilav hid_err(hdev, "Failed to start multitouch: %d\n", ret); 273*9a6a4193SAlexandrov Stansilav return ret; 274*9a6a4193SAlexandrov Stansilav } 275*9a6a4193SAlexandrov Stansilav 276*9a6a4193SAlexandrov Stansilav return 0; 277*9a6a4193SAlexandrov Stansilav } 278*9a6a4193SAlexandrov Stansilav 279*9a6a4193SAlexandrov Stansilav static enum led_brightness elan_mute_led_get_brigtness(struct led_classdev *led_cdev) 280*9a6a4193SAlexandrov Stansilav { 281*9a6a4193SAlexandrov Stansilav struct device *dev = led_cdev->dev->parent; 282*9a6a4193SAlexandrov Stansilav struct hid_device *hdev = to_hid_device(dev); 283*9a6a4193SAlexandrov Stansilav struct elan_drvdata *drvdata = hid_get_drvdata(hdev); 284*9a6a4193SAlexandrov Stansilav 285*9a6a4193SAlexandrov Stansilav return drvdata->mute_led_state; 286*9a6a4193SAlexandrov Stansilav } 287*9a6a4193SAlexandrov Stansilav 288*9a6a4193SAlexandrov Stansilav static int elan_mute_led_set_brigtness(struct led_classdev *led_cdev, 289*9a6a4193SAlexandrov Stansilav enum led_brightness value) 290*9a6a4193SAlexandrov Stansilav { 291*9a6a4193SAlexandrov Stansilav int ret; 292*9a6a4193SAlexandrov Stansilav u8 led_state; 293*9a6a4193SAlexandrov Stansilav struct device *dev = led_cdev->dev->parent; 294*9a6a4193SAlexandrov Stansilav struct hid_device *hdev = to_hid_device(dev); 295*9a6a4193SAlexandrov Stansilav struct elan_drvdata *drvdata = hid_get_drvdata(hdev); 296*9a6a4193SAlexandrov Stansilav 297*9a6a4193SAlexandrov Stansilav unsigned char *dmabuf = kzalloc(ELAN_LED_REPORT_SIZE, GFP_KERNEL); 298*9a6a4193SAlexandrov Stansilav 299*9a6a4193SAlexandrov Stansilav if (!dmabuf) 300*9a6a4193SAlexandrov Stansilav return -ENOMEM; 301*9a6a4193SAlexandrov Stansilav 302*9a6a4193SAlexandrov Stansilav led_state = !!value; 303*9a6a4193SAlexandrov Stansilav 304*9a6a4193SAlexandrov Stansilav dmabuf[0] = ELAN_MUTE_LED_REPORT; 305*9a6a4193SAlexandrov Stansilav dmabuf[1] = 0x02; 306*9a6a4193SAlexandrov Stansilav dmabuf[2] = led_state; 307*9a6a4193SAlexandrov Stansilav 308*9a6a4193SAlexandrov Stansilav ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, ELAN_LED_REPORT_SIZE, 309*9a6a4193SAlexandrov Stansilav HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 310*9a6a4193SAlexandrov Stansilav 311*9a6a4193SAlexandrov Stansilav kfree(dmabuf); 312*9a6a4193SAlexandrov Stansilav 313*9a6a4193SAlexandrov Stansilav if (ret != ELAN_LED_REPORT_SIZE) { 314*9a6a4193SAlexandrov Stansilav hid_err(hdev, "Failed to set mute led brightness: %d\n", ret); 315*9a6a4193SAlexandrov Stansilav return ret; 316*9a6a4193SAlexandrov Stansilav } 317*9a6a4193SAlexandrov Stansilav 318*9a6a4193SAlexandrov Stansilav drvdata->mute_led_state = led_state; 319*9a6a4193SAlexandrov Stansilav return 0; 320*9a6a4193SAlexandrov Stansilav } 321*9a6a4193SAlexandrov Stansilav 322*9a6a4193SAlexandrov Stansilav static int elan_init_mute_led(struct hid_device *hdev) 323*9a6a4193SAlexandrov Stansilav { 324*9a6a4193SAlexandrov Stansilav struct elan_drvdata *drvdata = hid_get_drvdata(hdev); 325*9a6a4193SAlexandrov Stansilav struct led_classdev *mute_led = &drvdata->mute_led; 326*9a6a4193SAlexandrov Stansilav 327*9a6a4193SAlexandrov Stansilav mute_led->name = "elan:red:mute"; 328*9a6a4193SAlexandrov Stansilav mute_led->brightness_get = elan_mute_led_get_brigtness; 329*9a6a4193SAlexandrov Stansilav mute_led->brightness_set_blocking = elan_mute_led_set_brigtness; 330*9a6a4193SAlexandrov Stansilav mute_led->max_brightness = LED_ON; 331*9a6a4193SAlexandrov Stansilav mute_led->dev = &hdev->dev; 332*9a6a4193SAlexandrov Stansilav 333*9a6a4193SAlexandrov Stansilav return devm_led_classdev_register(&hdev->dev, mute_led); 334*9a6a4193SAlexandrov Stansilav } 335*9a6a4193SAlexandrov Stansilav 336*9a6a4193SAlexandrov Stansilav static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id) 337*9a6a4193SAlexandrov Stansilav { 338*9a6a4193SAlexandrov Stansilav int ret; 339*9a6a4193SAlexandrov Stansilav struct elan_drvdata *drvdata; 340*9a6a4193SAlexandrov Stansilav 341*9a6a4193SAlexandrov Stansilav drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); 342*9a6a4193SAlexandrov Stansilav 343*9a6a4193SAlexandrov Stansilav if (!drvdata) 344*9a6a4193SAlexandrov Stansilav return -ENOMEM; 345*9a6a4193SAlexandrov Stansilav 346*9a6a4193SAlexandrov Stansilav drvdata->settings = (struct elan_touchpad_settings *)id->driver_data; 347*9a6a4193SAlexandrov Stansilav hid_set_drvdata(hdev, drvdata); 348*9a6a4193SAlexandrov Stansilav 349*9a6a4193SAlexandrov Stansilav ret = hid_parse(hdev); 350*9a6a4193SAlexandrov Stansilav if (ret) { 351*9a6a4193SAlexandrov Stansilav hid_err(hdev, "Hid Parse failed\n"); 352*9a6a4193SAlexandrov Stansilav return ret; 353*9a6a4193SAlexandrov Stansilav } 354*9a6a4193SAlexandrov Stansilav 355*9a6a4193SAlexandrov Stansilav ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 356*9a6a4193SAlexandrov Stansilav if (ret) { 357*9a6a4193SAlexandrov Stansilav hid_err(hdev, "Hid hw start failed\n"); 358*9a6a4193SAlexandrov Stansilav return ret; 359*9a6a4193SAlexandrov Stansilav } 360*9a6a4193SAlexandrov Stansilav 361*9a6a4193SAlexandrov Stansilav if (is_not_elan_touchpad(hdev)) 362*9a6a4193SAlexandrov Stansilav return 0; 363*9a6a4193SAlexandrov Stansilav 364*9a6a4193SAlexandrov Stansilav if (!drvdata->input) { 365*9a6a4193SAlexandrov Stansilav hid_err(hdev, "Input device is not registred\n"); 366*9a6a4193SAlexandrov Stansilav ret = -ENAVAIL; 367*9a6a4193SAlexandrov Stansilav goto err; 368*9a6a4193SAlexandrov Stansilav } 369*9a6a4193SAlexandrov Stansilav 370*9a6a4193SAlexandrov Stansilav ret = elan_start_multitouch(hdev); 371*9a6a4193SAlexandrov Stansilav if (ret) 372*9a6a4193SAlexandrov Stansilav goto err; 373*9a6a4193SAlexandrov Stansilav 374*9a6a4193SAlexandrov Stansilav ret = elan_init_mute_led(hdev); 375*9a6a4193SAlexandrov Stansilav if (ret) 376*9a6a4193SAlexandrov Stansilav goto err; 377*9a6a4193SAlexandrov Stansilav 378*9a6a4193SAlexandrov Stansilav return 0; 379*9a6a4193SAlexandrov Stansilav err: 380*9a6a4193SAlexandrov Stansilav hid_hw_stop(hdev); 381*9a6a4193SAlexandrov Stansilav return ret; 382*9a6a4193SAlexandrov Stansilav } 383*9a6a4193SAlexandrov Stansilav 384*9a6a4193SAlexandrov Stansilav static void elan_remove(struct hid_device *hdev) 385*9a6a4193SAlexandrov Stansilav { 386*9a6a4193SAlexandrov Stansilav hid_hw_stop(hdev); 387*9a6a4193SAlexandrov Stansilav } 388*9a6a4193SAlexandrov Stansilav 389*9a6a4193SAlexandrov Stansilav static const struct elan_touchpad_settings hp_x2_10_touchpad_data = { 390*9a6a4193SAlexandrov Stansilav .max_fingers = 5, 391*9a6a4193SAlexandrov Stansilav .max_x = 2930, 392*9a6a4193SAlexandrov Stansilav .max_y = 1250, 393*9a6a4193SAlexandrov Stansilav .max_area_x = 15, 394*9a6a4193SAlexandrov Stansilav .max_area_y = 15, 395*9a6a4193SAlexandrov Stansilav .max_w = 255, 396*9a6a4193SAlexandrov Stansilav .usb_bInterfaceNumber = 1, 397*9a6a4193SAlexandrov Stansilav }; 398*9a6a4193SAlexandrov Stansilav 399*9a6a4193SAlexandrov Stansilav static const struct hid_device_id elan_devices[] = { 400*9a6a4193SAlexandrov Stansilav { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER), 401*9a6a4193SAlexandrov Stansilav (kernel_ulong_t)&hp_x2_10_touchpad_data}, 402*9a6a4193SAlexandrov Stansilav { } 403*9a6a4193SAlexandrov Stansilav }; 404*9a6a4193SAlexandrov Stansilav 405*9a6a4193SAlexandrov Stansilav MODULE_DEVICE_TABLE(hid, elan_devices); 406*9a6a4193SAlexandrov Stansilav 407*9a6a4193SAlexandrov Stansilav static struct hid_driver elan_driver = { 408*9a6a4193SAlexandrov Stansilav .name = "elan", 409*9a6a4193SAlexandrov Stansilav .id_table = elan_devices, 410*9a6a4193SAlexandrov Stansilav .input_mapping = elan_input_mapping, 411*9a6a4193SAlexandrov Stansilav .input_configured = elan_input_configured, 412*9a6a4193SAlexandrov Stansilav .raw_event = elan_raw_event, 413*9a6a4193SAlexandrov Stansilav .probe = elan_probe, 414*9a6a4193SAlexandrov Stansilav .remove = elan_remove, 415*9a6a4193SAlexandrov Stansilav }; 416*9a6a4193SAlexandrov Stansilav 417*9a6a4193SAlexandrov Stansilav module_hid_driver(elan_driver); 418*9a6a4193SAlexandrov Stansilav 419*9a6a4193SAlexandrov Stansilav MODULE_LICENSE("GPL"); 420*9a6a4193SAlexandrov Stansilav MODULE_AUTHOR("Alexandrov Stanislav"); 421*9a6a4193SAlexandrov Stansilav MODULE_DESCRIPTION("Driver for HID ELAN Touchpads"); 422