All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] IR: add initial IR transmit support
@ 2010-07-02  3:37 Jarod Wilson
  2010-07-02  3:38 ` [PATCH v2 1/2] IR: add tx callbacks to ir-core Jarod Wilson
  2010-07-02  3:38 ` [PATCH v2 2/2] IR/mceusb: add and wire up tx callback functions Jarod Wilson
  0 siblings, 2 replies; 3+ messages in thread
From: Jarod Wilson @ 2010-07-02  3:37 UTC (permalink / raw)
  To: linux-media

To enable IR transmit support in the mceusb driver, I need to add just
three callbacks to achieve feature-parity with IR transmit using the old
lirc_mceusb driver. This series adds those callbacks to ir-core's
ir_dev_props struct, then wires them up for the mceusb driver.

At the moment, we have no "native" interface for transmitting IR, but a
later patchset to add "legacy" lirc device interface support provides a
means to transmit IR using this ir-core implementation.

[PATCH 1/2] IR: add tx callbacks to ir-core
[PATCH 2/2] IR/mceusb: add and wire up tx callback functions

Patches are against the linuxtv staging/rc tree, but will probably apply
elsewhere as well.

v2: the mceusb driver no longer makes a copy_from_user() call to pull in
its tx data buffer, it will be provided by whatever is providing the tx
data, be that an in-kernel IR encoder or a forthcoming lirc bridge driver
plugin, which gets *its* data from userspace using copy_from_user().

-- 
Jarod Wilson
jarod@redhat.com


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

* [PATCH v2 1/2] IR: add tx callbacks to ir-core
  2010-07-02  3:37 [PATCH v2 0/2] IR: add initial IR transmit support Jarod Wilson
@ 2010-07-02  3:38 ` Jarod Wilson
  2010-07-02  3:38 ` [PATCH v2 2/2] IR/mceusb: add and wire up tx callback functions Jarod Wilson
  1 sibling, 0 replies; 3+ messages in thread
From: Jarod Wilson @ 2010-07-02  3:38 UTC (permalink / raw)
  To: linux-media

v2: incoming IR buffer now an int pointer, and not fed from userspace.

Signed-off-by: Jarod Wilson <jarod@redhat.com>
---
 include/media/ir-core.h |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/include/media/ir-core.h b/include/media/ir-core.h
