2 * ISHTP-HID glue driver.
4 * Copyright (c) 2012-2016, Intel Corporation.
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.
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
16 #include <linux/hid.h>
17 #include <uapi/linux/input.h>
18 #include "ishtp/client.h"
19 #include "ishtp-hid.h"
22 * ishtp_hid_parse() - hid-core .parse() callback
23 * @hid: hid device instance
25 * This function gets called during call to hid_add_device
27 * Return: 0 on success and non zero on error
29 static int ishtp_hid_parse(struct hid_device
*hid
)
31 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
32 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
35 rv
= hid_parse_report(hid
, client_data
->report_descr
[hid_data
->index
],
36 client_data
->report_descr_size
[hid_data
->index
]);
43 /* Empty callbacks with success return code */
44 static int ishtp_hid_start(struct hid_device
*hid
)
49 static void ishtp_hid_stop(struct hid_device
*hid
)
53 static int ishtp_hid_open(struct hid_device
*hid
)
58 static void ishtp_hid_close(struct hid_device
*hid
)
62 static int ishtp_raw_request(struct hid_device
*hdev
, unsigned char reportnum
,
63 __u8
*buf
, size_t len
, unsigned char rtype
, int reqtype
)
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
74 * This function is used to set/get feaure/input report.
76 static void ishtp_hid_request(struct hid_device
*hid
, struct hid_report
*rep
,
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);
83 unsigned int header_size
= sizeof(struct hostif_msg
);
87 hid_data
->request_done
= false;
89 case HID_REQ_GET_REPORT
:
90 hid_ishtp_get_report(hid
, rep
->id
, rep
->type
);
92 case HID_REQ_SET_REPORT
:
94 * Spare 7 bytes for 64b accesses through
95 * get/put_unaligned_le64()
97 buf
= kzalloc(len
+ 7, GFP_KERNEL
);
101 hid_output_report(rep
, buf
+ header_size
);
102 hid_ishtp_set_feature(hid
, buf
, len
, rep
->id
);
109 * ishtp_wait_for_response() - hid-core .wait() callback
110 * @hid: hid device instance
112 * This function is used to wait after get feaure/input report.
114 * Return: 0 on success and non zero on error
116 static int ishtp_wait_for_response(struct hid_device
*hid
)
118 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
119 struct ishtp_cl_data
*client_data
= hid_data
->client_data
;
122 hid_ishtp_trace(client_data
, "%s hid %p\n", __func__
, hid
);
124 rv
= ishtp_hid_link_ready_wait(hid_data
->client_data
);
128 if (!hid_data
->request_done
)
129 wait_event_interruptible_timeout(hid_data
->hid_wait
,
130 hid_data
->request_done
, 3 * HZ
);
132 if (!hid_data
->request_done
) {
134 "timeout waiting for response from ISHTP device\n");
137 hid_ishtp_trace(client_data
, "%s hid %p done\n", __func__
, hid
);
139 hid_data
->request_done
= false;
145 * ishtp_hid_wakeup() - Wakeup caller
146 * @hid: hid device instance
148 * This function will wakeup caller waiting for Get/Set feature report
150 void ishtp_hid_wakeup(struct hid_device
*hid
)
152 struct ishtp_hid_data
*hid_data
= hid
->driver_data
;
154 hid_data
->request_done
= true;
155 wake_up_interruptible(&hid_data
->hid_wait
);
158 static 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
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
174 * This function is used to allocate and add HID device.
176 * Return: 0 on success, non zero on error
178 int ishtp_hid_probe(unsigned int cur_hid_dev
,
179 struct ishtp_cl_data
*client_data
)
182 struct hid_device
*hid
;
183 struct ishtp_hid_data
*hid_data
;
185 hid
= hid_allocate_device();
191 hid_data
= kzalloc(sizeof(*hid_data
), GFP_KERNEL
);
197 hid_data
->index
= cur_hid_dev
;
198 hid_data
->client_data
= client_data
;
199 init_waitqueue_head(&hid_data
->hid_wait
);
201 hid
->driver_data
= hid_data
;
203 client_data
->hid_sensor_hubs
[cur_hid_dev
] = hid
;
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 %04hX:%04hX", "hid-ishtp",
212 hid
->vendor
, hid
->product
);
214 rv
= hid_add_device(hid
);
218 hid_ishtp_trace(client_data
, "%s allocated hid %p\n", __func__
, hid
);
230 * ishtp_hid_probe() - Remove registered hid device
231 * @client_data: client data pointer
233 * This function is used to destroy allocatd HID device.
235 void ishtp_hid_remove(struct ishtp_cl_data
*client_data
)
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
;