rain
cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_NACK);
cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_LOW_DRIVE);
struct rain *rain =
container_of(work, struct rain, work);
spin_lock_irqsave(&rain->buf_lock, flags);
if (!rain->buf_len) {
spin_unlock_irqrestore(&rain->buf_lock, flags);
data = rain->buf[rain->buf_rd_idx];
rain->buf_len--;
rain->buf_rd_idx = (rain->buf_rd_idx + 1) & 0xff;
spin_unlock_irqrestore(&rain->buf_lock, flags);
if (!rain->cmd_started && data != '?')
rain->cmd[rain->cmd_idx] = '\0';
dev_dbg(rain->dev, "received: %s\n", rain->cmd);
if (!memcmp(rain->cmd, "REC", 3) ||
!memcmp(rain->cmd, "STA", 3)) {
rain_process_msg(rain);
strscpy(rain->cmd_reply, rain->cmd,
sizeof(rain->cmd_reply));
complete(&rain->cmd_done);
rain->cmd_idx = 0;
rain->cmd_started = false;
rain->cmd_idx = 0;
rain->cmd_started = false;
rain->cmd_idx = 0;
rain->cmd_started = true;
if (rain->cmd_idx >= DATA_SIZE - 1) {
dev_dbg(rain->dev,
"throwing away %d bytes of garbage\n", rain->cmd_idx);
rain->cmd_idx = 0;
rain->cmd[rain->cmd_idx++] = data;
struct rain *rain = serio_get_drvdata(serio);
spin_lock(&rain->buf_lock);
if (rain->buf_len == DATA_SIZE) {
spin_unlock(&rain->buf_lock);
dev_warn_once(rain->dev, "buffer overflow\n");
rain->buf_len++;
rain->buf[rain->buf_wr_idx] = data;
rain->buf_wr_idx = (rain->buf_wr_idx + 1) & 0xff;
spin_unlock(&rain->buf_lock);
schedule_work(&rain->work);
struct rain *rain = serio_get_drvdata(serio);
cancel_work_sync(&rain->work);
cec_unregister_adapter(rain->adap);
kfree(rain);
static int rain_send(struct rain *rain, const char *command)
int err = serio_write(rain->serio, '!');
dev_dbg(rain->dev, "send: %s\n", command);
err = serio_write(rain->serio, *command++);
err = serio_write(rain->serio, '~');
static int rain_send_and_wait(struct rain *rain,
init_completion(&rain->cmd_done);
mutex_lock(&rain->write_lock);
err = rain_send(rain, cmd);
if (!wait_for_completion_timeout(&rain->cmd_done, HZ)) {
if (reply && strncmp(rain->cmd_reply, reply, strlen(reply))) {
dev_dbg(rain->dev,
cmd, rain->cmd_reply, reply);
mutex_unlock(&rain->write_lock);
static int rain_setup(struct rain *rain, struct serio *serio,
err = rain_send_and_wait(rain, "R", "REV");
dev_info(rain->dev, "Firmware version %s\n", rain->cmd_reply + 4);
err = rain_send_and_wait(rain, "Q 1", "QTY");
err = rain_send_and_wait(rain, "c0000", "CFG");
return rain_send_and_wait(rain, "A F 0000", "ADR");
struct rain *rain = cec_get_drvdata(adap);
return rain_send_and_wait(rain, cmd, "ADR");
struct rain *rain = cec_get_drvdata(adap);
mutex_lock(&rain->write_lock);
err = rain_send(rain, cmd);
mutex_unlock(&rain->write_lock);
struct rain *rain;
rain = kzalloc_obj(*rain);
if (!rain)
rain->serio = serio;
rain->adap = cec_allocate_adapter(&rain_cec_adap_ops, rain,
err = PTR_ERR_OR_ZERO(rain->adap);
rain->dev = &serio->dev;
serio_set_drvdata(serio, rain);
INIT_WORK(&rain->work, rain_irq_work_handler);
mutex_init(&rain->write_lock);
spin_lock_init(&rain->buf_lock);
err = rain_setup(rain, serio, &log_addrs, &pa);
err = cec_register_adapter(rain->adap, &serio->dev);
rain->dev = &rain->adap->devnode.dev;
cec_delete_adapter(rain->adap);
kfree(rain);
static void rain_process_msg(struct rain *rain)
const char *cmd = rain->cmd + 3;
if (rain->cmd[0] == 'R') {
cec_received_msg(rain->adap, &msg);
cec_transmit_attempt_done(rain->adap, CEC_TX_STATUS_OK);