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