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