All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Pulse-Eight USB CEC driver
@ 2016-07-10 13:11 Hans Verkuil
  2016-07-10 13:11 ` [PATCH 1/5] cec: add check if adapter is unregistered Hans Verkuil
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-10 13:11 UTC (permalink / raw)
  To: linux-media; +Cc: lars

From: Hans Verkuil <hans.verkuil@cisco.com>

This adds support for the Pulse-Eight USB CEC dongle. It has been tested
with both v4 and v5 firmware.

It is still in staging because 1) the CEC framework it depends on is still in 
staging, 2) the code needs to be refactored a bit and 3) it needs more testing.

That said, it's in pretty decent shape. It's pretty neat, but I do wish it
would support a CEC bus snooping mode: that would make it an ideal CEC bus
sniffer. But I don't see any support for it, unfortunately.

If anyone knows how this can be achieved then please let me know!

Please note that this needs support from inputattach (part of linuxconsoletools),
a patch is included in the TODO file.

Regards,

	Hans

Hans Verkuil (5):
  cec: add check if adapter is unregistered.
  serio.h: add new define for the Pulse-Eight USB-CEC Adapter
  pulse8-cec: new driver for the Pulse-Eight USB-CEC Adapter
  MAINTAINERS: add entry for the pulse8-cec driver
  pulse8-cec: add TODO file

 MAINTAINERS                                   |   7 +
 drivers/staging/media/Kconfig                 |   2 +
 drivers/staging/media/Makefile                |   1 +
 drivers/staging/media/cec/cec-adap.c          |   5 +-
 drivers/staging/media/pulse8-cec/Kconfig      |  10 +
 drivers/staging/media/pulse8-cec/Makefile     |   1 +
 drivers/staging/media/pulse8-cec/TODO         |  35 ++
 drivers/staging/media/pulse8-cec/pulse8-cec.c | 502 ++++++++++++++++++++++++++
 include/uapi/linux/serio.h                    |   1 +
 9 files changed, 563 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/media/pulse8-cec/Kconfig
 create mode 100644 drivers/staging/media/pulse8-cec/Makefile
 create mode 100644 drivers/staging/media/pulse8-cec/TODO
 create mode 100644 drivers/staging/media/pulse8-cec/pulse8-cec.c

-- 
2.8.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/5] cec: add check if adapter is unregistered.
  2016-07-10 13:11 [PATCH 0/5] Pulse-Eight USB CEC driver Hans Verkuil
@ 2016-07-10 13:11 ` Hans Verkuil
  2016-07-10 13:11 ` [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter Hans Verkuil
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-10 13:11 UTC (permalink / raw)
  To: linux-media; +Cc: lars, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

CEC USB dongles can be unplugged at any time, and at that point they will
be unregistered. Make sure that any attempt afterwards to set the physical
or logical addresses will be ignored.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/cec/cec-adap.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/cec/cec-adap.c b/drivers/staging/media/cec/cec-adap.c
index 7df6187..2cd656b 100644
--- a/drivers/staging/media/cec/cec-adap.c
+++ b/drivers/staging/media/cec/cec-adap.c
@@ -1104,7 +1104,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
  */
 void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
 {
-	if (phys_addr == adap->phys_addr)
+	if (phys_addr == adap->phys_addr || adap->devnode.unregistered)
 		return;
 
 	if (phys_addr == CEC_PHYS_ADDR_INVALID ||
@@ -1158,6 +1158,9 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
 	u16 type_mask = 0;
 	int i;
 
+	if (adap->devnode.unregistered)
+		return -ENODEV;
+
 	if (!log_addrs || log_addrs->num_log_addrs == 0) {
 		adap->log_addrs.num_log_addrs = 0;
 		cec_adap_unconfigure(adap);
-- 
2.8.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter
  2016-07-10 13:11 [PATCH 0/5] Pulse-Eight USB CEC driver Hans Verkuil
  2016-07-10 13:11 ` [PATCH 1/5] cec: add check if adapter is unregistered Hans Verkuil
@ 2016-07-10 13:11 ` Hans Verkuil
  2016-07-10 13:20   ` Hans Verkuil
  2016-07-11 17:00   ` Dmitry Torokhov
  2016-07-10 13:11 ` [PATCH 3/5] pulse8-cec: new driver " Hans Verkuil
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-10 13:11 UTC (permalink / raw)
  To: linux-media; +Cc: lars, Hans Verkuil, Dmitry Torokhov

From: Hans Verkuil <hans.verkuil@cisco.com>

This is for the new pulse8-cec staging driver.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 include/uapi/linux/serio.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/serio.h b/include/uapi/linux/serio.h
index c2ea169..f2447a8 100644
--- a/include/uapi/linux/serio.h
+++ b/include/uapi/linux/serio.h
@@ -78,5 +78,6 @@
 #define SERIO_TSC40	0x3d
 #define SERIO_WACOM_IV	0x3e
 #define SERIO_EGALAX	0x3f
