2 * RainShadow Tech HDMI CEC driver
4 * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
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.
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.
19 * Documentation of the protocol is available here:
21 * http://rainshadowtech.com/doc/HDMICECtoUSBandRS232v2.0.pdf
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>
37 #include <media/cec.h>
39 MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
40 MODULE_DESCRIPTION("RainShadow Tech HDMI CEC driver");
41 MODULE_LICENSE("GPL");
48 struct cec_adapter
*adap
;
49 struct completion cmd_done
;
50 struct work_struct work
;
52 /* Low-level ringbuffer, collecting incoming characters */
54 unsigned int buf_rd_idx
;
55 unsigned int buf_wr_idx
;
64 /* reply to a command, only used to store the firmware version */
65 char cmd_reply
[DATA_SIZE
];
67 struct mutex write_lock
;
70 static void rain_process_msg(struct rain
*rain
)
72 struct cec_msg msg
= {};
73 const char *cmd
= rain
->cmd
+ 3;
79 if (isxdigit(cmd
[0]) && isxdigit(cmd
[1])) {
80 if (msg
.len
== CEC_MAX_MSG_SIZE
)
82 if (hex2bin(msg
.msg
+ msg
.len
, cmd
, 1))
89 stat
= hex_to_bin(cmd
[0]);
93 if (rain
->cmd
[0] == 'R') {
94 if (stat
== 1 || stat
== 2)
95 cec_received_msg(rain
->adap
, &msg
);
101 cec_transmit_done(rain
->adap
, CEC_TX_STATUS_OK
,
105 cec_transmit_done(rain
->adap
, CEC_TX_STATUS_NACK
,
109 cec_transmit_done(rain
->adap
, CEC_TX_STATUS_LOW_DRIVE
,
115 static void rain_irq_work_handler(struct work_struct
*work
)
118 container_of(work
, struct rain
, work
);
122 bool exit_loop
= false;
125 spin_lock_irqsave(&rain
->buf_lock
, flags
);
126 exit_loop
= rain
->buf_len
== 0;
128 data
= rain
->buf
[rain
->buf_rd_idx
];
130 rain
->buf_rd_idx
= (rain
->buf_rd_idx
+ 1) & 0xff;
132 spin_unlock_irqrestore(&rain
->buf_lock
, flags
);
137 if (!rain
->cmd_started
&& data
!= '?')
142 rain
->cmd
[rain
->cmd_idx
] = '\0';
143 dev_dbg(rain
->dev
, "received: %s\n", rain
->cmd
);
144 if (!memcmp(rain
->cmd
, "REC", 3) ||
145 !memcmp(rain
->cmd
, "STA", 3)) {
146 rain_process_msg(rain
);
148 strcpy(rain
->cmd_reply
, rain
->cmd
);
149 complete(&rain
->cmd_done
);
152 rain
->cmd_started
= false;
157 rain
->cmd_started
= false;
162 rain
->cmd_started
= true;
166 if (rain
->cmd_idx
>= DATA_SIZE
- 1) {
168 "throwing away %d bytes of garbage\n", rain
->cmd_idx
);
171 rain
->cmd
[rain
->cmd_idx
++] = data
;
177 static irqreturn_t
rain_interrupt(struct serio
*serio
, unsigned char data
,
180 struct rain
*rain
= serio_get_drvdata(serio
);
182 if (rain
->buf_len
== DATA_SIZE
) {
183 dev_warn_once(rain
->dev
, "buffer overflow\n");
186 spin_lock(&rain
->buf_lock
);
188 rain
->buf
[rain
->buf_wr_idx
] = data
;
189 rain
->buf_wr_idx
= (rain
->buf_wr_idx
+ 1) & 0xff;
190 spin_unlock(&rain
->buf_lock
);
191 schedule_work(&rain
->work
);
195 static void rain_disconnect(struct serio
*serio
)
197 struct rain
*rain
= serio_get_drvdata(serio
);
199 cancel_work_sync(&rain
->work
);
200 cec_unregister_adapter(rain
->adap
);
201 dev_info(&serio
->dev
, "disconnected\n");
203 serio_set_drvdata(serio
, NULL
);
207 static int rain_send(struct rain
*rain
, const char *command
)
209 int err
= serio_write(rain
->serio
, '!');
211 dev_dbg(rain
->dev
, "send: %s\n", command
);
212 while (!err
&& *command
)
213 err
= serio_write(rain
->serio
, *command
++);
215 err
= serio_write(rain
->serio
, '~');
220 static int rain_send_and_wait(struct rain
*rain
,
221 const char *cmd
, const char *reply
)
225 init_completion(&rain
->cmd_done
);
227 mutex_lock(&rain
->write_lock
);
228 err
= rain_send(rain
, cmd
);
232 if (!wait_for_completion_timeout(&rain
->cmd_done
, HZ
)) {
236 if (reply
&& strncmp(rain
->cmd_reply
, reply
, strlen(reply
))) {
238 "transmit of '%s': received '%s' instead of '%s'\n",
239 cmd
, rain
->cmd_reply
, reply
);
243 mutex_unlock(&rain
->write_lock
);
247 static int rain_setup(struct rain
*rain
, struct serio
*serio
,
248 struct cec_log_addrs
*log_addrs
, u16
*pa
)
252 err
= rain_send_and_wait(rain
, "R", "REV");
255 dev_info(rain
->dev
, "Firmware version %s\n", rain
->cmd_reply
+ 4);
257 err
= rain_send_and_wait(rain
, "Q 1", "QTY");
260 err
= rain_send_and_wait(rain
, "c0000", "CFG");
263 return rain_send_and_wait(rain
, "A F 0000", "ADR");
266 static int rain_cec_adap_enable(struct cec_adapter
*adap
, bool enable
)
271 static int rain_cec_adap_log_addr(struct cec_adapter
*adap
, u8 log_addr
)
273 struct rain
*rain
= cec_get_drvdata(adap
);
276 if (log_addr
== CEC_LOG_ADDR_INVALID
)
277 log_addr
= CEC_LOG_ADDR_UNREGISTERED
;
278 snprintf(cmd
, sizeof(cmd
), "A %x", log_addr
);
279 return rain_send_and_wait(rain
, cmd
, "ADR");
282 static int rain_cec_adap_transmit(struct cec_adapter
*adap
, u8 attempts
,
283 u32 signal_free_time
, struct cec_msg
*msg
)
285 struct rain
*rain
= cec_get_drvdata(adap
);
286 char cmd
[2 * CEC_MAX_MSG_SIZE
+ 16];
291 snprintf(cmd
, sizeof(cmd
), "x%x", cec_msg_destination(msg
));
295 snprintf(cmd
, sizeof(cmd
), "x%x %02x ",
296 cec_msg_destination(msg
), msg
->msg
[1]);
297 for (i
= 2; i
< msg
->len
; i
++) {
298 snprintf(hex
, sizeof(hex
), "%02x", msg
->msg
[i
]);
299 strncat(cmd
, hex
, sizeof(cmd
));
302 mutex_lock(&rain
->write_lock
);
303 err
= rain_send(rain
, cmd
);
304 mutex_unlock(&rain
->write_lock
);
308 static const struct cec_adap_ops rain_cec_adap_ops
= {
309 .adap_enable
= rain_cec_adap_enable
,
310 .adap_log_addr
= rain_cec_adap_log_addr
,
311 .adap_transmit
= rain_cec_adap_transmit
,
314 static int rain_connect(struct serio
*serio
, struct serio_driver
*drv
)
316 u32 caps
= CEC_CAP_TRANSMIT
| CEC_CAP_LOG_ADDRS
| CEC_CAP_PHYS_ADDR
|
317 CEC_CAP_PASSTHROUGH
| CEC_CAP_RC
| CEC_CAP_MONITOR_ALL
;
320 struct cec_log_addrs log_addrs
= {};
321 u16 pa
= CEC_PHYS_ADDR_INVALID
;
323 rain
= kzalloc(sizeof(*rain
), GFP_KERNEL
);
329 rain
->adap
= cec_allocate_adapter(&rain_cec_adap_ops
, rain
,
330 "HDMI CEC", caps
, 1);
331 err
= PTR_ERR_OR_ZERO(rain
->adap
);
335 rain
->dev
= &serio
->dev
;
336 serio_set_drvdata(serio
, rain
);
337 INIT_WORK(&rain
->work
, rain_irq_work_handler
);
338 mutex_init(&rain
->write_lock
);
339 spin_lock_init(&rain
->buf_lock
);
341 err
= serio_open(serio
, drv
);
345 err
= rain_setup(rain
, serio
, &log_addrs
, &pa
);
349 err
= cec_register_adapter(rain
->adap
, &serio
->dev
);
353 rain
->dev
= &rain
->adap
->devnode
.dev
;
359 cec_delete_adapter(rain
->adap
);
360 serio_set_drvdata(serio
, NULL
);
366 static struct serio_device_id rain_serio_ids
[] = {
369 .proto
= SERIO_RAINSHADOW_CEC
,
376 MODULE_DEVICE_TABLE(serio
, rain_serio_ids
);
378 static struct serio_driver rain_drv
= {
380 .name
= "rainshadow-cec",
382 .description
= "RainShadow Tech HDMI CEC driver",
383 .id_table
= rain_serio_ids
,
384 .interrupt
= rain_interrupt
,
385 .connect
= rain_connect
,
386 .disconnect
= rain_disconnect
,
389 module_serio_driver(rain_drv
);