linux/drivers/hid/intel-ish-hid/ishtp-hid.c
<<
>>
Prefs
   1/*
   2 * ISHTP-HID glue driver.
   3 *
   4 * Copyright (c) 2012-2016, Intel Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13 * more details.
  14 */
  15
  16#include <linux/hid.h>
  17#include <uapi/linux/input.h>
  18#include "ishtp/client.h"
  19#include "ishtp-hid.h"
  20
  21/**
  22 * ishtp_hid_parse() - hid-core .parse() callback
  23 * @hid:        hid device instance
  24 *
  25 * This function gets called during call to hid_add_device
  26 *
  27 * Return: 0 on success and non zero on error
  28 */
  29static int ishtp_hid_parse(struct hid_device *hid)
  30{
  31        struct ishtp_hid_data *hid_data =  hid->driver_data;
  32        struct ishtp_cl_data *client_data = hid_data->client_data;
  33        int rv;
  34
  35        rv = hid_parse_report(hid, client_data->report_descr[hid_data->index],
  36                              client_data->report_descr_size[hid_data->index]);
  37        if (rv)
  38                return  rv;
  39
  40        return 0;
  41}
  42
  43/* Empty callbacks with success return code */
  44static int ishtp_hid_start(struct hid_device *hid)
  45{
  46        return 0;
  47}
  48
  49static void ishtp_hid_stop(struct hid_device *hid)
  50{
  51}
  52
  53static int ishtp_hid_open(struct hid_device *hid)
  54{
  55        return 0;
  56}
  57
  58static void ishtp_hid_close(struct hid_device *hid)
  59{
  60}
  61
  62static int ishtp_raw_request(struct hid_device *hdev, unsigned char reportnum,
  63        __u8 *buf, size_t len, unsigned char rtype, int reqtype)
  64{
  65        return 0;
  66}
  67
  68/**
  69 * ishtp_hid_request() - hid-core .request() callback
  70 * @hid:        hid device instance
  71 * @rep:        pointer to hid_report
  72 * @reqtype:    type of req. [GET|SET]_REPORT
  73 *
  74 * This function is used to set/get feaure/input report.
  75 */
  76static void ishtp_hid_request(struct hid_device *hid, struct hid_report *rep,
  77        int reqtype)
  78{
  79        struct ishtp_hid_data *hid_data =  hid->driver_data;
  80        /* the specific report length, just HID part of it */
  81        unsigned int len = ((rep->size - 1) >> 3) + 1 + (rep->id > 0);
  82        char *buf;
  83        unsigned int header_size = sizeof(struct hostif_msg);
  84
  85        len += header_size;
  86
  87        hid_data->request_done = false;
  88        switch (reqtype) {
  89        case HID_REQ_GET_REPORT:
  90                hid_ishtp_get_report(hid, rep->id, rep->type);
  91                break;
  92        case HID_REQ_SET_REPORT:
  93                /*
  94                 * Spare 7 bytes for 64b accesses through
  95                 * get/put_unaligned_le64()
  96                 */
  97                buf = kzalloc(len + 7, GFP_KERNEL);
  98                if (!buf)
  99                        return;
 100
 101                hid_output_report(rep, buf + header_size);
 102                hid_ishtp_set_feature(hid, buf, len, rep->id);
 103                kfree(buf);
 104                break;
 105        }
 106}
 107
 108/**
 109 * ishtp_wait_for_response() - hid-core .wait() callback
 110 * @hid:        hid device instance
 111 *
 112 * This function is used to wait after get feaure/input report.
 113 *
 114 * Return: 0 on success and non zero on error
 115 */
 116static int ishtp_wait_for_response(struct hid_device *hid)
 117{
 118        struct ishtp_hid_data *hid_data =  hid->driver_data;
 119        struct ishtp_cl_data *client_data = hid_data->client_data;
 120        int rv;
 121
 122        hid_ishtp_trace(client_data,  "%s hid %p\n", __func__, hid);
 123
 124        rv = ishtp_hid_link_ready_wait(hid_data->client_data);
 125        if (rv)
 126                return rv;
 127
 128        if (!hid_data->request_done)
 129                wait_event_interruptible_timeout(hid_data->hid_wait,
 130                                        hid_data->request_done, 3 * HZ);
 131
 132        if (!hid_data->request_done) {
 133                hid_err(hid,
 134                        "timeout waiting for response from ISHTP device\n");
 135                return -ETIMEDOUT;
 136        }
 137        hid_ishtp_trace(client_data,  "%s hid %p done\n", __func__, hid);
 138
 139        hid_data->request_done = false;
 140
 141        return 0;
 142}
 143
 144/**
 145 * ishtp_hid_wakeup() - Wakeup caller
 146 * @hid:        hid device instance
 147 *
 148 * This function will wakeup caller waiting for Get/Set feature report
 149 */
 150void ishtp_hid_wakeup(struct hid_device *hid)
 151{
 152        struct ishtp_hid_data *hid_data = hid->driver_data;
 153
 154        hid_data->request_done = true;
 155        wake_up_interruptible(&hid_data->hid_wait);
 156}
 157
 158static struct hid_ll_driver ishtp_hid_ll_driver = {
 159        .parse = ishtp_hid_parse,
 160        .start = ishtp_hid_start,
 161        .stop = ishtp_hid_stop,
 162        .open = ishtp_hid_open,
 163        .close = ishtp_hid_close,
 164        .request = ishtp_hid_request,
 165        .wait = ishtp_wait_for_response,
 166        .raw_request = ishtp_raw_request
 167};
 168
 169/**
 170 * ishtp_hid_probe() - hid register ll driver
 171 * @cur_hid_dev:        Index of hid device calling to register
 172 * @client_data:        Client data pointer
 173 *
 174 * This function is used to allocate and add HID device.
 175 *
 176 * Return: 0 on success, non zero on error
 177 */
 178int ishtp_hid_probe(unsigned int cur_hid_dev,
 179                    struct ishtp_cl_data *client_data)
 180{
 181        int rv;
 182        struct hid_device *hid;
 183        struct ishtp_hid_data *hid_data;
 184
 185        hid = hid_allocate_device();
 186        if (IS_ERR(hid)) {
 187                rv = PTR_ERR(hid);
 188                return  -ENOMEM;
 189        }
 190
 191        hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL);
 192        if (!hid_data) {
 193                rv = -ENOMEM;
 194                goto err_hid_data;
 195        }
 196
 197        hid_data->index = cur_hid_dev;
 198        hid_data->client_data = client_data;
 199        init_waitqueue_head(&hid_data->hid_wait);
 200
 201        hid->driver_data = hid_data;
 202
 203        client_data->hid_sensor_hubs[cur_hid_dev] = hid;
 204
 205        hid->ll_driver = &ishtp_hid_ll_driver;
 206        hid->bus = BUS_INTEL_ISHTP;
 207        hid->dev.parent = &client_data->cl_device->dev;
 208        hid->version = le16_to_cpu(ISH_HID_VERSION);
 209        hid->vendor = le16_to_cpu(ISH_HID_VENDOR);
 210        hid->product = le16_to_cpu(ISH_HID_PRODUCT);
 211        snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-ishtp",
 212                hid->vendor, hid->product);
 213
 214        rv = hid_add_device(hid);
 215        if (rv)
 216                goto err_hid_device;
 217
 218        hid_ishtp_trace(client_data,  "%s allocated hid %p\n", __func__, hid);
 219
 220        return 0;
 221
 222err_hid_device:
 223        kfree(hid_data);
 224err_hid_data:
 225        kfree(hid);
 226        return rv;
 227}
 228
 229/**
 230 * ishtp_hid_probe() - Remove registered hid device
 231 * @client_data:        client data pointer
 232 *
 233 * This function is used to destroy allocatd HID device.
 234 */
 235void ishtp_hid_remove(struct ishtp_cl_data *client_data)
 236{
 237        int i;
 238
 239        for (i = 0; i < client_data->num_hid_devices; ++i) {
 240                if (client_data->hid_sensor_hubs[i]) {
 241                        kfree(client_data->hid_sensor_hubs[i]->driver_data);
 242                        hid_destroy_device(client_data->hid_sensor_hubs[i]);
 243                        client_data->hid_sensor_hubs[i] = NULL;
 244                }
 245        }
 246}
 247