+#define SERIO_PULSE8_CEC	0x40
 
 #endif /* _UAPI_SERIO_H */
-- 
2.8.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/5] pulse8-cec: new driver for the Pulse-Eight USB-CEC Adapter
  2016-07-10 13:11 [PATCH 0/5] Pulse-Eight USB CEC driver Hans Verkuil
  2016-07-10 13:11 ` [PATCH 1/5] cec: add check if adapter is unregistered Hans Verkuil
  2016-07-10 13:11 ` [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter Hans Verkuil
@ 2016-07-10 13:11 ` Hans Verkuil
  2016-07-10 13:11 ` [PATCH 4/5] MAINTAINERS: add entry for the pulse8-cec driver Hans Verkuil
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-10 13:11 UTC (permalink / raw)
  To: linux-media; +Cc: lars, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

This supports the Pulse-Eight USB-CEC Adapter.

It has been tested with firmware versions 4 and 5, but it should
hopefully work fine with older firmwares as well.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/Kconfig                 |   2 +
 drivers/staging/media/Makefile                |   1 +
 drivers/staging/media/pulse8-cec/Kconfig      |  10 +
 drivers/staging/media/pulse8-cec/Makefile     |   1 +
 drivers/staging/media/pulse8-cec/pulse8-cec.c | 502 ++++++++++++++++++++++++++
 5 files changed, 516 insertions(+)
 create mode 100644 drivers/staging/media/pulse8-cec/Kconfig
 create mode 100644 drivers/staging/media/pulse8-cec/Makefile
 create mode 100644 drivers/staging/media/pulse8-cec/pulse8-cec.c

diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index 5670789..cae42e5 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -29,6 +29,8 @@ source "drivers/staging/media/davinci_vpfe/Kconfig"
 
 source "drivers/staging/media/omap4iss/Kconfig"
 
+source "drivers/staging/media/pulse8-cec/Kconfig"
+
 source "drivers/staging/media/tw686x-kh/Kconfig"
 
 source "drivers/staging/media/s5p-cec/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 989c844..87ce8ad 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_DVB_CXD2099)	+= cxd2099/
 obj-$(CONFIG_LIRC_STAGING)	+= lirc/
 obj-$(CONFIG_VIDEO_DM365_VPFE)	+= davinci_vpfe/
 obj-$(CONFIG_VIDEO_OMAP4)	+= omap4iss/
+obj-$(CONFIG_USB_PULSE8_CEC)    += pulse8-cec/
 obj-$(CONFIG_VIDEO_TW686X_KH)	+= tw686x-kh/
diff --git a/drivers/staging/media/pulse8-cec/Kconfig b/drivers/staging/media/pulse8-cec/Kconfig
new file mode 100644
index 0000000..c6aa2d1
--- /dev/null
+++ b/drivers/staging/media/pulse8-cec/Kconfig
@@ -0,0 +1,10 @@
+config USB_PULSE8_CEC
+	tristate "Pulse Eight HDMI CEC"
+	depends on USB_ACM && MEDIA_CEC
+	select SERIO
+	select SERIO_SERPORT
+	---help---
+	  This is a cec driver for the Pulse Eight HDMI CEC device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pulse8-cec.
diff --git a/drivers/staging/media/pulse8-cec/Makefile b/drivers/staging/media/pulse8-cec/Makefile
new file mode 100644
index 0000000..9800690
--- /dev/null
+++ b/drivers/staging/media/pulse8-cec/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_PULSE8_CEC) += pulse8-cec.o
diff --git a/drivers/staging/media/pulse8-cec/pulse8-cec.c b/drivers/staging/media/pulse8-cec/pulse8-cec.c
new file mode 100644
index 0000000..e07d2ff
--- /dev/null
+++ b/drivers/staging/media/pulse8-cec/pulse8-cec.c
@@ -0,0 +1,502 @@
+/*
+ * Pulse Eight HDMI CEC driver
+ *
+ * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version of 2 of the License, or (at your
+ * option) any later version. See the file COPYING in the main directory of
+ * this archive for more details.
+ */
+
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <media/cec.h>
+
+MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
+MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-1)");
+
+enum pulse8_msgcodes {
+	MSGCODE_NOTHING = 0,
+	MSGCODE_PING,
+	MSGCODE_TIMEOUT_ERROR,
+	MSGCODE_HIGH_ERROR,
+	MSGCODE_LOW_ERROR,
+	MSGCODE_FRAME_START,
+	MSGCODE_FRAME_DATA,
+	MSGCODE_RECEIVE_FAILED,
+	MSGCODE_COMMAND_ACCEPTED,	/* 0x08 */
+	MSGCODE_COMMAND_REJECTED,
+	MSGCODE_SET_ACK_MASK,
+	MSGCODE_TRANSMIT,
+	MSGCODE_TRANSMIT_EOM,
+	MSGCODE_TRANSMIT_IDLETIME,
+	MSGCODE_TRANSMIT_ACK_POLARITY,
+	MSGCODE_TRANSMIT_LINE_TIMEOUT,
+	MSGCODE_TRANSMIT_SUCCEEDED,	/* 0x10 */
+	MSGCODE_TRANSMIT_FAILED_LINE,
+	MSGCODE_TRANSMIT_FAILED_ACK,
+	MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA,
+	MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
+	MSGCODE_FIRMWARE_VERSION,
+	MSGCODE_START_BOOTLOADER,
+	MSGCODE_GET_BUILDDATE,
+	MSGCODE_SET_CONTROLLED,		/* 0x18 */
+	MSGCODE_GET_AUTO_ENABLED,
+	MSGCODE_SET_AUTO_ENABLED,
+	MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS,
+	MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS,
+	MSGCODE_GET_LOGICAL_ADDRESS_MASK,
+	MSGCODE_SET_LOGICAL_ADDRESS_MASK,
+	MSGCODE_GET_PHYSICAL_ADDRESS,
+	MSGCODE_SET_PHYSICAL_ADDRESS,	/* 0x20 */
+	MSGCODE_GET_DEVICE_TYPE,
+	MSGCODE_SET_DEVICE_TYPE,
+	MSGCODE_GET_HDMI_VERSION,
+	MSGCODE_SET_HDMI_VERSION,
+	MSGCODE_GET_OSD_NAME,
+	MSGCODE_SET_OSD_NAME,
+	MSGCODE_WRITE_EEPROM,
+	MSGCODE_GET_ADAPTER_TYPE,	/* 0x28 */
+	MSGCODE_SET_ACTIVE_SOURCE,
+
+	MSGCODE_FRAME_EOM = 0x80,
+	MSGCODE_FRAME_ACK = 0x40,
+};
+
+#define DATA_SIZE 256
+
+struct pulse8 {
+	struct device *dev;
+	struct serio *serio;
+	struct cec_adapter *adap;
+	struct completion cmd_done;
+	struct work_struct work;
+	struct cec_msg rx_msg;
+	u8 data[DATA_SIZE];
+	unsigned int len;
+	u8 buf[DATA_SIZE];
+	unsigned int idx;
+	bool escape;
+	bool started;
+};
+
+void pulse8_irq_work_handler(struct work_struct *work)
+{
+	struct pulse8 *pulse8 =
+		container_of(work, struct pulse8, work);
+
+	switch (pulse8->data[0] & 0x3f) {
+	case MSGCODE_FRAME_DATA:
+		cec_received_msg(pulse8->adap, &pulse8->rx_msg);
+		break;
+	case MSGCODE_TRANSMIT_SUCCEEDED:
+		cec_transmit_done(pulse8->adap, CEC_TX_STATUS_OK,
+				  0, 0, 0, 0);
+		break;
+	case MSGCODE_TRANSMIT_FAILED_LINE:
+		cec_transmit_done(pulse8->adap, CEC_TX_STATUS_ARB_LOST,
+				  1, 0, 0, 0);
+		break;
+	case MSGCODE_TRANSMIT_FAILED_ACK:
+		cec_transmit_done(pulse8->adap, CEC_TX_STATUS_NACK,
+				  0, 1, 0, 0);
+		break;
+	case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
+	case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
+		cec_transmit_done(pulse8->adap, CEC_TX_STATUS_ERROR,
+				  0, 0, 0, 1);
+		break;
+	}
+}
+
+static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data,
+				    unsigned int flags)
+{
+	struct pulse8 *pulse8 = serio_get_drvdata(serio);
+
+	if (!pulse8->started && data != 0xff)
+		return IRQ_HANDLED;
+	if (data == 0xfd) {
+		pulse8->escape = true;
+		return IRQ_HANDLED;
+	}
+	if (pulse8->escape) {
+		data += 0xfd;
+		pulse8->escape = false;
+	} else if (data == 0xfe) {
+		struct cec_msg *msg = &pulse8->rx_msg;
+
+		if (debug)
+			dev_info(pulse8->dev, "received: %*ph\n",
+				 pulse8->idx, pulse8->buf);
+		pulse8->data[0] = pulse8->buf[0];
+		switch (pulse8->buf[0] & 0x3f) {
+		case MSGCODE_FRAME_START:
+			msg->len = 1;
+			msg->msg[0] = pulse8->buf[1];
+			break;
+		case MSGCODE_FRAME_DATA:
+			if (msg->len == CEC_MAX_MSG_SIZE)
+				break;
+			msg->msg[msg->len++] = pulse8->buf[1];
+			if (pulse8->buf[0] & MSGCODE_FRAME_EOM)
+				schedule_work(&pulse8->work);
+			break;
+		case MSGCODE_TRANSMIT_SUCCEEDED:
+		case MSGCODE_TRANSMIT_FAILED_LINE:
+		case MSGCODE_TRANSMIT_FAILED_ACK:
+		case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
+		case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
+			schedule_work(&pulse8->work);
+			break;
+		case MSGCODE_TIMEOUT_ERROR:
+			break;
+		case MSGCODE_COMMAND_ACCEPTED:
+		case MSGCODE_COMMAND_REJECTED:
+		default:
+			if (pulse8->idx == 0)
+				break;
+			memcpy(pulse8->data, pulse8->buf, pulse8->idx);
+			pulse8->len = pulse8->idx;
+			complete(&pulse8->cmd_done);
+			break;
+		}
+		pulse8->idx = 0;
+		pulse8->started = false;
+		return IRQ_HANDLED;
+	} else if (data == 0xff) {
+		pulse8->idx = 0;
+		pulse8->started = true;
+		return IRQ_HANDLED;
+	}
+
+	if (pulse8->idx >= DATA_SIZE) {
+		dev_dbg(pulse8->dev,
+			"throwing away %d bytes of garbage\n", pulse8->idx);
+		pulse8->idx = 0;
+	}
+	pulse8->buf[pulse8->idx++] = data;
+	return IRQ_HANDLED;
+}
+
+static void pulse8_disconnect(struct serio *serio)
+{
+	struct pulse8 *pulse8 = serio_get_drvdata(serio);
+
+	cec_unregister_adapter(pulse8->adap);
+	dev_info(&serio->dev, "disconnected\n");
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	kfree(pulse8);
+}
+
+static int pulse8_send(struct serio *serio, const u8 *command, u8 cmd_len)
+{
+	int err = 0;
+
+	err = serio_write(serio, 0xff);
+	if (err)
+		return err;
+	for (; !err && cmd_len; command++, cmd_len--) {
+		if (*command >= 0xfd) {
+			err = serio_write(serio, 0xfd);
+			if (!err)
+				err = serio_write(serio, *command - 0xfd);
+		} else {
+			err = serio_write(serio, *command);
+		}
+	}
+	if (!err)
+		err = serio_write(serio, 0xfe);
+
+	return err;
+}
+
+static int pulse8_send_and_wait(struct pulse8 *pulse8,
+				const u8 *cmd, u8 cmd_len, u8 response, u8 size)
+{
+	int err;
+
+	/*dev_info(pulse8->dev, "transmit: %*ph\n", cmd_len, cmd);*/
+	init_completion(&pulse8->cmd_done);
+
+	err = pulse8_send(pulse8->serio, cmd, cmd_len);
+	if (err)
+		return err;
+
+	if (!wait_for_completion_timeout(&pulse8->cmd_done, HZ))
+		return -ETIMEDOUT;
+	if ((pulse8->data[0] & 0x3f) == MSGCODE_COMMAND_REJECTED &&
+	    cmd[0] != MSGCODE_SET_CONTROLLED &&
+	    cmd[0] != MSGCODE_SET_AUTO_ENABLED &&
+	    cmd[0] != MSGCODE_GET_BUILDDATE) {
+		u8 cmd_sc[2];
+
+		cmd_sc[0] = MSGCODE_SET_CONTROLLED;
+		cmd_sc[1] = 1;
+		err = pulse8_send_and_wait(pulse8, cmd_sc, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+		if (err)
+			return err;
+		init_completion(&pulse8->cmd_done);
+
+		err = pulse8_send(pulse8->serio, cmd, cmd_len);
+		if (err)
+			return err;
+
+		if (!wait_for_completion_timeout(&pulse8->cmd_done, HZ))
+			return -ETIMEDOUT;
+	}
+	if (response &&
+	    ((pulse8->data[0] & 0x3f) != response || pulse8->len < size + 1)) {
+		dev_info(pulse8->dev, "transmit: failed %02x\n",
+			 pulse8->data[0] & 0x3f);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio)
+{
+	u8 *data = pulse8->data + 1;
+	unsigned int count = 0;
+	unsigned int vers = 0;
+	u8 cmd[2];
+	int err;
+
+	cmd[0] = MSGCODE_PING;
+	err = pulse8_send_and_wait(pulse8, cmd, 1,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	cmd[0] = MSGCODE_FIRMWARE_VERSION;
+	if (!err)
+		err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
+	if (!err) {
+		vers = (data[0] << 8) | data[1];
+
+		dev_info(pulse8->dev, "Firmware version %04x\n", vers);
+		if (vers < 2)
+			return 0;
+	}
+
+	cmd[0] = MSGCODE_GET_BUILDDATE;
+	if (!err)
+		err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 4);
+	if (!err) {
+		time_t date = (data[0] << 24) | (data[1] << 16) |
+			(data[2] << 8) | data[3];
+		struct tm tm;
+
+		time_to_tm(date, 0, &tm);
+
+		dev_info(pulse8->dev, "Firmware build date %04ld.%02d.%02d %02d:%02d:%02d\n",
+			 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+			 tm.tm_hour, tm.tm_min, tm.tm_sec);
+	}
+
+	if (vers < 2)
+		return err;
+
+	do {
+		if (count)
+			msleep(500);
+		cmd[0] = MSGCODE_SET_AUTO_ENABLED;
+		cmd[1] = 0;
+		err = pulse8_send_and_wait(pulse8, cmd, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+		if (err && count == 0) {
+			dev_info(pulse8->dev, "No Auto Enabled supported\n");
+			return 0;
+		}
+
+		cmd[0] = MSGCODE_GET_AUTO_ENABLED;
+		if (!err)
+			err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
+		if (!err && !data[0]) {
+			cmd[0] = MSGCODE_WRITE_EEPROM;
+			err = pulse8_send_and_wait(pulse8, cmd, 1,
+						   MSGCODE_COMMAND_ACCEPTED, 1);
+			cmd[0] = MSGCODE_GET_AUTO_ENABLED;
+			if (!err)
+				err = pulse8_send_and_wait(pulse8, cmd, 1,
+							   cmd[0], 1);
+		}
+	} while (!err && data[0] && count++ < 5);
+
+	if (!err && data[0])
+		err = -EIO;
+
+	return err;
+}
+
+static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+	struct pulse8 *pulse8 = adap->priv;
+	u8 cmd[16];
+	int err;
+
+	cmd[0] = MSGCODE_SET_CONTROLLED;
+	cmd[1] = enable;
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 1);
+	return enable ? err : 0;
+}
+
+static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
+{
+	struct pulse8 *pulse8 = adap->priv;
+	u16 mask = 0;
+	u8 cmd[3];
+	int err;
+
+	if (log_addr != CEC_LOG_ADDR_INVALID)
+		mask = 1 << log_addr;
+	cmd[0] = MSGCODE_SET_ACK_MASK;
+	cmd[1] = mask >> 8;
+	cmd[2] = mask & 0xff;
+	err = pulse8_send_and_wait(pulse8, cmd, 3,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if (mask == 0)
+		return 0;
+	return err;
+}
+
+static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
+				    u32 signal_free_time, struct cec_msg *msg)
+{
+	struct pulse8 *pulse8 = adap->priv;
+	u8 cmd[2];
+	unsigned int i;
+	int err;
+
+	cmd[0] = MSGCODE_TRANSMIT_IDLETIME;
+	cmd[1] = 3;
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 1);
+	cmd[0] = MSGCODE_TRANSMIT_ACK_POLARITY;
+	cmd[1] = cec_msg_is_broadcast(msg);
+	if (!err)
+		err = pulse8_send_and_wait(pulse8, cmd, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+	cmd[0] = msg->len == 1 ? MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
+	cmd[1] = msg->msg[0];
+	if (!err)
+		err = pulse8_send_and_wait(pulse8, cmd, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+	if (!err && msg->len > 1) {
+		cmd[0] = msg->len == 2 ? MSGCODE_TRANSMIT_EOM :
+					 MSGCODE_TRANSMIT;
+		cmd[1] = msg->msg[1];
+		err = pulse8_send_and_wait(pulse8, cmd, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+		for (i = 0; !err && i + 2 < msg->len; i++) {
+			cmd[0] = (i + 2 == msg->len - 1) ?
+				MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
+			cmd[1] = msg->msg[i + 2];
+			err = pulse8_send_and_wait(pulse8, cmd, 2,
+						   MSGCODE_COMMAND_ACCEPTED, 1);
+		}
+	}
+
+	return err;
+}
+
+static int pulse8_received(struct cec_adapter *adap, struct cec_msg *msg)
+{
+	return -ENOMSG;
+}
+
+const struct cec_adap_ops pulse8_cec_adap_ops = {
+	.adap_enable = pulse8_cec_adap_enable,
+	.adap_log_addr = pulse8_cec_adap_log_addr,
+	.adap_transmit = pulse8_cec_adap_transmit,
+	.received = pulse8_received,
+};
+
+static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
+{
+	u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR |
+		CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL;
+	struct pulse8 *pulse8;
+	int err = -ENOMEM;
+
+	pulse8 = kzalloc(sizeof(*pulse8), GFP_KERNEL);
+
+	if (!pulse8)
+		return -ENOMEM;
+
+	pulse8->serio = serio;
+	pulse8->adap = cec_allocate_adapter(&pulse8_cec_adap_ops, pulse8,
+		"HDMI CEC", caps, 1, &serio->dev);
+	err = PTR_ERR_OR_ZERO(pulse8->adap);
+	if (err < 0)
+		goto free_device;
+
+	pulse8->dev = &serio->dev;
+	serio_set_drvdata(serio, pulse8);
+	INIT_WORK(&pulse8->work, pulse8_irq_work_handler);
+
+	err = serio_open(serio, drv);
+	if (err)
+		goto delete_adap;
+
+	err = pulse8_setup(pulse8, serio);
+	if (err)
+		goto close_serio;
+
+	err = cec_register_adapter(pulse8->adap);
+	if (err < 0)
+		goto close_serio;
+
+	pulse8->dev = &pulse8->adap->devnode.dev;
+	return 0;
+
+close_serio:
+	serio_close(serio);
+delete_adap:
+	cec_delete_adapter(pulse8->adap);
+	serio_set_drvdata(serio, NULL);
+free_device:
+	kfree(pulse8);
+	return err;
+}
+
+static struct serio_device_id pulse8_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_PULSE8_CEC,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, pulse8_serio_ids);
+
+static struct serio_driver pulse8_drv = {
+	.driver		= {
+		.name	= "pulse8-cec",
+	},
+	.description	= "Pulse Eight HDMI CEC driver",
+	.id_table	= pulse8_serio_ids,
+	.interrupt	= pulse8_interrupt,
+	.connect	= pulse8_connect,
+	.disconnect	= pulse8_disconnect,
+};
+
+module_serio_driver(pulse8_drv);
-- 
2.8.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/5] MAINTAINERS: add entry for the pulse8-cec driver
  2016-07-10 13:11 [PATCH 0/5] Pulse-Eight USB CEC driver Hans Verkuil
                   ` (2 preceding siblings ...)
  2016-07-10 13:11 ` [PATCH 3/5] pulse8-cec: new driver " Hans Verkuil
@ 2016-07-10 13:11 ` Hans Verkuil
  2016-07-10 13:11 ` [PATCH 5/5] pulse8-cec: add TODO file Hans Verkuil
  2016-07-11  7:34 ` [PATCH 0/5] Pulse-Eight USB CEC driver Lars Op den Kamp
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-10 13:11 UTC (permalink / raw)
  To: linux-media; +Cc: lars, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Add entry for the pulse8-cec driver.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index a975b8e..7486757 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9258,6 +9258,13 @@ F:	include/linux/tracehook.h
 F:	include/uapi/linux/ptrace.h
 F:	kernel/ptrace.c
 
+PULSE8-CEC DRIVER
+M:	Hans Verkuil <hverkuil@xs4all.nl>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Maintained
+F:	drivers/staging/media/pulse8-cec
+
 PVRUSB2 VIDEO4LINUX DRIVER
 M:	Mike Isely <isely@pobox.com>
 L:	pvrusb2@isely.net	(subscribers-only)
-- 
2.8.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/5] pulse8-cec: add TODO file
  2016-07-10 13:11 [PATCH 0/5] Pulse-Eight USB CEC driver Hans Verkuil
                   ` (3 preceding siblings ...)
  2016-07-10 13:11 ` [PATCH 4/5] MAINTAINERS: add entry for the pulse8-cec driver Hans Verkuil
@ 2016-07-10 13:11 ` Hans Verkuil
  2016-07-11  7:34 ` [PATCH 0/5] Pulse-Eight USB CEC driver Lars Op den Kamp
  5 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-10 13:11 UTC (permalink / raw)
  To: linux-media; +Cc: lars, Hans Verkuil

From: Hans Verkuil <hans.verkuil@cisco.com>

Explain what needs to be done to move this driver out of staging.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
 drivers/staging/media/pulse8-cec/TODO | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 drivers/staging/media/pulse8-cec/TODO

diff --git a/drivers/staging/media/pulse8-cec/TODO b/drivers/staging/media/pulse8-cec/TODO
new file mode 100644
index 0000000..6860a33
--- /dev/null
+++ b/drivers/staging/media/pulse8-cec/TODO
@@ -0,0 +1,35 @@
+This driver needs to mature a bit more and another round of
+code cleanups.
+
+Otherwise it looks to be in good shape. And of course the fact
+that the CEC framework is in staging at the moment also prevents
+this driver from being mainlined.
+
+To use this driver you also need to patch the inputattach utility,
+this patch will be submitted once this driver is moved out of staging.
+
+diff -urN linuxconsoletools-1.4.9/utils/inputattach.c linuxconsoletools-1.4.9.new/utils/inputattach.c
+--- linuxconsoletools-1.4.9/utils/inputattach.c	2016-01-09 16:27:02.000000000 +0100
++++ linuxconsoletools-1.4.9.new/utils/inputattach.c	2016-03-20 11:35:31.707788967 +0100
+@@ -861,6 +861,9 @@
+ { "--wacom_iv",		"-wacom_iv",	"Wacom protocol IV tablet",
+ 	B9600, CS8 | CRTSCTS,
+ 	SERIO_WACOM_IV,		0x00,	0x00,	0,	wacom_iv_init },
++{ "--pulse8-cec",		"-pulse8-cec",	"Pulse Eight HDMI CEC dongle",
++	B9600, CS8,
++	SERIO_PULSE8_CEC,		0x00,	0x00,	0,	NULL },
+ { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL }
+ };
+ 
+diff -urN linuxconsoletools-1.4.9/utils/serio-ids.h linuxconsoletools-1.4.9.new/utils/serio-ids.h
+--- linuxconsoletools-1.4.9/utils/serio-ids.h	2015-04-26 18:29:42.000000000 +0200
++++ linuxconsoletools-1.4.9.new/utils/serio-ids.h	2016-03-20 11:41:00.153558539 +0100
+@@ -131,5 +131,8 @@
+ #ifndef SERIO_EASYPEN
+ # define SERIO_EASYPEN		0x3f
+ #endif
++#ifndef SERIO_PULSE8_CEC
++# define SERIO_PULSE8_CEC	0x40
++#endif
+ 
+ #endif
-- 
2.8.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter
  2016-07-10 13:11 ` [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter Hans Verkuil
@ 2016-07-10 13:20   ` Hans Verkuil
  2016-07-11 17:00   ` Dmitry Torokhov
  1 sibling, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-10 13:20 UTC (permalink / raw)
  To: linux-media; +Cc: lars, linux-input, Dmitry Torokhov

Added linux-input to the Cc list.

Dmitry, it probably makes the most sense if this goes through the media
tree with your Ack, unless you know there will be a conflict.

Regards,

	Hans

On 07/10/2016 03:11 PM, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> This is for the new pulse8-cec staging driver.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
>  include/uapi/linux/serio.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/uapi/linux/serio.h b/include/uapi/linux/serio.h
> index c2ea169..f2447a8 100644
> --- a/include/uapi/linux/serio.h
> +++ b/include/uapi/linux/serio.h
> @@ -78,5 +78,6 @@
>  #define SERIO_TSC40	0x3d
>  #define SERIO_WACOM_IV	0x3e
>  #define SERIO_EGALAX	0x3f
> +#define SERIO_PULSE8_CEC	0x40
>  
>  #endif /* _UAPI_SERIO_H */
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/5] Pulse-Eight USB CEC driver
  2016-07-10 13:11 [PATCH 0/5] Pulse-Eight USB CEC driver Hans Verkuil
                   ` (4 preceding siblings ...)
  2016-07-10 13:11 ` [PATCH 5/5] pulse8-cec: add TODO file Hans Verkuil
@ 2016-07-11  7:34 ` Lars Op den Kamp
  2016-07-11  8:57   ` Hans Verkuil
  5 siblings, 1 reply; 10+ messages in thread
From: Lars Op den Kamp @ 2016-07-11  7:34 UTC (permalink / raw)
  To: Hans Verkuil, linux-media

Hi Hans,

I'm subscribed to this mailing list, though haven't been participating 
in discussions here (no time). I work for Pulse-Eight and did most of 
the CEC software.

There's no difference between firmware v4 and v5 for the USB model of 
the adapter. v5 just adds support for the new Intel NUC internal CEC 
adapter.

You can snoop the bus by setting the ack mask to 0 and just read what 
comes in (MSGCODE_SET_ACK_MASK 0)
This is the same as "cec-client -m" does when using libCEC: 
https://github.com/Pulse-Eight/libcec/blob/master/src/libcec/adapter/Pulse-Eight/USBCECAdapterCommands.cpp#L584

Let me know if you need more help, or send an email to 
support@pulse-eight.com (which will likely end up in my inbox anyway 
eventually).

thanks, Lars

On 10-07-16 15:11, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> This adds support for the Pulse-Eight USB CEC dongle. It has been tested
> with both v4 and v5 firmware.
>
> It is still in staging because 1) the CEC framework it depends on is still in
> staging, 2) the code needs to be refactored a bit and 3) it needs more testing.
>
> That said, it's in pretty decent shape. It's pretty neat, but I do wish it
> would support a CEC bus snooping mode: that would make it an ideal CEC bus
> sniffer. But I don't see any support for it, unfortunately.
>
> If anyone knows how this can be achieved then please let me know!
>
> Please note that this needs support from inputattach (part of linuxconsoletools),
> a patch is included in the TODO file.
>
> Regards,
>
> 	Hans
>
> Hans Verkuil (5):
>    cec: add check if adapter is unregistered.
>    serio.h: add new define for the Pulse-Eight USB-CEC Adapter
>    pulse8-cec: new driver for the Pulse-Eight USB-CEC Adapter
>    MAINTAINERS: add entry for the pulse8-cec driver
>    pulse8-cec: add TODO file
>
>   MAINTAINERS                                   |   7 +
>   drivers/staging/media/Kconfig                 |   2 +
>   drivers/staging/media/Makefile                |   1 +
>   drivers/staging/media/cec/cec-adap.c          |   5 +-
>   drivers/staging/media/pulse8-cec/Kconfig      |  10 +
>   drivers/staging/media/pulse8-cec/Makefile     |   1 +
>   drivers/staging/media/pulse8-cec/TODO         |  35 ++
>   drivers/staging/media/pulse8-cec/pulse8-cec.c | 502 ++++++++++++++++++++++++++
>   include/uapi/linux/serio.h                    |   1 +
>   9 files changed, 563 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/staging/media/pulse8-cec/Kconfig
>   create mode 100644 drivers/staging/media/pulse8-cec/Makefile
>   create mode 100644 drivers/staging/media/pulse8-cec/TODO
>   create mode 100644 drivers/staging/media/pulse8-cec/pulse8-cec.c
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/5] Pulse-Eight USB CEC driver
  2016-07-11  7:34 ` [PATCH 0/5] Pulse-Eight USB CEC driver Lars Op den Kamp
@ 2016-07-11  8:57   ` Hans Verkuil
  0 siblings, 0 replies; 10+ messages in thread