index ad1303f..513e60d 100644
--- a/include/media/ir-core.h
+++ b/include/media/ir-core.h
@@ -47,15 +47,21 @@ enum rc_driver_type {
  *	is opened.
  * @close: callback to allow drivers to disable polling/irq when IR input device
  *	is opened.
+ * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs)
+ * @s_tx_carrier: set transmit carrier frequency
+ * @tx_ir: transmit IR
  */
 struct ir_dev_props {
 	enum rc_driver_type	driver_type;
 	unsigned long		allowed_protos;
 	u32			scanmask;
-	void 			*priv;
+	void			*priv;
 	int			(*change_protocol)(void *priv, u64 ir_type);
 	int			(*open)(void *priv);
 	void			(*close)(void *priv);
+	int			(*s_tx_mask)(void *priv, u32 mask);
+	int			(*s_tx_carrier)(void *priv, u32 carrier);
+	int			(*tx_ir)(void *priv, int *txbuf, u32 n);
 };
 
 struct ir_input_dev {
-- 
1.7.0.1


-- 
Jarod Wilson
jarod@redhat.com


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

* [PATCH v2 2/2] IR/mceusb: add and wire up tx callback functions
  2010-07-02  3:37 [PATCH v2 0/2] IR: add initial IR transmit support Jarod Wilson
  2010-07-02  3:38 ` [PATCH v2 1/2] IR: add tx callbacks to ir-core Jarod Wilson
@ 2010-07-02  3:38 ` Jarod Wilson
  1 sibling, 0 replies; 3+ messages in thread
From: Jarod Wilson @ 2010-07-02  3:38 UTC (permalink / raw)
  To: linux-media

v2: userspace buffer copy moved out of driver and into lirc bridge
driver

Signed-off-by: Jarod Wilson <jarod@redhat.com>
---
 drivers/media/IR/mceusb.c |  148 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 138 insertions(+), 10 deletions(-)

diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
index f3c736c..c6c0375 100644
--- a/drivers/media/IR/mceusb.c
+++ b/drivers/media/IR/mceusb.c
@@ -15,10 +15,6 @@
  * Jon Smirl, which included enhancements and simplifications to the
  * incoming IR buffer parsing routines.
  *
- * TODO:
- * - add rc-core transmit support, once available
- * - enable support for forthcoming ir-lirc-codec interface
- *
  *
  * 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
@@ -51,7 +47,6 @@
 #define DRIVER_NAME	"mceusb"
 
 #define USB_BUFLEN	32	/* USB reception buffer length */
-#define IRBUF_SIZE	256	/* IR work buffer length */
 #define USB_CTRL_MSG_SZ	2	/* Size of usb ctrl msg on gen1 hw */
 #define MCE_G1_INIT_MSGS 40	/* Init messages on gen1 hw to throw out */
 
@@ -263,14 +258,13 @@ struct mceusb_dev {
 		u32 reserved:28;
 	} flags;
 
-	/* handle sending (init strings) */
+	/* transmit support */
 	int send_flags;
-	int carrier;
+	u32 carrier;
+	unsigned char tx_mask;
 
 	char name[128];
 	char phys[64];
-
-	unsigned char tx_mask;
 };
 
 /*
@@ -520,6 +514,91 @@ static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
 	mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX);
 }
 
+/* Send data out the IR blaster port(s) */
+static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
+{
+	struct mceusb_dev *ir = priv;
+	int i, ret = 0;
+	int count, cmdcount = 0;
+	unsigned char *cmdbuf; /* MCE command buffer */
+	long signal_duration = 0; /* Singnal length in us */
+	struct timeval start_time, end_time;
+
+	do_gettimeofday(&start_time);
+
+	count = n / sizeof(int);
+
+	cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL);
+	if (!cmdbuf)
+		return -ENOMEM;
+
+	/* MCE tx init header */
+	cmdbuf[cmdcount++] = MCE_CONTROL_HEADER;
+	cmdbuf[cmdcount++] = 0x08;
+	cmdbuf[cmdcount++] = ir->tx_mask;
+
+	/* Generate mce packet data */
+	for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
+		signal_duration += txbuf[i];
+		txbuf[i] = txbuf[i] / MCE_TIME_UNIT;
+
+		do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
+
+			/* Insert mce packet header every 4th entry */
+			if ((cmdcount < MCE_CMDBUF_SIZE) &&
+			    (cmdcount - MCE_TX_HEADER_LENGTH) %
+			     MCE_CODE_LENGTH == 0)
+				cmdbuf[cmdcount++] = MCE_PACKET_HEADER;
+
+			/* Insert mce packet data */
+			if (cmdcount < MCE_CMDBUF_SIZE)
+				cmdbuf[cmdcount++] =
+					(txbuf[i] < MCE_PULSE_BIT ?
+					 txbuf[i] : MCE_MAX_PULSE_LENGTH) |
+					 (i & 1 ? 0x00 : MCE_PULSE_BIT);
+			else {
+				ret = -EINVAL;
+				goto out;
+			}
+
+		} while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) &&
+			 (txbuf[i] -= MCE_MAX_PULSE_LENGTH));
+	}
+
+	/* Fix packet length in last header */
+	cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
+		0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1;
+
+	/* Check if we have room for the empty packet at the end */
+	if (cmdcount >= MCE_CMDBUF_SIZE) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* All mce commands end with an empty packet (0x80) */
+	cmdbuf[cmdcount++] = 0x80;
+
+	/* Transmit the command to the mce device */
+	mce_async_out(ir, cmdbuf, cmdcount);
+
+	/*
+	 * The lircd gap calculation expects the write function to
+	 * wait the time it takes for the ircommand to be sent before
+	 * it returns.
+	 */
+	do_gettimeofday(&end_time);
+	signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
+			   (end_time.tv_sec - start_time.tv_sec) * 1000000;
+
+	/* delay with the closest number of ticks */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(signal_duration));
+
+out:
+	kfree(cmdbuf);
+	return ret ? ret : n;
+}
+
 /* Sets active IR outputs -- mce devices typically (all?) have two */
 static int mceusb_set_tx_mask(void *priv, u32 mask)
 {
@@ -533,6 +612,49 @@ static int mceusb_set_tx_mask(void *priv, u32 mask)
 	return 0;
 }
 
