[kernel] r19663 - in dists/sid/linux/debian: . config patches patches/features/all/iguanair
Ben Hutchings
benh at alioth.debian.org
Sat Dec 29 13:57:45 UTC 2012
Author: benh
Date: Sat Dec 29 13:57:44 2012
New Revision: 19663
Log:
media/rc: Add iguanair driver from Linux 3.7 (Closes: #696925)
Added:
dists/sid/linux/debian/patches/features/all/iguanair/
dists/sid/linux/debian/patches/features/all/iguanair/0001-media-Add-support-for-the-IguanaWorks-USB-IR-Transce.patch
dists/sid/linux/debian/patches/features/all/iguanair/0002-media-iguanair-reuse-existing-urb-callback-for-comma.patch
dists/sid/linux/debian/patches/features/all/iguanair/0003-media-iguanair-ignore-unsupported-firmware-versions.patch
dists/sid/linux/debian/patches/features/all/iguanair/0004-media-iguanair-support-suspend-and-resume.patch
dists/sid/linux/debian/patches/features/all/iguanair/0005-media-iguanair-fix-return-value-for-transmit.patch
dists/sid/linux/debian/patches/features/all/iguanair/0006-media-iguanair-reset-the-IR-state-after-rx-overflow-.patch
dists/sid/linux/debian/patches/features/all/iguanair/0007-media-iguanair-advertise-the-resolution-and-timeout-.patch
dists/sid/linux/debian/patches/features/all/iguanair/0008-media-iguanair-fix-receiver-overflow.patch
dists/sid/linux/debian/patches/features/all/iguanair/0009-media-rc-do-not-wake-up-rc-thread-unless-there-is-so.patch
dists/sid/linux/debian/patches/features/all/iguanair/0010-media-iguanair-do-not-modify-transmit-buffer.patch
dists/sid/linux/debian/patches/features/all/iguanair/0011-media-iguanair-cannot-send-data-from-the-stack.patch
Modified:
dists/sid/linux/debian/changelog
dists/sid/linux/debian/config/config
dists/sid/linux/debian/patches/series
Modified: dists/sid/linux/debian/changelog
==============================================================================
--- dists/sid/linux/debian/changelog Sat Dec 29 13:04:21 2012 (r19662)
+++ dists/sid/linux/debian/changelog Sat Dec 29 13:57:44 2012 (r19663)
@@ -2,6 +2,7 @@
[ Ben Hutchings ]
* Input: wacom - fix touch support for Bamboo Fun CTH-461
+ * media/rc: Add iguanair driver from Linux 3.7 (Closes: #696925)
-- Ben Hutchings <ben at decadent.org.uk> Thu, 27 Dec 2012 02:17:44 +0100
Modified: dists/sid/linux/debian/config/config
==============================================================================
--- dists/sid/linux/debian/config/config Sat Dec 29 13:04:21 2012 (r19662)
+++ dists/sid/linux/debian/config/config Sat Dec 29 13:57:44 2012 (r19663)
@@ -1144,6 +1144,7 @@
# CONFIG_IR_NUVOTON is not set
CONFIG_IR_REDRAT3=m
CONFIG_IR_STREAMZAP=m
+CONFIG_IR_IGUANA=m
CONFIG_RC_LOOPBACK=m
##
Added: dists/sid/linux/debian/patches/features/all/iguanair/0001-media-Add-support-for-the-IguanaWorks-USB-IR-Transce.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0001-media-Add-support-for-the-IguanaWorks-USB-IR-Transce.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,684 @@
+From: Sean Young <sean at mess.org>
+Date: Sun, 15 Jul 2012 13:31:00 -0300
+Subject: [01/11] [media] Add support for the IguanaWorks USB IR Transceiver
+
+commit 26ff63137c45886169ed102bddd6e90d6c27f00d upstream.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/Kconfig | 11 +
+ drivers/media/rc/Makefile | 1 +
+ drivers/media/rc/iguanair.c | 639 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 651 insertions(+)
+ create mode 100644 drivers/media/rc/iguanair.c
+
+--- a/drivers/media/rc/Kconfig
++++ b/drivers/media/rc/Kconfig
+@@ -243,6 +243,17 @@ config IR_WINBOND_CIR
+ To compile this driver as a module, choose M here: the module will
+ be called winbond_cir.
+
++config IR_IGUANA
++ tristate "IguanaWorks USB IR Transceiver"
++ depends on RC_CORE
++ select USB
++ ---help---
++ Say Y here if you want to use the IgaunaWorks USB IR Transceiver.
++ Both infrared receive and send are supported.
++
++ To compile this driver as a module, choose M here: the module will
++ be called iguanair.
++
+ config RC_LOOPBACK
+ tristate "Remote Control Loopback Driver"
+ depends on RC_CORE
+--- a/drivers/media/rc/Makefile
++++ b/drivers/media/rc/Makefile
+@@ -25,3 +25,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o
+ obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
+ obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o
+ obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o
++obj-$(CONFIG_IR_IGUANA) += iguanair.o
+--- /dev/null
++++ b/drivers/media/rc/iguanair.c
+@@ -0,0 +1,639 @@
++/*
++ * IguanaWorks USB IR Transceiver support
++ *
++ * Copyright (C) 2012 Sean Young <sean at mess.org>
++ *
++ * 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 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/usb.h>
++#include <linux/usb/input.h>
++#include <linux/slab.h>
++#include <linux/completion.h>
++#include <media/rc-core.h>
++
++#define DRIVER_NAME "iguanair"
++
++struct iguanair {
++ struct rc_dev *rc;
++
++ struct device *dev;
++ struct usb_device *udev;
++
++ int pipe_in, pipe_out;
++ uint8_t bufsize;
++ uint8_t version[2];
++
++ struct mutex lock;
++
++ /* receiver support */
++ bool receiver_on;
++ dma_addr_t dma_in;
++ uint8_t *buf_in;
++ struct urb *urb_in;
++ struct completion completion;
++
++ /* transmit support */
++ bool tx_overflow;
++ uint32_t carrier;
++ uint8_t cycle_overhead;
++ uint8_t channels;
++ uint8_t busy4;
++ uint8_t busy7;
++
++ char name[64];
++ char phys[64];
++};
++
++#define CMD_GET_VERSION 0x01
++#define CMD_GET_BUFSIZE 0x11
++#define CMD_GET_FEATURES 0x10
++#define CMD_SEND 0x15
++#define CMD_EXECUTE 0x1f
++#define CMD_RX_OVERFLOW 0x31
++#define CMD_TX_OVERFLOW 0x32
++#define CMD_RECEIVER_ON 0x12
++#define CMD_RECEIVER_OFF 0x14
++
++#define DIR_IN 0xdc
++#define DIR_OUT 0xcd
++
++#define MAX_PACKET_SIZE 8u
++#define TIMEOUT 1000
++
++struct packet {
++ uint16_t start;
++ uint8_t direction;
++ uint8_t cmd;
++};
++
++struct response_packet {
++ struct packet header;
++ uint8_t data[4];
++};
++
++struct send_packet {
++ struct packet header;
++ uint8_t length;
++ uint8_t channels;
++ uint8_t busy7;
++ uint8_t busy4;
++ uint8_t payload[0];
++};
++
++static void process_ir_data(struct iguanair *ir, unsigned len)
++{
++ if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) {
++ switch (ir->buf_in[3]) {
++ case CMD_TX_OVERFLOW:
++ ir->tx_overflow = true;
++ case CMD_RECEIVER_OFF:
++ case CMD_RECEIVER_ON:
++ case CMD_SEND:
++ complete(&ir->completion);
++ break;
++ case CMD_RX_OVERFLOW:
++ dev_warn(ir->dev, "receive overflow\n");
++ break;
++ default:
++ dev_warn(ir->dev, "control code %02x received\n",
++ ir->buf_in[3]);
++ break;
++ }
++ } else if (len >= 7) {
++ DEFINE_IR_RAW_EVENT(rawir);
++ unsigned i;
++
++ init_ir_raw_event(&rawir);
++
++ for (i = 0; i < 7; i++) {
++ if (ir->buf_in[i] == 0x80) {
++ rawir.pulse = false;
++ rawir.duration = US_TO_NS(21845);
++ } else {
++ rawir.pulse = (ir->buf_in[i] & 0x80) == 0;
++ rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) *
++ 21330;
++ }
++
++ ir_raw_event_store_with_filter(ir->rc, &rawir);
++ }
++
++ ir_raw_event_handle(ir->rc);
++ }
++}
++
++static void iguanair_rx(struct urb *urb)
++{
++ struct iguanair *ir;
++
++ if (!urb)
++ return;
++
++ ir = urb->context;
++ if (!ir) {
++ usb_unlink_urb(urb);
++ return;
++ }
++
++ switch (urb->status) {
++ case 0:
++ process_ir_data(ir, urb->actual_length);
++ break;
++ case -ECONNRESET:
++ case -ENOENT:
++ case -ESHUTDOWN:
++ usb_unlink_urb(urb);
++ return;
++ case -EPIPE:
++ default:
++ dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
++ break;
++ }
++
++ usb_submit_urb(urb, GFP_ATOMIC);
++}
++
++static int iguanair_send(struct iguanair *ir, void *data, unsigned size,
++ struct response_packet *response, unsigned *res_len)
++{
++ unsigned offset, len;
++ int rc, transferred;
++
++ for (offset = 0; offset < size; offset += MAX_PACKET_SIZE) {
++ len = min(size - offset, MAX_PACKET_SIZE);
++
++ if (ir->tx_overflow)
++ return -EOVERFLOW;
++
++ rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data + offset,
++ len, &transferred, TIMEOUT);
++ if (rc)
++ return rc;
++
++ if (transferred != len)
++ return -EIO;
++ }
++
++ if (response) {
++ rc = usb_interrupt_msg(ir->udev, ir->pipe_in, response,
++ sizeof(*response), res_len, TIMEOUT);
++ }
++
++ return rc;
++}
++
++static int iguanair_get_features(struct iguanair *ir)
++{
++ struct packet packet;
++ struct response_packet response;
++ int rc, len;
++
++ packet.start = 0;
++ packet.direction = DIR_OUT;
++ packet.cmd = CMD_GET_VERSION;
++
++ rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
++ if (rc) {
++ dev_info(ir->dev, "failed to get version\n");
++ goto out;
++ }
++
++ if (len != 6) {
++ dev_info(ir->dev, "failed to get version\n");
++ rc = -EIO;
++ goto out;
++ }
++
++ ir->version[0] = response.data[0];
++ ir->version[1] = response.data[1];
++ ir->bufsize = 150;
++ ir->cycle_overhead = 65;
++
++ packet.cmd = CMD_GET_BUFSIZE;
++
++ rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
++ if (rc) {
++ dev_info(ir->dev, "failed to get buffer size\n");
++ goto out;
++ }
++
++ if (len != 5) {
++ dev_info(ir->dev, "failed to get buffer size\n");
++ rc = -EIO;
++ goto out;
++ }
++
++ ir->bufsize = response.data[0];
++
++ if (ir->version[0] == 0 || ir->version[1] == 0)
++ goto out;
++
++ packet.cmd = CMD_GET_FEATURES;
++
++ rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
++ if (rc) {
++ dev_info(ir->dev, "failed to get features\n");
++ goto out;
++ }
++
++ if (len < 5) {
++ dev_info(ir->dev, "failed to get features\n");
++ rc = -EIO;
++ goto out;
++ }
++
++ if (len > 5 && ir->version[0] >= 4)
++ ir->cycle_overhead = response.data[1];
++
++out:
++ return rc;
++}
++
++static int iguanair_receiver(struct iguanair *ir, bool enable)
++{
++ struct packet packet = { 0, DIR_OUT, enable ?
++ CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
++ int rc;
++
++ INIT_COMPLETION(ir->completion);
++
++ rc = iguanair_send(ir, &packet, sizeof(packet), NULL, NULL);
++ if (rc)
++ return rc;
++
++ wait_for_completion_timeout(&ir->completion, TIMEOUT);
++
++ return 0;
++}
++
++/*
++ * The iguana ir creates the carrier by busy spinning after each pulse or
++ * space. This is counted in CPU cycles, with the CPU running at 24MHz. It is
++ * broken down into 7-cycles and 4-cyles delays, with a preference for
++ * 4-cycle delays.
++ */
++static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier)
++{
++ struct iguanair *ir = dev->priv;
++
++ if (carrier < 25000 || carrier > 150000)
++ return -EINVAL;
++
++ mutex_lock(&ir->lock);
++
++ if (carrier != ir->carrier) {
++ uint32_t cycles, fours, sevens;
++
++ ir->carrier = carrier;
++
++ cycles = DIV_ROUND_CLOSEST(24000000, carrier * 2) -
++ ir->cycle_overhead;
++
++ /* make up the the remainer of 4-cycle blocks */
++ switch (cycles & 3) {
++ case 0:
++ sevens = 0;
++ break;
++ case 1:
++ sevens = 3;
++ break;
++ case 2:
++ sevens = 2;
++ break;
++ case 3:
++ sevens = 1;
++ break;
++ }
++
++ fours = (cycles - sevens * 7) / 4;
++
++ /* magic happens here */
++ ir->busy7 = (4 - sevens) * 2;
++ ir->busy4 = 110 - fours;
++ }
++
++ mutex_unlock(&ir->lock);
++
++ return carrier;
++}
++
++static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
++{
++ struct iguanair *ir = dev->priv;
++
++ if (mask > 15)
++ return 4;
++
++ mutex_lock(&ir->lock);
++ ir->channels = mask;
++ mutex_unlock(&ir->lock);
++
++ return 0;
++}
++
++static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
++{
++ struct iguanair *ir = dev->priv;
++ uint8_t space, *payload;
++ unsigned i, size, rc;
++ struct send_packet *packet;
++
++ mutex_lock(&ir->lock);
++
++ /* convert from us to carrier periods */
++ for (i = size = 0; i < count; i++) {
++ txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
++ size += (txbuf[i] + 126) / 127;
++ }
++
++ packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL);
++ if (!packet) {
++ rc = -ENOMEM;
++ goto out;
++ }
++
++ if (size > ir->bufsize) {
++ rc = -E2BIG;
++ goto out;
++ }
++
++ packet->header.start = 0;
++ packet->header.direction = DIR_OUT;
++ packet->header.cmd = CMD_SEND;
++ packet->length = size;
++ packet->channels = ir->channels << 4;
++ packet->busy7 = ir->busy7;
++ packet->busy4 = ir->busy4;
++
++ space = 0;
++ payload = packet->payload;
++
++ for (i = 0; i < count; i++) {
++ unsigned periods = txbuf[i];
++
++ while (periods > 127) {
++ *payload++ = 127 | space;
++ periods -= 127;
++ }
++
++ *payload++ = periods | space;
++ space ^= 0x80;
++ }
++
++ if (ir->receiver_on) {
++ rc = iguanair_receiver(ir, false);
++ if (rc) {
++ dev_warn(ir->dev, "disable receiver before transmit failed\n");
++ goto out;
++ }
++ }
++
++ ir->tx_overflow = false;
++
++ INIT_COMPLETION(ir->completion);
++
++ rc = iguanair_send(ir, packet, size + 8, NULL, NULL);
++
++ if (rc == 0) {
++ wait_for_completion_timeout(&ir->completion, TIMEOUT);
++ if (ir->tx_overflow)
++ rc = -EOVERFLOW;
++ }
++
++ ir->tx_overflow = false;
++
++ if (ir->receiver_on) {
++ if (iguanair_receiver(ir, true))
++ dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
++ }
++
++out:
++ mutex_unlock(&ir->lock);
++ kfree(packet);
++
++ return rc;
++}
++
++static int iguanair_open(struct rc_dev *rdev)
++{
++ struct iguanair *ir = rdev->priv;
++ int rc;
++
++ mutex_lock(&ir->lock);
++
++ usb_submit_urb(ir->urb_in, GFP_KERNEL);
++
++ BUG_ON(ir->receiver_on);
++
++ rc = iguanair_receiver(ir, true);
++ if (rc == 0)
++ ir->receiver_on = true;
++
++ mutex_unlock(&ir->lock);
++
++ return rc;
++}
++
++static void iguanair_close(struct rc_dev *rdev)
++{
++ struct iguanair *ir = rdev->priv;
++ int rc;
++
++ mutex_lock(&ir->lock);
++
++ rc = iguanair_receiver(ir, false);
++ ir->receiver_on = false;
++ if (rc)
++ dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
++
++ usb_kill_urb(ir->urb_in);
++
++ mutex_unlock(&ir->lock);
++}
++
++static int __devinit iguanair_probe(struct usb_interface *intf,
++ const struct usb_device_id *id)
++{
++ struct usb_device *udev = interface_to_usbdev(intf);
++ struct iguanair *ir;
++ struct rc_dev *rc;
++ int ret;
++ struct usb_host_interface *idesc;
++
++ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
++ rc = rc_allocate_device();
++ if (!ir || !rc) {
++ ret = ENOMEM;
++ goto out;
++ }
++
++ ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_ATOMIC,
++ &ir->dma_in);
++ ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
++
++ if (!ir->buf_in || !ir->urb_in) {
++ ret = ENOMEM;
++ goto out;
++ }
++
++ idesc = intf->altsetting;
++
++ if (idesc->desc.bNumEndpoints < 2) {
++ ret = -ENODEV;
++ goto out;
++ }
++
++ ir->rc = rc;
++ ir->dev = &intf->dev;
++ ir->udev = udev;
++ ir->pipe_in = usb_rcvintpipe(udev,
++ idesc->endpoint[0].desc.bEndpointAddress);
++ ir->pipe_out = usb_sndintpipe(udev,
++ idesc->endpoint[1].desc.bEndpointAddress);
++ mutex_init(&ir->lock);
++ init_completion(&ir->completion);
++
++ ret = iguanair_get_features(ir);
++ if (ret) {
++ dev_warn(&intf->dev, "failed to get device features");
++ goto out;
++ }
++
++ usb_fill_int_urb(ir->urb_in, ir->udev, ir->pipe_in, ir->buf_in,
++ MAX_PACKET_SIZE, iguanair_rx, ir,
++ idesc->endpoint[0].desc.bInterval);
++ ir->urb_in->transfer_dma = ir->dma_in;
++ ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++
++ snprintf(ir->name, sizeof(ir->name),
++ "IguanaWorks USB IR Transceiver version %d.%d",
++ ir->version[0], ir->version[1]);
++
++ usb_make_path(ir->udev, ir->phys, sizeof(ir->phys));
++
++ rc->input_name = ir->name;
++ rc->input_phys = ir->phys;
++ usb_to_input_id(ir->udev, &rc->input_id);
++ rc->dev.parent = &intf->dev;
++ rc->driver_type = RC_DRIVER_IR_RAW;
++ rc->allowed_protos = RC_TYPE_ALL;
++ rc->priv = ir;
++ rc->open = iguanair_open;
++ rc->close = iguanair_close;
++ rc->s_tx_mask = iguanair_set_tx_mask;
++ rc->s_tx_carrier = iguanair_set_tx_carrier;
++ rc->tx_ir = iguanair_tx;
++ rc->driver_name = DRIVER_NAME;
++ rc->map_name = RC_MAP_EMPTY;
++
++ iguanair_set_tx_carrier(rc, 38000);
++
++ ret = rc_register_device(rc);
++ if (ret < 0) {
++ dev_err(&intf->dev, "failed to register rc device %d", ret);
++ goto out;
++ }
++
++ usb_set_intfdata(intf, ir);
++
++ dev_info(&intf->dev, "Registered %s", ir->name);
++
++ return 0;
++out:
++ if (ir) {
++ usb_free_urb(ir->urb_in);
++ usb_free_coherent(udev, MAX_PACKET_SIZE, ir->buf_in,
++ ir->dma_in);
++ }
++ rc_free_device(rc);
++ kfree(ir);
++ return ret;
++}
++
++static void __devexit iguanair_disconnect(struct usb_interface *intf)
++{
++ struct iguanair *ir = usb_get_intfdata(intf);
++
++ usb_set_intfdata(intf, NULL);
++
++ usb_kill_urb(ir->urb_in);
++ usb_free_urb(ir->urb_in);
++ usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in);
++ rc_unregister_device(ir->rc);
++ kfree(ir);
++}
++
++static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
++{
++ struct iguanair *ir = usb_get_intfdata(intf);
++ int rc = 0;
++
++ mutex_lock(&ir->lock);
++
++ if (ir->receiver_on) {
++ rc = iguanair_receiver(ir, false);
++ if (rc)
++ dev_warn(ir->dev, "failed to disable receiver for suspend\n");
++ }
++
++ mutex_unlock(&ir->lock);
++
++ return rc;
++}
++
++static int iguanair_resume(struct usb_interface *intf)
++{
++ struct iguanair *ir = usb_get_intfdata(intf);
++ int rc = 0;
++
++ mutex_lock(&ir->lock);
++
++ if (ir->receiver_on) {
++ rc = iguanair_receiver(ir, true);
++ if (rc)
++ dev_warn(ir->dev, "failed to enable receiver after resume\n");
++ }
++
++ mutex_unlock(&ir->lock);
++
++ return rc;
++}
++
++static const struct usb_device_id iguanair_table[] = {
++ { USB_DEVICE(0x1781, 0x0938) },
++ { }
++};
++
++static struct usb_driver iguanair_driver = {
++ .name = DRIVER_NAME,
++ .probe = iguanair_probe,
++ .disconnect = __devexit_p(iguanair_disconnect),
++ .suspend = iguanair_suspend,
++ .resume = iguanair_resume,
++ .reset_resume = iguanair_resume,
++ .id_table = iguanair_table
++};
++
++module_usb_driver(iguanair_driver);
++
++MODULE_DESCRIPTION("IguanaWorks USB IR Transceiver");
++MODULE_AUTHOR("Sean Young <sean at mess.org>");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(usb, iguanair_table);
++
Added: dists/sid/linux/debian/patches/features/all/iguanair/0002-media-iguanair-reuse-existing-urb-callback-for-comma.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0002-media-iguanair-reuse-existing-urb-callback-for-comma.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,313 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:39 -0300
+Subject: [02/11] [media] iguanair: reuse existing urb callback for command
+ responses
+
+commit e99a7cfe93fd9b853d80e7dda8b86ecca71c22bb upstream.
+
+Rather than using usb_interrupt_msg() to receive responses, reuse the
+urb callback we already have in place.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 147 +++++++++++++++++--------------------------
+ 1 file changed, 56 insertions(+), 91 deletions(-)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 5e2eaf8..bdd526d 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -35,7 +35,7 @@ struct iguanair {
+ struct device *dev;
+ struct usb_device *udev;
+
+- int pipe_in, pipe_out;
++ int pipe_out;
+ uint8_t bufsize;
+ uint8_t version[2];
+
+@@ -82,11 +82,6 @@ struct packet {
+ uint8_t cmd;
+ };
+
+-struct response_packet {
+- struct packet header;
+- uint8_t data[4];
+-};
+-
+ struct send_packet {
+ struct packet header;
+ uint8_t length;
+@@ -100,6 +95,26 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ {
+ if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) {
+ switch (ir->buf_in[3]) {
++ case CMD_GET_VERSION:
++ if (len == 6) {
++ ir->version[0] = ir->buf_in[4];
++ ir->version[1] = ir->buf_in[5];
++ complete(&ir->completion);
++ }
++ break;
++ case CMD_GET_BUFSIZE:
++ if (len >= 5) {
++ ir->bufsize = ir->buf_in[4];
++ complete(&ir->completion);
++ }
++ break;
++ case CMD_GET_FEATURES:
++ if (len > 5) {
++ if (ir->version[0] >= 4)
++ ir->cycle_overhead = ir->buf_in[5];
++ complete(&ir->completion);
++ }
++ break;
+ case CMD_TX_OVERFLOW:
+ ir->tx_overflow = true;
+ case CMD_RECEIVER_OFF:
+@@ -169,31 +184,22 @@ static void iguanair_rx(struct urb *urb)
+ usb_submit_urb(urb, GFP_ATOMIC);
+ }
+
+-static int iguanair_send(struct iguanair *ir, void *data, unsigned size,
+- struct response_packet *response, unsigned *res_len)
++static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
+ {
+- unsigned offset, len;
+ int rc, transferred;
+
+- for (offset = 0; offset < size; offset += MAX_PACKET_SIZE) {
+- len = min(size - offset, MAX_PACKET_SIZE);
+-
+- if (ir->tx_overflow)
+- return -EOVERFLOW;
++ INIT_COMPLETION(ir->completion);
+
+- rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data + offset,
+- len, &transferred, TIMEOUT);
+- if (rc)
+- return rc;
++ rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size,
++ &transferred, TIMEOUT);
++ if (rc)
++ return rc;
+
+- if (transferred != len)
+- return -EIO;
+- }
++ if (transferred != size)
++ return -EIO;
+
+- if (response) {
+- rc = usb_interrupt_msg(ir->udev, ir->pipe_in, response,
+- sizeof(*response), res_len, TIMEOUT);
+- }
++ if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
++ return -ETIMEDOUT;
+
+ return rc;
+ }
+@@ -201,66 +207,40 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size,
+ static int iguanair_get_features(struct iguanair *ir)
+ {
+ struct packet packet;
+- struct response_packet response;
+- int rc, len;
++ int rc;
+
+ packet.start = 0;
+ packet.direction = DIR_OUT;
+ packet.cmd = CMD_GET_VERSION;
+
+- rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
++ rc = iguanair_send(ir, &packet, sizeof(packet));
+ if (rc) {
+ dev_info(ir->dev, "failed to get version\n");
+ goto out;
+ }
+
+- if (len != 6) {
+- dev_info(ir->dev, "failed to get version\n");
+- rc = -EIO;
+- goto out;
+- }
+-
+- ir->version[0] = response.data[0];
+- ir->version[1] = response.data[1];
+ ir->bufsize = 150;
+ ir->cycle_overhead = 65;
+
+ packet.cmd = CMD_GET_BUFSIZE;
+
+- rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
++ rc = iguanair_send(ir, &packet, sizeof(packet));
+ if (rc) {
+ dev_info(ir->dev, "failed to get buffer size\n");
+ goto out;
+ }
+
+- if (len != 5) {
+- dev_info(ir->dev, "failed to get buffer size\n");
+- rc = -EIO;
+- goto out;
+- }
+-
+- ir->bufsize = response.data[0];
+-
+ if (ir->version[0] == 0 || ir->version[1] == 0)
+ goto out;
+
+ packet.cmd = CMD_GET_FEATURES;
+
+- rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
++ rc = iguanair_send(ir, &packet, sizeof(packet));
+ if (rc) {
+ dev_info(ir->dev, "failed to get features\n");
+ goto out;
+ }
+
+- if (len < 5) {
+- dev_info(ir->dev, "failed to get features\n");
+- rc = -EIO;
+- goto out;
+- }
+-
+- if (len > 5 && ir->version[0] >= 4)
+- ir->cycle_overhead = response.data[1];
+-
+ out:
+ return rc;
+ }
+@@ -269,17 +249,8 @@ static int iguanair_receiver(struct iguanair *ir, bool enable)
+ {
+ struct packet packet = { 0, DIR_OUT, enable ?
+ CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
+- int rc;
+-
+- INIT_COMPLETION(ir->completion);
+-
+- rc = iguanair_send(ir, &packet, sizeof(packet), NULL, NULL);
+- if (rc)
+- return rc;
+-
+- wait_for_completion_timeout(&ir->completion, TIMEOUT);
+
+- return 0;
++ return iguanair_send(ir, &packet, sizeof(packet));
+ }
+
+ /*
+@@ -406,17 +377,10 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+
+ ir->tx_overflow = false;
+
+- INIT_COMPLETION(ir->completion);
+-
+- rc = iguanair_send(ir, packet, size + 8, NULL, NULL);
++ rc = iguanair_send(ir, packet, size + 8);
+
+- if (rc == 0) {
+- wait_for_completion_timeout(&ir->completion, TIMEOUT);
+- if (ir->tx_overflow)
+- rc = -EOVERFLOW;
+- }
+-
+- ir->tx_overflow = false;
++ if (rc == 0 && ir->tx_overflow)
++ rc = -EOVERFLOW;
+
+ if (ir->receiver_on) {
+ if (iguanair_receiver(ir, true))
+@@ -437,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev)
+
+ mutex_lock(&ir->lock);
+
+- usb_submit_urb(ir->urb_in, GFP_KERNEL);
+-
+ BUG_ON(ir->receiver_on);
+
+ rc = iguanair_receiver(ir, true);
+@@ -462,8 +424,6 @@ static void iguanair_close(struct rc_dev *rdev)
+ if (rc)
+ dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
+
+- usb_kill_urb(ir->urb_in);
+-
+ mutex_unlock(&ir->lock);
+ }
+
+@@ -473,7 +433,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct iguanair *ir;
+ struct rc_dev *rc;
+- int ret;
++ int ret, pipein;
+ struct usb_host_interface *idesc;
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+@@ -483,7 +443,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ goto out;
+ }
+
+- ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_ATOMIC,
++ ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL,
+ &ir->dma_in);
+ ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+
+@@ -502,25 +462,28 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ ir->rc = rc;
+ ir->dev = &intf->dev;
+ ir->udev = udev;
+- ir->pipe_in = usb_rcvintpipe(udev,
+- idesc->endpoint[0].desc.bEndpointAddress);
+ ir->pipe_out = usb_sndintpipe(udev,
+ idesc->endpoint[1].desc.bEndpointAddress);
+ mutex_init(&ir->lock);
+ init_completion(&ir->completion);
+
+- ret = iguanair_get_features(ir);
+- if (ret) {
+- dev_warn(&intf->dev, "failed to get device features");
+- goto out;
+- }
+-
+- usb_fill_int_urb(ir->urb_in, ir->udev, ir->pipe_in, ir->buf_in,
++ pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
++ usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in,
+ MAX_PACKET_SIZE, iguanair_rx, ir,
+ idesc->endpoint[0].desc.bInterval);
+ ir->urb_in->transfer_dma = ir->dma_in;
+ ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
++ ret = usb_submit_urb(ir->urb_in, GFP_KERNEL);
++ if (ret) {
++ dev_warn(&intf->dev, "failed to submit urb: %d\n", ret);
++ goto out;
++ }
++
++ ret = iguanair_get_features(ir);
++ if (ret)
++ goto out2;
++
+ snprintf(ir->name, sizeof(ir->name),
+ "IguanaWorks USB IR Transceiver version %d.%d",
+ ir->version[0], ir->version[1]);
+@@ -547,7 +510,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ ret = rc_register_device(rc);
+ if (ret < 0) {
+ dev_err(&intf->dev, "failed to register rc device %d", ret);
+- goto out;
++ goto out2;
+ }
+
+ usb_set_intfdata(intf, ir);
+@@ -555,6 +518,8 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ dev_info(&intf->dev, "Registered %s", ir->name);
+
+ return 0;
++out2:
++ usb_kill_urb(ir->urb_in);
+ out:
+ if (ir) {
+ usb_free_urb(ir->urb_in);
Added: dists/sid/linux/debian/patches/features/all/iguanair/0003-media-iguanair-ignore-unsupported-firmware-versions.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0003-media-iguanair-ignore-unsupported-firmware-versions.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,103 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:40 -0300
+Subject: [03/11] [media] iguanair: ignore unsupported firmware versions
+
+commit 0797b4802b57ce88e9361c8d64b0980508370649 upstream.
+
+Firmware versions lower than 0x0205 use a different interface which is not
+supported. Also report the firmware version in the standard format.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/Kconfig | 8 ++++++--
+ drivers/media/rc/iguanair.c | 21 +++++++++++----------
+ 2 files changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
+index 5180390..2e91e66 100644
+--- a/drivers/media/rc/Kconfig
++++ b/drivers/media/rc/Kconfig
+@@ -264,8 +264,12 @@ config IR_IGUANA
+ depends on RC_CORE
+ select USB
+ ---help---
+- Say Y here if you want to use the IgaunaWorks USB IR Transceiver.
+- Both infrared receive and send are supported.
++ Say Y here if you want to use the IguanaWorks USB IR Transceiver.
++ Both infrared receive and send are supported. If you want to
++ change the ID or the pin config, use the user space driver from
++ IguanaWorks.
++
++ Only firmware 0x0205 and later is supported.
+
+ To compile this driver as a module, choose M here: the module will
+ be called iguanair.
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index bdd526d..5885400 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -36,8 +36,8 @@ struct iguanair {
+ struct usb_device *udev;
+
+ int pipe_out;
++ uint16_t version;
+ uint8_t bufsize;
+- uint8_t version[2];
+
+ struct mutex lock;
+
+@@ -97,8 +97,8 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ switch (ir->buf_in[3]) {
+ case CMD_GET_VERSION:
+ if (len == 6) {
+- ir->version[0] = ir->buf_in[4];
+- ir->version[1] = ir->buf_in[5];
++ ir->version = (ir->buf_in[5] << 8) |
++ ir->buf_in[4];
+ complete(&ir->completion);
+ }
+ break;
+@@ -110,8 +110,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ break;
+ case CMD_GET_FEATURES:
+ if (len > 5) {
+- if (ir->version[0] >= 4)
+- ir->cycle_overhead = ir->buf_in[5];
++ ir->cycle_overhead = ir->buf_in[5];
+ complete(&ir->completion);
+ }
+ break;
+@@ -219,6 +218,12 @@ static int iguanair_get_features(struct iguanair *ir)
+ goto out;
+ }
+
++ if (ir->version < 0x205) {
++ dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version);
++ rc = -ENODEV;
++ goto out;
++ }
++
+ ir->bufsize = 150;
+ ir->cycle_overhead = 65;
+
+@@ -230,9 +235,6 @@ static int iguanair_get_features(struct iguanair *ir)
+ goto out;
+ }
+
+- if (ir->version[0] == 0 || ir->version[1] == 0)
+- goto out;
+-
+ packet.cmd = CMD_GET_FEATURES;
+
+ rc = iguanair_send(ir, &packet, sizeof(packet));
+@@ -485,8 +487,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ goto out2;
+
+ snprintf(ir->name, sizeof(ir->name),
+- "IguanaWorks USB IR Transceiver version %d.%d",
+- ir->version[0], ir->version[1]);
++ "IguanaWorks USB IR Transceiver version 0x%04x", ir->version);
+
+ usb_make_path(ir->udev, ir->phys, sizeof(ir->phys));
+
Added: dists/sid/linux/debian/patches/features/all/iguanair/0004-media-iguanair-support-suspend-and-resume.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0004-media-iguanair-support-suspend-and-resume.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,99 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:43 -0300
+Subject: [04/11] [media] iguanair: support suspend and resume
+
+commit 7c0bd96b767da250e5aa5ee135c530d87454d9fe upstream.
+
+Now unbind also stops the receiver.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 5885400..f1c5846 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -155,6 +155,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ static void iguanair_rx(struct urb *urb)
+ {
+ struct iguanair *ir;
++ int rc;
+
+ if (!urb)
+ return;
+@@ -180,7 +181,9 @@ static void iguanair_rx(struct urb *urb)
+ break;
+ }
+
+- usb_submit_urb(urb, GFP_ATOMIC);
++ rc = usb_submit_urb(urb, GFP_ATOMIC);
++ if (rc && rc != -ENODEV)
++ dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
+ }
+
+ static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
+@@ -423,7 +426,7 @@ static void iguanair_close(struct rc_dev *rdev)
+
+ rc = iguanair_receiver(ir, false);
+ ir->receiver_on = false;
+- if (rc)
++ if (rc && rc != -ENODEV)
+ dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
+
+ mutex_unlock(&ir->lock);
+@@ -516,8 +519,6 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+
+ usb_set_intfdata(intf, ir);
+
+- dev_info(&intf->dev, "Registered %s", ir->name);
+-
+ return 0;
+ out2:
+ usb_kill_urb(ir->urb_in);
+@@ -536,12 +537,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf)
+ {
+ struct iguanair *ir = usb_get_intfdata(intf);
+
++ rc_unregister_device(ir->rc);
+ usb_set_intfdata(intf, NULL);
+-
+ usb_kill_urb(ir->urb_in);
+ usb_free_urb(ir->urb_in);
+ usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in);
+- rc_unregister_device(ir->rc);
+ kfree(ir);
+ }
+
+@@ -558,6 +558,8 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
+ dev_warn(ir->dev, "failed to disable receiver for suspend\n");
+ }
+
++ usb_kill_urb(ir->urb_in);
++
+ mutex_unlock(&ir->lock);
+
+ return rc;
+@@ -570,6 +572,10 @@ static int iguanair_resume(struct usb_interface *intf)
+
+ mutex_lock(&ir->lock);
+
++ rc = usb_submit_urb(ir->urb_in, GFP_KERNEL);
++ if (rc)
++ dev_warn(&intf->dev, "failed to submit urb: %d\n", rc);
++
+ if (ir->receiver_on) {
+ rc = iguanair_receiver(ir, true);
+ if (rc)
+@@ -593,7 +599,8 @@ static struct usb_driver iguanair_driver = {
+ .suspend = iguanair_suspend,
+ .resume = iguanair_resume,
+ .reset_resume = iguanair_resume,
+- .id_table = iguanair_table
++ .id_table = iguanair_table,
++ .soft_unbind = 1 /* we want to disable receiver on unbind */
+ };
+
+ module_usb_driver(iguanair_driver);
Added: dists/sid/linux/debian/patches/features/all/iguanair/0005-media-iguanair-fix-return-value-for-transmit.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0005-media-iguanair-fix-return-value-for-transmit.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,98 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:42 -0300
+Subject: [05/11] [media] iguanair: fix return value for transmit
+
+commit 884bfd08e3d4f694574e54bd1886cd8817d9b986 upstream.
+
+Also fix error codes returned from open.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index f1c5846..6817258 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -327,7 +327,7 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ {
+ struct iguanair *ir = dev->priv;
+ uint8_t space, *payload;
+- unsigned i, size, rc;
++ unsigned i, size, rc, bytes;
+ struct send_packet *packet;
+
+ mutex_lock(&ir->lock);
+@@ -335,17 +335,22 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ /* convert from us to carrier periods */
+ for (i = size = 0; i < count; i++) {
+ txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
+- size += (txbuf[i] + 126) / 127;
++ bytes = (txbuf[i] + 126) / 127;
++ if (size + bytes > ir->bufsize) {
++ count = i;
++ break;
++ }
++ size += bytes;
+ }
+
+- packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL);
+- if (!packet) {
+- rc = -ENOMEM;
++ if (count == 0) {
++ rc = -EINVAL;
+ goto out;
+ }
+
+- if (size > ir->bufsize) {
+- rc = -E2BIG;
++ packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL);
++ if (!packet) {
++ rc = -ENOMEM;
+ goto out;
+ }
+
+@@ -376,7 +381,7 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ rc = iguanair_receiver(ir, false);
+ if (rc) {
+ dev_warn(ir->dev, "disable receiver before transmit failed\n");
+- goto out;
++ goto out_kfree;
+ }
+ }
+
+@@ -392,11 +397,12 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
+ }
+
++out_kfree:
++ kfree(packet);
+ out:
+ mutex_unlock(&ir->lock);
+- kfree(packet);
+
+- return rc;
++ return rc ? rc : count;
+ }
+
+ static int iguanair_open(struct rc_dev *rdev)
+@@ -444,7 +450,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ rc = rc_allocate_device();
+ if (!ir || !rc) {
+- ret = ENOMEM;
++ ret = -ENOMEM;
+ goto out;
+ }
+
+@@ -453,7 +459,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (!ir->buf_in || !ir->urb_in) {
+- ret = ENOMEM;
++ ret = -ENOMEM;
+ goto out;
+ }
+
Added: dists/sid/linux/debian/patches/features/all/iguanair/0006-media-iguanair-reset-the-IR-state-after-rx-overflow-.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0006-media-iguanair-reset-the-IR-state-after-rx-overflow-.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,35 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:44 -0300
+Subject: [06/11] [media] iguanair: reset the IR state after rx overflow or
+ receiver enable
+
+commit 116e4f592a4d207031b2eaf9dacb57de587146ef upstream.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 6817258..8de690a 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -123,6 +123,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ break;
+ case CMD_RX_OVERFLOW:
+ dev_warn(ir->dev, "receive overflow\n");
++ ir_raw_event_reset(ir->rc);
+ break;
+ default:
+ dev_warn(ir->dev, "control code %02x received\n",
+@@ -255,6 +256,9 @@ static int iguanair_receiver(struct iguanair *ir, bool enable)
+ struct packet packet = { 0, DIR_OUT, enable ?
+ CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
+
++ if (enable)
++ ir_raw_event_reset(ir->rc);
++
+ return iguanair_send(ir, &packet, sizeof(packet));
+ }
+
Added: dists/sid/linux/debian/patches/features/all/iguanair/0007-media-iguanair-advertise-the-resolution-and-timeout-.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0007-media-iguanair-advertise-the-resolution-and-timeout-.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,48 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:41 -0300
+Subject: [07/11] [media] iguanair: advertise the resolution and timeout
+ properly
+
+commit 2eec676cd3097bc37618e57c19b17cbeac13cdf4 upstream.
+
+With the timeout supplied the interface can go idle. The keymap is
+the same one as other drivers which do not come with a remote.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 8de690a..9810008 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -75,6 +75,7 @@ struct iguanair {
+
+ #define MAX_PACKET_SIZE 8u
+ #define TIMEOUT 1000
++#define RX_RESOLUTION 21333
+
+ struct packet {
+ uint16_t start;
+@@ -143,7 +144,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ } else {
+ rawir.pulse = (ir->buf_in[i] & 0x80) == 0;
+ rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) *
+- 21330;
++ RX_RESOLUTION;
+ }
+
+ ir_raw_event_store_with_filter(ir->rc, &rawir);
+@@ -517,7 +518,9 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ rc->s_tx_carrier = iguanair_set_tx_carrier;
+ rc->tx_ir = iguanair_tx;
+ rc->driver_name = DRIVER_NAME;
+- rc->map_name = RC_MAP_EMPTY;
++ rc->map_name = RC_MAP_RC6_MCE;
++ rc->timeout = MS_TO_NS(100);
++ rc->rx_resolution = RX_RESOLUTION;
+
+ iguanair_set_tx_carrier(rc, 38000);
+
Added: dists/sid/linux/debian/patches/features/all/iguanair/0008-media-iguanair-fix-receiver-overflow.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0008-media-iguanair-fix-receiver-overflow.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,36 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:45 -0300
+Subject: [08/11] [media] iguanair: fix receiver overflow
+
+commit 640583836b9488c806349e3839c9d8b0f15da1fa upstream.
+
+The Pioneer CU-700 remote causes receiver overflows if you hold down any
+button. The remote does not send NEC IR repeats, it repeats the entire
+NEC code after 20ms.
+
+The iguanair hardware advertises an interval of 10 which just not enough;
+with 100 URBs per second and at most 7 edges per URB, we handle at most
+700 edges per second. The remote generates about 900.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 9810008..6a09c2e 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -484,9 +484,8 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ init_completion(&ir->completion);
+
+ pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
+- usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in,
+- MAX_PACKET_SIZE, iguanair_rx, ir,
+- idesc->endpoint[0].desc.bInterval);
++ usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE,
++ iguanair_rx, ir, 1);
+ ir->urb_in->transfer_dma = ir->dma_in;
+ ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
Added: dists/sid/linux/debian/patches/features/all/iguanair/0009-media-rc-do-not-wake-up-rc-thread-unless-there-is-so.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0009-media-rc-do-not-wake-up-rc-thread-unless-there-is-so.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,42 @@
+From: Sean Young <sean at mess.org>
+Date: Mon, 13 Aug 2012 08:59:47 -0300
+Subject: [09/12] [media] rc: do not wake up rc thread unless there is
+ something to do
+
+commit b83bfd1b0127b0963fcac39280280e365e7e04d8 upstream.
+
+The TechnoTrend USB IR Receiver sends 125 ISO URBs per second, even when
+there is no IR activity. Reduce the number of wake ups from the other
+drivers too.
+
+This saves about 0.25ms/s on a 2.4GHz Core 2 according to powertop.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+[bwh: Restricted to iguanair driver]
+---
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -134,6 +134,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ } else if (len >= 7) {
+ DEFINE_IR_RAW_EVENT(rawir);
+ unsigned i;
++ bool event = false;
+
+ init_ir_raw_event(&rawir);
+
+@@ -147,10 +148,12 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
+ RX_RESOLUTION;
+ }
+
+- ir_raw_event_store_with_filter(ir->rc, &rawir);
++ if (ir_raw_event_store_with_filter(ir->rc, &rawir))
++ event = true;
+ }
+
+- ir_raw_event_handle(ir->rc);
++ if (event)
++ ir_raw_event_handle(ir->rc);
+ }
+ }
+
Added: dists/sid/linux/debian/patches/features/all/iguanair/0010-media-iguanair-do-not-modify-transmit-buffer.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0010-media-iguanair-do-not-modify-transmit-buffer.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,112 @@
+From: Sean Young <sean at mess.org>
+Date: Sat, 25 Aug 2012 07:01:45 -0300
+Subject: [10/11] [media] iguanair: do not modify transmit buffer
+
+commit 3920631c4b8af70893fe70df53e94adb0cd66f71 upstream.
+
+Since commit "[media] rc-core: move timeout and checks to lirc", the
+incoming buffer is used after the driver transmits.
+
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 51 ++++++++++++++++++-------------------------
+ 1 file changed, 21 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 66ba237..1e4c68a 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -334,21 +334,34 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
+ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ {
+ struct iguanair *ir = dev->priv;
+- uint8_t space, *payload;
+- unsigned i, size, rc, bytes;
++ uint8_t space;
++ unsigned i, size, periods, bytes;
++ int rc;
+ struct send_packet *packet;
+
+ mutex_lock(&ir->lock);
+
++ packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL);
++ if (!packet) {
++ rc = -ENOMEM;
++ goto out;
++ }
++
+ /* convert from us to carrier periods */
+- for (i = size = 0; i < count; i++) {
+- txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
+- bytes = (txbuf[i] + 126) / 127;
++ for (i = space = size = 0; i < count; i++) {
++ periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
++ bytes = DIV_ROUND_UP(periods, 127);
+ if (size + bytes > ir->bufsize) {
+ count = i;
+ break;
+ }
+- size += bytes;
++ while (periods > 127) {
++ packet->payload[size++] = 127 | space;
++ periods -= 127;
++ }
++
++ packet->payload[size++] = periods | space;
++ space ^= 0x80;
+ }
+
+ if (count == 0) {
+@@ -356,12 +369,6 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ goto out;
+ }
+
+- packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL);
+- if (!packet) {
+- rc = -ENOMEM;
+- goto out;
+- }
+-
+ packet->header.start = 0;
+ packet->header.direction = DIR_OUT;
+ packet->header.cmd = CMD_SEND;
+@@ -370,26 +377,11 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ packet->busy7 = ir->busy7;
+ packet->busy4 = ir->busy4;
+
+- space = 0;
+- payload = packet->payload;
+-
+- for (i = 0; i < count; i++) {
+- unsigned periods = txbuf[i];
+-
+- while (periods > 127) {
+- *payload++ = 127 | space;
+- periods -= 127;
+- }
+-
+- *payload++ = periods | space;
+- space ^= 0x80;
+- }
+-
+ if (ir->receiver_on) {
+ rc = iguanair_receiver(ir, false);
+ if (rc) {
+ dev_warn(ir->dev, "disable receiver before transmit failed\n");
+- goto out_kfree;
++ goto out;
+ }
+ }
+
+@@ -405,9 +397,8 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
+ }
+
+-out_kfree:
+- kfree(packet);
+ out:
++ kfree(packet);
+ mutex_unlock(&ir->lock);
+
+ return rc ? rc : count;
Added: dists/sid/linux/debian/patches/features/all/iguanair/0011-media-iguanair-cannot-send-data-from-the-stack.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/sid/linux/debian/patches/features/all/iguanair/0011-media-iguanair-cannot-send-data-from-the-stack.patch Sat Dec 29 13:57:44 2012 (r19663)
@@ -0,0 +1,359 @@
+From: Sean Young <sean at mess.org>
+Date: Fri, 28 Sep 2012 04:44:29 -0300
+Subject: [11/11] [media] iguanair: cannot send data from the stack
+
+commit 48b0fa6afa7ee6a274e060564d2389ffea413762 upstream.
+
+Note that the firmware already disables the receiver before transmit,
+there is no need to do this from the driver.
+
+Reported-by: Fengguang Wu <fengguang.wu at intel.com>
+Signed-off-by: Sean Young <sean at mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab at redhat.com>
+---
+ drivers/media/rc/iguanair.c | 147 ++++++++++++++++++++++---------------------
+ 1 file changed, 75 insertions(+), 72 deletions(-)
+
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 1e4c68a..51d7057 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -28,6 +28,7 @@
+ #include <media/rc-core.h>
+
+ #define DRIVER_NAME "iguanair"
++#define BUF_SIZE 152
+
+ struct iguanair {
+ struct rc_dev *rc;
+@@ -35,26 +36,23 @@ struct iguanair {
+ struct device *dev;
+ struct usb_device *udev;
+
+- int pipe_out;
+ uint16_t version;
+ uint8_t bufsize;
++ uint8_t cycle_overhead;
+
+ struct mutex lock;
+
+ /* receiver support */
+ bool receiver_on;
+- dma_addr_t dma_in;
++ dma_addr_t dma_in, dma_out;
+ uint8_t *buf_in;
+- struct urb *urb_in;
++ struct urb *urb_in, *urb_out;
+ struct completion completion;
+
+ /* transmit support */
+ bool tx_overflow;
+ uint32_t carrier;
+- uint8_t cycle_overhead;
+- uint8_t channels;
+- uint8_t busy4;
+- uint8_t busy7;
++ struct send_packet *packet;
+
+ char name[64];
+ char phys[64];
+@@ -73,7 +71,8 @@ struct iguanair {
+ #define DIR_IN 0xdc
+ #define DIR_OUT 0xcd
+
+-#define MAX_PACKET_SIZE 8u
++#define MAX_IN_PACKET 8u
++#define MAX_OUT_PACKET (sizeof(struct send_packet) + BUF_SIZE)
+ #define TIMEOUT 1000
+ #define RX_RESOLUTION 21333
+
+@@ -191,20 +190,25 @@ static void iguanair_rx(struct urb *urb)
+ dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
+ }
+
+-static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
++static void iguanair_irq_out(struct urb *urb)
+ {
+- int rc, transferred;
++ struct iguanair *ir = urb->context;
++
++ if (urb->status)
++ dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status);
++}
++
++static int iguanair_send(struct iguanair *ir, unsigned size)
++{
++ int rc;
+
+ INIT_COMPLETION(ir->completion);
+
+- rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size,
+- &transferred, TIMEOUT);
++ ir->urb_out->transfer_buffer_length = size;
++ rc = usb_submit_urb(ir->urb_out, GFP_KERNEL);
+ if (rc)
+ return rc;
+
+- if (transferred != size)
+- return -EIO;
+-
+ if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
+ return -ETIMEDOUT;
+
+@@ -213,14 +217,13 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
+
+ static int iguanair_get_features(struct iguanair *ir)
+ {
+- struct packet packet;
+ int rc;
+
+- packet.start = 0;
+- packet.direction = DIR_OUT;
+- packet.cmd = CMD_GET_VERSION;
++ ir->packet->header.start = 0;
++ ir->packet->header.direction = DIR_OUT;
++ ir->packet->header.cmd = CMD_GET_VERSION;
+
+- rc = iguanair_send(ir, &packet, sizeof(packet));
++ rc = iguanair_send(ir, sizeof(ir->packet->header));
+ if (rc) {
+ dev_info(ir->dev, "failed to get version\n");
+ goto out;
+@@ -235,17 +238,23 @@ static int iguanair_get_features(struct iguanair *ir)
+ ir->bufsize = 150;
+ ir->cycle_overhead = 65;
+
+- packet.cmd = CMD_GET_BUFSIZE;
++ ir->packet->header.cmd = CMD_GET_BUFSIZE;
+
+- rc = iguanair_send(ir, &packet, sizeof(packet));
++ rc = iguanair_send(ir, sizeof(ir->packet->header));
+ if (rc) {
+ dev_info(ir->dev, "failed to get buffer size\n");
+ goto out;
+ }
+
+- packet.cmd = CMD_GET_FEATURES;
++ if (ir->bufsize > BUF_SIZE) {
++ dev_info(ir->dev, "buffer size %u larger than expected\n",
++ ir->bufsize);
++ ir->bufsize = BUF_SIZE;
++ }
++
++ ir->packet->header.cmd = CMD_GET_FEATURES;
+
+- rc = iguanair_send(ir, &packet, sizeof(packet));
++ rc = iguanair_send(ir, sizeof(ir->packet->header));
+ if (rc) {
+ dev_info(ir->dev, "failed to get features\n");
+ goto out;
+@@ -257,13 +266,18 @@ out:
+
+ static int iguanair_receiver(struct iguanair *ir, bool enable)
+ {
+- struct packet packet = { 0, DIR_OUT, enable ?
+- CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
++ int rc;
++
++ ir->packet->header.start = 0;
++ ir->packet->header.direction = DIR_OUT;
++ ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF;
+
+ if (enable)
+ ir_raw_event_reset(ir->rc);
+
+- return iguanair_send(ir, &packet, sizeof(packet));
++ rc = iguanair_send(ir, sizeof(ir->packet->header));
++
++ return rc;
+ }
+
+ /*
+@@ -308,8 +322,8 @@ static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier)
+ fours = (cycles - sevens * 7) / 4;
+
+ /* magic happens here */
+- ir->busy7 = (4 - sevens) * 2;
+- ir->busy4 = 110 - fours;
++ ir->packet->busy7 = (4 - sevens) * 2;
++ ir->packet->busy4 = 110 - fours;
+ }
+
+ mutex_unlock(&ir->lock);
+@@ -325,7 +339,7 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
+ return 4;
+
+ mutex_lock(&ir->lock);
+- ir->channels = mask;
++ ir->packet->channels = mask << 4;
+ mutex_unlock(&ir->lock);
+
+ return 0;
+@@ -337,16 +351,9 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ uint8_t space;
+ unsigned i, size, periods, bytes;
+ int rc;
+- struct send_packet *packet;
+
+ mutex_lock(&ir->lock);
+
+- packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL);
+- if (!packet) {
+- rc = -ENOMEM;
+- goto out;
+- }
+-
+ /* convert from us to carrier periods */
+ for (i = space = size = 0; i < count; i++) {
+ periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
+@@ -356,11 +363,11 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ break;
+ }
+ while (periods > 127) {
+- packet->payload[size++] = 127 | space;
++ ir->packet->payload[size++] = 127 | space;
+ periods -= 127;
+ }
+
+- packet->payload[size++] = periods | space;
++ ir->packet->payload[size++] = periods | space;
+ space ^= 0x80;
+ }
+
+@@ -369,36 +376,19 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
+ goto out;
+ }
+
+- packet->header.start = 0;
+- packet->header.direction = DIR_OUT;
+- packet->header.cmd = CMD_SEND;
+- packet->length = size;
+- packet->channels = ir->channels << 4;
+- packet->busy7 = ir->busy7;
+- packet->busy4 = ir->busy4;
+-
+- if (ir->receiver_on) {
+- rc = iguanair_receiver(ir, false);
+- if (rc) {
+- dev_warn(ir->dev, "disable receiver before transmit failed\n");
+- goto out;
+- }
+- }
++ ir->packet->header.start = 0;
++ ir->packet->header.direction = DIR_OUT;
++ ir->packet->header.cmd = CMD_SEND;
++ ir->packet->length = size;
+
+ ir->tx_overflow = false;
+
+- rc = iguanair_send(ir, packet, size + 8);
++ rc = iguanair_send(ir, sizeof(*ir->packet) + size);
+
+ if (rc == 0 && ir->tx_overflow)
+ rc = -EOVERFLOW;
+
+- if (ir->receiver_on) {
+- if (iguanair_receiver(ir, true))
+- dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
+- }
+-
+ out:
+- kfree(packet);
+ mutex_unlock(&ir->lock);
+
+ return rc ? rc : count;
+@@ -411,8 +401,6 @@ static int iguanair_open(struct rc_dev *rdev)
+
+ mutex_lock(&ir->lock);
+
+- BUG_ON(ir->receiver_on);
+-
+ rc = iguanair_receiver(ir, true);
+ if (rc == 0)
+ ir->receiver_on = true;
+@@ -443,7 +431,7 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct iguanair *ir;
+ struct rc_dev *rc;
+- int ret, pipein;
++ int ret, pipein, pipeout;
+ struct usb_host_interface *idesc;
+
+ ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+@@ -453,11 +441,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ goto out;
+ }
+
+- ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL,
++ ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL,
+ &ir->dma_in);
++ ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL,
++ &ir->dma_out);
+ ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
++ ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
+
+- if (!ir->buf_in || !ir->urb_in) {
++ if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
+ ret = -ENOMEM;
+ goto out;
+ }
+@@ -472,13 +463,18 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ ir->rc = rc;
+ ir->dev = &intf->dev;
+ ir->udev = udev;
+- ir->pipe_out = usb_sndintpipe(udev,
+- idesc->endpoint[1].desc.bEndpointAddress);
+ mutex_init(&ir->lock);
++
+ init_completion(&ir->completion);
++ pipeout = usb_sndintpipe(udev,
++ idesc->endpoint[1].desc.bEndpointAddress);
++ usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET,
++ iguanair_irq_out, ir, 1);
++ ir->urb_out->transfer_dma = ir->dma_out;
++ ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
+- usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE,
++ usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET,
+ iguanair_rx, ir, 1);
+ ir->urb_in->transfer_dma = ir->dma_in;
+ ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+@@ -528,11 +524,14 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
+ return 0;
+ out2:
+ usb_kill_urb(ir->urb_in);
++ usb_kill_urb(ir->urb_out);
+ out:
+ if (ir) {
+ usb_free_urb(ir->urb_in);
+- usb_free_coherent(udev, MAX_PACKET_SIZE, ir->buf_in,
+- ir->dma_in);
++ usb_free_urb(ir->urb_out);
++ usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
++ usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet,
++ ir->dma_out);
+ }
+ rc_free_device(rc);
+ kfree(ir);
+@@ -546,8 +545,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf)
+ rc_unregister_device(ir->rc);
+ usb_set_intfdata(intf, NULL);
+ usb_kill_urb(ir->urb_in);
++ usb_kill_urb(ir->urb_out);
+ usb_free_urb(ir->urb_in);
+- usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in);
++ usb_free_urb(ir->urb_out);
++ usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
++ usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out);
+ kfree(ir);
+ }
+
+@@ -565,6 +567,7 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
+ }
+
+ usb_kill_urb(ir->urb_in);
++ usb_kill_urb(ir->urb_out);
+
+ mutex_unlock(&ir->lock);
+
Modified: dists/sid/linux/debian/patches/series
==============================================================================
--- dists/sid/linux/debian/patches/series Sat Dec 29 13:04:21 2012 (r19662)
+++ dists/sid/linux/debian/patches/series Sat Dec 29 13:57:44 2012 (r19663)
@@ -440,3 +440,16 @@
features/all/I2C-Add-helper-macro-for-i2c_driver-boilerplate.patch
features/all/USB-Add-helper-macro-for-usb_driver-boilerplate.patch
features/all/PCI-Add-helper-macro-for-pci_register_driver-boilerp.patch
+
+# iguanair driver from 3.7
+features/all/iguanair/0001-media-Add-support-for-the-IguanaWorks-USB-IR-Transce.patch
+features/all/iguanair/0002-media-iguanair-reuse-existing-urb-callback-for-comma.patch
+features/all/iguanair/0003-media-iguanair-ignore-unsupported-firmware-versions.patch
+features/all/iguanair/0004-media-iguanair-support-suspend-and-resume.patch
+features/all/iguanair/0005-media-iguanair-fix-return-value-for-transmit.patch
+features/all/iguanair/0006-media-iguanair-reset-the-IR-state-after-rx-overflow-.patch
+features/all/iguanair/0007-media-iguanair-advertise-the-resolution-and-timeout-.patch
+features/all/iguanair/0008-media-iguanair-fix-receiver-overflow.patch
+features/all/iguanair/0009-media-rc-do-not-wake-up-rc-thread-unless-there-is-so.patch
+features/all/iguanair/0010-media-iguanair-do-not-modify-transmit-buffer.patch
+features/all/iguanair/0011-media-iguanair-cannot-send-data-from-the-stack.patch
More information about the Kernel-svn-changes
mailing list