linux/drivers/staging/greybus/hid.c
<<
>>
Prefs
   1/*
   2 * HID class driver for the Greybus.
   3 *
   4 * Copyright 2014 Google Inc.
   5 * Copyright 2014 Linaro Ltd.
   6 *
   7 * Released under the GPLv2 only.
   8 */
   9
  10#include <linux/bitops.h>
  11#include <linux/hid.h>
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/mutex.h>
  15#include <linux/slab.h>
  16
  17#include "greybus.h"
  18
  19/* Greybus HID device's structure */
  20struct gb_hid {
  21        struct gb_bundle *bundle;
  22        struct gb_connection            *connection;
  23
  24        struct hid_device               *hid;
  25        struct gb_hid_desc_response     hdesc;
  26
  27        unsigned long                   flags;
  28#define GB_HID_STARTED                  0x01
  29#define GB_HID_READ_PENDING             0x04
  30
  31        unsigned int                    bufsize;
  32        char                            *inbuf;
  33};
  34
  35/* Routines to get controller's information over greybus */
  36
  37/* Operations performed on greybus */
  38static int gb_hid_get_desc(struct gb_hid *ghid)
  39{
  40        return gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_DESC, NULL,
  41                                 0, &ghid->hdesc, sizeof(ghid->hdesc));
  42}
  43
  44static int gb_hid_get_report_desc(struct gb_hid *ghid, char *rdesc)
  45{
  46        int ret;
  47
  48        ret = gb_pm_runtime_get_sync(ghid->bundle);
  49        if (ret)
  50                return ret;
  51
  52        ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT_DESC,
  53                                 NULL, 0, rdesc,
  54                                 le16_to_cpu(ghid->hdesc.wReportDescLength));
  55
  56        gb_pm_runtime_put_autosuspend(ghid->bundle);
  57
  58        return ret;
  59}
  60
  61static int gb_hid_set_power(struct gb_hid *ghid, int type)
  62{
  63        int ret;
  64
  65        ret = gb_pm_runtime_get_sync(ghid->bundle);
  66        if (ret)
  67                return ret;
  68
  69        ret = gb_operation_sync(ghid->connection, type, NULL, 0, NULL, 0);
  70
  71        gb_pm_runtime_put_autosuspend(ghid->bundle);
  72
  73        return ret;
  74}
  75
  76static int gb_hid_get_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
  77                             unsigned char *buf, int len)
  78{
  79        struct gb_hid_get_report_request request;
  80        int ret;
  81
  82        ret = gb_pm_runtime_get_sync(ghid->bundle);
  83        if (ret)
  84                return ret;
  85
  86        request.report_type = report_type;
  87        request.report_id = report_id;
  88
  89        ret = gb_operation_sync(ghid->connection, GB_HID_TYPE_GET_REPORT,
  90                                 &request, sizeof(request), buf, len);
  91
  92        gb_pm_runtime_put_autosuspend(ghid->bundle);
  93
  94        return ret;
  95}
  96
  97static int gb_hid_set_report(struct gb_hid *ghid, u8 report_type, u8 report_id,
  98                             unsigned char *buf, int len)
  99{
 100        struct gb_hid_set_report_request *request;
 101        struct gb_operation *operation;
 102        int ret, size = sizeof(*request) + len - 1;
 103
 104        ret = gb_pm_runtime_get_sync(ghid->bundle);
 105        if (ret)
 106                return ret;
 107
 108        operation = gb_operation_create(ghid->connection,
 109                                        GB_HID_TYPE_SET_REPORT, size, 0,
 110                                        GFP_KERNEL);
 111        if (!operation) {
 112                gb_pm_runtime_put_autosuspend(ghid->bundle);
 113                return -ENOMEM;
 114        }
 115
 116        request = operation->request->payload;
 117        request->report_type = report_type;
 118        request->report_id = report_id;
 119        memcpy(request->report, buf, len);
 120
 121        ret = gb_operation_request_send_sync(operation);
 122        if (ret) {
 123                dev_err(&operation->connection->bundle->dev,
 124                        "failed to set report: %d\n", ret);
 125        } else {
 126                ret = len;
 127        }
 128
 129        gb_operation_put(operation);
 130        gb_pm_runtime_put_autosuspend(ghid->bundle);
 131
 132        return ret;
 133}
 134
 135static int gb_hid_request_handler(struct gb_operation *op)
 136{
 137        struct gb_connection *connection = op->connection;
 138        struct gb_hid *ghid = gb_connection_get_data(connection);
 139        struct gb_hid_input_report_request *request = op->request->payload;
 140
 141        if (op->type != GB_HID_TYPE_IRQ_EVENT) {
 142                dev_err(&connection->bundle->dev,
 143                        "unsupported unsolicited request\n");
 144                return -EINVAL;
 145        }
 146
 147        if (test_bit(GB_HID_STARTED, &ghid->flags))
 148                hid_input_report(ghid->hid, HID_INPUT_REPORT,
 149                                 request->report, op->request->payload_size, 1);
 150
 151        return 0;
 152}
 153
 154static int gb_hid_report_len(struct hid_report *report)
 155{
 156        return ((report->size - 1) >> 3) + 1 +
 157                report->device->report_enum[report->type].numbered;
 158}
 159
 160static void gb_hid_find_max_report(struct hid_device *hid, unsigned int type,
 161                                   unsigned int *max)
 162{
 163        struct hid_report *report;
 164        unsigned int size;
 165
 166        list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
 167                size = gb_hid_report_len(report);
 168                if (*max < size)
 169                        *max = size;
 170        }
 171}
 172
 173static void gb_hid_free_buffers(struct gb_hid *ghid)
 174{
 175        kfree(ghid->inbuf);
 176        ghid->inbuf = NULL;
 177        ghid->bufsize = 0;
 178}
 179
 180static int gb_hid_alloc_buffers(struct gb_hid *ghid, size_t bufsize)
 181{
 182        ghid->inbuf = kzalloc(bufsize, GFP_KERNEL);
 183        if (!ghid->inbuf)
 184                return -ENOMEM;
 185
 186        ghid->bufsize = bufsize;
 187
 188        return 0;
 189}
 190
 191/* Routines dealing with reports */
 192static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report)
 193{
 194        unsigned int size;
 195
 196        size = gb_hid_report_len(report);
 197        if (gb_hid_get_report(ghid, report->type, report->id, ghid->inbuf,
 198                              size))
 199                return;
 200
 201        /*
 202         * hid->driver_lock is held as we are in probe function,
 203         * we just need to setup the input fields, so using
 204         * hid_report_raw_event is safe.
 205         */
 206        hid_report_raw_event(ghid->hid, report->type, ghid->inbuf, size, 1);
 207}
 208
 209static void gb_hid_init_reports(struct gb_hid *ghid)
 210{
 211        struct hid_device *hid = ghid->hid;
 212        struct hid_report *report;
 213
 214        list_for_each_entry(report,
 215                &hid->report_enum[HID_INPUT_REPORT].report_list, list)
 216                gb_hid_init_report(ghid, report);
 217
 218        list_for_each_entry(report,
 219                &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
 220                gb_hid_init_report(ghid, report);
 221}
 222
 223static int __gb_hid_get_raw_report(struct hid_device *hid,
 224                unsigned char report_number, __u8 *buf, size_t count,
 225                unsigned char report_type)
 226{
 227        struct gb_hid *ghid = hid->driver_data;
 228        int ret;
 229
 230        if (report_type == HID_OUTPUT_REPORT)
 231                return -EINVAL;
 232
 233        ret = gb_hid_get_report(ghid, report_type, report_number, buf, count);
 234        if (!ret)
 235                ret = count;
 236
 237        return ret;
 238}
 239
 240static int __gb_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
 241                                      size_t len, unsigned char report_type)
 242{
 243        struct gb_hid *ghid = hid->driver_data;
 244        int report_id = buf[0];
 245        int ret;
 246
 247        if (report_type == HID_INPUT_REPORT)
 248                return -EINVAL;
 249
 250        if (report_id) {
 251                buf++;
 252                len--;
 253        }
 254
 255        ret = gb_hid_set_report(ghid, report_type, report_id, buf, len);
 256        if (report_id && ret >= 0)
 257                ret++; /* add report_id to the number of transfered bytes */
 258
 259        return 0;
 260}
 261
 262static int gb_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
 263                               __u8 *buf, size_t len, unsigned char rtype,
 264                               int reqtype)
 265{
 266        switch (reqtype) {
 267        case HID_REQ_GET_REPORT:
 268                return __gb_hid_get_raw_report(hid, reportnum, buf, len, rtype);
 269        case HID_REQ_SET_REPORT:
 270                if (buf[0] != reportnum)
 271                        return -EINVAL;
 272                return __gb_hid_output_raw_report(hid, buf, len, rtype);
 273        default:
 274                return -EIO;
 275        }
 276}
 277
 278/* HID Callbacks */
 279static int gb_hid_parse(struct hid_device *hid)
 280{
 281        struct gb_hid *ghid = hid->driver_data;
 282        unsigned int rsize;
 283        char *rdesc;
 284        int ret;
 285
 286        rsize = le16_to_cpu(ghid->hdesc.wReportDescLength);
 287        if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
 288                dbg_hid("weird size of report descriptor (%u)\n", rsize);
 289                return -EINVAL;
 290        }
 291
 292        rdesc = kzalloc(rsize, GFP_KERNEL);
 293        if (!rdesc) {
 294                dbg_hid("couldn't allocate rdesc memory\n");
 295                return -ENOMEM;
 296        }
 297
 298        ret = gb_hid_get_report_desc(ghid, rdesc);
 299        if (ret) {
 300                hid_err(hid, "reading report descriptor failed\n");
 301                goto free_rdesc;
 302        }
 303
 304        ret = hid_parse_report(hid, rdesc, rsize);
 305        if (ret)
 306                dbg_hid("parsing report descriptor failed\n");
 307
 308free_rdesc:
 309        kfree(rdesc);
 310
 311        return ret;
 312}
 313
 314static int gb_hid_start(struct hid_device *hid)
 315{
 316        struct gb_hid *ghid = hid->driver_data;
 317        unsigned int bufsize = HID_MIN_BUFFER_SIZE;
 318        int ret;
 319
 320        gb_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize);
 321        gb_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize);
 322        gb_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize);
 323
 324        if (bufsize > HID_MAX_BUFFER_SIZE)
 325                bufsize = HID_MAX_BUFFER_SIZE;
 326
 327        ret = gb_hid_alloc_buffers(ghid, bufsize);
 328        if (ret)
 329                return ret;
 330
 331        if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
 332                gb_hid_init_reports(ghid);
 333
 334        return 0;
 335}
 336
 337static void gb_hid_stop(struct hid_device *hid)
 338{
 339        struct gb_hid *ghid = hid->driver_data;
 340
 341        gb_hid_free_buffers(ghid);
 342}
 343
 344static int gb_hid_open(struct hid_device *hid)
 345{
 346        struct gb_hid *ghid = hid->driver_data;
 347        int ret;
 348
 349        ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON);
 350        if (ret < 0)
 351                return ret;
 352
 353        set_bit(GB_HID_STARTED, &ghid->flags);
 354        return 0;
 355}
 356
 357static void gb_hid_close(struct hid_device *hid)
 358{
 359        struct gb_hid *ghid = hid->driver_data;
 360        int ret;
 361
 362        clear_bit(GB_HID_STARTED, &ghid->flags);
 363
 364        /* Save some power */
 365        ret = gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF);
 366        if (ret)
 367                dev_err(&ghid->connection->bundle->dev,
 368                        "failed to power off (%d)\n", ret);
 369}
 370
 371static int gb_hid_power(struct hid_device *hid, int lvl)
 372{
 373        struct gb_hid *ghid = hid->driver_data;
 374
 375        switch (lvl) {
 376        case PM_HINT_FULLON:
 377                return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_ON);
 378        case PM_HINT_NORMAL:
 379                return gb_hid_set_power(ghid, GB_HID_TYPE_PWR_OFF);
 380        }
 381
 382        return 0;
 383}
 384
 385/* HID structure to pass callbacks */
 386static struct hid_ll_driver gb_hid_ll_driver = {
 387        .parse = gb_hid_parse,
 388        .start = gb_hid_start,
 389        .stop = gb_hid_stop,
 390        .open = gb_hid_open,
 391        .close = gb_hid_close,
 392        .power = gb_hid_power,
 393        .raw_request = gb_hid_raw_request,
 394};
 395
 396static int gb_hid_init(struct gb_hid *ghid)
 397{
 398        struct hid_device *hid = ghid->hid;
 399        int ret;
 400
 401        ret = gb_hid_get_desc(ghid);
 402        if (ret)
 403                return ret;
 404
 405        hid->version = le16_to_cpu(ghid->hdesc.bcdHID);
 406        hid->vendor = le16_to_cpu(ghid->hdesc.wVendorID);
 407        hid->product = le16_to_cpu(ghid->hdesc.wProductID);
 408        hid->country = ghid->hdesc.bCountryCode;
 409
 410        hid->driver_data = ghid;
 411        hid->ll_driver = &gb_hid_ll_driver;
 412        hid->dev.parent = &ghid->connection->bundle->dev;
 413//      hid->bus = BUS_GREYBUS; /* Need a bustype for GREYBUS in <linux/input.h> */
 414
 415        /* Set HID device's name */
 416        snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
 417                 dev_name(&ghid->connection->bundle->dev),
 418                 hid->vendor, hid->product);
 419
 420        return 0;
 421}
 422
 423static int gb_hid_probe(struct gb_bundle *bundle,
 424                        const struct greybus_bundle_id *id)
 425{
 426        struct greybus_descriptor_cport *cport_desc;
 427        struct gb_connection *connection;
 428        struct hid_device *hid;
 429        struct gb_hid *ghid;
 430        int ret;
 431
 432        if (bundle->num_cports != 1)
 433                return -ENODEV;
 434
 435        cport_desc = &bundle->cport_desc[0];
 436        if (cport_desc->protocol_id != GREYBUS_PROTOCOL_HID)
 437                return -ENODEV;
 438
 439        ghid = kzalloc(sizeof(*ghid), GFP_KERNEL);
 440        if (!ghid)
 441                return -ENOMEM;
 442
 443        connection = gb_connection_create(bundle, le16_to_cpu(cport_desc->id),
 444                                                gb_hid_request_handler);
 445        if (IS_ERR(connection)) {
 446                ret = PTR_ERR(connection);
 447                goto err_free_ghid;
 448        }
 449
 450        gb_connection_set_data(connection, ghid);
 451        ghid->connection = connection;
 452
 453        hid = hid_allocate_device();
 454        if (IS_ERR(hid)) {
 455                ret = PTR_ERR(hid);
 456                goto err_connection_destroy;
 457        }
 458
 459        ghid->hid = hid;
 460        ghid->bundle = bundle;
 461
 462        greybus_set_drvdata(bundle, ghid);
 463
 464        ret = gb_connection_enable(connection);
 465        if (ret)
 466                goto err_destroy_hid;
 467
 468        ret = gb_hid_init(ghid);
 469        if (ret)
 470                goto err_connection_disable;
 471
 472        ret = hid_add_device(hid);
 473        if (ret) {
 474                hid_err(hid, "can't add hid device: %d\n", ret);
 475                goto err_connection_disable;
 476        }
 477
 478        gb_pm_runtime_put_autosuspend(bundle);
 479
 480        return 0;
 481
 482err_connection_disable:
 483        gb_connection_disable(connection);
 484err_destroy_hid:
 485        hid_destroy_device(hid);
 486err_connection_destroy:
 487        gb_connection_destroy(connection);
 488err_free_ghid:
 489        kfree(ghid);
 490
 491        return ret;
 492}
 493
 494static void gb_hid_disconnect(struct gb_bundle *bundle)
 495{
 496        struct gb_hid *ghid = greybus_get_drvdata(bundle);
 497
 498        if (gb_pm_runtime_get_sync(bundle))
 499                gb_pm_runtime_get_noresume(bundle);
 500
 501        hid_destroy_device(ghid->hid);
 502        gb_connection_disable(ghid->connection);
 503        gb_connection_destroy(ghid->connection);
 504        kfree(ghid);
 505}
 506
 507static const struct greybus_bundle_id gb_hid_id_table[] = {
 508        { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) },
 509        { }
 510};
 511MODULE_DEVICE_TABLE(greybus, gb_hid_id_table);
 512
 513static struct greybus_driver gb_hid_driver = {
 514        .name           = "hid",
 515        .probe          = gb_hid_probe,
 516        .disconnect     = gb_hid_disconnect,
 517        .id_table       = gb_hid_id_table,
 518};
 519module_greybus_driver(gb_hid_driver);
 520
 521MODULE_LICENSE("GPL v2");
 522