]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/media/usb/rainshadow-cec/rainshadow-cec.c
Merge tag 'for-linus-20170812' of git://git.infradead.org/linux-mtd
[karo-tx-linux.git] / drivers / media / usb / rainshadow-cec / rainshadow-cec.c
1 /*
2  * RainShadow Tech HDMI CEC driver
3  *
4  * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version of 2 of the License, or (at your
9  * option) any later version. See the file COPYING in the main directory of
10  * this archive for more details.
11  */
12
13 /*
14  * Notes:
15  *
16  * The higher level protocols are currently disabled. This can be added
17  * later, similar to how this is done for the Pulse Eight CEC driver.
18  *
19  * Documentation of the protocol is available here:
20  *
21  * http://rainshadowtech.com/doc/HDMICECtoUSBandRS232v2.0.pdf
22  */
23
24 #include <linux/completion.h>
25 #include <linux/ctype.h>
26 #include <linux/delay.h>
27 #include <linux/init.h>
28 #include <linux/interrupt.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/serio.h>
32 #include <linux/slab.h>
33 #include <linux/spinlock.h>
34 #include <linux/time.h>
35 #include <linux/workqueue.h>
36
37 #include <media/cec.h>
38
39 MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
40 MODULE_DESCRIPTION("RainShadow Tech HDMI CEC driver");
41 MODULE_LICENSE("GPL");
42
43 #define DATA_SIZE 256
44
45 struct rain {
46         struct device *dev;
47         struct serio *serio;
48         struct cec_adapter *adap;
49         struct completion cmd_done;
50         struct work_struct work;
51
52         /* Low-level ringbuffer, collecting incoming characters */
53         char buf[DATA_SIZE];
54         unsigned int buf_rd_idx;
55         unsigned int buf_wr_idx;
56         unsigned int buf_len;
57         spinlock_t buf_lock;
58
59         /* command buffer */
60         char cmd[DATA_SIZE];
61         unsigned int cmd_idx;
62         bool cmd_started;
63
64         /* reply to a command, only used to store the firmware version */
65         char cmd_reply[DATA_SIZE];
66
67         struct mutex write_lock;
68 };
69
70 static void rain_process_msg(struct rain *rain)
71 {
72         struct cec_msg msg = {};
73         const char *cmd = rain->cmd + 3;
74         int stat = -1;
75
76         for (; *cmd; cmd++) {
77                 if (!isxdigit(*cmd))
78                         continue;
79                 if (isxdigit(cmd[0]) && isxdigit(cmd[1])) {
80                         if (msg.len == CEC_MAX_MSG_SIZE)
81                                 break;
82                         if (hex2bin(msg.msg + msg.len, cmd, 1))
83                                 continue;
84                         msg.len++;
85                         cmd++;
86                         continue;
87                 }
88                 if (!cmd[1])
89                         stat = hex_to_bin(cmd[0]);
90                 break;
91         }
92
93         if (rain->cmd[0] == 'R') {
94                 if (stat == 1 || stat == 2)
95                         cec_received_msg(rain->adap, &msg);
96                 return;
97         }
98
99         switch (stat) {
100         case 1:
101                 cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_OK);
102                 break;
103         case 2:
104                 cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_NACK);
105                 break;
106         default:
107                 cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_LOW_DRIVE);
108                 break;
109         }
110 }
111
112 static void rain_irq_work_handler(struct work_struct *work)
113 {
114         struct rain *rain =
115                 container_of(work, struct rain, work);
116
117         while (true) {
118                 unsigned long flags;
119                 char data;
120
121                 spin_lock_irqsave(&rain->buf_lock, flags);
122                 if (!rain->buf_len) {
123                         spin_unlock_irqrestore(&rain->buf_lock, flags);
124                         break;
125                 }
126
127                 data = rain->buf[rain->buf_rd_idx];
128                 rain->buf_len--;
129                 rain->buf_rd_idx = (rain->buf_rd_idx + 1) & 0xff;
130
131                 spin_unlock_irqrestore(&rain->buf_lock, flags);
132
133                 if (!rain->cmd_started && data != '?')
134                         continue;
135
136                 switch (data) {
137                 case '\r':
138                         rain->cmd[rain->cmd_idx] = '\0';
139                         dev_dbg(rain->dev, "received: %s\n", rain->cmd);
140                         if (!memcmp(rain->cmd, "REC", 3) ||
141                             !memcmp(rain->cmd, "STA", 3)) {
142                                 rain_process_msg(rain);
143                         } else {
144                                 strcpy(rain->cmd_reply, rain->cmd);
145                                 complete(&rain->cmd_done);
146                         }
147                         rain->cmd_idx = 0;
148                         rain->cmd_started = false;
149                         break;
150
151                 case '\n':
152                         rain->cmd_idx = 0;
153                         rain->cmd_started = false;
154                         break;
155
156                 case '?':
157                         rain->cmd_idx = 0;
158                         rain->cmd_started = true;
159                         break;
160
161                 default:
162                         if (rain->cmd_idx >= DATA_SIZE - 1) {
163                                 dev_dbg(rain->dev,
164                                         "throwing away %d bytes of garbage\n", rain->cmd_idx);
165                                 rain->cmd_idx = 0;
166                         }
167                         rain->cmd[rain->cmd_idx++] = data;
168                         break;
169                 }
170         }
171 }
172
173 static irqreturn_t rain_interrupt(struct serio *serio, unsigned char data,
174                                     unsigned int flags)
175 {
176         struct rain *rain = serio_get_drvdata(serio);
177
178         if (rain->buf_len == DATA_SIZE) {
179                 dev_warn_once(rain->dev, "buffer overflow\n");
180                 return IRQ_HANDLED;
181         }
182         spin_lock(&rain->buf_lock);
183         rain->buf_len++;
184         rain->buf[rain->buf_wr_idx] = data;
185         rain->buf_wr_idx = (rain->buf_wr_idx + 1) & 0xff;
186         spin_unlock(&rain->buf_lock);
187         schedule_work(&rain->work);
188         return IRQ_HANDLED;
189 }
190
191 static void rain_disconnect(struct serio *serio)
192 {
193         struct rain *rain = serio_get_drvdata(serio);
194
195         cancel_work_sync(&rain->work);
196         cec_unregister_adapter(rain->adap);
197         dev_info(&serio->dev, "disconnected\n");
198         serio_close(serio);
199         serio_set_drvdata(serio, NULL);
200         kfree(rain);
201 }
202
203 static int rain_send(struct rain *rain, const char *command)
204 {
205         int err = serio_write(rain->serio, '!');
206
207         dev_dbg(rain->dev, "send: %s\n", command);
208         while (!err && *command)
209                 err = serio_write(rain->serio, *command++);
210         if (!err)
211                 err = serio_write(rain->serio, '~');
212
213         return err;
214 }
215
216 static int rain_send_and_wait(struct rain *rain,
217                               const char *cmd, const char *reply)
218 {
219         int err;
220
221         init_completion(&rain->cmd_done);
222
223         mutex_lock(&rain->write_lock);
224         err = rain_send(rain, cmd);
225         if (err)
226                 goto err;
227
228         if (!wait_for_completion_timeout(&rain->cmd_done, HZ)) {
229                 err = -ETIMEDOUT;
230                 goto err;
231         }
232         if (reply && strncmp(rain->cmd_reply, reply, strlen(reply))) {
233                 dev_dbg(rain->dev,
234                          "transmit of '%s': received '%s' instead of '%s'\n",
235                          cmd, rain->cmd_reply, reply);
236                 err = -EIO;
237         }
238 err:
239         mutex_unlock(&rain->write_lock);
240         return err;
241 }
242
243 static int rain_setup(struct rain *rain, struct serio *serio,
244                         struct cec_log_addrs *log_addrs, u16 *pa)
245 {
246         int err;
247
248         err = rain_send_and_wait(rain, "R", "REV");
249         if (err)
250                 return err;
251         dev_info(rain->dev, "Firmware version %s\n", rain->cmd_reply + 4);
252
253         err = rain_send_and_wait(rain, "Q 1", "QTY");
254         if (err)
255                 return err;
256         err = rain_send_and_wait(rain, "c0000", "CFG");
257         if (err)
258                 return err;
259         return rain_send_and_wait(rain, "A F 0000", "ADR");
260 }
261
262 static int rain_cec_adap_enable(struct cec_adapter *adap, bool enable)
263 {
264         return 0;
265 }
266
267 static int rain_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
268 {
269         struct rain *rain = cec_get_drvdata(adap);
270         u8 cmd[16];
271
272         if (log_addr == CEC_LOG_ADDR_INVALID)
273                 log_addr = CEC_LOG_ADDR_UNREGISTERED;
274         snprintf(cmd, sizeof(cmd), "A %x", log_addr);
275         return rain_send_and_wait(rain, cmd, "ADR");
276 }
277
278 static int rain_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
279                                     u32 signal_free_time, struct cec_msg *msg)
280 {
281         struct rain *rain = cec_get_drvdata(adap);
282         char cmd[2 * CEC_MAX_MSG_SIZE + 16];
283         unsigned int i;
284         int err;
285
286         if (msg->len == 1) {
287                 snprintf(cmd, sizeof(cmd), "x%x", cec_msg_destination(msg));
288         } else {
289                 char hex[3];
290
291                 snprintf(cmd, sizeof(cmd), "x%x %02x ",
292                          cec_msg_destination(msg), msg->msg[1]);
293                 for (i = 2; i < msg->len; i++) {
294                         snprintf(hex, sizeof(hex), "%02x", msg->msg[i]);
295                         strlcat(cmd, hex, sizeof(cmd));
296                 }
297         }
298         mutex_lock(&rain->write_lock);
299         err = rain_send(rain, cmd);
300         mutex_unlock(&rain->write_lock);
301         return err;
302 }
303
304 static const struct cec_adap_ops rain_cec_adap_ops = {
305         .adap_enable = rain_cec_adap_enable,
306         .adap_log_addr = rain_cec_adap_log_addr,
307         .adap_transmit = rain_cec_adap_transmit,
308 };
309
310 static int rain_connect(struct serio *serio, struct serio_driver *drv)
311 {
312         u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR |
313                 CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL;
314         struct rain *rain;
315         int err = -ENOMEM;
316         struct cec_log_addrs log_addrs = {};
317         u16 pa = CEC_PHYS_ADDR_INVALID;
318
319         rain = kzalloc(sizeof(*rain), GFP_KERNEL);
320
321         if (!rain)
322                 return -ENOMEM;
323
324         rain->serio = serio;
325         rain->adap = cec_allocate_adapter(&rain_cec_adap_ops, rain,
326                 "HDMI CEC", caps, 1);
327         err = PTR_ERR_OR_ZERO(rain->adap);
328         if (err < 0)
329                 goto free_device;
330
331         rain->dev = &serio->dev;
332         serio_set_drvdata(serio, rain);
333         INIT_WORK(&rain->work, rain_irq_work_handler);
334         mutex_init(&rain->write_lock);
335         spin_lock_init(&rain->buf_lock);
336
337         err = serio_open(serio, drv);
338         if (err)
339                 goto delete_adap;
340
341         err = rain_setup(rain, serio, &log_addrs, &pa);
342         if (err)
343                 goto close_serio;
344
345         err = cec_register_adapter(rain->adap, &serio->dev);
346         if (err < 0)
347                 goto close_serio;
348
349         rain->dev = &rain->adap->devnode.dev;
350         return 0;
351
352 close_serio:
353         serio_close(serio);
354 delete_adap:
355         cec_delete_adapter(rain->adap);
356         serio_set_drvdata(serio, NULL);
357 free_device:
358         kfree(rain);
359         return err;
360 }
361
362 static struct serio_device_id rain_serio_ids[] = {
363         {
364                 .type   = SERIO_RS232,
365                 .proto  = SERIO_RAINSHADOW_CEC,
366                 .id     = SERIO_ANY,
367                 .extra  = SERIO_ANY,
368         },
369         { 0 }
370 };
371
372 MODULE_DEVICE_TABLE(serio, rain_serio_ids);
373
374 static struct serio_driver rain_drv = {
375         .driver         = {
376                 .name   = "rainshadow-cec",
377         },
378         .description    = "RainShadow Tech HDMI CEC driver",
379         .id_table       = rain_serio_ids,
380         .interrupt      = rain_interrupt,
381         .connect        = rain_connect,
382         .disconnect     = rain_disconnect,
383 };
384
385 module_serio_driver(rain_drv);