Blob Blame History Raw
commit f9e50d2945d5760df718926edb6d27f328e0b935
Author: Jarod Wilson <jarod@redhat.com>
Date:   Mon Nov 22 15:40:20 2010 -0500

    mceusb: add another device ID
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit a89055498d24d1d464d62fbe37aeb82b404be262
Author: Dan Carpenter <error27@gmail.com>
Date:   Wed Nov 17 05:20:15 2010 +0000

    lirc_dev: fixes in lirc_dev_fop_read()
    
    This makes several changes but they're in one function and sort of
    related:
    
    "buf" was leaked on error.  The leak if we try to read an invalid
    length is the main concern because it could be triggered over and
    over.
    
    If the copy_to_user() failed, then the original code returned the
    number of bytes remaining.  read() is supposed to be the opposite way,
    where we return the number of bytes copied.  I changed it to just return
    -EFAULT on errors.
    
    Also I changed the debug output from "-EFAULT" to just "<fail>" because
    it isn't -EFAULT necessarily.  And since we go though that path if the
    length is invalid now, there was another debug print that I removed.
    
    Signed-off-by: Dan Carpenter <error27@gmail.com>
    Reviewed-by: Jarod Wilson <jarod@redhat.com>
    Acked-by: Jarod Wilson <jarod@redhat.com>

commit c745bf29fb25c909e1f9a4921bec24890b6fd3a8
Author: Dan Carpenter <error27@gmail.com>
Date:   Wed Nov 17 05:13:39 2010 +0000

    lirc_dev: add some __user annotations
    
    Sparse complains because there are no __user annotations.
    
    drivers/media/rc/lirc_dev.c:156:27: warning:
    	incorrect type in initializer (incompatible argument 2 (different address spaces))
    drivers/media/rc/lirc_dev.c:156:27:    expected int ( *read )( ... )
    drivers/media/rc/lirc_dev.c:156:27:    got int ( extern [toplevel] *<noident> )( ... )
    
    Signed-off-by: Dan Carpenter <error27@gmail.com>
    Acked-by: Jarod Wilson <jarod@redhat.com>

commit 175a1933735cdf3cb0aeedbd313c67a522b06a35
Author: Dan Carpenter <error27@gmail.com>
Date:   Wed Nov 17 05:12:23 2010 +0000

    lirc_dev: stray unlock in lirc_dev_fop_poll()
    
    We shouldn't unlock here.  I think this was a cut and paste error.
    
    Signed-off-by: Dan Carpenter <error27@gmail.com>
    Acked-by: Jarod Wilson <jarod@redhat.com>

commit 8dab0da0eab009933e6ef108cf6ccb07f0f8f9dd
Author: Paul Bender <pebender@gmail.com>
Date:   Wed Nov 17 14:56:17 2010 -0500

    rc: fix sysfs entry for mceusb and streamzap
    
    When trying to create persistent device names for mceusb and streamzap
    devices, I noticed that their respective drivers are not creating the rc
    device as a child of the USB device. Rather it creates it as virtual
    device. As a result, udev cannot use the USB device information to
    create persistent device names for event and lirc devices associated
    with the rc device. Not having persistent device names makes it more
    difficult to make use of the devices in userspace as their names can
    change.
    
    Signed-off-by: Paul Bender <pebender@gmail.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 244ca200149ebfc47138ffdb9a1e57ea75a037bd
Author: Jarod Wilson <jarod@redhat.com>
Date:   Wed Nov 17 15:25:45 2010 +0000

    streamzap: merge timeout space with trailing space
    
    There are cases where we get an ending space, and our trailing timeout
    space then gets sent right after it, which breaks repeat, at least for
    lirc userspace decoding. Merge the two spaces by way of using
    ir_raw_event_store_filter, set a timeout value, and we're back to good.
    
    Successfully tested with streamzap and windows mce remotes.
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 9a72f7df26f4b68627c3ebc340d146065703c0cb
Author: Jarod Wilson <jarod@redhat.com>
Date:   Fri Nov 12 19:49:04 2010 -0300

    [media] mceusb: fix keybouce issue after parser simplification
    
    Something I failed to notice while testing the mceusb RLE buffer
    decoding simplification patches was that we were getting an extra event
    from the previously pressed key.
    
    As was pointed out to me on irc by Maxim, this is actually due to using
    ir_raw_event_store_with_filter without having set up a timeout value.
    The hardware has a timeout value we're now reading and storing, which
    properly enables the transition to idle in the raw event storage
    process, and makes IR decode behave correctly w/o keybounce.
    
    Also remove no-longer-used ir_raw_event struct from mceusb_dev struct
    and add as-yet-unused enable flags for carrier reports and learning
    mode, which I'll hopefully start wiring up sooner than later. While
    looking into that, found evidence that 0x9f 0x15 responses are only
    non-zero when the short-range learning sensor is used, so correct the
    debug spew message, and then suppress it when using the standard
    long-range sensor.
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

