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