linux/drivers/hid/hid-alps.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) 2016 Masaki Ota <masaki.ota@jp.alps.com>
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms of the GNU General Public License as published by the Free
   6 * Software Foundation; either version 2 of the License, or (at your option)
   7 * any later version.
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/hid.h>
  12#include <linux/input.h>
  13#include <linux/input/mt.h>
  14#include <linux/module.h>
  15#include <asm/unaligned.h>
  16#include "hid-ids.h"
  17
  18/* ALPS Device Product ID */
  19#define HID_PRODUCT_ID_T3_BTNLESS       0xD0C0
  20#define HID_PRODUCT_ID_COSMO            0x1202
  21#define HID_PRODUCT_ID_U1_PTP_1         0x1207
  22#define HID_PRODUCT_ID_U1                       0x1209
  23#define HID_PRODUCT_ID_U1_PTP_2         0x120A
  24#define HID_PRODUCT_ID_U1_DUAL          0x120B
  25#define HID_PRODUCT_ID_T4_BTNLESS       0x120C
  26
  27#define DEV_SINGLEPOINT                         0x01
  28#define DEV_DUALPOINT                           0x02
  29
  30#define U1_MOUSE_REPORT_ID                      0x01 /* Mouse data ReportID */
  31#define U1_ABSOLUTE_REPORT_ID           0x03 /* Absolute data ReportID */
  32#define U1_FEATURE_REPORT_ID            0x05 /* Feature ReportID */
  33#define U1_SP_ABSOLUTE_REPORT_ID        0x06 /* Feature ReportID */
  34
  35#define U1_FEATURE_REPORT_LEN           0x08 /* Feature Report Length */
  36#define U1_FEATURE_REPORT_LEN_ALL       0x0A
  37#define U1_CMD_REGISTER_READ            0xD1
  38#define U1_CMD_REGISTER_WRITE           0xD2
  39
  40#define U1_DEVTYPE_SP_SUPPORT           0x10 /* SP Support */
  41#define U1_DISABLE_DEV                          0x01
  42#define U1_TP_ABS_MODE                          0x02
  43#define U1_SP_ABS_MODE                          0x80
  44
  45#define ADDRESS_U1_DEV_CTRL_1   0x00800040
  46#define ADDRESS_U1_DEVICE_TYP   0x00800043
  47#define ADDRESS_U1_NUM_SENS_X   0x00800047
  48#define ADDRESS_U1_NUM_SENS_Y   0x00800048
  49#define ADDRESS_U1_PITCH_SENS_X 0x00800049
  50#define ADDRESS_U1_PITCH_SENS_Y 0x0080004A
  51#define ADDRESS_U1_RESO_DWN_ABS 0x0080004E
  52#define ADDRESS_U1_PAD_BTN              0x00800052
  53#define ADDRESS_U1_SP_BTN               0x0080009F
  54
  55#define MAX_TOUCHES     5
  56
  57/**
  58 * struct u1_data
  59 *
  60 * @input: pointer to the kernel input device
  61 * @input2: pointer to the kernel input2 device
  62 * @hdev: pointer to the struct hid_device
  63 *
  64 * @dev_ctrl: device control parameter
  65 * @dev_type: device type
  66 * @sen_line_num_x: number of sensor line of X
  67 * @sen_line_num_y: number of sensor line of Y
  68 * @pitch_x: sensor pitch of X
  69 * @pitch_y: sensor pitch of Y
  70 * @resolution: resolution
  71 * @btn_info: button information
  72 * @x_active_len_mm: active area length of X (mm)
  73 * @y_active_len_mm: active area length of Y (mm)
  74 * @x_max: maximum x coordinate value
  75 * @y_max: maximum y coordinate value
  76 * @btn_cnt: number of buttons
  77 * @sp_btn_cnt: number of stick buttons
  78 */
  79struct u1_dev {
  80        struct input_dev *input;
  81        struct input_dev *input2;
  82        struct hid_device *hdev;
  83
  84        u8      dev_ctrl;
  85        u8      dev_type;
  86        u8      sen_line_num_x;
  87        u8      sen_line_num_y;
  88        u8      pitch_x;
  89        u8      pitch_y;
  90        u8      resolution;
  91        u8      btn_info;
  92        u8      sp_btn_info;
  93        u32     x_active_len_mm;
  94        u32     y_active_len_mm;
  95        u32     x_max;
  96        u32     y_max;
  97        u32     btn_cnt;
  98        u32     sp_btn_cnt;
  99};
 100
 101static int u1_read_write_register(struct hid_device *hdev, u32 address,
 102        u8 *read_val, u8 write_val, bool read_flag)
 103{
 104        int ret, i;
 105        u8 check_sum;
 106        u8 *input;
 107        u8 *readbuf;
 108
 109        input = kzalloc(U1_FEATURE_REPORT_LEN, GFP_KERNEL);
 110        if (!input)
 111                return -ENOMEM;
 112
 113        input[0] = U1_FEATURE_REPORT_ID;
 114        if (read_flag) {
 115                input[1] = U1_CMD_REGISTER_READ;
 116                input[6] = 0x00;
 117        } else {
 118                input[1] = U1_CMD_REGISTER_WRITE;
 119                input[6] = write_val;
 120        }
 121
 122        put_unaligned_le32(address, input + 2);
 123
 124        /* Calculate the checksum */
 125        check_sum = U1_FEATURE_REPORT_LEN_ALL;
 126        for (i = 0; i < U1_FEATURE_REPORT_LEN - 1; i++)
 127                check_sum += input[i];
 128
 129        input[7] = check_sum;
 130        ret = hid_hw_raw_request(hdev, U1_FEATURE_REPORT_ID, input,
 131                        U1_FEATURE_REPORT_LEN,
 132                        HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 133
 134        if (ret < 0) {
 135                dev_err(&hdev->dev, "failed to read command (%d)\n", ret);
 136                goto exit;
 137        }
 138
 139        if (read_flag) {
 140                readbuf = kzalloc(U1_FEATURE_REPORT_LEN, GFP_KERNEL);
 141                if (!readbuf) {
 142                        ret = -ENOMEM;
 143                        goto exit;
 144                }
 145
 146                ret = hid_hw_raw_request(hdev, U1_FEATURE_REPORT_ID, readbuf,
 147                                U1_FEATURE_REPORT_LEN,
 148                                HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 149
 150                if (ret < 0) {
 151                        dev_err(&hdev->dev, "failed read register (%d)\n", ret);
 152                        kfree(readbuf);
 153                        goto exit;
 154                }
 155
 156                *read_val = readbuf[6];
 157
 158                kfree(readbuf);
 159        }
 160
 161        ret = 0;
 162
 163exit:
 164        kfree(input);
 165        return ret;
 166}
 167
 168static int alps_raw_event(struct hid_device *hdev,
 169                struct hid_report *report, u8 *data, int size)
 170{
 171        unsigned int x, y, z;
 172        int i;
 173        short sp_x, sp_y;
 174        struct u1_dev *hdata = hid_get_drvdata(hdev);
 175
 176        switch (data[0]) {
 177        case U1_MOUSE_REPORT_ID:
 178                break;
 179        case U1_FEATURE_REPORT_ID:
 180                break;
 181        case U1_ABSOLUTE_REPORT_ID:
 182                for (i = 0; i < MAX_TOUCHES; i++) {
 183                        u8 *contact = &data[i * 5];
 184
 185                        x = get_unaligned_le16(contact + 3);
 186                        y = get_unaligned_le16(contact + 5);
 187                        z = contact[7] & 0x7F;
 188
 189                        input_mt_slot(hdata->input, i);
 190
 191                        if (z != 0) {
 192                                input_mt_report_slot_state(hdata->input,
 193                                        MT_TOOL_FINGER, 1);
 194                                input_report_abs(hdata->input,
 195                                        ABS_MT_POSITION_X, x);
 196                                input_report_abs(hdata->input,
 197                                        ABS_MT_POSITION_Y, y);
 198                                input_report_abs(hdata->input,
 199                                        ABS_MT_PRESSURE, z);
 200                        } else {
 201                                input_mt_report_slot_state(hdata->input,
 202                                        MT_TOOL_FINGER, 0);
 203                        }
 204                }
 205
 206                input_mt_sync_frame(hdata->input);
 207
 208                input_report_key(hdata->input, BTN_LEFT,
 209                        data[1] & 0x1);
 210                input_report_key(hdata->input, BTN_RIGHT,
 211                        (data[1] & 0x2));
 212                input_report_key(hdata->input, BTN_MIDDLE,
 213                        (data[1] & 0x4));
 214
 215                input_sync(hdata->input);
 216
 217                return 1;
 218
 219        case U1_SP_ABSOLUTE_REPORT_ID:
 220                sp_x = get_unaligned_le16(data+2);
 221                sp_y = get_unaligned_le16(data+4);
 222
 223                sp_x = sp_x / 8;
 224                sp_y = sp_y / 8;
 225
 226                input_report_rel(hdata->input2, REL_X, sp_x);
 227                input_report_rel(hdata->input2, REL_Y, sp_y);
 228
 229                input_report_key(hdata->input2, BTN_LEFT,
 230                        data[1] & 0x1);
 231                input_report_key(hdata->input2, BTN_RIGHT,
 232                        (data[1] & 0x2));
 233                input_report_key(hdata->input2, BTN_MIDDLE,
 234                        (data[1] & 0x4));
 235
 236                input_sync(hdata->input2);
 237
 238                return 1;
 239        }
 240
 241        return 0;
 242}
 243
 244#ifdef CONFIG_PM
 245static int alps_post_reset(struct hid_device *hdev)
 246{
 247        return u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
 248                                NULL, U1_TP_ABS_MODE | U1_SP_ABS_MODE, false);
 249}
 250
 251static int alps_post_resume(struct hid_device *hdev)
 252{
 253        return u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
 254                                NULL, U1_TP_ABS_MODE | U1_SP_ABS_MODE, false);
 255}
 256#endif /* CONFIG_PM */
 257
 258static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
 259{
 260        struct u1_dev *data = hid_get_drvdata(hdev);
 261        struct input_dev *input = hi->input, *input2;
 262        struct u1_dev devInfo;
 263        int ret;
 264        int res_x, res_y, i;
 265
 266        data->input = input;
 267
 268        hid_dbg(hdev, "Opening low level driver\n");
 269        ret = hid_hw_open(hdev);
 270        if (ret)
 271                return ret;
 272
 273        /* Allow incoming hid reports */
 274        hid_device_io_start(hdev);
 275
 276        /* Device initialization */
 277        ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
 278                        &devInfo.dev_ctrl, 0, true);
 279        if (ret < 0) {
 280                dev_err(&hdev->dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
 281                goto exit;
 282        }
 283
 284        devInfo.dev_ctrl &= ~U1_DISABLE_DEV;
 285        devInfo.dev_ctrl |= U1_TP_ABS_MODE;
 286        ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
 287                        NULL, devInfo.dev_ctrl, false);
 288        if (ret < 0) {
 289                dev_err(&hdev->dev, "failed to change TP mode (%d)\n", ret);
 290                goto exit;
 291        }
 292
 293        ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
 294                        &devInfo.sen_line_num_x, 0, true);
 295        if (ret < 0) {
 296                dev_err(&hdev->dev, "failed U1_NUM_SENS_X (%d)\n", ret);
 297                goto exit;
 298        }
 299
 300        ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
 301                        &devInfo.sen_line_num_y, 0, true);
 302                if (ret < 0) {
 303                dev_err(&hdev->dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
 304                goto exit;
 305        }
 306
 307        ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
 308                        &devInfo.pitch_x, 0, true);
 309        if (ret < 0) {
 310                dev_err(&hdev->dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
 311                goto exit;
 312        }
 313
 314        ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
 315                        &devInfo.pitch_y, 0, true);
 316        if (ret < 0) {
 317                dev_err(&hdev->dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
 318                goto exit;
 319        }
 320
 321        ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
 322                &devInfo.resolution, 0, true);
 323        if (ret < 0) {
 324                dev_err(&hdev->dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
 325                goto exit;
 326        }
 327
 328        ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
 329                        &devInfo.btn_info, 0, true);
 330        if (ret < 0) {
 331                dev_err(&hdev->dev, "failed U1_PAD_BTN (%d)\n", ret);
 332                goto exit;
 333        }
 334
 335        /* Check StickPointer device */
 336        ret = u1_read_write_register(hdev, ADDRESS_U1_DEVICE_TYP,
 337                        &devInfo.dev_type, 0, true);
 338        if (ret < 0) {
 339                dev_err(&hdev->dev, "failed U1_DEVICE_TYP (%d)\n", ret);
 340                goto exit;
 341        }
 342
 343        devInfo.x_active_len_mm =
 344                (devInfo.pitch_x * (devInfo.sen_line_num_x - 1)) / 10;
 345        devInfo.y_active_len_mm =
 346                (devInfo.pitch_y * (devInfo.sen_line_num_y - 1)) / 10;
 347
 348        devInfo.x_max =
 349                (devInfo.resolution << 2) * (devInfo.sen_line_num_x - 1);
 350        devInfo.y_max =
 351                (devInfo.resolution << 2) * (devInfo.sen_line_num_y - 1);
 352
 353        __set_bit(EV_ABS, input->evbit);
 354        input_set_abs_params(input, ABS_MT_POSITION_X, 1, devInfo.x_max, 0, 0);
 355        input_set_abs_params(input, ABS_MT_POSITION_Y, 1, devInfo.y_max, 0, 0);
 356
 357        if (devInfo.x_active_len_mm && devInfo.y_active_len_mm) {
 358                res_x = (devInfo.x_max - 1) / devInfo.x_active_len_mm;
 359                res_y = (devInfo.y_max - 1) / devInfo.y_active_len_mm;
 360
 361                input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
 362                input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
 363        }
 364
 365        input_set_abs_params(input, ABS_MT_PRESSURE, 0, 64, 0, 0);
 366
 367        input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_POINTER);
 368
 369        __set_bit(EV_KEY, input->evbit);
 370        if ((devInfo.btn_info & 0x0F) == (devInfo.btn_info & 0xF0) >> 4) {
 371                devInfo.btn_cnt = (devInfo.btn_info & 0x0F);
 372        } else {
 373                /* Button pad */
 374                devInfo.btn_cnt = 1;
 375                __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 376        }
 377
 378        for (i = 0; i < devInfo.btn_cnt; i++)
 379                __set_bit(BTN_LEFT + i, input->keybit);
 380
 381
 382        /* Stick device initialization */
 383        if (devInfo.dev_type & U1_DEVTYPE_SP_SUPPORT) {
 384
 385                input2 = input_allocate_device();
 386                if (!input2) {
 387                        ret = -ENOMEM;
 388                        goto exit;
 389                }
 390
 391                data->input2 = input2;
 392
 393                devInfo.dev_ctrl |= U1_SP_ABS_MODE;
 394                ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
 395                        NULL, devInfo.dev_ctrl, false);
 396                if (ret < 0) {
 397                        dev_err(&hdev->dev, "failed SP mode (%d)\n", ret);
 398                        input_free_device(input2);
 399                        goto exit;
 400                }
 401
 402                ret = u1_read_write_register(hdev, ADDRESS_U1_SP_BTN,
 403                        &devInfo.sp_btn_info, 0, true);
 404                if (ret < 0) {
 405                        dev_err(&hdev->dev, "failed U1_SP_BTN (%d)\n", ret);
 406                        input_free_device(input2);
 407                        goto exit;
 408                }
 409
 410                input2->phys = input->phys;
 411                input2->name = "DualPoint Stick";
 412                input2->id.bustype = BUS_I2C;
 413                input2->id.vendor  = input->id.vendor;
 414                input2->id.product = input->id.product;
 415                input2->id.version = input->id.version;
 416                input2->dev.parent = input->dev.parent;
 417
 418                __set_bit(EV_KEY, input2->evbit);
 419                devInfo.sp_btn_cnt = (devInfo.sp_btn_info & 0x0F);
 420                for (i = 0; i < devInfo.sp_btn_cnt; i++)
 421                        __set_bit(BTN_LEFT + i, input2->keybit);
 422
 423                __set_bit(EV_REL, input2->evbit);
 424                __set_bit(REL_X, input2->relbit);
 425                __set_bit(REL_Y, input2->relbit);
 426                __set_bit(INPUT_PROP_POINTER, input2->propbit);
 427                __set_bit(INPUT_PROP_POINTING_STICK, input2->propbit);
 428
 429                ret = input_register_device(data->input2);
 430                if (ret) {
 431                        input_free_device(input2);
 432                        goto exit;
 433                }
 434        }
 435
 436exit:
 437        hid_device_io_stop(hdev);
 438        hid_hw_close(hdev);
 439        return ret;
 440}
 441
 442static int alps_input_mapping(struct hid_device *hdev,
 443                struct hid_input *hi, struct hid_field *field,
 444                struct hid_usage *usage, unsigned long **bit, int *max)
 445{
 446        return -1;
 447}
 448
 449static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
 450{
 451        struct u1_dev *data = NULL;
 452        int ret;
 453
 454        data = devm_kzalloc(&hdev->dev, sizeof(struct u1_dev), GFP_KERNEL);
 455        if (!data)
 456                return -ENOMEM;
 457
 458        data->hdev = hdev;
 459        hid_set_drvdata(hdev, data);
 460
 461        hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
 462
 463        ret = hid_parse(hdev);
 464        if (ret) {
 465                hid_err(hdev, "parse failed\n");
 466                return ret;
 467        }
 468
 469        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 470        if (ret) {
 471                hid_err(hdev, "hw start failed\n");
 472                return ret;
 473        }
 474
 475        return 0;
 476}
 477
 478static void alps_remove(struct hid_device *hdev)
 479{
 480        hid_hw_stop(hdev);
 481}
 482
 483static const struct hid_device_id alps_id[] = {
 484        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
 485                USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
 486        { }
 487};
 488MODULE_DEVICE_TABLE(hid, alps_id);
 489
 490static struct hid_driver alps_driver = {
 491        .name = "hid-alps",
 492        .id_table               = alps_id,
 493        .probe                  = alps_probe,
 494        .remove                 = alps_remove,
 495        .raw_event              = alps_raw_event,
 496        .input_mapping          = alps_input_mapping,
 497        .input_configured       = alps_input_configured,
 498#ifdef CONFIG_PM
 499        .resume                 = alps_post_resume,
 500        .reset_resume           = alps_post_reset,
 501#endif
 502};
 503
 504module_hid_driver(alps_driver);
 505
 506MODULE_AUTHOR("Masaki Ota <masaki.ota@jp.alps.com>");
 507MODULE_DESCRIPTION("ALPS HID driver");
 508MODULE_LICENSE("GPL");
 509