---
 drivers/media/IR/lirc_dev.c  |   33 +++++++++++---------
 drivers/media/IR/mceusb.c    |   65 ++++++++++++++++++++++++++++++++++--------
 drivers/media/IR/streamzap.c |   21 ++++++++------
 include/media/lirc_dev.h     |    6 ++--
 4 files changed, 86 insertions(+), 39 deletions(-)

Index: linux-2.6.35.x86_64/drivers/media/IR/lirc_dev.c
===================================================================
--- linux-2.6.35.x86_64.orig/drivers/media/IR/lirc_dev.c
+++ linux-2.6.35.x86_64/drivers/media/IR/lirc_dev.c
@@ -519,10 +519,8 @@ unsigned int lirc_dev_fop_poll(struct fi
 
 	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
 
-	if (!ir->attached) {
-		mutex_unlock(&ir->irctl_lock);
+	if (!ir->attached)
 		return POLLERR;
-	}
 
 	poll_wait(file, &ir->buf->wait_poll, wait);
 
@@ -626,7 +624,7 @@ long lirc_dev_fop_ioctl(struct file *fil
 EXPORT_SYMBOL(lirc_dev_fop_ioctl);
 
 ssize_t lirc_dev_fop_read(struct file *file,
-			  char *buffer,
+			  char __user *buffer,
 			  size_t length,
 			  loff_t *ppos)
 {
@@ -646,18 +644,18 @@ ssize_t lirc_dev_fop_read(struct file *f
 	if (!buf)
 		return -ENOMEM;
 
-	if (mutex_lock_interruptible(&ir->irctl_lock))
-		return -ERESTARTSYS;
+	if (mutex_lock_interruptible(&ir->irctl_lock)) {
+		ret = -ERESTARTSYS;
+		goto out_unlocked;
+	}
 	if (!ir->attached) {
-		mutex_unlock(&ir->irctl_lock);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_locked;
 	}
 
 	if (length % ir->chunk_size) {
-		dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
-			ir->d.name, ir->d.minor);
-		mutex_unlock(&ir->irctl_lock);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_locked;
 	}
 
 	/*
@@ -708,18 +706,23 @@ ssize_t lirc_dev_fop_read(struct file *f
 			lirc_buffer_read(ir->buf, buf);
 			ret = copy_to_user((void *)buffer+written, buf,
 					   ir->buf->chunk_size);
-			written += ir->buf->chunk_size;
+			if (!ret)
+				written += ir->buf->chunk_size;
+			else
+				ret = -EFAULT;
 		}
 	}
 
 	remove_wait_queue(&ir->buf->wait_poll, &wait);
 	set_current_state(TASK_RUNNING);
+
+out_locked:
 	mutex_unlock(&ir->irctl_lock);
 
 out_unlocked:
 	kfree(buf);
 	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
-		ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
+		ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
 
 	return ret ? ret : written;
 }
@@ -741,7 +744,7 @@ void *lirc_get_pdata(struct file *file)
 EXPORT_SYMBOL(lirc_get_pdata);
 
 
-ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
+ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
 			   size_t length, loff_t *ppos)
 {
 	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
Index: linux-2.6.35.x86_64/drivers/media/IR/mceusb.c
===================================================================
--- linux-2.6.35.x86_64.orig/drivers/media/IR/mceusb.c
+++ linux-2.6.35.x86_64/drivers/media/IR/mceusb.c
@@ -35,10 +35,10 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
 #include <media/ir-core.h>
-#include <media/ir-common.h>
 
 #define DRIVER_VERSION	"1.91"
 #define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
@@ -49,6 +49,7 @@
 #define USB_BUFLEN		32 /* USB reception 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 */
+#define MS_TO_NS(msec)		((msec) * 1000)
 
 /* MCE constants */
 #define MCE_CMDBUF_SIZE		384  /* MCE Command buffer length */
@@ -92,6 +93,7 @@
 #define MCE_CMD_G_TXMASK	0x13	/* Set TX port bitmask */
 #define MCE_CMD_S_RXSENSOR	0x14	/* Set RX sensor (std/learning) */
 #define MCE_CMD_G_RXSENSOR	0x15	/* Get RX sensor (std/learning) */
+#define MCE_RSP_PULSE_COUNT	0x15	/* RX pulse count (only if learning) */
 #define MCE_CMD_TX_PORTS	0x16	/* Get number of TX ports */
 #define MCE_CMD_G_WAKESRC	0x17	/* Get wake source */
 #define MCE_CMD_UNKNOWN7	0x18	/* Unknown */
@@ -281,6 +283,8 @@ static struct usb_device_id mceusb_dev_t
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
 	/* Formosa Industrial Computing */
 	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
+	/* Fintek eHome Infrared Transceiver (HP branded) */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x5168) },
 	/* Fintek eHome Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
 	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
@@ -315,6 +319,10 @@ struct mceusb_dev {
 	/* ir-core bits */
 	struct ir_dev_props *props;
 
+	/* optional features we can enable */
+	bool carrier_report_enabled;
+	bool learning_enabled;
+
 	/* core device bits */
 	struct device *dev;
 	struct input_dev *idev;
@@ -328,6 +336,8 @@ struct mceusb_dev {
 	/* buffers and dma */
 	unsigned char *buf_in;
 	unsigned int len_in;
+	dma_addr_t dma_in;
+	dma_addr_t dma_out;
 
 	enum {
 		CMD_HEADER = 0,
@@ -335,10 +345,8 @@ struct mceusb_dev {
 		CMD_DATA,
 		PARSE_IRDATA,
 	} parser_state;
-	u8 cmd, rem;		/* Remaining IR data bytes in packet */
 
-	dma_addr_t dma_in;
-	dma_addr_t dma_out;
+	u8 cmd, rem;		/* Remaining IR data bytes in packet */
 
 	struct {
 		u32 connected:1;
@@ -419,7 +427,7 @@ static int mceusb_cmdsize(u8 cmd, u8 sub
 		case MCE_CMD_UNKNOWN:
 		case MCE_CMD_S_CARRIER:
 		case MCE_CMD_S_TIMEOUT:
-		case MCE_CMD_G_RXSENSOR:
+		case MCE_RSP_PULSE_COUNT:
 			datasize = 2;
 			break;
 		case MCE_CMD_SIG_END:
@@ -540,10 +548,11 @@ static void mceusb_dev_printdata(struct 
 				 inout, data1 == 0x02 ? "short" : "long");
 			break;
 		case MCE_CMD_G_RXSENSOR:
-			if (len == 2)
+		/* aka MCE_RSP_PULSE_COUNT */
+			if (out)
 				dev_info(dev, "Get receive sensor\n");
-			else
-				dev_info(dev, "Remaining pulse count is %d\n",
+			else if (ir->learning_enabled)
+				dev_info(dev, "RX pulse count: %d\n",
 					 ((data1 << 8) | data2));
 			break;
 		case MCE_RSP_CMD_INVALID:
@@ -797,6 +806,34 @@ static int mceusb_set_tx_carrier(void *p
 	return carrier;
 }
 
+/*
+ * We don't do anything but print debug spew for many of the command bits
+ * we receive from the hardware, but some of them are useful information
+ * we want to store so that we can use them.
+ */
+static void mceusb_handle_command(struct mceusb_dev *ir, int index)
+{
+	u8 hi = ir->buf_in[index + 1] & 0xff;
+	u8 lo = ir->buf_in[index + 2] & 0xff;
+
+	switch (ir->buf_in[index]) {
+	/* 2-byte return value commands */
+	case MCE_CMD_S_TIMEOUT:
+		ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2);
+		break;
+
+	/* 1-byte return value commands */
+	case MCE_CMD_S_TXMASK:
+		ir->tx_mask = hi;
+		break;
+	case MCE_CMD_S_RXSENSOR:
+		ir->learning_enabled = (hi == 0x02);
+		break;
+	default:
+		break;
+	}
+}
+
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
 	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
@@ -816,13 +853,14 @@ static void mceusb_process_ir_data(struc
 			ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
 			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
 					     ir->rem + 2, false);
+			mceusb_handle_command(ir, i);
 			ir->parser_state = CMD_DATA;
 			break;
 		case PARSE_IRDATA:
 			ir->rem--;
 			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
 			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
-					 * MCE_TIME_UNIT * 1000;
+					 * MS_TO_NS(MCE_TIME_UNIT);
 
 			dev_dbg(ir->dev, "Storing %s with duration %d\n",
 				rawir.pulse ? "pulse" : "space",
@@ -844,7 +882,8 @@ static void mceusb_process_ir_data(struc
 				continue;
 			}
 			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
-			mceusb_dev_printdata(ir, ir->buf_in, i, ir->rem + 1, false);
+			mceusb_dev_printdata(ir, ir->buf_in,
+					     i, ir->rem + 1, false);
 			if (ir->rem)
 				ir->parser_state = PARSE_IRDATA;
 			break;
@@ -1042,6 +1081,9 @@ static struct input_dev *mceusb_init_inp
 
 	ir->props = props;
 
+	usb_to_input_id(ir->usbdev, &idev->id);
+	idev->dev.parent = ir->dev;
+
 	if (mceusb_model[ir->model].rc_map)
 		rc_map = mceusb_model[ir->model].rc_map;
 
Index: linux-2.6.35.x86_64/drivers/media/IR/streamzap.c
===================================================================
--- linux-2.6.35.x86_64.orig/drivers/media/IR/streamzap.c
+++ linux-2.6.35.x86_64/drivers/media/IR/streamzap.c
@@ -34,8 +34,9 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
 #include <media/ir-core.h>
 
 #define DRIVER_VERSION	"1.61"
@@ -140,7 +141,9 @@ static struct usb_driver streamzap_drive
 
 static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
 {
-	ir_raw_event_store(sz->idev, &rawir);
+	dev_dbg(sz->dev, "Storing %s with duration %u us\n",
+		(rawir.pulse ? "pulse" : "space"), rawir.duration);
+	ir_raw_event_store_with_filter(sz->idev, &rawir);
 }
 
 static void sz_push_full_pulse(struct streamzap_ir *sz,
@@ -167,7 +170,6 @@ static void sz_push_full_pulse(struct st
 			rawir.duration *= 1000;
 			rawir.duration &= IR_MAX_DURATION;
 		}
-		dev_dbg(sz->dev, "ls %u\n", rawir.duration);
 		sz_push(sz, rawir);
 
 		sz->idle = false;
@@ -180,7 +182,6 @@ static void sz_push_full_pulse(struct st
 	sz->sum += rawir.duration;
 	rawir.duration *= 1000;
 	rawir.duration &= IR_MAX_DURATION;
-	dev_dbg(sz->dev, "p %u\n", rawir.duration);
 	sz_push(sz, rawir);
 }
 
@@ -200,7 +201,6 @@ static void sz_push_full_space(struct st
 	rawir.duration += SZ_RESOLUTION / 2;
 	sz->sum += rawir.duration;
 	rawir.duration *= 1000;
-	dev_dbg(sz->dev, "s %u\n", rawir.duration);
 	sz_push(sz, rawir);
 }
 
@@ -221,8 +221,6 @@ static void streamzap_callback(struct ur
 	struct streamzap_ir *sz;
 	unsigned int i;
 	int len;
-	static int timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
-				IR_MAX_DURATION) | 0x03000000);
 
 	if (!urb)
 		return;
@@ -246,7 +244,7 @@ static void streamzap_callback(struct ur
 
 	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
 	for (i = 0; i < len; i++) {
-		dev_dbg(sz->dev, "sz idx %d: %x\n",
+		dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
 			i, (unsigned char)sz->buf_in[i]);
 		switch (sz->decoder_state) {
 		case PulseSpace:
@@ -273,7 +271,7 @@ static void streamzap_callback(struct ur
 				struct ir_raw_event rawir;
 
 				rawir.pulse = false;
-				rawir.duration = timeout;
+				rawir.duration = sz->props->timeout;
 				sz->idle = true;
 				if (sz->timeout_enabled)
 					sz_push(sz, rawir);
@@ -335,6 +333,9 @@ static struct input_dev *streamzap_init_
 
 	sz->props = props;
 
+	usb_to_input_id(sz->usbdev, &idev->id);
+	idev->dev.parent = sz->dev;
+
 	ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
 	if (ret < 0) {
 		dev_err(dev, "remote input device register failed\n");
@@ -444,6 +445,8 @@ static int __devinit streamzap_probe(str
 	sz->decoder_state = PulseSpace;
 	/* FIXME: don't yet have a way to set this */
 	sz->timeout_enabled = true;
+	sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
+				IR_MAX_DURATION) | 0x03000000);
 	#if 0
 	/* not yet supported, depends on patches from maxim */
 	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
Index: linux-2.6.35.x86_64/include/media/lirc_dev.h
===================================================================
--- linux-2.6.35.x86_64.orig/include/media/lirc_dev.h
+++ linux-2.6.35.x86_64/include/media/lirc_dev.h
@@ -217,9 +217,9 @@ int lirc_dev_fop_open(struct inode *inod
 int lirc_dev_fop_close(struct inode *inode, struct file *file);
 unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
 long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-ssize_t lirc_dev_fop_read(struct file *file, char *buffer, size_t length,
+ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length,
 			  loff_t *ppos);
-ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, size_t length,
-			   loff_t *ppos);
+ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
+			   size_t length, loff_t *ppos);
 
 #endif