10b28cb4bSSrinivas Pandruvada /* 20b28cb4bSSrinivas Pandruvada * ISHTP-HID glue driver. 30b28cb4bSSrinivas Pandruvada * 40b28cb4bSSrinivas Pandruvada * Copyright (c) 2012-2016, Intel Corporation. 50b28cb4bSSrinivas Pandruvada * 60b28cb4bSSrinivas Pandruvada * This program is free software; you can redistribute it and/or modify it 70b28cb4bSSrinivas Pandruvada * under the terms and conditions of the GNU General Public License, 80b28cb4bSSrinivas Pandruvada * version 2, as published by the Free Software Foundation. 90b28cb4bSSrinivas Pandruvada * 100b28cb4bSSrinivas Pandruvada * This program is distributed in the hope it will be useful, but WITHOUT 110b28cb4bSSrinivas Pandruvada * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 120b28cb4bSSrinivas Pandruvada * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 130b28cb4bSSrinivas Pandruvada * more details. 140b28cb4bSSrinivas Pandruvada */ 150b28cb4bSSrinivas Pandruvada 160b28cb4bSSrinivas Pandruvada #include <linux/hid.h> 170b28cb4bSSrinivas Pandruvada #include <uapi/linux/input.h> 180b28cb4bSSrinivas Pandruvada #include "ishtp/client.h" 190b28cb4bSSrinivas Pandruvada #include "ishtp-hid.h" 200b28cb4bSSrinivas Pandruvada 210b28cb4bSSrinivas Pandruvada /** 220b28cb4bSSrinivas Pandruvada * ishtp_hid_parse() - hid-core .parse() callback 230b28cb4bSSrinivas Pandruvada * @hid: hid device instance 240b28cb4bSSrinivas Pandruvada * 250b28cb4bSSrinivas Pandruvada * This function gets called during call to hid_add_device 260b28cb4bSSrinivas Pandruvada * 270b28cb4bSSrinivas Pandruvada * Return: 0 on success and non zero on error 280b28cb4bSSrinivas Pandruvada */ 290b28cb4bSSrinivas Pandruvada static int ishtp_hid_parse(struct hid_device *hid) 300b28cb4bSSrinivas Pandruvada { 310b28cb4bSSrinivas Pandruvada struct ishtp_hid_data *hid_data = hid->driver_data; 320b28cb4bSSrinivas Pandruvada struct ishtp_cl_data *client_data = hid_data->client_data; 330b28cb4bSSrinivas Pandruvada int rv; 340b28cb4bSSrinivas Pandruvada 350b28cb4bSSrinivas Pandruvada rv = hid_parse_report(hid, client_data->report_descr[hid_data->index], 360b28cb4bSSrinivas Pandruvada client_data->report_descr_size[hid_data->index]); 370b28cb4bSSrinivas Pandruvada if (rv) 380b28cb4bSSrinivas Pandruvada return rv; 390b28cb4bSSrinivas Pandruvada 400b28cb4bSSrinivas Pandruvada return 0; 410b28cb4bSSrinivas Pandruvada } 420b28cb4bSSrinivas Pandruvada 430b28cb4bSSrinivas Pandruvada /* Empty callbacks with success return code */ 440b28cb4bSSrinivas Pandruvada static int ishtp_hid_start(struct hid_device *hid) 450b28cb4bSSrinivas Pandruvada { 460b28cb4bSSrinivas Pandruvada return 0; 470b28cb4bSSrinivas Pandruvada } 480b28cb4bSSrinivas Pandruvada 490b28cb4bSSrinivas Pandruvada static void ishtp_hid_stop(struct hid_device *hid) 500b28cb4bSSrinivas Pandruvada { 510b28cb4bSSrinivas Pandruvada } 520b28cb4bSSrinivas Pandruvada 530b28cb4bSSrinivas Pandruvada static int ishtp_hid_open(struct hid_device *hid) 540b28cb4bSSrinivas Pandruvada { 550b28cb4bSSrinivas Pandruvada return 0; 560b28cb4bSSrinivas Pandruvada } 570b28cb4bSSrinivas Pandruvada 580b28cb4bSSrinivas Pandruvada static void ishtp_hid_close(struct hid_device *hid) 590b28cb4bSSrinivas Pandruvada { 600b28cb4bSSrinivas Pandruvada } 610b28cb4bSSrinivas Pandruvada 620b28cb4bSSrinivas Pandruvada static int ishtp_raw_request(struct hid_device *hdev, unsigned char reportnum, 630b28cb4bSSrinivas Pandruvada __u8 *buf, size_t len, unsigned char rtype, int reqtype) 640b28cb4bSSrinivas Pandruvada { 650b28cb4bSSrinivas Pandruvada return 0; 660b28cb4bSSrinivas Pandruvada } 670b28cb4bSSrinivas Pandruvada 680b28cb4bSSrinivas Pandruvada /** 690b28cb4bSSrinivas Pandruvada * ishtp_hid_request() - hid-core .request() callback 700b28cb4bSSrinivas Pandruvada * @hid: hid device instance 710b28cb4bSSrinivas Pandruvada * @rep: pointer to hid_report 720b28cb4bSSrinivas Pandruvada * @reqtype: type of req. [GET|SET]_REPORT 730b28cb4bSSrinivas Pandruvada * 740b28cb4bSSrinivas Pandruvada * This function is used to set/get feaure/input report. 750b28cb4bSSrinivas Pandruvada */ 760b28cb4bSSrinivas Pandruvada static void ishtp_hid_request(struct hid_device *hid, struct hid_report *rep, 770b28cb4bSSrinivas Pandruvada int reqtype) 780b28cb4bSSrinivas Pandruvada { 790b28cb4bSSrinivas Pandruvada struct ishtp_hid_data *hid_data = hid->driver_data; 800b28cb4bSSrinivas Pandruvada /* the specific report length, just HID part of it */ 810b28cb4bSSrinivas Pandruvada unsigned int len = ((rep->size - 1) >> 3) + 1 + (rep->id > 0); 820b28cb4bSSrinivas Pandruvada char *buf; 830b28cb4bSSrinivas Pandruvada unsigned int header_size = sizeof(struct hostif_msg); 840b28cb4bSSrinivas Pandruvada 850b28cb4bSSrinivas Pandruvada len += header_size; 860b28cb4bSSrinivas Pandruvada 870b28cb4bSSrinivas Pandruvada hid_data->request_done = false; 880b28cb4bSSrinivas Pandruvada switch (reqtype) { 890b28cb4bSSrinivas Pandruvada case HID_REQ_GET_REPORT: 900b28cb4bSSrinivas Pandruvada hid_ishtp_get_report(hid, rep->id, rep->type); 910b28cb4bSSrinivas Pandruvada break; 920b28cb4bSSrinivas Pandruvada case HID_REQ_SET_REPORT: 930b28cb4bSSrinivas Pandruvada /* 940b28cb4bSSrinivas Pandruvada * Spare 7 bytes for 64b accesses through 950b28cb4bSSrinivas Pandruvada * get/put_unaligned_le64() 960b28cb4bSSrinivas Pandruvada */ 970b28cb4bSSrinivas Pandruvada buf = kzalloc(len + 7, GFP_KERNEL); 980b28cb4bSSrinivas Pandruvada if (!buf) 990b28cb4bSSrinivas Pandruvada return; 1000b28cb4bSSrinivas Pandruvada 1010b28cb4bSSrinivas Pandruvada hid_output_report(rep, buf + header_size); 1020b28cb4bSSrinivas Pandruvada hid_ishtp_set_feature(hid, buf, len, rep->id); 1030b28cb4bSSrinivas Pandruvada kfree(buf); 1040b28cb4bSSrinivas Pandruvada break; 1050b28cb4bSSrinivas Pandruvada } 1060b28cb4bSSrinivas Pandruvada } 1070b28cb4bSSrinivas Pandruvada 1080b28cb4bSSrinivas Pandruvada /** 1090b28cb4bSSrinivas Pandruvada * ishtp_wait_for_response() - hid-core .wait() callback 1100b28cb4bSSrinivas Pandruvada * @hid: hid device instance 1110b28cb4bSSrinivas Pandruvada * 1120b28cb4bSSrinivas Pandruvada * This function is used to wait after get feaure/input report. 1130b28cb4bSSrinivas Pandruvada * 1140b28cb4bSSrinivas Pandruvada * Return: 0 on success and non zero on error 1150b28cb4bSSrinivas Pandruvada */ 1160b28cb4bSSrinivas Pandruvada static int ishtp_wait_for_response(struct hid_device *hid) 1170b28cb4bSSrinivas Pandruvada { 1180b28cb4bSSrinivas Pandruvada struct ishtp_hid_data *hid_data = hid->driver_data; 1190b28cb4bSSrinivas Pandruvada struct ishtp_cl_data *client_data = hid_data->client_data; 1200b28cb4bSSrinivas Pandruvada int rv; 1210b28cb4bSSrinivas Pandruvada 1220b28cb4bSSrinivas Pandruvada hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid); 1230b28cb4bSSrinivas Pandruvada 1240b28cb4bSSrinivas Pandruvada rv = ishtp_hid_link_ready_wait(hid_data->client_data); 1250b28cb4bSSrinivas Pandruvada if (rv) 1260b28cb4bSSrinivas Pandruvada return rv; 1270b28cb4bSSrinivas Pandruvada 1280b28cb4bSSrinivas Pandruvada if (!hid_data->request_done) 1290b28cb4bSSrinivas Pandruvada wait_event_interruptible_timeout(hid_data->hid_wait, 1300b28cb4bSSrinivas Pandruvada hid_data->request_done, 3 * HZ); 1310b28cb4bSSrinivas Pandruvada 1320b28cb4bSSrinivas Pandruvada if (!hid_data->request_done) { 1330b28cb4bSSrinivas Pandruvada hid_err(hid, 1340b28cb4bSSrinivas Pandruvada "timeout waiting for response from ISHTP device\n"); 1350b28cb4bSSrinivas Pandruvada return -ETIMEDOUT; 1360b28cb4bSSrinivas Pandruvada } 1370b28cb4bSSrinivas Pandruvada hid_ishtp_trace(client_data, "%s hid %p done\n", __func__, hid); 1380b28cb4bSSrinivas Pandruvada 1390b28cb4bSSrinivas Pandruvada hid_data->request_done = false; 1400b28cb4bSSrinivas Pandruvada 1410b28cb4bSSrinivas Pandruvada return 0; 1420b28cb4bSSrinivas Pandruvada } 1430b28cb4bSSrinivas Pandruvada 1440b28cb4bSSrinivas Pandruvada /** 1450b28cb4bSSrinivas Pandruvada * ishtp_hid_wakeup() - Wakeup caller 1460b28cb4bSSrinivas Pandruvada * @hid: hid device instance 1470b28cb4bSSrinivas Pandruvada * 1480b28cb4bSSrinivas Pandruvada * This function will wakeup caller waiting for Get/Set feature report 1490b28cb4bSSrinivas Pandruvada */ 1500b28cb4bSSrinivas Pandruvada void ishtp_hid_wakeup(struct hid_device *hid) 1510b28cb4bSSrinivas Pandruvada { 1520b28cb4bSSrinivas Pandruvada struct ishtp_hid_data *hid_data = hid->driver_data; 1530b28cb4bSSrinivas Pandruvada 1540b28cb4bSSrinivas Pandruvada hid_data->request_done = true; 1550b28cb4bSSrinivas Pandruvada wake_up_interruptible(&hid_data->hid_wait); 1560b28cb4bSSrinivas Pandruvada } 1570b28cb4bSSrinivas Pandruvada 1580b28cb4bSSrinivas Pandruvada static struct hid_ll_driver ishtp_hid_ll_driver = { 1590b28cb4bSSrinivas Pandruvada .parse = ishtp_hid_parse, 1600b28cb4bSSrinivas Pandruvada .start = ishtp_hid_start, 1610b28cb4bSSrinivas Pandruvada .stop = ishtp_hid_stop, 1620b28cb4bSSrinivas Pandruvada .open = ishtp_hid_open, 1630b28cb4bSSrinivas Pandruvada .close = ishtp_hid_close, 1640b28cb4bSSrinivas Pandruvada .request = ishtp_hid_request, 1650b28cb4bSSrinivas Pandruvada .wait = ishtp_wait_for_response, 1660b28cb4bSSrinivas Pandruvada .raw_request = ishtp_raw_request 1670b28cb4bSSrinivas Pandruvada }; 1680b28cb4bSSrinivas Pandruvada 1690b28cb4bSSrinivas Pandruvada /** 1700b28cb4bSSrinivas Pandruvada * ishtp_hid_probe() - hid register ll driver 1710b28cb4bSSrinivas Pandruvada * @cur_hid_dev: Index of hid device calling to register 1720b28cb4bSSrinivas Pandruvada * @client_data: Client data pointer 1730b28cb4bSSrinivas Pandruvada * 1740b28cb4bSSrinivas Pandruvada * This function is used to allocate and add HID device. 1750b28cb4bSSrinivas Pandruvada * 1760b28cb4bSSrinivas Pandruvada * Return: 0 on success, non zero on error 1770b28cb4bSSrinivas Pandruvada */ 1780b28cb4bSSrinivas Pandruvada int ishtp_hid_probe(unsigned int cur_hid_dev, 1790b28cb4bSSrinivas Pandruvada struct ishtp_cl_data *client_data) 1800b28cb4bSSrinivas Pandruvada { 1810b28cb4bSSrinivas Pandruvada int rv; 1820b28cb4bSSrinivas Pandruvada struct hid_device *hid; 1830b28cb4bSSrinivas Pandruvada struct ishtp_hid_data *hid_data; 1840b28cb4bSSrinivas Pandruvada 1850b28cb4bSSrinivas Pandruvada hid = hid_allocate_device(); 1860b28cb4bSSrinivas Pandruvada if (IS_ERR(hid)) { 1870b28cb4bSSrinivas Pandruvada rv = PTR_ERR(hid); 1880b28cb4bSSrinivas Pandruvada return -ENOMEM; 1890b28cb4bSSrinivas Pandruvada } 1900b28cb4bSSrinivas Pandruvada 1910b28cb4bSSrinivas Pandruvada hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL); 1920b28cb4bSSrinivas Pandruvada if (!hid_data) { 1930b28cb4bSSrinivas Pandruvada rv = -ENOMEM; 1940b28cb4bSSrinivas Pandruvada goto err_hid_data; 1950b28cb4bSSrinivas Pandruvada } 1960b28cb4bSSrinivas Pandruvada 1970b28cb4bSSrinivas Pandruvada hid_data->index = cur_hid_dev; 1980b28cb4bSSrinivas Pandruvada hid_data->client_data = client_data; 1990b28cb4bSSrinivas Pandruvada init_waitqueue_head(&hid_data->hid_wait); 2000b28cb4bSSrinivas Pandruvada 2010b28cb4bSSrinivas Pandruvada hid->driver_data = hid_data; 2020b28cb4bSSrinivas Pandruvada 2030b28cb4bSSrinivas Pandruvada client_data->hid_sensor_hubs[cur_hid_dev] = hid; 2040b28cb4bSSrinivas Pandruvada 2050b28cb4bSSrinivas Pandruvada hid->ll_driver = &ishtp_hid_ll_driver; 2060b28cb4bSSrinivas Pandruvada hid->bus = BUS_INTEL_ISHTP; 2070b28cb4bSSrinivas Pandruvada hid->dev.parent = &client_data->cl_device->dev; 2080b28cb4bSSrinivas Pandruvada hid->version = le16_to_cpu(ISH_HID_VERSION); 209*1578461aSSrinivas Pandruvada hid->vendor = le16_to_cpu(client_data->hid_devices[cur_hid_dev].vid); 210*1578461aSSrinivas Pandruvada hid->product = le16_to_cpu(client_data->hid_devices[cur_hid_dev].pid); 2115299a92aSNicolas Iooss snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-ishtp", 2120b28cb4bSSrinivas Pandruvada hid->vendor, hid->product); 2130b28cb4bSSrinivas Pandruvada 2140b28cb4bSSrinivas Pandruvada rv = hid_add_device(hid); 2150b28cb4bSSrinivas Pandruvada if (rv) 2160b28cb4bSSrinivas Pandruvada goto err_hid_device; 2170b28cb4bSSrinivas Pandruvada 2180b28cb4bSSrinivas Pandruvada hid_ishtp_trace(client_data, "%s allocated hid %p\n", __func__, hid); 2190b28cb4bSSrinivas Pandruvada 2200b28cb4bSSrinivas Pandruvada return 0; 2210b28cb4bSSrinivas Pandruvada 2220b28cb4bSSrinivas Pandruvada err_hid_device: 2230b28cb4bSSrinivas Pandruvada kfree(hid_data); 2240b28cb4bSSrinivas Pandruvada err_hid_data: 2256e0856d3SPan Bian hid_destroy_device(hid); 2260b28cb4bSSrinivas Pandruvada return rv; 2270b28cb4bSSrinivas Pandruvada } 2280b28cb4bSSrinivas Pandruvada 2290b28cb4bSSrinivas Pandruvada /** 2300b28cb4bSSrinivas Pandruvada * ishtp_hid_probe() - Remove registered hid device 2310b28cb4bSSrinivas Pandruvada * @client_data: client data pointer 2320b28cb4bSSrinivas Pandruvada * 2330b28cb4bSSrinivas Pandruvada * This function is used to destroy allocatd HID device. 2340b28cb4bSSrinivas Pandruvada */ 2350b28cb4bSSrinivas Pandruvada void ishtp_hid_remove(struct ishtp_cl_data *client_data) 2360b28cb4bSSrinivas Pandruvada { 2370b28cb4bSSrinivas Pandruvada int i; 2380b28cb4bSSrinivas Pandruvada 2390b28cb4bSSrinivas Pandruvada for (i = 0; i < client_data->num_hid_devices; ++i) { 2400b28cb4bSSrinivas Pandruvada if (client_data->hid_sensor_hubs[i]) { 2410b28cb4bSSrinivas Pandruvada kfree(client_data->hid_sensor_hubs[i]->driver_data); 2420b28cb4bSSrinivas Pandruvada hid_destroy_device(client_data->hid_sensor_hubs[i]); 2430b28cb4bSSrinivas Pandruvada client_data->hid_sensor_hubs[i] = NULL; 2440b28cb4bSSrinivas Pandruvada } 2450b28cb4bSSrinivas Pandruvada } 2460b28cb4bSSrinivas Pandruvada } 247