From: Hans Verkuil @ 2016-07-11  8:57 UTC (permalink / raw)
  To: Lars Op den Kamp, linux-media

On 07/11/2016 09:34 AM, Lars Op den Kamp wrote:
> Hi Hans,
> 
> I'm subscribed to this mailing list, though haven't been participating 
> in discussions here (no time). I work for Pulse-Eight and did most of 
> the CEC software.
> 
> There's no difference between firmware v4 and v5 for the USB model of 
> the adapter. v5 just adds support for the new Intel NUC internal CEC 
> adapter.
> 
> You can snoop the bus by setting the ack mask to 0 and just read what 
> comes in (MSGCODE_SET_ACK_MASK 0)

It turned out to be two small bugs (one in the CEC framework and one in the
cec-ctl utility) that prevented this from working. The driver was actually
fine.

Thanks for the reply, it forced me to look more closely at the code.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter
  2016-07-10 13:11 ` [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter Hans Verkuil
  2016-07-10 13:20   ` Hans Verkuil
@ 2016-07-11 17:00   ` Dmitry Torokhov
  1 sibling, 0 replies; 10+ messages in thread
From: Dmitry Torokhov @ 2016-07-11 17:00 UTC (permalink / raw)
  To: Hans Verkuil; +Cc: linux-media, lars, Hans Verkuil

On Sun, Jul 10, 2016 at 03:11:18PM +0200, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
> 
> This is for the new pulse8-cec staging driver.
> 
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>


Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Please feel free to merge through media tree. If you could change the
subject to read:

Input: serio - add new protocol for the Pulse-Eight USB-CEC Adapter

That would be great.

Thanks!

> ---
>  include/uapi/linux/serio.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/uapi/linux/serio.h b/include/uapi/linux/serio.h
> index c2ea169..f2447a8 100644
> --- a/include/uapi/linux/serio.h
> +++ b/include/uapi/linux/serio.h
> @@ -78,5 +78,6 @@
>  #define SERIO_TSC40	0x3d
>  #define SERIO_WACOM_IV	0x3e
>  #define SERIO_EGALAX	0x3f
> +#define SERIO_PULSE8_CEC	0x40
>  
>  #endif /* _UAPI_SERIO_H */
> -- 
> 2.8.1
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2016-07-11 17:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-10 13:11 [PATCH 0/5] Pulse-Eight USB CEC driver Hans Verkuil
2016-07-10 13:11 ` [PATCH 1/5] cec: add check if adapter is unregistered Hans Verkuil
2016-07-10 13:11 ` [PATCH 2/5] serio.h: add new define for the Pulse-Eight USB-CEC Adapter Hans Verkuil
2016-07-10 13:20   ` Hans Verkuil
2016-07-11 17:00   ` Dmitry Torokhov
2016-07-10 13:11 ` [PATCH 3/5] pulse8-cec: new driver " Hans Verkuil
2016-07-10 13:11 ` [PATCH 4/5] MAINTAINERS: add entry for the pulse8-cec driver Hans Verkuil
2016-07-10 13:11 ` [PATCH 5/5] pulse8-cec: add TODO file Hans Verkuil
2016-07-11  7:34 ` [PATCH 0/5] Pulse-Eight USB CEC driver Lars Op den Kamp
2016-07-11  8:57   ` Hans Verkuil

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.