linux/drivers/hid/intel-ish-hid/ishtp-hid-client.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ISHTP client driver for HID (ISH)
   4 *
   5 * Copyright (c) 2014-2016, Intel Corporation.
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/hid.h>
  10#include <linux/intel-ish-client-if.h>
  11#include <linux/sched.h>
  12#include "ishtp-hid.h"
  13
  14/* Rx ring buffer pool size */
  15#define HID_CL_RX_RING_SIZE     32
  16#define HID_CL_TX_RING_SIZE     16
  17
  18#define cl_data_to_dev(client_data) ishtp_device(client_data->cl_device)
  19
  20/**
  21 * report_bad_packets() - Report bad packets
  22 * @hid_ishtp_cl:       Client instance to get stats
  23 * @recv_buf:           Raw received host interface message
  24 * @cur_pos:            Current position index in payload
  25 * @payload_len:        Length of payload expected
  26 *
  27 * Dumps error in case bad packet is received
  28 */
  29static void report_bad_packet(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
  30                              size_t cur_pos,  size_t payload_len)
  31{
  32        struct hostif_msg *recv_msg = recv_buf;
  33        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
  34
  35        dev_err(cl_data_to_dev(client_data), "[hid-ish]: BAD packet %02X\n"
  36                "total_bad=%u cur_pos=%u\n"
  37                "[%02X %02X %02X %02X]\n"
  38                "payload_len=%u\n"
  39                "multi_packet_cnt=%u\n"
  40                "is_response=%02X\n",
  41                recv_msg->hdr.command, client_data->bad_recv_cnt,
  42                (unsigned int)cur_pos,
  43                ((unsigned char *)recv_msg)[0], ((unsigned char *)recv_msg)[1],
  44                ((unsigned char *)recv_msg)[2], ((unsigned char *)recv_msg)[3],
  45                (unsigned int)payload_len, client_data->multi_packet_cnt,
  46                recv_msg->hdr.command & ~CMD_MASK);
  47}
  48
  49/**
  50 * process_recv() - Received and parse incoming packet
  51 * @hid_ishtp_cl:       Client instance to get stats
  52 * @recv_buf:           Raw received host interface message
  53 * @data_len:           length of the message
  54 *
  55 * Parse the incoming packet. If it is a response packet then it will update
  56 * per instance flags and wake up the caller waiting to for the response.
  57 */
  58static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
  59                         size_t data_len)
  60{
  61        struct hostif_msg *recv_msg;
  62        unsigned char *payload;
  63        struct device_info *dev_info;
  64        int i, j;
  65        size_t  payload_len, total_len, cur_pos, raw_len;
  66        int report_type;
  67        struct report_list *reports_list;
  68        char *reports;
  69        size_t report_len;
  70        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
  71        int curr_hid_dev = client_data->cur_hid_dev;
  72        struct ishtp_hid_data *hid_data = NULL;
  73        struct hid_device *hid = NULL;
  74
  75        payload = recv_buf + sizeof(struct hostif_msg_hdr);
  76        total_len = data_len;
  77        cur_pos = 0;
  78
  79        do {
  80                if (cur_pos + sizeof(struct hostif_msg) > total_len) {
  81                        dev_err(cl_data_to_dev(client_data),
  82                                "[hid-ish]: error, received %u which is less than data header %u\n",
  83                                (unsigned int)data_len,
  84                                (unsigned int)sizeof(struct hostif_msg_hdr));
  85                        ++client_data->bad_recv_cnt;
  86                        ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
  87                        break;
  88                }
  89
  90                recv_msg = (struct hostif_msg *)(recv_buf + cur_pos);
  91                payload_len = recv_msg->hdr.size;
  92
  93                /* Sanity checks */
  94                if (cur_pos + payload_len + sizeof(struct hostif_msg) >
  95                                total_len) {
  96                        ++client_data->bad_recv_cnt;
  97                        report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
  98                                          payload_len);
  99                        ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
 100                        break;
 101                }
 102
 103                hid_ishtp_trace(client_data,  "%s %d\n",
 104                                __func__, recv_msg->hdr.command & CMD_MASK);
 105
 106                switch (recv_msg->hdr.command & CMD_MASK) {
 107                case HOSTIF_DM_ENUM_DEVICES:
 108                        if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
 109                                        client_data->init_done)) {
 110                                ++client_data->bad_recv_cnt;
 111                                report_bad_packet(hid_ishtp_cl, recv_msg,
 112                                                  cur_pos,
 113                                                  payload_len);
 114                                ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
 115                                break;
 116                        }
 117                        client_data->hid_dev_count = (unsigned int)*payload;
 118                        if (!client_data->hid_devices)
 119                                client_data->hid_devices = devm_kcalloc(
 120                                                cl_data_to_dev(client_data),
 121                                                client_data->hid_dev_count,
 122                                                sizeof(struct device_info),
 123                                                GFP_KERNEL);
 124                        if (!client_data->hid_devices) {
 125                                dev_err(cl_data_to_dev(client_data),
 126                                "Mem alloc failed for hid device info\n");
 127                                wake_up_interruptible(&client_data->init_wait);
 128                                break;
 129                        }
 130                        for (i = 0; i < client_data->hid_dev_count; ++i) {
 131                                if (1 + sizeof(struct device_info) * i >=
 132                                                payload_len) {
 133                                        dev_err(cl_data_to_dev(client_data),
 134                                                "[hid-ish]: [ENUM_DEVICES]: content size %zu is bigger than payload_len %zu\n",
 135                                                1 + sizeof(struct device_info)
 136                                                * i, payload_len);
 137                                }
 138
 139                                if (1 + sizeof(struct device_info) * i >=
 140                                                data_len)
 141                                        break;
 142
 143                                dev_info = (struct device_info *)(payload + 1 +
 144                                        sizeof(struct device_info) * i);
 145                                if (client_data->hid_devices)
 146                                        memcpy(client_data->hid_devices + i,
 147                                               dev_info,
 148                                               sizeof(struct device_info));
 149                        }
 150
 151                        client_data->enum_devices_done = true;
 152                        wake_up_interruptible(&client_data->init_wait);
 153
 154                        break;
 155
 156                case HOSTIF_GET_HID_DESCRIPTOR:
 157                        if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
 158                                        client_data->init_done)) {
 159                                ++client_data->bad_recv_cnt;
 160                                report_bad_packet(hid_ishtp_cl, recv_msg,
 161                                                  cur_pos,
 162                                                  payload_len);
 163                                ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
 164                                break;
 165                        }
 166                        if (!client_data->hid_descr[curr_hid_dev])
 167                                client_data->hid_descr[curr_hid_dev] =
 168                                devm_kmalloc(cl_data_to_dev(client_data),
 169                                             payload_len, GFP_KERNEL);
 170                        if (client_data->hid_descr[curr_hid_dev]) {
 171                                memcpy(client_data->hid_descr[curr_hid_dev],
 172                                       payload, payload_len);
 173                                client_data->hid_descr_size[curr_hid_dev] =
 174                                        payload_len;
 175                                client_data->hid_descr_done = true;
 176                        }
 177                        wake_up_interruptible(&client_data->init_wait);
 178
 179                        break;
 180
 181                case HOSTIF_GET_REPORT_DESCRIPTOR:
 182                        if ((!(recv_msg->hdr.command & ~CMD_MASK) ||
 183                                        client_data->init_done)) {
 184                                ++client_data->bad_recv_cnt;
 185                                report_bad_packet(hid_ishtp_cl, recv_msg,
 186                                                  cur_pos,
 187                                                  payload_len);
 188                                ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
 189                                break;
 190                        }
 191                        if (!client_data->report_descr[curr_hid_dev])
 192                                client_data->report_descr[curr_hid_dev] =
 193                                devm_kmalloc(cl_data_to_dev(client_data),
 194                                             payload_len, GFP_KERNEL);
 195                        if (client_data->report_descr[curr_hid_dev])  {
 196                                memcpy(client_data->report_descr[curr_hid_dev],
 197                                       payload,
 198                                       payload_len);
 199                                client_data->report_descr_size[curr_hid_dev] =
 200                                        payload_len;
 201                                client_data->report_descr_done = true;
 202                        }
 203                        wake_up_interruptible(&client_data->init_wait);
 204
 205                        break;
 206
 207                case HOSTIF_GET_FEATURE_REPORT:
 208                        report_type = HID_FEATURE_REPORT;
 209                        goto    do_get_report;
 210
 211                case HOSTIF_GET_INPUT_REPORT:
 212                        report_type = HID_INPUT_REPORT;
 213do_get_report:
 214                        /* Get index of device that matches this id */
 215                        for (i = 0; i < client_data->num_hid_devices; ++i) {
 216                                if (recv_msg->hdr.device_id ==
 217                                          client_data->hid_devices[i].dev_id) {
 218                                        hid = client_data->hid_sensor_hubs[i];
 219                                        if (!hid)
 220                                                break;
 221
 222                                        hid_data = hid->driver_data;
 223                                        if (hid_data->raw_get_req) {
 224                                                raw_len =
 225                                                  (hid_data->raw_buf_size <
 226                                                                payload_len) ?
 227                                                  hid_data->raw_buf_size :
 228                                                  payload_len;
 229
 230                                                memcpy(hid_data->raw_buf,
 231                                                       payload, raw_len);
 232                                        } else {
 233                                                hid_input_report
 234                                                        (hid, report_type,
 235                                                         payload, payload_len,
 236                                                         0);
 237                                        }
 238
 239                                        ishtp_hid_wakeup(hid);
 240                                        break;
 241                                }
 242                        }
 243                        break;
 244
 245                case HOSTIF_SET_FEATURE_REPORT:
 246                        /* Get index of device that matches this id */
 247                        for (i = 0; i < client_data->num_hid_devices; ++i) {
 248                                if (recv_msg->hdr.device_id ==
 249                                        client_data->hid_devices[i].dev_id)
 250                                        if (client_data->hid_sensor_hubs[i]) {
 251                                                ishtp_hid_wakeup(
 252                                                client_data->hid_sensor_hubs[
 253                                                        i]);
 254                                                break;
 255                                        }
 256                        }
 257                        break;
 258
 259                case HOSTIF_PUBLISH_INPUT_REPORT:
 260                        report_type = HID_INPUT_REPORT;
 261                        for (i = 0; i < client_data->num_hid_devices; ++i)
 262                                if (recv_msg->hdr.device_id ==
 263                                        client_data->hid_devices[i].dev_id)
 264                                        if (client_data->hid_sensor_hubs[i])
 265                                                hid_input_report(
 266                                                client_data->hid_sensor_hubs[
 267                                                                        i],
 268                                                report_type, payload,
 269                                                payload_len, 0);
 270                        break;
 271
 272                case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
 273                        report_type = HID_INPUT_REPORT;
 274                        reports_list = (struct report_list *)payload;
 275                        reports = (char *)reports_list->reports;
 276
 277                        for (j = 0; j < reports_list->num_of_reports; j++) {
 278                                recv_msg = (struct hostif_msg *)(reports +
 279                                        sizeof(uint16_t));
 280                                report_len = *(uint16_t *)reports;
 281                                payload = reports + sizeof(uint16_t) +
 282                                        sizeof(struct hostif_msg_hdr);
 283                                payload_len = report_len -
 284                                        sizeof(struct hostif_msg_hdr);
 285
 286                                for (i = 0; i < client_data->num_hid_devices;
 287                                     ++i)
 288                                        if (recv_msg->hdr.device_id ==
 289                                        client_data->hid_devices[i].dev_id &&
 290                                        client_data->hid_sensor_hubs[i]) {
 291                                                hid_input_report(
 292                                                client_data->hid_sensor_hubs[
 293                                                                        i],
 294                                                report_type,
 295                                                payload, payload_len,
 296                                                0);
 297                                        }
 298
 299                                reports += sizeof(uint16_t) + report_len;
 300                        }
 301                        break;
 302                default:
 303                        ++client_data->bad_recv_cnt;
 304                        report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos,
 305                                          payload_len);
 306                        ish_hw_reset(ishtp_get_ishtp_device(hid_ishtp_cl));
 307                        break;
 308
 309                }
 310
 311                if (!cur_pos && cur_pos + payload_len +
 312                                sizeof(struct hostif_msg) < total_len)
 313                        ++client_data->multi_packet_cnt;
 314
 315                cur_pos += payload_len + sizeof(struct hostif_msg);
 316                payload += payload_len + sizeof(struct hostif_msg);
 317
 318        } while (cur_pos < total_len);
 319}
 320
 321/**
 322 * ish_cl_event_cb() - bus driver callback for incoming message/packet
 323 * @device:     Pointer to the the ishtp client device for which this message
 324 *              is targeted
 325 *
 326 * Remove the packet from the list and process the message by calling
 327 * process_recv
 328 */
 329static void ish_cl_event_cb(struct ishtp_cl_device *device)
 330{
 331        struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(device);
 332        struct ishtp_cl_rb *rb_in_proc;
 333        size_t r_length;
 334
 335        if (!hid_ishtp_cl)
 336                return;
 337
 338        while ((rb_in_proc = ishtp_cl_rx_get_rb(hid_ishtp_cl)) != NULL) {
 339                if (!rb_in_proc->buffer.data)
 340                        return;
 341
 342                r_length = rb_in_proc->buf_idx;
 343
 344                /* decide what to do with received data */
 345                process_recv(hid_ishtp_cl, rb_in_proc->buffer.data, r_length);
 346
 347                ishtp_cl_io_rb_recycle(rb_in_proc);
 348        }
 349}
 350
 351/**
 352 * hid_ishtp_set_feature() - send request to ISH FW to set a feature request
 353 * @hid:        hid device instance for this request
 354 * @buf:        feature buffer
 355 * @len:        Length of feature buffer
 356 * @report_id:  Report id for the feature set request
 357 *
 358 * This is called from hid core .request() callback. This function doesn't wait
 359 * for response.
 360 */
 361void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len,
 362                           int report_id)
 363{
 364        struct ishtp_hid_data *hid_data =  hid->driver_data;
 365        struct ishtp_cl_data *client_data = hid_data->client_data;
 366        struct hostif_msg *msg = (struct hostif_msg *)buf;
 367        int     rv;
 368        int     i;
 369
 370        hid_ishtp_trace(client_data,  "%s hid %p\n", __func__, hid);
 371
 372        rv = ishtp_hid_link_ready_wait(client_data);
 373        if (rv) {
 374                hid_ishtp_trace(client_data,  "%s hid %p link not ready\n",
 375                                __func__, hid);
 376                return;
 377        }
 378
 379        memset(msg, 0, sizeof(struct hostif_msg));
 380        msg->hdr.command = HOSTIF_SET_FEATURE_REPORT;
 381        for (i = 0; i < client_data->num_hid_devices; ++i) {
 382                if (hid == client_data->hid_sensor_hubs[i]) {
 383                        msg->hdr.device_id =
 384                                client_data->hid_devices[i].dev_id;
 385                        break;
 386                }
 387        }
 388
 389        if (i == client_data->num_hid_devices)
 390                return;
 391
 392        rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len);
 393        if (rv)
 394                hid_ishtp_trace(client_data,  "%s hid %p send failed\n",
 395                                __func__, hid);
 396}
 397
 398/**
 399 * hid_ishtp_get_report() - request to get feature/input report
 400 * @hid:        hid device instance for this request
 401 * @report_id:  Report id for the get request
 402 * @report_type:        Report type for the this request
 403 *
 404 * This is called from hid core .request() callback. This function will send
 405 * request to FW and return without waiting for response.
 406 */
 407void hid_ishtp_get_report(struct hid_device *hid, int report_id,
 408                          int report_type)
 409{
 410        struct ishtp_hid_data *hid_data =  hid->driver_data;
 411        struct ishtp_cl_data *client_data = hid_data->client_data;
 412        struct hostif_msg_to_sensor msg = {};
 413        int     rv;
 414        int     i;
 415
 416        hid_ishtp_trace(client_data,  "%s hid %p\n", __func__, hid);
 417        rv = ishtp_hid_link_ready_wait(client_data);
 418        if (rv) {
 419                hid_ishtp_trace(client_data,  "%s hid %p link not ready\n",
 420                                __func__, hid);
 421                return;
 422        }
 423
 424        msg.hdr.command = (report_type == HID_FEATURE_REPORT) ?
 425                HOSTIF_GET_FEATURE_REPORT : HOSTIF_GET_INPUT_REPORT;
 426        for (i = 0; i < client_data->num_hid_devices; ++i) {
 427                if (hid == client_data->hid_sensor_hubs[i]) {
 428                        msg.hdr.device_id =
 429                                client_data->hid_devices[i].dev_id;
 430                        break;
 431                }
 432        }
 433
 434        if (i == client_data->num_hid_devices)
 435                return;
 436
 437        msg.report_id = report_id;
 438        rv = ishtp_cl_send(client_data->hid_ishtp_cl, (uint8_t *)&msg,
 439                            sizeof(msg));
 440        if (rv)
 441                hid_ishtp_trace(client_data,  "%s hid %p send failed\n",
 442                                __func__, hid);
 443}
 444
 445/**
 446 * ishtp_hid_link_ready_wait() - Wait for link ready
 447 * @client_data:        client data instance
 448 *
 449 * If the transport link started suspend process, then wait, till either
 450 * resumed or timeout
 451 *
 452 * Return: 0 on success, non zero on error
 453 */
 454int ishtp_hid_link_ready_wait(struct ishtp_cl_data *client_data)
 455{
 456        int rc;
 457
 458        if (client_data->suspended) {
 459                hid_ishtp_trace(client_data,  "wait for link ready\n");
 460                rc = wait_event_interruptible_timeout(
 461                                        client_data->ishtp_resume_wait,
 462                                        !client_data->suspended,
 463                                        5 * HZ);
 464
 465                if (rc == 0) {
 466                        hid_ishtp_trace(client_data,  "link not ready\n");
 467                        return -EIO;
 468                }
 469                hid_ishtp_trace(client_data,  "link ready\n");
 470        }
 471
 472        return 0;
 473}
 474
 475/**
 476 * ishtp_enum_enum_devices() - Enumerate hid devices
 477 * @hid_ishtp_cl:       client instance
 478 *
 479 * Helper function to send request to firmware to enumerate HID devices
 480 *
 481 * Return: 0 on success, non zero on error
 482 */
 483static int ishtp_enum_enum_devices(struct ishtp_cl *hid_ishtp_cl)
 484{
 485        struct hostif_msg msg;
 486        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 487        int retry_count;
 488        int rv;
 489
 490        /* Send HOSTIF_DM_ENUM_DEVICES */
 491        memset(&msg, 0, sizeof(struct hostif_msg));
 492        msg.hdr.command = HOSTIF_DM_ENUM_DEVICES;
 493        rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *)&msg,
 494                           sizeof(struct hostif_msg));
 495        if (rv)
 496                return rv;
 497
 498        retry_count = 0;
 499        while (!client_data->enum_devices_done &&
 500               retry_count < 10) {
 501                wait_event_interruptible_timeout(client_data->init_wait,
 502                                         client_data->enum_devices_done,
 503                                         3 * HZ);
 504                ++retry_count;
 505                if (!client_data->enum_devices_done)
 506                        /* Send HOSTIF_DM_ENUM_DEVICES */
 507                        rv = ishtp_cl_send(hid_ishtp_cl,
 508                                           (unsigned char *) &msg,
 509                                           sizeof(struct hostif_msg));
 510        }
 511        if (!client_data->enum_devices_done) {
 512                dev_err(cl_data_to_dev(client_data),
 513                        "[hid-ish]: timed out waiting for enum_devices\n");
 514                return -ETIMEDOUT;
 515        }
 516        if (!client_data->hid_devices) {
 517                dev_err(cl_data_to_dev(client_data),
 518                        "[hid-ish]: failed to allocate HID dev structures\n");
 519                return -ENOMEM;
 520        }
 521
 522        client_data->num_hid_devices = client_data->hid_dev_count;
 523        dev_info(ishtp_device(client_data->cl_device),
 524                "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n",
 525                client_data->num_hid_devices);
 526
 527        return  0;
 528}
 529
 530/**
 531 * ishtp_get_hid_descriptor() - Get hid descriptor
 532 * @hid_ishtp_cl:       client instance
 533 * @index:              Index into the hid_descr array
 534 *
 535 * Helper function to send request to firmware get HID descriptor of a device
 536 *
 537 * Return: 0 on success, non zero on error
 538 */
 539static int ishtp_get_hid_descriptor(struct ishtp_cl *hid_ishtp_cl, int index)
 540{
 541        struct hostif_msg msg;
 542        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 543        int rv;
 544
 545        /* Get HID descriptor */
 546        client_data->hid_descr_done = false;
 547        memset(&msg, 0, sizeof(struct hostif_msg));
 548        msg.hdr.command = HOSTIF_GET_HID_DESCRIPTOR;
 549        msg.hdr.device_id = client_data->hid_devices[index].dev_id;
 550        rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
 551                           sizeof(struct hostif_msg));
 552        if (rv)
 553                return rv;
 554
 555        if (!client_data->hid_descr_done) {
 556                wait_event_interruptible_timeout(client_data->init_wait,
 557                                                 client_data->hid_descr_done,
 558                                                 3 * HZ);
 559                if (!client_data->hid_descr_done) {
 560                        dev_err(cl_data_to_dev(client_data),
 561                                "[hid-ish]: timed out for hid_descr_done\n");
 562                        return -EIO;
 563                }
 564
 565                if (!client_data->hid_descr[index]) {
 566                        dev_err(cl_data_to_dev(client_data),
 567                                "[hid-ish]: allocation HID desc fail\n");
 568                        return -ENOMEM;
 569                }
 570        }
 571
 572        return 0;
 573}
 574
 575/**
 576 * ishtp_get_report_descriptor() - Get report descriptor
 577 * @hid_ishtp_cl:       client instance
 578 * @index:              Index into the hid_descr array
 579 *
 580 * Helper function to send request to firmware get HID report descriptor of
 581 * a device
 582 *
 583 * Return: 0 on success, non zero on error
 584 */
 585static int ishtp_get_report_descriptor(struct ishtp_cl *hid_ishtp_cl,
 586                                       int index)
 587{
 588        struct hostif_msg msg;
 589        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 590        int rv;
 591
 592        /* Get report descriptor */
 593        client_data->report_descr_done = false;
 594        memset(&msg, 0, sizeof(struct hostif_msg));
 595        msg.hdr.command = HOSTIF_GET_REPORT_DESCRIPTOR;
 596        msg.hdr.device_id = client_data->hid_devices[index].dev_id;
 597        rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg,
 598                           sizeof(struct hostif_msg));
 599        if (rv)
 600                return rv;
 601
 602        if (!client_data->report_descr_done)
 603                wait_event_interruptible_timeout(client_data->init_wait,
 604                                         client_data->report_descr_done,
 605                                         3 * HZ);
 606        if (!client_data->report_descr_done) {
 607                dev_err(cl_data_to_dev(client_data),
 608                                "[hid-ish]: timed out for report descr\n");
 609                return -EIO;
 610        }
 611        if (!client_data->report_descr[index]) {
 612                dev_err(cl_data_to_dev(client_data),
 613                        "[hid-ish]: failed to alloc report descr\n");
 614                return -ENOMEM;
 615        }
 616
 617        return 0;
 618}
 619
 620/**
 621 * hid_ishtp_cl_init() - Init function for ISHTP client
 622 * @hid_ishtp_cl:       ISHTP client instance
 623 * @reset:              true if called for init after reset
 624 *
 625 * This function complete the initializtion of the client. The summary of
 626 * processing:
 627 * - Send request to enumerate the hid clients
 628 *      Get the HID descriptor for each enumearated device
 629 *      Get report description of each device
 630 *      Register each device wik hid core by calling ishtp_hid_probe
 631 *
 632 * Return: 0 on success, non zero on error
 633 */
 634static int hid_ishtp_cl_init(struct ishtp_cl *hid_ishtp_cl, int reset)
 635{
 636        struct ishtp_device *dev;
 637        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 638        struct ishtp_fw_client *fw_client;
 639        int i;
 640        int rv;
 641
 642        dev_dbg(cl_data_to_dev(client_data), "%s\n", __func__);
 643        hid_ishtp_trace(client_data,  "%s reset flag: %d\n", __func__, reset);
 644
 645        rv = ishtp_cl_link(hid_ishtp_cl);
 646        if (rv) {
 647                dev_err(cl_data_to_dev(client_data),
 648                        "ishtp_cl_link failed\n");
 649                return  -ENOMEM;
 650        }
 651
 652        client_data->init_done = 0;
 653
 654        dev = ishtp_get_ishtp_device(hid_ishtp_cl);
 655
 656        /* Connect to FW client */
 657        ishtp_set_tx_ring_size(hid_ishtp_cl, HID_CL_TX_RING_SIZE);
 658        ishtp_set_rx_ring_size(hid_ishtp_cl, HID_CL_RX_RING_SIZE);
 659
 660        fw_client = ishtp_fw_cl_get_client(dev, &hid_ishtp_guid);
 661        if (!fw_client) {
 662                dev_err(cl_data_to_dev(client_data),
 663                        "ish client uuid not found\n");
 664                return -ENOENT;
 665        }
 666        ishtp_cl_set_fw_client_id(hid_ishtp_cl,
 667                                  ishtp_get_fw_client_id(fw_client));
 668        ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_CONNECTING);
 669
 670        rv = ishtp_cl_connect(hid_ishtp_cl);
 671        if (rv) {
 672                dev_err(cl_data_to_dev(client_data),
 673                        "client connect fail\n");
 674                goto err_cl_unlink;
 675        }
 676
 677        hid_ishtp_trace(client_data,  "%s client connected\n", __func__);
 678
 679        /* Register read callback */
 680        ishtp_register_event_cb(client_data->cl_device, ish_cl_event_cb);
 681
 682        rv = ishtp_enum_enum_devices(hid_ishtp_cl);
 683        if (rv)
 684                goto err_cl_disconnect;
 685
 686        hid_ishtp_trace(client_data,  "%s enumerated device count %d\n",
 687                        __func__, client_data->num_hid_devices);
 688
 689        for (i = 0; i < client_data->num_hid_devices; ++i) {
 690                client_data->cur_hid_dev = i;
 691
 692                rv = ishtp_get_hid_descriptor(hid_ishtp_cl, i);
 693                if (rv)
 694                        goto err_cl_disconnect;
 695
 696                rv = ishtp_get_report_descriptor(hid_ishtp_cl, i);
 697                if (rv)
 698                        goto err_cl_disconnect;
 699
 700                if (!reset) {
 701                        rv = ishtp_hid_probe(i, client_data);
 702                        if (rv) {
 703                                dev_err(cl_data_to_dev(client_data),
 704                                "[hid-ish]: HID probe for #%u failed: %d\n",
 705                                i, rv);
 706                                goto err_cl_disconnect;
 707                        }
 708                }
 709        } /* for() on all hid devices */
 710
 711        client_data->init_done = 1;
 712        client_data->suspended = false;
 713        wake_up_interruptible(&client_data->ishtp_resume_wait);
 714        hid_ishtp_trace(client_data,  "%s successful init\n", __func__);
 715        return 0;
 716
 717err_cl_disconnect:
 718        ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_DISCONNECTING);
 719        ishtp_cl_disconnect(hid_ishtp_cl);
 720err_cl_unlink:
 721        ishtp_cl_unlink(hid_ishtp_cl);
 722        return rv;
 723}
 724
 725/**
 726 * hid_ishtp_cl_deinit() - Deinit function for ISHTP client
 727 * @hid_ishtp_cl:       ISHTP client instance
 728 *
 729 * Unlink and free hid client
 730 */
 731static void hid_ishtp_cl_deinit(struct ishtp_cl *hid_ishtp_cl)
 732{
 733        ishtp_cl_unlink(hid_ishtp_cl);
 734        ishtp_cl_flush_queues(hid_ishtp_cl);
 735
 736        /* disband and free all Tx and Rx client-level rings */
 737        ishtp_cl_free(hid_ishtp_cl);
 738}
 739
 740static void hid_ishtp_cl_reset_handler(struct work_struct *work)
 741{
 742        struct ishtp_cl_data *client_data;
 743        struct ishtp_cl *hid_ishtp_cl;
 744        struct ishtp_cl_device *cl_device;
 745        int retry;
 746        int rv;
 747
 748        client_data = container_of(work, struct ishtp_cl_data, work);
 749
 750        hid_ishtp_cl = client_data->hid_ishtp_cl;
 751        cl_device = client_data->cl_device;
 752
 753        hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
 754                        hid_ishtp_cl);
 755        dev_dbg(ishtp_device(client_data->cl_device), "%s\n", __func__);
 756
 757        hid_ishtp_cl_deinit(hid_ishtp_cl);
 758
 759        hid_ishtp_cl = ishtp_cl_allocate(cl_device);
 760        if (!hid_ishtp_cl)
 761                return;
 762
 763        ishtp_set_drvdata(cl_device, hid_ishtp_cl);
 764        ishtp_set_client_data(hid_ishtp_cl, client_data);
 765        client_data->hid_ishtp_cl = hid_ishtp_cl;
 766
 767        client_data->num_hid_devices = 0;
 768
 769        for (retry = 0; retry < 3; ++retry) {
 770                rv = hid_ishtp_cl_init(hid_ishtp_cl, 1);
 771                if (!rv)
 772                        break;
 773                dev_err(cl_data_to_dev(client_data), "Retry reset init\n");
 774        }
 775        if (rv) {
 776                dev_err(cl_data_to_dev(client_data), "Reset Failed\n");
 777                hid_ishtp_trace(client_data, "%s Failed hid_ishtp_cl %p\n",
 778                                __func__, hid_ishtp_cl);
 779        }
 780}
 781
 782void (*hid_print_trace)(void *unused, const char *format, ...);
 783
 784/**
 785 * hid_ishtp_cl_probe() - ISHTP client driver probe
 786 * @cl_device:          ISHTP client device instance
 787 *
 788 * This function gets called on device create on ISHTP bus
 789 *
 790 * Return: 0 on success, non zero on error
 791 */
 792static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device)
 793{
 794        struct ishtp_cl *hid_ishtp_cl;
 795        struct ishtp_cl_data *client_data;
 796        int rv;
 797
 798        if (!cl_device)
 799                return  -ENODEV;
 800
 801        client_data = devm_kzalloc(ishtp_device(cl_device),
 802                                   sizeof(*client_data),
 803                                   GFP_KERNEL);
 804        if (!client_data)
 805                return -ENOMEM;
 806
 807        hid_ishtp_cl = ishtp_cl_allocate(cl_device);
 808        if (!hid_ishtp_cl)
 809                return -ENOMEM;
 810
 811        ishtp_set_drvdata(cl_device, hid_ishtp_cl);
 812        ishtp_set_client_data(hid_ishtp_cl, client_data);
 813        client_data->hid_ishtp_cl = hid_ishtp_cl;
 814        client_data->cl_device = cl_device;
 815
 816        init_waitqueue_head(&client_data->init_wait);
 817        init_waitqueue_head(&client_data->ishtp_resume_wait);
 818
 819        INIT_WORK(&client_data->work, hid_ishtp_cl_reset_handler);
 820
 821        hid_print_trace = ishtp_trace_callback(cl_device);
 822
 823        rv = hid_ishtp_cl_init(hid_ishtp_cl, 0);
 824        if (rv) {
 825                ishtp_cl_free(hid_ishtp_cl);
 826                return rv;
 827        }
 828        ishtp_get_device(cl_device);
 829
 830        return 0;
 831}
 832
 833/**
 834 * hid_ishtp_cl_remove() - ISHTP client driver remove
 835 * @cl_device:          ISHTP client device instance
 836 *
 837 * This function gets called on device remove on ISHTP bus
 838 *
 839 * Return: 0
 840 */
 841static int hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device)
 842{
 843        struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
 844        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 845
 846        hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
 847                        hid_ishtp_cl);
 848
 849        dev_dbg(ishtp_device(cl_device), "%s\n", __func__);
 850        ishtp_set_connection_state(hid_ishtp_cl, ISHTP_CL_DISCONNECTING);
 851        ishtp_cl_disconnect(hid_ishtp_cl);
 852        ishtp_put_device(cl_device);
 853        ishtp_hid_remove(client_data);
 854        hid_ishtp_cl_deinit(hid_ishtp_cl);
 855
 856        hid_ishtp_cl = NULL;
 857
 858        client_data->num_hid_devices = 0;
 859
 860        return 0;
 861}
 862
 863/**
 864 * hid_ishtp_cl_reset() - ISHTP client driver reset
 865 * @cl_device:          ISHTP client device instance
 866 *
 867 * This function gets called on device reset on ISHTP bus
 868 *
 869 * Return: 0
 870 */
 871static int hid_ishtp_cl_reset(struct ishtp_cl_device *cl_device)
 872{
 873        struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
 874        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 875
 876        hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
 877                        hid_ishtp_cl);
 878
 879        schedule_work(&client_data->work);
 880
 881        return 0;
 882}
 883
 884/**
 885 * hid_ishtp_cl_suspend() - ISHTP client driver suspend
 886 * @device:     device instance
 887 *
 888 * This function gets called on system suspend
 889 *
 890 * Return: 0
 891 */
 892static int hid_ishtp_cl_suspend(struct device *device)
 893{
 894        struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
 895        struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
 896        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 897
 898        hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
 899                        hid_ishtp_cl);
 900        client_data->suspended = true;
 901
 902        return 0;
 903}
 904
 905/**
 906 * hid_ishtp_cl_resume() - ISHTP client driver resume
 907 * @device:     device instance
 908 *
 909 * This function gets called on system resume
 910 *
 911 * Return: 0
 912 */
 913static int hid_ishtp_cl_resume(struct device *device)
 914{
 915        struct ishtp_cl_device *cl_device = ishtp_dev_to_cl_device(device);
 916        struct ishtp_cl *hid_ishtp_cl = ishtp_get_drvdata(cl_device);
 917        struct ishtp_cl_data *client_data = ishtp_get_client_data(hid_ishtp_cl);
 918
 919        hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__,
 920                        hid_ishtp_cl);
 921        client_data->suspended = false;
 922        return 0;
 923}
 924
 925static const struct dev_pm_ops hid_ishtp_pm_ops = {
 926        .suspend = hid_ishtp_cl_suspend,
 927        .resume = hid_ishtp_cl_resume,
 928};
 929
 930static struct ishtp_cl_driver   hid_ishtp_cl_driver = {
 931        .name = "ish-hid",
 932        .guid = &hid_ishtp_guid,
 933        .probe = hid_ishtp_cl_probe,
 934        .remove = hid_ishtp_cl_remove,
 935        .reset = hid_ishtp_cl_reset,
 936        .driver.pm = &hid_ishtp_pm_ops,
 937};
 938
 939static int __init ish_hid_init(void)
 940{
 941        int     rv;
 942
 943        /* Register ISHTP client device driver with ISHTP Bus */
 944        rv = ishtp_cl_driver_register(&hid_ishtp_cl_driver, THIS_MODULE);
 945
 946        return rv;
 947
 948}
 949
 950static void __exit ish_hid_exit(void)
 951{
 952        ishtp_cl_driver_unregister(&hid_ishtp_cl_driver);
 953}
 954
 955late_initcall(ish_hid_init);
 956module_exit(ish_hid_exit);
 957
 958MODULE_DESCRIPTION("ISH ISHTP HID client driver");
 959/* Primary author */
 960MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
 961/*
 962 * Several modification for multi instance support
 963 * suspend/resume and clean up
 964 */
 965MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
 966
 967MODULE_LICENSE("GPL");
 968MODULE_ALIAS("ishtp:*");
 969