CHROMEOS: HID: MT-B driver for Logitech wireless touchpads
[cascardo/linux.git] / drivers / hid / hid-logitech-hidpp.c
1 /*
2  *  HIDPP protocol for Logitech Unifying receivers
3  *
4  *  Copyright (c) 2011 Logitech (c)
5  */
6
7 /*
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * Should you need to contact me, the author, you can do so by e-mail send
22  * your message to Benjamin Tissoires <benjamin.tissoires at gmail com>
23  *
24  */
25
26
27 #include <linux/device.h>
28 #include <linux/hid.h>
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #include <linux/sched.h>
32 #include "hid-logitech-hidpp.h"
33
34 MODULE_LICENSE("GPL");
35 MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
36 MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>");
37
38 #define MAX_INIT_RETRY 5
39
40 enum delayed_work_type {
41         HIDPP_INIT = 0
42 };
43
44 static void hidpp_print_raw_event(const char *header, u8 *data, int size)
45 {
46         int i;
47         unsigned char log[96];
48         unsigned char tmpstr[60];
49
50         snprintf(log, sizeof(tmpstr), "%s (size=%d)", header, size);
51
52         for (i = 0; i < size; i++) {
53                 snprintf(tmpstr, sizeof(tmpstr), " %02x", data[i]);
54                 strlcat(log, tmpstr, sizeof(log));
55         }
56
57         dbg_hid("%s\n", log);
58 }
59
60 static int __hidpp_send_report(struct hid_device *hdev,
61                                 struct hidpp_report *hidpp_rept)
62 {
63         int sent_bytes;
64
65         if (!hdev->hid_output_raw_report) {
66                 dev_err(&hdev->dev, "%s:"
67                         "hid_output_raw_report is null\n", __func__);
68                 return -ENODEV;
69         }
70
71         hidpp_print_raw_event("sending ", (u8 *)hidpp_rept,
72                                 HIDPP_REPORT_LONG_LENGTH);
73         sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) hidpp_rept,
74                                                  sizeof(struct hidpp_report),
75                                                  HID_OUTPUT_REPORT);
76
77         return (sent_bytes < 0) ? sent_bytes : 0;
78 }
79
80 static int hidpp_send_message_sync(struct hidpp_device *hidpp_dev,
81         struct hidpp_report *message,
82         struct hidpp_report *response)
83 {
84         int ret;
85
86         mutex_lock(&hidpp_dev->send_mutex);
87
88         hidpp_dev->send_receive_buf = response;
89         hidpp_dev->answer_available = false;
90
91         /* So that we can later validate the answer when it arrives
92          * in hidpp_raw_event */
93         *response = *message;
94
95         ret = __hidpp_send_report(hidpp_dev->hid_dev, message);
96
97         if (ret) {
98           dbg_hid("__hidpp_send_report returned err: %d\n", ret);
99                 memset(response, 0, sizeof(struct hidpp_report));
100                 goto exit;
101         }
102
103         if (!wait_event_timeout(hidpp_dev->wait, hidpp_dev->answer_available, 10*HZ)) {
104                 dbg_hid("%s:timeout waiting for response\n", __func__);
105                 memset(response, 0, sizeof(struct hidpp_report));
106                 ret = -1;
107         }
108
109         if (response->report_id == REPORT_ID_HIDPP_SHORT &&
110             response->fap.feature_index == HIDPP_ERROR) {
111                 ret = response->fap.params[0];
112           dbg_hid("__hidpp_send_report got hidpp error %d\n", ret);
113                 goto exit;
114         }
115
116 exit:
117         mutex_unlock(&hidpp_dev->send_mutex);
118         return ret;
119
120 }
121
122 int hidpp_send_fap_command_sync(struct hidpp_device *hidpp_dev,
123         u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count,
124         struct hidpp_report *response)
125 {
126         struct hidpp_report message;
127
128         if (param_count > sizeof(message.rap.params))
129                 return -EINVAL;
130
131         memset(&message, 0, sizeof(message));
132         message.report_id = REPORT_ID_HIDPP_LONG;
133         message.fap.feature_index = feat_index;
134         message.fap.funcindex_clientid = funcindex_clientid;
135         memcpy(&message.fap.params, params, param_count);
136
137         return hidpp_send_message_sync(hidpp_dev, &message, response);
138 }
139 EXPORT_SYMBOL_GPL(hidpp_send_fap_command_sync);
140
141 int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
142         u8 report_id, u8 sub_id, u8 reg_address, u8 *params,
143         int param_count,
144         struct hidpp_report *response)
145 {
146         struct hidpp_report message;
147
148         if ((report_id != REPORT_ID_HIDPP_SHORT) &&
149             (report_id != REPORT_ID_HIDPP_LONG))
150                 return -EINVAL;
151
152         if (param_count > sizeof(message.rap.params))
153                 return -EINVAL;
154
155         memset(&message, 0, sizeof(message));
156         message.report_id = report_id;
157         message.rap.sub_id = sub_id;
158         message.rap.reg_address = reg_address;
159         memcpy(&message.rap.params, params, param_count);
160
161         return hidpp_send_message_sync(hidpp_dev, &message, response);
162 }
163 EXPORT_SYMBOL_GPL(hidpp_send_rap_command_sync);
164
165 int hidpp_get_hidpp2_feature_index(struct hidpp_device *hidpp_dev,
166                                         u8 software_id,
167                                         u16 feature_id,
168                                         u8 *feature_idx)
169 {
170         struct hidpp_report response;
171         u8 params[2];
172         int ret;
173
174         params[0] = feature_id >> 8;
175         params[1] = feature_id & 0xff;
176         ret = hidpp_send_hidpp2_sync(hidpp_dev,
177                                         REPORT_ID_HIDPP_SHORT,
178                                         0,
179                                         0,
180                                         software_id,
181                                         params,
182                                         sizeof(params),
183                                         &response);
184         if (ret)
185                 return ret;
186         *feature_idx = response.rap.params[0];
187         return ret;
188 }
189 EXPORT_SYMBOL_GPL(hidpp_get_hidpp2_feature_index);
190
191 static void schedule_delayed_hidpp_init(struct hidpp_device *hidpp_dev)
192 {
193         enum delayed_work_type work_type = HIDPP_INIT;
194
195         kfifo_in(&hidpp_dev->delayed_work_fifo, &work_type,
196                                 sizeof(enum delayed_work_type));
197
198         if (schedule_work(&hidpp_dev->work) == 0) {
199                 dbg_hid("%s: did not schedule the work item,"
200                         " was already queued\n",
201                         __func__);
202         }
203 }
204
205 void hidpp_delayed_init(struct hidpp_device *hidpp_device)
206 {
207         struct hid_device *hdev = hidpp_device->hid_dev;
208         int ret = 0;
209
210         dbg_hid("%s: hdev:%p\n", __func__, hdev);
211
212         if (hidpp_device->initialized)
213                 return;
214
215         if (down_trylock(&hidpp_device->hid_dev->driver_lock)) {
216                 if (hidpp_device->init_retry < MAX_INIT_RETRY) {
217                         dbg_hid("%s: we need to reschedule the work item."
218                                 "Semaphore still held on device\n", __func__);
219                         schedule_delayed_hidpp_init(hidpp_device);
220                         hidpp_device->init_retry++;
221                 } else {
222                         dbg_hid("%s: giving up initialization now.", __func__);
223                         hidpp_device->init_retry = 0;
224                 }
225                 return;
226         }
227         up(&hidpp_device->hid_dev->driver_lock);
228
229         if (hidpp_device->device_init)
230                 ret = hidpp_device->device_init(hidpp_device);
231
232         if (!ret)
233                 hidpp_device->initialized = true;
234 }
235 EXPORT_SYMBOL_GPL(hidpp_delayed_init);
236
237 static void delayed_work_cb(struct work_struct *work)
238 {
239         struct hidpp_device *hidpp_device =
240                 container_of(work, struct hidpp_device, work);
241         unsigned long flags;
242         int count;
243         enum delayed_work_type work_type;
244
245         dbg_hid("%s\n", __func__);
246
247         spin_lock_irqsave(&hidpp_device->lock, flags);
248
249         count = kfifo_out(&hidpp_device->delayed_work_fifo, &work_type,
250                                 sizeof(enum delayed_work_type));
251
252         if (count != sizeof(enum delayed_work_type)) {
253                 dev_err(&hidpp_device->hid_dev->dev, "%s: workitem triggered without "
254                         "notifications available\n", __func__);
255                 spin_unlock_irqrestore(&hidpp_device->lock, flags);
256                 return;
257         }
258
259         if (!kfifo_is_empty(&hidpp_device->delayed_work_fifo)) {
260                 if (schedule_work(&hidpp_device->work) == 0) {
261                         dbg_hid("%s: did not schedule the work item, was "
262                                 "already queued\n", __func__);
263                 }
264         }
265
266         spin_unlock_irqrestore(&hidpp_device->lock, flags);
267
268         switch (work_type) {
269         case HIDPP_INIT:
270                 hidpp_delayed_init(hidpp_device);
271                 break;
272         default:
273                 dbg_hid("%s: unexpected report type\n", __func__);
274         }
275 }
276
277 int hidpp_init(struct hidpp_device *hidpp_dev, struct hid_device *hid_dev)
278 {
279         if (hidpp_dev->initialized)
280                 return 0;
281
282         hidpp_dev->init_retry = 0;
283         hidpp_dev->hid_dev = hid_dev;
284         hidpp_dev->initialized = 1;
285
286         INIT_WORK(&hidpp_dev->work, delayed_work_cb);
287         mutex_init(&hidpp_dev->send_mutex);
288         init_waitqueue_head(&hidpp_dev->wait);
289
290         spin_lock_init(&hidpp_dev->lock);
291         if (kfifo_alloc(&hidpp_dev->delayed_work_fifo,
292                         4 * sizeof(struct hidpp_report),
293                         GFP_KERNEL)) {
294                 dev_err(&hidpp_dev->hid_dev->dev,
295                         "%s:failed allocating delayed_work_fifo\n", __func__);
296                 mutex_destroy(&hidpp_dev->send_mutex);
297                 return -ENOMEM;
298         }
299
300         return 0;
301 }
302 EXPORT_SYMBOL_GPL(hidpp_init);
303
304 void hidpp_connect_change(struct hidpp_device *hidpp_dev, bool connected)
305 {
306         if ((!hidpp_dev->initialized) && (connected))
307                 hidpp_delayed_init(hidpp_dev);
308
309         if (hidpp_dev->connect_change)
310                 hidpp_dev->connect_change(hidpp_dev, connected);
311 }
312 EXPORT_SYMBOL_GPL(hidpp_connect_change);
313
314 void hidpp_remove(struct hidpp_device *hidpp_dev)
315 {
316         dbg_hid("%s\n", __func__);
317         cancel_work_sync(&hidpp_dev->work);
318         mutex_destroy(&hidpp_dev->send_mutex);
319         kfifo_free(&hidpp_dev->delayed_work_fifo);
320         hidpp_dev->initialized = false;
321         hidpp_dev->hid_dev = NULL;
322 }
323 EXPORT_SYMBOL_GPL(hidpp_remove);
324
325 int hidpp_raw_event(struct hid_device *hdev, struct hid_report *hid_report,
326                         u8 *data, int size)
327 {
328         struct hidpp_device *hidpp_dev = hid_get_drvdata(hdev);
329         struct hidpp_report *report = (struct hidpp_report *)data;
330         struct hidpp_report *question = hidpp_dev->send_receive_buf;
331         struct hidpp_report *answer = hidpp_dev->send_receive_buf;
332
333         dbg_hid("%s\n", __func__);
334
335         hidpp_print_raw_event("hidpp_raw_event", data, size);
336
337         if ((report->report_id != REPORT_ID_HIDPP_LONG) &&
338             (report->report_id != REPORT_ID_HIDPP_SHORT)) {
339                 dbg_hid("hid-logitech-hidpp.c:%s: ignore report_id:%d\n",
340                         __func__, report->report_id);
341                 return 0;
342         }
343
344         /* If the mutex is locked then we have a pending answer from a
345          * previoulsly sent command
346          */
347         if (unlikely(mutex_is_locked(&hidpp_dev->send_mutex))) {
348                 /* Check for a correct hidpp20 answer */
349                 bool correct_answer =
350                         report->fap.feature_index == question->fap.feature_index &&
351                 report->fap.funcindex_clientid == question->fap.funcindex_clientid;
352                 dbg_hid("%s mutex is locked, waiting for reply\n", __func__);
353
354                 /* Check for a "correct" hidpp10 error message, this means the
355                  * device is hidpp10 and does not support the command sent */
356                 correct_answer = correct_answer ||
357                         (report->fap.feature_index == HIDPP_ERROR &&
358                 report->fap.funcindex_clientid == question->fap.feature_index &&
359                 report->fap.params[0] == question->fap.funcindex_clientid);
360
361                 if (correct_answer) {
362                         hidpp_print_raw_event("answer", data, size);
363                         *answer = *report;
364                         hidpp_dev->answer_available = true;
365                         wake_up(&hidpp_dev->wait);
366                         /* This was an answer to a command that this driver sent
367                          * we return 1 to hid-core to avoid forwarding the command
368                          * upstream as it has been treated by the driver */
369
370                         return 1;
371                 }
372         }
373
374         if (hidpp_dev->raw_event != NULL) {
375                 return hidpp_dev->raw_event(hidpp_dev, report);
376         }
377
378         hidpp_print_raw_event("event not treated", data, size);
379
380         return 0;
381 }
382 EXPORT_SYMBOL_GPL(hidpp_raw_event);