+/* Sets the send carrier frequency and mode */
+static int mceusb_set_tx_carrier(void *priv, u32 carrier)
+{
+	struct mceusb_dev *ir = priv;
+	int clk = 10000000;
+	int prescaler = 0, divisor = 0;
+	unsigned char cmdbuf[4] = { 0x9f, 0x06, 0x00, 0x00 };
+
+	/* Carrier has changed */
+	if (ir->carrier != carrier) {
+
+		if (carrier == 0) {
+			ir->carrier = carrier;
+			cmdbuf[2] = 0x01;
+			cmdbuf[3] = 0x80;
+			dev_dbg(ir->dev, "%s: disabling carrier "
+				"modulation\n", __func__);
+			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+			return carrier;
+		}
+
+		for (prescaler = 0; prescaler < 4; ++prescaler) {
+			divisor = (clk >> (2 * prescaler)) / carrier;
+			if (divisor <= 0xFF) {
+				ir->carrier = carrier;
+				cmdbuf[2] = prescaler;
+				cmdbuf[3] = divisor;
+				dev_dbg(ir->dev, "%s: requesting %u HZ "
+					"carrier\n", __func__, carrier);
+
+				/* Transmit new carrier to mce device */
+				mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+				return carrier;
+			}
+		}
+
+		return -EINVAL;
+
+	}
+
+	return carrier;
+}
+
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
 	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
@@ -752,6 +874,9 @@ static void mceusb_gen3_init(struct mceusb_dev *ir)
 	mce_sync_in(ir, NULL, maxp);
 	mce_sync_in(ir, NULL, maxp);
 
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(msecs_to_jiffies(100));
+
 	/* device reset */
 	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
 	mce_sync_in(ir, NULL, maxp);
@@ -804,7 +929,7 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
 		goto ir_dev_alloc_failed;
 	}
 
-	snprintf(ir->name, sizeof(ir->name), "Media Center Edition eHome "
+	snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
 		 "Infrared Remote Transceiver (%04x:%04x)",
 		 le16_to_cpu(ir->usbdev->descriptor.idVendor),
 		 le16_to_cpu(ir->usbdev->descriptor.idProduct));
@@ -817,6 +942,9 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
 	props->priv = ir;
 	props->driver_type = RC_DRIVER_IR_RAW;
 	props->allowed_protos = IR_TYPE_ALL;
+	props->s_tx_mask = mceusb_set_tx_mask;
+	props->s_tx_carrier = mceusb_set_tx_carrier;
+	props->tx_ir = mceusb_tx_ir;
 
 	ir->props = props;
 	ir->irdev = irdev;
-- 
1.7.0.1


-- 
Jarod Wilson
jarod@redhat.com


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

end of thread, other threads:[~2010-07-02  3:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-02  3:37 [PATCH v2 0/2] IR: add initial IR transmit support Jarod Wilson
2010-07-02  3:38 ` [PATCH v2 1/2] IR: add tx callbacks to ir-core Jarod Wilson
2010-07-02  3:38 ` [PATCH v2 2/2] IR/mceusb: add and wire up tx callback functions Jarod Wilson

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.