* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (505 commits)
[media] af9015: Fix max I2C message size when used with tda18271
[media] IR: initialize ir_raw_event in few more drivers
[media] Guard a divide in v4l1 compat layer
[media] imon: fix nomouse modprobe option
[media] imon: remove redundant change_protocol call
[media] imon: fix my egregious brown paper bag w/rdev/idev split
[media] cafe_ccic: Configure ov7670 correctly
[media] ov7670: allow configuration of image size, clock speed, and I/O method
[media] af9015: support for DigitalNow TinyTwin v3 [1f4d:9016]
[media] af9015: map DigitalNow TinyTwin v2 remote
[media] DigitalNow TinyTwin remote controller
[media] af9015: RC fixes and improvements
videodev2.h.xml: Update to reflect the latest changes at videodev2.h
[media] v4l: document new Bayer and monochrome pixel formats
[media] DocBook/v4l: Add missing formats used on gspca cpia1 and sn9c2028
[media] firedtv: add parameter to fake ca_system_ids in CA_INFO
[media] tm6000: fix a macro coding style issue
tm6000: Remove some ugly debug code
[media] Nova-S-Plus audio line input
[media] [RFC,1/1] V4L2: Use new CAP bits in existing RDS capable drivers
...
0 = /dev/tty Current TTY device
1 = /dev/console System console
2 = /dev/ptmx PTY master multiplex
+ 3 = /dev/ttyprintk User messages via printk TTY device
64 = /dev/cua0 Callout device for ttyS0
...
255 = /dev/cua191 Callout device for ttyS191
64 = /dev/radio0 Radio device
...
127 = /dev/radio63 Radio device
- 192 = /dev/vtx0 Teletext device
- ...
- 223 = /dev/vtx31 Teletext device
224 = /dev/vbi0 Vertical blank interrupt
...
255 = /dev/vbi31 Vertical blank interrupt
8 = /dev/mmcblk1 Second SD/MMC card
...
+ The start of next SD/MMC card can be configured with
+ CONFIG_MMC_BLOCK_MINORS, or overridden at boot/modprobe
+ time using the mmcblk.perdev_minors option. That would
+ bump the offset between each card to be the configured
+ value instead of the default 8.
+
179 char CCube DVXChip-based PCI products
0 = /dev/dvxirq0 First DVX device
1 = /dev/dvxirq1 Second DVX device
175 = /dev/usb/legousbtower15 16th USB Legotower device
176 = /dev/usb/usbtmc1 First USB TMC device
...
- 192 = /dev/usb/usbtmc16 16th USB TMC device
+ 191 = /dev/usb/usbtmc16 16th USB TMC device
+ 192 = /dev/usb/yurex1 First USB Yurex device
+ ...
+ 209 = /dev/usb/yurex16 16th USB Yurex device
240 = /dev/usb/dabusb0 First daubusb device
...
243 = /dev/usb/dabusb3 Fourth dabusb device
---------------------------
What: Video4Linux API 1 ioctls and from Video devices.
- When: July 2009
+ When: kernel 2.6.38
Files: include/linux/videodev.h
Check: include/linux/videodev.h
Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
---------------------------
+ What: Video4Linux obsolete drivers using V4L1 API
+ When: kernel 2.6.38
+ Files: drivers/staging/cpia/* drivers/staging/stradis/*
+ Check: drivers/staging/cpia/cpia.c drivers/staging/stradis/stradis.c
+ Why: There are some drivers still using V4L1 API, despite all efforts we've done
+ to migrate. Those drivers are for obsolete hardware that the old maintainer
+ didn't care (or not have the hardware anymore), and that no other developer
+ could find any hardware to buy. They probably have no practical usage today,
+ and people with such old hardware could probably keep using an older version
+ of the kernel. Those drivers will be moved to staging on 2.6.37 and, if nobody
+ care enough to port and test them with V4L2 API, they'll be removed on 2.6.38.
+ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ ---------------------------
+
What: sys_sysctl
When: September 2010
Option: CONFIG_SYSCTL_SYSCALL
----------------------------
-What: Support for VMware's guest paravirtuliazation technique [VMI] will be
- dropped.
-When: 2.6.37 or earlier.
-Why: With the recent innovations in CPU hardware acceleration technologies
- from Intel and AMD, VMware ran a few experiments to compare these
- techniques to guest paravirtualization technique on VMware's platform.
- These hardware assisted virtualization techniques have outperformed the
- performance benefits provided by VMI in most of the workloads. VMware
- expects that these hardware features will be ubiquitous in a couple of
- years, as a result, VMware has started a phased retirement of this
- feature from the hypervisor. We will be removing this feature from the
- Kernel too. Right now we are targeting 2.6.37 but can retire earlier if
- technical reasons (read opportunity to remove major chunk of pvops)
- arise.
-
- Please note that VMI has always been an optimization and non-VMI kernels
- still work fine on VMware's platform.
- Latest versions of VMware's product which support VMI are,
- Workstation 7.0 and VSphere 4.0 on ESX side, future maintainence
- releases for these products will continue supporting VMI.
-
- For more details about VMI retirement take a look at this,
- http://blogs.vmware.com/guestosguide/2009/09/vmi-retirement.html
-
-Who: Alok N Kataria <akataria@vmware.com>
-
-----------------------------
-
What: Support for lcd_switch and display_get in asus-laptop driver
When: March 2010
Why: These two features use non-standard interfaces. There are the
Why: Superseded by xt_CT
Who: Netfilter developer team <netfilter-devel@vger.kernel.org>
- ---------------------------
-
- What: video4linux /dev/vtx teletext API support
- When: 2.6.35
- Files: drivers/media/video/saa5246a.c drivers/media/video/saa5249.c
- include/linux/videotext.h
- Why: The vtx device nodes have been superseded by vbi device nodes
- for many years. No applications exist that use the vtx support.
- Of the two i2c drivers that actually support this API the saa5249
- has been impossible to use for a year now and no known hardware
- that supports this device exists. The saa5246a is theoretically
- supported by the old mxb boards, but it never actually worked.
-
- In summary: there is no hardware that can use this API and there
- are no applications actually implementing this API.
-
- The vtx support still reserves minors 192-223 and we would really
- like to reuse those for upcoming new functionality. In the unlikely
- event that new hardware appears that wants to use the functionality
- provided by the vtx API, then that functionality should be build
- around the sliced VBI API instead.
- Who: Hans Verkuil <hverkuil@xs4all.nl>
-
----------------------------
What: IRQF_DISABLED
----------------------------
-What: old ieee1394 subsystem (CONFIG_IEEE1394)
-When: 2.6.37
-Files: drivers/ieee1394/ except init_ohci1394_dma.c
-Why: superseded by drivers/firewire/ (CONFIG_FIREWIRE) which offers more
- features, better performance, and better security, all with smaller
- and more modern code base
-Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
-
-----------------------------
-
What: The acpi_sleep=s4_nonvs command line option
When: 2.6.37
Files: arch/x86/kernel/acpi/sleep.c
----------------------------
+What: namespace cgroup (ns_cgroup)
+When: 2.6.38
+Why: The ns_cgroup leads to some problems:
+ * cgroup creation is out-of-control
+ * cgroup name can conflict when pids are looping
+ * it is not possible to have a single process handling
+ a lot of namespaces without falling in a exponential creation time
+ * we may want to create a namespace without creating a cgroup
+
+ The ns_cgroup is replaced by a compatibility flag 'clone_children',
+ where a newly created cgroup will copy the parent cgroup values.
+ The userspace has to manually create a cgroup and add a task to
+ the 'tasks' file.
+Who: Daniel Lezcano <daniel.lezcano@free.fr>
+
+----------------------------
+
+What: iwlwifi disable_hw_scan module parameters
+When: 2.6.40
+Why: Hareware scan is the prefer method for iwlwifi devices for
+ scanning operation. Remove software scan support for all the
+ iwlwifi devices.
+
+Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
+
+----------------------------
+
+What: access to nfsd auth cache through sys_nfsservctl or '.' files
+ in the 'nfsd' filesystem.
+When: 2.6.40
+Why: This is a legacy interface which have been replaced by a more
+ dynamic cache. Continuing to maintain this interface is an
+ unnecessary burden.
+Who: NeilBrown <neilb@suse.de>
+
+----------------------------
.bus_id = 0, /* Must match with the camera ID */
.board_info = &pcm037_i2c_camera[1],
.i2c_adapter_id = 2,
- .module_name = "mt9v022",
};
static struct soc_camera_link iclink_mt9t031 = {
.power = pcm037_camera_power,
.board_info = &pcm037_i2c_camera[0],
.i2c_adapter_id = 2,
- .module_name = "mt9t031",
};
static struct i2c_board_info pcm037_i2c_devices[] = {
MACHINE_START(PCM037, "Phytec Phycore pcm037")
/* Maintainer: Pengutronix */
- .phys_io = MX31_AIPS1_BASE_ADDR,
- .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31_map_io,
.init_irq = mx31_init_irq,
#include <mach/pxafb.h>
#include <mach/ohci.h>
#include <mach/mmc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <plat/i2c.h>
#include <mach/camera.h>
#include <mach/pxa2xx_spi.h>
.power = em_x270_sensor_power,
.board_info = &em_x270_i2c_cam_info[0],
.i2c_adapter_id = 0,
- .module_name = "mt9m111",
};
static struct platform_device em_x270_camera = {
MACHINE_START(EM_X270, "Compulab EM-X270")
.boot_params = 0xa0000100,
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
MACHINE_START(EXEDA, "Compulab eXeda")
.boot_params = 0xa0000100,
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = pxa_map_io,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
#include <mach/ohci.h>
#include <plat/i2c.h>
#include <mach/hardware.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/camera.h>
#include "devices.h"
#include "generic.h"
+#define EZX_NR_IRQS (IRQ_BOARD_START + 24)
+
#define GPIO12_A780_FLIP_LID 12
#define GPIO15_A1200_FLIP_LID 15
#define GPIO15_A910_FLIP_LID 15
.flags = SOCAM_SENSOR_INVERT_PCLK,
.i2c_adapter_id = 0,
.board_info = &a780_camera_i2c_board_info,
- .module_name = "mt9m111",
.power = a780_camera_power,
.reset = a780_camera_reset,
};
}
MACHINE_START(EZX_A780, "Motorola EZX A780")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = a780_init,
}
MACHINE_START(EZX_E680, "Motorola EZX E680")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = e680_init,
}
MACHINE_START(EZX_A1200, "Motorola EZX A1200")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = a1200_init,
.bus_id = 0,
.i2c_adapter_id = 0,
.board_info = &a910_camera_i2c_board_info,
- .module_name = "mt9m111",
.power = a910_camera_power,
.reset = a910_camera_reset,
};
}
MACHINE_START(EZX_A910, "Motorola EZX A910")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = a910_init,
}
MACHINE_START(EZX_E6, "Motorola EZX E6")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = e6_init,
}
MACHINE_START(EZX_E2, "Motorola EZX E2")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = pxa_map_io,
+ .nr_irqs = EZX_NR_IRQS,
.init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
.init_machine = e2_init,
#include <mach/pxa27x.h>
#include <mach/regs-rtc.h>
-#include <mach/pxa27x_keypad.h>
+#include <plat/pxa27x_keypad.h>
#include <mach/pxafb.h>
#include <mach/mmc.h>
#include <mach/udc.h>
.bus_id = 0, /* Match id in pxa27x_device_camera in device.c */
.board_info = &mioa701_i2c_devices[0],
.i2c_adapter_id = 0,
- .module_name = "mt9m111",
};
struct i2c_pxa_platform_data i2c_pdata = {
}
MACHINE_START(MIOA701, "MIO A701")
- .phys_io = 0x40000000,
- .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.boot_params = 0xa0000100,
.map_io = &pxa_map_io,
.init_irq = &pxa27x_init_irq,
.bus_id = 1,
.power = tw9910_power,
.board_info = &i2c_camera[0],
- .module_name = "tw9910",
.priv = &tw9910_info,
};
.power = mt9t112_power1,
.bus_id = 0,
.board_info = &i2c_camera[1],
- .module_name = "mt9t112",
.priv = &mt9t112_info1,
};
.power = mt9t112_power2,
.bus_id = 1,
.board_info = &i2c_camera[2],
- .module_name = "mt9t112",
.priv = &mt9t112_info2,
};
.flags = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
.board_info = &ak8813,
.i2c_adap = 0,
- .module_name = "ak881x",
};
static struct resource sh_vou_resources[] = {
/* set SPU2 clock to 83.4 MHz */
clk = clk_get(NULL, "spu_clk");
- if (clk) {
+ if (!IS_ERR(clk)) {
clk_set_rate(clk, clk_round_rate(clk, 83333333));
clk_put(clk);
}
/* change parent of FSI B */
clk = clk_get(NULL, "fsib_clk");
- if (clk) {
+ if (!IS_ERR(clk)) {
clk_register(&fsimckb_clk);
clk_set_parent(clk, &fsimckb_clk);
clk_set_rate(clk, 11000);
/* set VPU clock to 166 MHz */
clk = clk_get(NULL, "vpu_clk");
- if (clk) {
+ if (!IS_ERR(clk)) {
clk_set_rate(clk, clk_round_rate(clk, 166000000));
clk_put(clk);
}
/*
* imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD
*
- * Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com>
+ * Copyright(C) 2010 Jarod Wilson <jarod@wilsonet.com>
* Portions based on the original lirc_imon driver,
* Copyright(C) 2004 Venky Raju(dev@venky.ws)
*
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+ #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#define MOD_AUTHOR "Jarod Wilson <jarod@wilsonet.com>"
#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display"
#define MOD_NAME "imon"
- #define MOD_VERSION "0.9.1"
+ #define MOD_VERSION "0.9.2"
#define DISPLAY_MINOR_BASE 144
#define DEVICE_NAME "lcd%d"
u16 vendor; /* usb vendor ID */
u16 product; /* usb product ID */
- struct input_dev *idev; /* input device for remote */
+ struct input_dev *rdev; /* input device for remote */
+ struct input_dev *idev; /* input device for panel & IR mouse */
struct input_dev *touch; /* input device for touchscreen */
+ spinlock_t kc_lock; /* make sure we get keycodes right */
u32 kc; /* current input keycode */
u32 last_keycode; /* last reported input keycode */
+ u32 rc_scancode; /* the computed remote scancode */
+ u8 rc_toggle; /* the computed remote toggle bit */
u64 ir_type; /* iMON or MCE (RC6) IR protocol? */
- u8 mce_toggle_bit; /* last mce toggle bit */
bool release_code; /* some keys send a release code */
u8 display_type; /* store the display type */
bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */
+ char name_rdev[128]; /* rc input device name */
+ char phys_rdev[64]; /* rc input device phys path */
+
char name_idev[128]; /* input device name */
char phys_idev[64]; /* input device phys path */
- struct timer_list itimer; /* input device timer, need for rc6 */
char name_touch[128]; /* touch screen name */
char phys_touch[64]; /* touch screen phys path */
.owner = THIS_MODULE,
.open = &display_open,
.write = &vfd_write,
- .release = &display_close
+ .release = &display_close,
+ .llseek = noop_llseek,
};
/* lcd character device file operations */
.owner = THIS_MODULE,
.open = &display_open,
.write = &lcd_write,
- .release = &display_close
+ .release = &display_close,
+ .llseek = noop_llseek,
};
enum {
{ 0x000100000000ffeell, KEY_VOLUMEUP },
{ 0x010000000000ffeell, KEY_VOLUMEDOWN },
{ 0x000000000100ffeell, KEY_MUTE },
+ /* 0xffdc iMON MCE VFD */
+ { 0x00010000ffffffeell, KEY_VOLUMEUP },
+ { 0x01000000ffffffeell, KEY_VOLUMEDOWN },
/* iMON Knob values */
{ 0x000100ffffffffeell, KEY_VOLUMEUP },
{ 0x010000ffffffffeell, KEY_VOLUMEDOWN },
static bool debug;
module_param(debug, bool, S_IRUGO | S_IWUSR);
- MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
+ MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
static int display_type;
subminor = iminor(inode);
interface = usb_find_interface(&imon_driver, subminor);
if (!interface) {
- err("%s: could not find interface for minor %d",
- __func__, subminor);
+ pr_err("could not find interface for minor %d\n", subminor);
retval = -ENODEV;
goto exit;
}
ictx = usb_get_intfdata(interface);
if (!ictx) {
- err("%s: no context found for minor %d", __func__, subminor);
+ pr_err("no context found for minor %d\n", subminor);
retval = -ENODEV;
goto exit;
}
mutex_lock(&ictx->lock);
if (!ictx->display_supported) {
- err("%s: display not supported by device", __func__);
+ pr_err("display not supported by device\n");
retval = -ENODEV;
} else if (ictx->display_isopen) {
- err("%s: display port is already open", __func__);
+ pr_err("display port is already open\n");
retval = -EBUSY;
} else {
ictx->display_isopen = true;
ictx = file->private_data;
if (!ictx) {
- err("%s: no context for device", __func__);
+ pr_err("no context for device\n");
return -ENODEV;
}
mutex_lock(&ictx->lock);
if (!ictx->display_supported) {
- err("%s: display not supported by device", __func__);
+ pr_err("display not supported by device\n");
retval = -ENODEV;
} else if (!ictx->display_isopen) {
- err("%s: display is not open", __func__);
+ pr_err("display is not open\n");
retval = -EIO;
} else {
ictx->display_isopen = false;
if (retval) {
ictx->tx.busy = false;
smp_rmb(); /* ensure later readers know we're not busy */
- err("%s: error submitting urb(%d)", __func__, retval);
+ pr_err("error submitting urb(%d)\n", retval);
} else {
/* Wait for transmission to complete (or abort) */
mutex_unlock(&ictx->lock);
retval = wait_for_completion_interruptible(
&ictx->tx.finished);
if (retval)
- err("%s: task interrupted", __func__);
+ pr_err("task interrupted\n");
mutex_lock(&ictx->lock);
retval = ictx->tx.status;
if (retval)
- err("%s: packet tx failed (%d)", __func__, retval);
+ pr_err("packet tx failed (%d)\n", retval);
}
kfree(control_req);
0x00, 0x00, 0x00, 0x20 };
if (!ictx) {
- err("%s: no context for device", __func__);
+ pr_err("no context for device\n");
return -ENODEV;
}
if (!ictx->dev_present_intf0) {
- err("%s: no iMON device present", __func__);
+ pr_err("no iMON device present\n");
return -ENODEV;
}
int i;
if (!ictx) {
- err("%s: no context for device", __func__);
+ pr_err("no context for device\n");
return -ENODEV;
}
memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8);
retval = send_packet(ictx);
if (retval) {
- err("%s: send_packet failed for packet %d",
- __func__, i);
+ pr_err("send_packet failed for packet %d\n", i);
break;
}
}
NULL
};
- static struct attribute_group imon_display_attribute_group = {
+ static struct attribute_group imon_display_attr_group = {
.attrs = imon_display_sysfs_entries
};
NULL
};
- static struct attribute_group imon_rf_attribute_group = {
+ static struct attribute_group imon_rf_attr_group = {
.attrs = imon_rf_sysfs_entries
};
ictx = file->private_data;
if (!ictx) {
- err("%s: no context for device", __func__);
+ pr_err("no context for device\n");
return -ENODEV;
}
mutex_lock(&ictx->lock);
if (!ictx->dev_present_intf0) {
- err("%s: no iMON device present", __func__);
+ pr_err("no iMON device present\n");
retval = -ENODEV;
goto exit;
}
if (n_bytes <= 0 || n_bytes > 32) {
- err("%s: invalid payload size", __func__);
+ pr_err("invalid payload size\n");
retval = -EINVAL;
goto exit;
}
retval = send_packet(ictx);
if (retval) {
- err("%s: send packet failed for packet #%d",
- __func__, seq/2);
+ pr_err("send packet failed for packet #%d\n", seq / 2);
goto exit;
} else {
seq += 2;
ictx->usb_tx_buf[7] = (unsigned char) seq;
retval = send_packet(ictx);
if (retval)
- err("%s: send packet failed for packet #%d",
- __func__, seq / 2);
+ pr_err("send packet failed for packet #%d\n", seq / 2);
exit:
mutex_unlock(&ictx->lock);
ictx = file->private_data;
if (!ictx) {
- err("%s: no context for device", __func__);
+ pr_err("no context for device\n");
return -ENODEV;
}
mutex_lock(&ictx->lock);
if (!ictx->display_supported) {
- err("%s: no iMON display present", __func__);
+ pr_err("no iMON display present\n");
retval = -ENODEV;
goto exit;
}
if (n_bytes != 8) {
- err("%s: invalid payload size: %d (expecting 8)",
- __func__, (int) n_bytes);
+ pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes);
retval = -EINVAL;
goto exit;
}
retval = send_packet(ictx);
if (retval) {
- err("%s: send packet failed!", __func__);
+ pr_err("send packet failed!\n");
goto exit;
} else {
dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
complete(&ictx->tx.finished);
}
- /**
- * mce/rc6 keypresses have no distinct release code, use timer
- */
- static void imon_mce_timeout(unsigned long data)
- {
- struct imon_context *ictx = (struct imon_context *)data;
-
- input_report_key(ictx->idev, ictx->last_keycode, 0);
- input_sync(ictx->idev);
- }
-
/**
* report touchscreen input
*/
dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
ir_proto_packet[0] = 0x01;
pad_mouse = false;
- init_timer(&ictx->itimer);
- ictx->itimer.data = (unsigned long)ictx;
- ictx->itimer.function = imon_mce_timeout;
break;
case IR_TYPE_UNKNOWN:
case IR_TYPE_OTHER:
dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
- if (pad_stabilize)
+ if (pad_stabilize && !nomouse)
pad_mouse = true;
else {
dev_dbg(dev, "PAD stabilize functionality disabled\n");
default:
dev_warn(dev, "Unsupported IR protocol specified, overriding "
"to iMON IR protocol\n");
- if (pad_stabilize)
+ if (pad_stabilize && !nomouse)
pad_mouse = true;
else {
dev_dbg(dev, "PAD stabilize functionality disabled\n");
return result;
}
- static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code)
+ static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode)
{
- u32 scancode = be32_to_cpu(hw_code);
u32 keycode;
u32 release;
bool is_release_code = false;
/* Look for the initial press of a button */
- keycode = ir_g_keycode_from_table(ictx->idev, scancode);
+ keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
+ ictx->rc_toggle = 0x0;
+ ictx->rc_scancode = scancode;
/* Look for the release of a button */
if (keycode == KEY_RESERVED) {
release = scancode & ~0x4000;
- keycode = ir_g_keycode_from_table(ictx->idev, release);
+ keycode = ir_g_keycode_from_table(ictx->rdev, release);
if (keycode != KEY_RESERVED)
is_release_code = true;
}
return keycode;
}
- static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code)
+ static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode)
{
- u32 scancode = be32_to_cpu(hw_code);
u32 keycode;
#define MCE_KEY_MASK 0x7000
* but we can't or them into all codes, as some keys are decoded in
* a different way w/o the same use of the toggle bit...
*/
- if ((scancode >> 24) & 0x80)
+ if (scancode & 0x80000000)
scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
- keycode = ir_g_keycode_from_table(ictx->idev, scancode);
+ ictx->rc_scancode = scancode;
+ keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
+
+ /* not used in mce mode, but make sure we know its false */
+ ictx->release_code = false;
return keycode;
}
- static u32 imon_panel_key_lookup(u64 hw_code)
+ static u32 imon_panel_key_lookup(u64 code)
{
int i;
- u64 code = be64_to_cpu(hw_code);
u32 keycode = KEY_RESERVED;
for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
u8 right_shift = 1;
bool mouse_input = true;
int dir = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ictx->kc_lock, flags);
/* newer iMON device PAD or mouse button */
if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) {
} else
mouse_input = false;
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
if (mouse_input) {
dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
buf[1] >> right_shift & 0x1);
}
input_sync(ictx->idev);
+ spin_lock_irqsave(&ictx->kc_lock, flags);
ictx->last_keycode = ictx->kc;
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
}
return mouse_input;
int dir = 0;
char rel_x = 0x00, rel_y = 0x00;
u16 timeout, threshold;
- u64 temp_key;
- u32 remote_key;
+ u32 scancode = KEY_RESERVED;
+ unsigned long flags;
/*
* The imon directional pad functions more like a touchpad. Bytes 3 & 4
dir = stabilize((int)rel_x, (int)rel_y,
timeout, threshold);
if (!dir) {
+ spin_lock_irqsave(&ictx->kc_lock,
+ flags);
ictx->kc = KEY_UNKNOWN;
+ spin_unlock_irqrestore(&ictx->kc_lock,
+ flags);
return;
}
buf[2] = dir & 0xFF;
buf[3] = (dir >> 8) & 0xFF;
- memcpy(&temp_key, buf, sizeof(temp_key));
- remote_key = (u32) (le64_to_cpu(temp_key)
- & 0xffffffff);
- ictx->kc = imon_remote_key_lookup(ictx,
- remote_key);
+ scancode = be32_to_cpu(*((u32 *)buf));
}
} else {
+ /*
+ * Hack alert: instead of using keycodes, we have
+ * to use hard-coded scancodes here...
+ */
if (abs(rel_y) > abs(rel_x)) {
buf[2] = (rel_y > 0) ? 0x7F : 0x80;
buf[3] = 0;
- ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP;
+ if (rel_y > 0)
+ scancode = 0x01007f00; /* KEY_DOWN */
+ else
+ scancode = 0x01008000; /* KEY_UP */
} else {
buf[2] = 0;
buf[3] = (rel_x > 0) ? 0x7F : 0x80;
- ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
+ if (rel_x > 0)
+ scancode = 0x0100007f; /* KEY_RIGHT */
+ else
+ scancode = 0x01000080; /* KEY_LEFT */
}
}
dir = stabilize((int)rel_x, (int)rel_y,
timeout, threshold);
if (!dir) {
+ spin_lock_irqsave(&ictx->kc_lock, flags);
ictx->kc = KEY_UNKNOWN;
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
return;
}
buf[2] = dir & 0xFF;
buf[3] = (dir >> 8) & 0xFF;
- memcpy(&temp_key, buf, sizeof(temp_key));
- remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
- ictx->kc = imon_remote_key_lookup(ictx, remote_key);
+ scancode = be32_to_cpu(*((u32 *)buf));
} else {
+ /*
+ * Hack alert: instead of using keycodes, we have
+ * to use hard-coded scancodes here...
+ */
if (abs(rel_y) > abs(rel_x)) {
buf[2] = (rel_y > 0) ? 0x7F : 0x80;
buf[3] = 0;
- ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP;
+ if (rel_y > 0)
+ scancode = 0x01007f00; /* KEY_DOWN */
+ else
+ scancode = 0x01008000; /* KEY_UP */
} else {
buf[2] = 0;
buf[3] = (rel_x > 0) ? 0x7F : 0x80;
- ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
+ if (rel_x > 0)
+ scancode = 0x0100007f; /* KEY_RIGHT */
+ else
+ scancode = 0x01000080; /* KEY_LEFT */
}
}
}
+
+ if (scancode) {
+ spin_lock_irqsave(&ictx->kc_lock, flags);
+ ictx->kc = imon_remote_key_lookup(ictx, scancode);
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
+ }
}
+ /**
+ * figure out if these is a press or a release. We don't actually
+ * care about repeats, as those will be auto-generated within the IR
+ * subsystem for repeating scancodes.
+ */
static int imon_parse_press_type(struct imon_context *ictx,
unsigned char *buf, u8 ktype)
{
int press_type = 0;
- int rep_delay = ictx->idev->rep[REP_DELAY];
- int rep_period = ictx->idev->rep[REP_PERIOD];
+ unsigned long flags;
+
+ spin_lock_irqsave(&ictx->kc_lock, flags);
/* key release of 0x02XXXXXX key */
if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00)
buf[2] == 0x81 && buf[3] == 0xb7)
ictx->kc = ictx->last_keycode;
- /* mce-specific button handling */
+ /* mce-specific button handling, no keyup events */
else if (ktype == IMON_KEY_MCE) {
- /* initial press */
- if (ictx->kc != ictx->last_keycode
- || buf[2] != ictx->mce_toggle_bit) {
- ictx->last_keycode = ictx->kc;
- ictx->mce_toggle_bit = buf[2];
- press_type = 1;
- mod_timer(&ictx->itimer,
- jiffies + msecs_to_jiffies(rep_delay));
- /* repeat */
- } else {
- press_type = 2;
- mod_timer(&ictx->itimer,
- jiffies + msecs_to_jiffies(rep_period));
- }
+ ictx->rc_toggle = buf[2];
+ press_type = 1;
/* incoherent or irrelevant data */
} else if (ictx->kc == KEY_RESERVED)
else
press_type = 1;
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
return press_type;
}
int len = urb->actual_length;
unsigned char *buf = urb->transfer_buffer;
struct device *dev = ictx->dev;
+ unsigned long flags;
u32 kc;
bool norelease = false;
int i;
- u64 temp_key;
- u64 panel_key = 0;
- u32 remote_key = 0;
- struct input_dev *idev = NULL;
+ u64 scancode;
+ struct input_dev *rdev = NULL;
+ struct ir_input_dev *irdev = NULL;
int press_type = 0;
int msec;
struct timeval t;
static struct timeval prev_time = { 0, 0 };
- u8 ktype = IMON_KEY_IMON;
+ u8 ktype;
- idev = ictx->idev;
+ rdev = ictx->rdev;
+ irdev = input_get_drvdata(rdev);
/* filter out junk data on the older 0xffdc imon devices */
if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
return;
/* Figure out what key was pressed */
- memcpy(&temp_key, buf, sizeof(temp_key));
if (len == 8 && buf[7] == 0xee) {
+ scancode = be64_to_cpu(*((u64 *)buf));
ktype = IMON_KEY_PANEL;
- panel_key = le64_to_cpu(temp_key);
- kc = imon_panel_key_lookup(panel_key);
+ kc = imon_panel_key_lookup(scancode);
} else {
- remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
+ scancode = be32_to_cpu(*((u32 *)buf));
if (ictx->ir_type == IR_TYPE_RC6) {
+ ktype = IMON_KEY_IMON;
if (buf[0] == 0x80)
ktype = IMON_KEY_MCE;
- kc = imon_mce_key_lookup(ictx, remote_key);
- } else
- kc = imon_remote_key_lookup(ictx, remote_key);
+ kc = imon_mce_key_lookup(ictx, scancode);
+ } else {
+ ktype = IMON_KEY_IMON;
+ kc = imon_remote_key_lookup(ictx, scancode);
+ }
}
+ spin_lock_irqsave(&ictx->kc_lock, flags);
/* keyboard/mouse mode toggle button */
if (kc == KEY_KEYBOARD && !ictx->release_code) {
ictx->last_keycode = kc;
ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
dev_dbg(dev, "toggling to %s mode\n",
ictx->pad_mouse ? "mouse" : "keyboard");
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
return;
} else {
ictx->pad_mouse = 0;
}
ictx->kc = kc;
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
/* send touchscreen events through input subsystem if touchpad data */
if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
buf[7] == 0x86) {
imon_touch_event(ictx, buf);
+ return;
/* look for mouse events with pad in mouse mode */
} else if (ictx->pad_mouse) {
if (press_type < 0)
goto not_input_data;
+ spin_lock_irqsave(&ictx->kc_lock, flags);
if (ictx->kc == KEY_UNKNOWN)
goto unknown_key;
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
+
+ if (ktype != IMON_KEY_PANEL) {
+ if (press_type == 0)
+ ir_keyup(irdev);
+ else {
+ ir_keydown(rdev, ictx->rc_scancode, ictx->rc_toggle);
+ spin_lock_irqsave(&ictx->kc_lock, flags);
+ ictx->last_keycode = ictx->kc;
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
+ }
+ return;
+ }
- /* KEY_MUTE repeats from MCE and knob need to be suppressed */
- if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode)
- && (buf[7] == 0xee || ktype == IMON_KEY_MCE)) {
+ /* Only panel type events left to process now */
+ spin_lock_irqsave(&ictx->kc_lock, flags);
+
+ /* KEY_MUTE repeats from knob need to be suppressed */
+ if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
do_gettimeofday(&t);
msec = tv2int(&t, &prev_time);
prev_time = t;
- if (msec < idev->rep[REP_DELAY])
+ if (msec < ictx->idev->rep[REP_DELAY]) {
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
return;
+ }
}
+ kc = ictx->kc;
- input_report_key(idev, ictx->kc, press_type);
- input_sync(idev);
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
- /* panel keys and some remote keys don't generate a release */
- if (panel_key || norelease) {
- input_report_key(idev, ictx->kc, 0);
- input_sync(idev);
- }
+ input_report_key(ictx->idev, kc, press_type);
+ input_sync(ictx->idev);
- ictx->last_keycode = ictx->kc;
+ /* panel keys don't generate a release */
+ input_report_key(ictx->idev, kc, 0);
+ input_sync(ictx->idev);
+
+ ictx->last_keycode = kc;
return;
unknown_key:
+ spin_unlock_irqrestore(&ictx->kc_lock, flags);
dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
- (panel_key ? be64_to_cpu(panel_key) :
- be32_to_cpu(remote_key)));
+ (long long)scancode);
return;
not_input_data:
usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
}
+ /*
+ * The 0x15c2:0xffdc device ID was used for umpteen different imon
+ * devices, and all of them constantly spew interrupts, even when there
+ * is no actual data to report. However, byte 6 of this buffer looks like
+ * its unique across device variants, so we're trying to key off that to
+ * figure out which display type (if any) and what IR protocol the device
+ * actually supports. These devices have their IR protocol hard-coded into
+ * their firmware, they can't be changed on the fly like the newer hardware.
+ */
+ static void imon_get_ffdc_type(struct imon_context *ictx)
+ {
+ u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
+ u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
+ u64 allowed_protos = IR_TYPE_OTHER;
+
+ switch (ffdc_cfg_byte) {
+ /* iMON Knob, no display, iMON IR + vol knob */
+ case 0x21:
+ dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
+ ictx->display_supported = false;
+ break;
+ /* iMON 2.4G LT (usb stick), no display, iMON RF */
+ case 0x4e:
+ dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
+ ictx->display_supported = false;
+ ictx->rf_device = true;
+ break;
+ /* iMON VFD, no IR (does have vol knob tho) */
+ case 0x35:
+ dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
+ detected_display_type = IMON_DISPLAY_TYPE_VFD;
+ break;
+ /* iMON VFD, iMON IR */
+ case 0x24:
+ case 0x85:
+ dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR");
+ detected_display_type = IMON_DISPLAY_TYPE_VFD;
+ break;
+ /* iMON VFD, MCE IR */
+ case 0x9e:
+ dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
+ detected_display_type = IMON_DISPLAY_TYPE_VFD;
+ allowed_protos = IR_TYPE_RC6;
+ break;
+ /* iMON LCD, MCE IR */
+ case 0x9f:
+ dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
+ detected_display_type = IMON_DISPLAY_TYPE_LCD;
+ allowed_protos = IR_TYPE_RC6;
+ break;
+ default:
+ dev_info(ictx->dev, "Unknown 0xffdc device, "
+ "defaulting to VFD and iMON IR");
+ detected_display_type = IMON_DISPLAY_TYPE_VFD;
+ break;
+ }
+
+ printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
+
+ ictx->display_type = detected_display_type;
+ ictx->props->allowed_protos = allowed_protos;
+ ictx->ir_type = allowed_protos;
+ }
+
+ static void imon_set_display_type(struct imon_context *ictx)
+ {
+ u8 configured_display_type = IMON_DISPLAY_TYPE_VFD;
+
+ /*
+ * Try to auto-detect the type of display if the user hasn't set
+ * it by hand via the display_type modparam. Default is VFD.
+ */
+
+ if (display_type == IMON_DISPLAY_TYPE_AUTO) {
+ switch (ictx->product) {
+ case 0xffdc:
+ /* set in imon_get_ffdc_type() */
+ configured_display_type = ictx->display_type;
+ break;
+ case 0x0034:
+ case 0x0035:
+ configured_display_type = IMON_DISPLAY_TYPE_VGA;
+ break;
+ case 0x0038:
+ case 0x0039:
+ case 0x0045:
+ configured_display_type = IMON_DISPLAY_TYPE_LCD;
+ break;
+ case 0x003c:
+ case 0x0041:
+ case 0x0042:
+ case 0x0043:
+ configured_display_type = IMON_DISPLAY_TYPE_NONE;
+ ictx->display_supported = false;
+ break;
+ case 0x0036:
+ case 0x0044:
+ default:
+ configured_display_type = IMON_DISPLAY_TYPE_VFD;
+ break;
+ }
+ } else {
+ configured_display_type = display_type;
+ if (display_type == IMON_DISPLAY_TYPE_NONE)
+ ictx->display_supported = false;
+ else
+ ictx->display_supported = true;
+ dev_info(ictx->dev, "%s: overriding display type to %d via "
+ "modparam\n", __func__, display_type);
+ }
+
+ ictx->display_type = configured_display_type;
+ }
+
+ static struct input_dev *imon_init_rdev(struct imon_context *ictx)
+ {
+ struct input_dev *rdev;
+ struct ir_dev_props *props;
+ int ret;
+ char *ir_codes = NULL;
+ const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x88 };
+
+ rdev = input_allocate_device();
+ props = kzalloc(sizeof(*props), GFP_KERNEL);
+ if (!rdev || !props) {
+ dev_err(ictx->dev, "remote control dev allocation failed\n");
+ goto out;
+ }
+
+ snprintf(ictx->name_rdev, sizeof(ictx->name_rdev),
+ "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
+ usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev,
+ sizeof(ictx->phys_rdev));
+ strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev));
+
+ rdev->name = ictx->name_rdev;
+ rdev->phys = ictx->phys_rdev;
+ usb_to_input_id(ictx->usbdev_intf0, &rdev->id);
+ rdev->dev.parent = ictx->dev;
+ rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+ input_set_drvdata(rdev, ictx);
+
+ props->priv = ictx;
+ props->driver_type = RC_DRIVER_SCANCODE;
+ props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */
+ props->change_protocol = imon_ir_change_protocol;
+ ictx->props = props;
+
+ /* Enable front-panel buttons and/or knobs */
+ memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet));
+ ret = send_packet(ictx);
+ /* Not fatal, but warn about it */
+ if (ret)
+ dev_info(ictx->dev, "panel buttons/knobs setup failed\n");
+
+ if (ictx->product == 0xffdc)
+ imon_get_ffdc_type(ictx);
+
+ imon_set_display_type(ictx);
+
+ if (ictx->ir_type == IR_TYPE_RC6)
+ ir_codes = RC_MAP_IMON_MCE;
+ else
+ ir_codes = RC_MAP_IMON_PAD;
+
+ ret = ir_input_register(rdev, ir_codes, props, MOD_NAME);
+ if (ret < 0) {
+ dev_err(ictx->dev, "remote input dev register failed\n");
+ goto out;
+ }
+
+ return rdev;
+
+ out:
+ kfree(props);
+ input_free_device(rdev);
+ return NULL;
+ }
+
static struct input_dev *imon_init_idev(struct imon_context *ictx)
{
struct input_dev *idev;
- struct ir_dev_props *props;
int ret, i;
idev = input_allocate_device();
if (!idev) {
- dev_err(ictx->dev, "remote input dev allocation failed\n");
- goto idev_alloc_failed;
- }
-
- props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
- if (!props) {
- dev_err(ictx->dev, "remote ir dev props allocation failed\n");
- goto props_alloc_failed;
+ dev_err(ictx->dev, "input dev allocation failed\n");
+ goto out;
}
snprintf(ictx->name_idev, sizeof(ictx->name_idev),
- "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
+ "iMON Panel, Knob and Mouse(%04x:%04x)",
+ ictx->vendor, ictx->product);
idev->name = ictx->name_idev;
usb_make_path(ictx->usbdev_intf0, ictx->phys_idev,
sizeof(ictx->phys_idev));
- strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev));
+ strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev));
idev->phys = ictx->phys_idev;
idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL);
__set_bit(kc, idev->keybit);
}
- props->priv = ictx;
- props->driver_type = RC_DRIVER_SCANCODE;
- /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */
- props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6;
- props->change_protocol = imon_ir_change_protocol;
- ictx->props = props;
-
usb_to_input_id(ictx->usbdev_intf0, &idev->id);
idev->dev.parent = ictx->dev;
+ input_set_drvdata(idev, ictx);
- ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
+ ret = input_register_device(idev);
if (ret < 0) {
- dev_err(ictx->dev, "remote input dev register failed\n");
- goto idev_register_failed;
+ dev_err(ictx->dev, "input dev register failed\n");
+ goto out;
}
return idev;
- idev_register_failed:
- kfree(props);
- props_alloc_failed:
+ out:
input_free_device(idev);
- idev_alloc_failed:
-
return NULL;
}
usb_make_path(ictx->usbdev_intf1, ictx->phys_touch,
sizeof(ictx->phys_touch));
- strlcat(ictx->phys_touch, "/input1", sizeof(ictx->phys_touch));
+ strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch));
touch->phys = ictx->phys_touch;
touch->evbit[0] =
/* Input endpoint is mandatory */
if (!ir_ep_found)
- err("%s: no valid input (IR) endpoint found.", __func__);
+ pr_err("no valid input (IR) endpoint found\n");
ictx->tx_control = tx_control;
}
mutex_init(&ictx->lock);
+ spin_lock_init(&ictx->kc_lock);
mutex_lock(&ictx->lock);
goto idev_setup_failed;
}
+ ictx->rdev = imon_init_rdev(ictx);
+ if (!ictx->rdev) {
+ dev_err(dev, "%s: rc device setup failed\n", __func__);
+ goto rdev_setup_failed;
+ }
+
usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
usb_rcvintpipe(ictx->usbdev_intf0,
ictx->rx_endpoint_intf0->bEndpointAddress),
ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL);
if (ret) {
- err("%s: usb_submit_urb failed for intf0 (%d)",
- __func__, ret);
+ pr_err("usb_submit_urb failed for intf0 (%d)\n", ret);
goto urb_submit_failed;
}
return ictx;
urb_submit_failed:
- ir_input_unregister(ictx->idev);
+ ir_input_unregister(ictx->rdev);
+ rdev_setup_failed:
+ input_unregister_device(ictx->idev);
idev_setup_failed:
find_endpoint_failed:
mutex_unlock(&ictx->lock);
rx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!rx_urb) {
- err("%s: usb_alloc_urb failed for IR urb", __func__);
+ pr_err("usb_alloc_urb failed for IR urb\n");
goto rx_urb_alloc_failed;
}
ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL);
if (ret) {
- err("%s: usb_submit_urb failed for intf1 (%d)",
- __func__, ret);
+ pr_err("usb_submit_urb failed for intf1 (%d)\n", ret);
goto urb_submit_failed;
}
return NULL;
}
- /*
- * The 0x15c2:0xffdc device ID was used for umpteen different imon
- * devices, and all of them constantly spew interrupts, even when there
- * is no actual data to report. However, byte 6 of this buffer looks like
- * its unique across device variants, so we're trying to key off that to
- * figure out which display type (if any) and what IR protocol the device
- * actually supports. These devices have their IR protocol hard-coded into
- * their firmware, they can't be changed on the fly like the newer hardware.
- */
- static void imon_get_ffdc_type(struct imon_context *ictx)
- {
- u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
- u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
- u64 allowed_protos = IR_TYPE_OTHER;
-
- switch (ffdc_cfg_byte) {
- /* iMON Knob, no display, iMON IR + vol knob */
- case 0x21:
- dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
- ictx->display_supported = false;
- break;
- /* iMON 2.4G LT (usb stick), no display, iMON RF */
- case 0x4e:
- dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
- ictx->display_supported = false;
- ictx->rf_device = true;
- break;
- /* iMON VFD, no IR (does have vol knob tho) */
- case 0x35:
- dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
- detected_display_type = IMON_DISPLAY_TYPE_VFD;
- break;
- /* iMON VFD, iMON IR */
- case 0x24:
- case 0x85:
- dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR");
- detected_display_type = IMON_DISPLAY_TYPE_VFD;
- break;
- /* iMON LCD, MCE IR */
- case 0x9e:
- case 0x9f:
- dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
- detected_display_type = IMON_DISPLAY_TYPE_LCD;
- allowed_protos = IR_TYPE_RC6;
- break;
- default:
- dev_info(ictx->dev, "Unknown 0xffdc device, "
- "defaulting to VFD and iMON IR");
- detected_display_type = IMON_DISPLAY_TYPE_VFD;
- break;
- }
-
- printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
-
- ictx->display_type = detected_display_type;
- ictx->props->allowed_protos = allowed_protos;
- ictx->ir_type = allowed_protos;
- }
-
- static void imon_set_display_type(struct imon_context *ictx,
- struct usb_interface *intf)
- {
- u8 configured_display_type = IMON_DISPLAY_TYPE_VFD;
-
- /*
- * Try to auto-detect the type of display if the user hasn't set
- * it by hand via the display_type modparam. Default is VFD.
- */
-
- if (display_type == IMON_DISPLAY_TYPE_AUTO) {
- switch (ictx->product) {
- case 0xffdc:
- /* set in imon_get_ffdc_type() */
- configured_display_type = ictx->display_type;
- break;
- case 0x0034:
- case 0x0035:
- configured_display_type = IMON_DISPLAY_TYPE_VGA;
- break;
- case 0x0038:
- case 0x0039:
- case 0x0045:
- configured_display_type = IMON_DISPLAY_TYPE_LCD;
- break;
- case 0x003c:
- case 0x0041:
- case 0x0042:
- case 0x0043:
- configured_display_type = IMON_DISPLAY_TYPE_NONE;
- ictx->display_supported = false;
- break;
- case 0x0036:
- case 0x0044:
- default:
- configured_display_type = IMON_DISPLAY_TYPE_VFD;
- break;
- }
- } else {
- configured_display_type = display_type;
- if (display_type == IMON_DISPLAY_TYPE_NONE)
- ictx->display_supported = false;
- else
- ictx->display_supported = true;
- dev_info(ictx->dev, "%s: overriding display type to %d via "
- "modparam\n", __func__, display_type);
- }
-
- ictx->display_type = configured_display_type;
- }
-
static void imon_init_display(struct imon_context *ictx,
struct usb_interface *intf)
{
dev_dbg(ictx->dev, "Registering iMON display with sysfs\n");
/* set up sysfs entry for built-in clock */
- ret = sysfs_create_group(&intf->dev.kobj,
- &imon_display_attribute_group);
+ ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group);
if (ret)
dev_err(ictx->dev, "Could not create display sysfs "
"entries(%d)", ret);
struct imon_context *ictx = NULL;
struct imon_context *first_if_ctx = NULL;
u16 vendor, product;
- const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x88 };
code_length = BUF_CHUNK_SIZE * 8;
if (ifnum == 0) {
ictx = imon_init_intf0(interface);
if (!ictx) {
- err("%s: failed to initialize context!\n", __func__);
+ pr_err("failed to initialize context!\n");
ret = -ENODEV;
goto fail;
}
/* this is the secondary interface on the device */
ictx = imon_init_intf1(interface, first_if_ctx);
if (!ictx) {
- err("%s: failed to attach to context!\n", __func__);
+ pr_err("failed to attach to context!\n");
ret = -ENODEV;
goto fail;
}
usb_set_intfdata(interface, ictx);
if (ifnum == 0) {
- /* Enable front-panel buttons and/or knobs */
- memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet));
- ret = send_packet(ictx);
- /* Not fatal, but warn about it */
- if (ret)
- dev_info(dev, "failed to enable panel buttons "
- "and/or knobs\n");
-
- if (product == 0xffdc)
- imon_get_ffdc_type(ictx);
-
- imon_set_display_type(ictx, interface);
-
if (product == 0xffdc && ictx->rf_device) {
sysfs_err = sysfs_create_group(&interface->dev.kobj,
- &imon_rf_attribute_group);
+ &imon_rf_attr_group);
if (sysfs_err)
- err("%s: Could not create RF sysfs entries(%d)",
- __func__, sysfs_err);
+ pr_err("Could not create RF sysfs entries(%d)\n",
+ sysfs_err);
}
if (ictx->display_supported)
imon_init_display(ictx, interface);
}
- /* set IR protocol/remote type */
- ret = imon_ir_change_protocol(ictx, ictx->ir_type);
- if (ret) {
- dev_warn(dev, "%s: failed to set IR protocol, falling back "
- "to standard iMON protocol mode\n", __func__);
- ictx->ir_type = IR_TYPE_OTHER;
- }
-
dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
"usb<%d:%d> initialized\n", vendor, product, ifnum,
usbdev->bus->busnum, usbdev->devnum);
* sysfs_remove_group is safe to call even if sysfs_create_group
* hasn't been called
*/
- sysfs_remove_group(&interface->dev.kobj,
- &imon_display_attribute_group);
- sysfs_remove_group(&interface->dev.kobj,
- &imon_rf_attribute_group);
+ sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group);
+ sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group);
usb_set_intfdata(interface, NULL);
if (ifnum == 0) {
ictx->dev_present_intf0 = false;
usb_kill_urb(ictx->rx_urb_intf0);
- ir_input_unregister(ictx->idev);
+ input_unregister_device(ictx->idev);
+ ir_input_unregister(ictx->rdev);
if (ictx->display_supported) {
if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
usb_deregister_dev(interface, &imon_lcd_class);
mutex_unlock(&ictx->lock);
if (!ictx->display_isopen)
free_imon_context(ictx);
- } else {
- if (ictx->ir_type == IR_TYPE_RC6)
- del_timer_sync(&ictx->itimer);
+ } else
mutex_unlock(&ictx->lock);
- }
mutex_unlock(&driver_lock);
rc = usb_register(&imon_driver);
if (rc) {
- err("%s: usb register failed(%d)", __func__, rc);
+ pr_err("usb register failed(%d)\n", rc);
rc = -ENODEV;
}
/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
#define IR_KEYPRESS_TIMEOUT 250
+/**
+ * ir_create_table() - initializes a scancode table
+ * @rc_tab: the ir_scancode_table to initialize
+ * @name: name to assign to the table
+ * @ir_type: ir type to assign to the new table
+ * @size: initial size of the table
+ * @return: zero on success or a negative error code
+ *
+ * This routine will initialize the ir_scancode_table and will allocate
+ * memory to hold at least the specified number elements.
+ */
+static int ir_create_table(struct ir_scancode_table *rc_tab,
+ const char *name, u64 ir_type, size_t size)
+{
+ rc_tab->name = name;
+ rc_tab->ir_type = ir_type;
+ rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
+ rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
+ rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
+ if (!rc_tab->scan)
+ return -ENOMEM;
+
+ IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+ rc_tab->size, rc_tab->alloc);
+ return 0;
+}
+
+/**
+ * ir_free_table() - frees memory allocated by a scancode table
+ * @rc_tab: the table whose mappings need to be freed
+ *
+ * This routine will free memory alloctaed for key mappings used by given
+ * scancode table.
+ */
+static void ir_free_table(struct ir_scancode_table *rc_tab)
+{
+ rc_tab->size = 0;
+ kfree(rc_tab->scan);
+ rc_tab->scan = NULL;
+}
+
/**
* ir_resize_table() - resizes a scancode table if necessary
* @rc_tab: the ir_scancode_table to resize
+ * @gfp_flags: gfp flags to use when allocating memory
* @return: zero on success or a negative error code
*
* This routine will shrink the ir_scancode_table if it has lots of
* unused entries and grow it if it is full.
*/
-static int ir_resize_table(struct ir_scancode_table *rc_tab)
+static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
{
unsigned int oldalloc = rc_tab->alloc;
unsigned int newalloc = oldalloc;
if (newalloc == oldalloc)
return 0;
- newscan = kmalloc(newalloc, GFP_ATOMIC);
+ newscan = kmalloc(newalloc, gfp_flags);
if (!newscan) {
IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
return -ENOMEM;
}
/**
- * ir_do_setkeycode() - internal function to set a keycode in the
- * scancode->keycode table
+ * ir_update_mapping() - set a keycode in the scancode->keycode table
* @dev: the struct input_dev device descriptor
- * @rc_tab: the struct ir_scancode_table to set the keycode in
- * @scancode: the scancode for the ir command
- * @keycode: the keycode for the ir command
- * @resize: whether the keytable may be shrunk
- * @return: -EINVAL if the keycode could not be inserted, otherwise zero.
+ * @rc_tab: scancode table to be adjusted
+ * @index: index of the mapping that needs to be updated
+ * @keycode: the desired keycode
+ * @return: previous keycode assigned to the mapping
+ *
+ * This routine is used to update scancode->keycopde mapping at given
+ * position.
+ */
+static unsigned int ir_update_mapping(struct input_dev *dev,
+ struct ir_scancode_table *rc_tab,
+ unsigned int index,
+ unsigned int new_keycode)
+{
+ int old_keycode = rc_tab->scan[index].keycode;
+ int i;
+
+ /* Did the user wish to remove the mapping? */
+ if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
+ IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
+ index, rc_tab->scan[index].scancode);
+ rc_tab->len--;
+ memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
+ (rc_tab->len - index) * sizeof(struct ir_scancode));
+ } else {
+ IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
+ index,
+ old_keycode == KEY_RESERVED ? "New" : "Replacing",
+ rc_tab->scan[index].scancode, new_keycode);
+ rc_tab->scan[index].keycode = new_keycode;
+ __set_bit(new_keycode, dev->keybit);
+ }
+
+ if (old_keycode != KEY_RESERVED) {
+ /* A previous mapping was updated... */
+ __clear_bit(old_keycode, dev->keybit);
+ /* ... but another scancode might use the same keycode */
+ for (i = 0; i < rc_tab->len; i++) {
+ if (rc_tab->scan[i].keycode == old_keycode) {
+ __set_bit(old_keycode, dev->keybit);
+ break;
+ }
+ }
+
+ /* Possibly shrink the keytable, failure is not a problem */
+ ir_resize_table(rc_tab, GFP_ATOMIC);
+ }
+
+ return old_keycode;
+}
+
+/**
+ * ir_locate_scancode() - set a keycode in the scancode->keycode table
+ * @ir_dev: the struct ir_input_dev device descriptor
+ * @rc_tab: scancode table to be searched
+ * @scancode: the desired scancode
+ * @resize: controls whether we allowed to resize the table to
+ * accomodate not yet present scancodes
+ * @return: index of the mapping containing scancode in question
+ * or -1U in case of failure.
*
- * This routine is used internally to manipulate the scancode->keycode table.
- * The caller has to hold @rc_tab->lock.
+ * This routine is used to locate given scancode in ir_scancode_table.
+ * If scancode is not yet present the routine will allocate a new slot
+ * for it.
*/
-static int ir_do_setkeycode(struct input_dev *dev,
- struct ir_scancode_table *rc_tab,
- unsigned scancode, unsigned keycode,
- bool resize)
+static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
+ struct ir_scancode_table *rc_tab,
+ unsigned int scancode,
+ bool resize)
{
unsigned int i;
- int old_keycode = KEY_RESERVED;
- struct ir_input_dev *ir_dev = input_get_drvdata(dev);
/*
* Unfortunately, some hardware-based IR decoders don't provide
* the provided IR with another one, it is needed to allow loading
* IR tables from other remotes. So,
*/
- if (ir_dev->props && ir_dev->props->scanmask) {
+ if (ir_dev->props && ir_dev->props->scanmask)
scancode &= ir_dev->props->scanmask;
- }
/* First check if we already have a mapping for this ir command */
for (i = 0; i < rc_tab->len; i++) {
+ if (rc_tab->scan[i].scancode == scancode)
+ return i;
+
/* Keytable is sorted from lowest to highest scancode */
- if (rc_tab->scan[i].scancode > scancode)
+ if (rc_tab->scan[i].scancode >= scancode)
break;
- else if (rc_tab->scan[i].scancode < scancode)
- continue;
-
- old_keycode = rc_tab->scan[i].keycode;
- rc_tab->scan[i].keycode = keycode;
-
- /* Did the user wish to remove the mapping? */
- if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) {
- IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
- i, scancode);
- rc_tab->len--;
- memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1],
- (rc_tab->len - i) * sizeof(struct ir_scancode));
- }
-
- /* Possibly shrink the keytable, failure is not a problem */
- ir_resize_table(rc_tab);
- break;
}
- if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) {
- /* No previous mapping found, we might need to grow the table */
- if (resize && ir_resize_table(rc_tab))
- return -ENOMEM;
-
- IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
- i, scancode, keycode);
+ /* No previous mapping found, we might need to grow the table */
+ if (rc_tab->size == rc_tab->len) {
+ if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
+ return -1U;
+ }
- /* i is the proper index to insert our new keycode */
+ /* i is the proper index to insert our new keycode */
+ if (i < rc_tab->len)
memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
(rc_tab->len - i) * sizeof(struct ir_scancode));
- rc_tab->scan[i].scancode = scancode;
- rc_tab->scan[i].keycode = keycode;
- rc_tab->len++;
- set_bit(keycode, dev->keybit);
- } else {
- IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
- i, scancode, keycode);
- /* A previous mapping was updated... */
- clear_bit(old_keycode, dev->keybit);
- /* ...but another scancode might use the same keycode */
- for (i = 0; i < rc_tab->len; i++) {
- if (rc_tab->scan[i].keycode == old_keycode) {
- set_bit(old_keycode, dev->keybit);
- break;
- }
- }
- }
+ rc_tab->scan[i].scancode = scancode;
+ rc_tab->scan[i].keycode = KEY_RESERVED;
+ rc_tab->len++;
- return 0;
+ return i;
}
/**
* This routine is used to handle evdev EVIOCSKEY ioctl.
*/
static int ir_setkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int keycode)
+ const struct input_keymap_entry *ke,
+ unsigned int *old_keycode)
{
- int rc;
- unsigned long flags;
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+ unsigned int index;
+ unsigned int scancode;
+ int retval;
+ unsigned long flags;
spin_lock_irqsave(&rc_tab->lock, flags);
- rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true);
+
+ if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+ index = ke->index;
+ if (index >= rc_tab->len) {
+ retval = -EINVAL;
+ goto out;
+ }
+ } else {
+ retval = input_scancode_to_scalar(ke, &scancode);
+ if (retval)
+ goto out;
+
+ index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
+ if (index >= rc_tab->len) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ }
+
+ *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
+
+out:
spin_unlock_irqrestore(&rc_tab->lock, flags);
- return rc;
+ return retval;
}
/**
* @dev: the struct input_dev device descriptor
* @to: the struct ir_scancode_table to copy entries to
* @from: the struct ir_scancode_table to copy entries from
- * @return: -EINVAL if all keycodes could not be inserted, otherwise zero.
+ * @return: -ENOMEM if all keycodes could not be inserted, otherwise zero.
*
* This routine is used to handle table initialization.
*/
-static int ir_setkeytable(struct input_dev *dev,
- struct ir_scancode_table *to,
+static int ir_setkeytable(struct ir_input_dev *ir_dev,
const struct ir_scancode_table *from)
{
- struct ir_input_dev *ir_dev = input_get_drvdata(dev);
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
- unsigned long flags;
- unsigned int i;
- int rc = 0;
+ unsigned int i, index;
+ int rc;
+
+ rc = ir_create_table(&ir_dev->rc_tab,
+ from->name, from->ir_type, from->size);
+ if (rc)
+ return rc;
+
+ IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+ rc_tab->size, rc_tab->alloc);
- spin_lock_irqsave(&rc_tab->lock, flags);
for (i = 0; i < from->size; i++) {
- rc = ir_do_setkeycode(dev, to, from->scan[i].scancode,
- from->scan[i].keycode, false);
- if (rc)
+ index = ir_establish_scancode(ir_dev, rc_tab,
+ from->scan[i].scancode, false);
+ if (index >= rc_tab->len) {
+ rc = -ENOMEM;
break;
+ }
+
+ ir_update_mapping(ir_dev->input_dev, rc_tab, index,
+ from->scan[i].keycode);
}
- spin_unlock_irqrestore(&rc_tab->lock, flags);
+
+ if (rc)
+ ir_free_table(rc_tab);
+
return rc;
}
+/**
+ * ir_lookup_by_scancode() - locate mapping by scancode
+ * @rc_tab: the &struct ir_scancode_table to search
+ * @scancode: scancode to look for in the table
+ * @return: index in the table, -1U if not found
+ *
+ * This routine performs binary search in RC keykeymap table for
+ * given scancode.
+ */
+static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
+ unsigned int scancode)
+{
+ unsigned int start = 0;
+ unsigned int end = rc_tab->len - 1;
+ unsigned int mid;
+
+ while (start <= end) {
+ mid = (start + end) / 2;
+ if (rc_tab->scan[mid].scancode < scancode)
+ start = mid + 1;
+ else if (rc_tab->scan[mid].scancode > scancode)
+ end = mid - 1;
+ else
+ return mid;
+ }
+
+ return -1U;
+}
+
/**
* ir_getkeycode() - get a keycode from the scancode->keycode table
* @dev: the struct input_dev device descriptor
* This routine is used to handle evdev EVIOCGKEY ioctl.
*/
static int ir_getkeycode(struct input_dev *dev,
- unsigned int scancode, unsigned int *keycode)
+ struct input_keymap_entry *ke)
{
- int start, end, mid;
- unsigned long flags;
- int key = KEY_RESERVED;
struct ir_input_dev *ir_dev = input_get_drvdata(dev);
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+ struct ir_scancode *entry;
+ unsigned long flags;
+ unsigned int index;
+ unsigned int scancode;
+ int retval;
spin_lock_irqsave(&rc_tab->lock, flags);
- start = 0;
- end = rc_tab->len - 1;
- while (start <= end) {
- mid = (start + end) / 2;
- if (rc_tab->scan[mid].scancode < scancode)
- start = mid + 1;
- else if (rc_tab->scan[mid].scancode > scancode)
- end = mid - 1;
- else {
- key = rc_tab->scan[mid].keycode;
- break;
- }
+
+ if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+ index = ke->index;
+ } else {
+ retval = input_scancode_to_scalar(ke, &scancode);
+ if (retval)
+ goto out;
+
+ index = ir_lookup_by_scancode(rc_tab, scancode);
+ }
+
+ if (index >= rc_tab->len) {
+ if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
+ IR_dprintk(1, "unknown key for scancode 0x%04x\n",
+ scancode);
+ retval = -EINVAL;
+ goto out;
}
- spin_unlock_irqrestore(&rc_tab->lock, flags);
- if (key == KEY_RESERVED)
- IR_dprintk(1, "unknown key for scancode 0x%04x\n",
- scancode);
+ entry = &rc_tab->scan[index];
- *keycode = key;
- return 0;
+ ke->index = index;
+ ke->keycode = entry->keycode;
+ ke->len = sizeof(entry->scancode);
+ memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
+
+out:
+ spin_unlock_irqrestore(&rc_tab->lock, flags);
+ return retval;
}
/**
*/
u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
{
- int keycode;
+ struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+ struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+ unsigned int keycode;
+ unsigned int index;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rc_tab->lock, flags);
+
+ index = ir_lookup_by_scancode(rc_tab, scancode);
+ keycode = index < rc_tab->len ?
+ rc_tab->scan[index].keycode : KEY_RESERVED;
+
+ spin_unlock_irqrestore(&rc_tab->lock, flags);
- ir_getkeycode(dev, scancode, &keycode);
if (keycode != KEY_RESERVED)
IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
dev->name, scancode, keycode);
+
return keycode;
}
EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
* This routine is used to signal that a key has been released on the
* remote control. It reports a keyup input event via input_report_key().
*/
- static void ir_keyup(struct ir_input_dev *ir)
+ void ir_keyup(struct ir_input_dev *ir)
{
if (!ir->keypressed)
return;
input_sync(ir->input_dev);
ir->keypressed = false;
}
+ EXPORT_SYMBOL_GPL(ir_keyup);
/**
* ir_timer_keyup() - generates a keyup event after a timeout
goto out_dev;
}
- input_dev->getkeycode = ir_getkeycode;
- input_dev->setkeycode = ir_setkeycode;
+ input_dev->getkeycode_new = ir_getkeycode;
+ input_dev->setkeycode_new = ir_setkeycode;
input_set_drvdata(input_dev, ir_dev);
ir_dev->input_dev = input_dev;
spin_lock_init(&ir_dev->keylock);
setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
- ir_dev->rc_tab.name = rc_tab->name;
- ir_dev->rc_tab.ir_type = rc_tab->ir_type;
- ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size *
- sizeof(struct ir_scancode));
- ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL);
- ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode);
if (props) {
ir_dev->props = props;
if (props->open)
input_dev->close = ir_close;
}
- if (!ir_dev->rc_tab.scan) {
- rc = -ENOMEM;
- goto out_name;
- }
-
- IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
- ir_dev->rc_tab.size, ir_dev->rc_tab.alloc);
-
set_bit(EV_KEY, input_dev->evbit);
set_bit(EV_REP, input_dev->evbit);
set_bit(EV_MSC, input_dev->evbit);
set_bit(MSC_SCAN, input_dev->mscbit);
- if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
- rc = -ENOMEM;
- goto out_table;
- }
+ rc = ir_setkeytable(ir_dev, rc_tab);
+ if (rc)
+ goto out_name;
rc = ir_register_class(input_dev);
if (rc < 0)
goto out_event;
}
+ rc = ir_register_input(input_dev);
+ if (rc < 0)
+ goto out_event;
+
IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
driver_name, rc_tab->name,
(ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
out_event:
ir_unregister_class(input_dev);
out_table:
- kfree(ir_dev->rc_tab.scan);
+ ir_free_table(&ir_dev->rc_tab);
out_name:
kfree(ir_dev->driver_name);
out_dev:
void ir_input_unregister(struct input_dev *input_dev)
{
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
- struct ir_scancode_table *rc_tab;
if (!ir_dev)
return;
if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
ir_raw_event_unregister(input_dev);
- rc_tab = &ir_dev->rc_tab;
- rc_tab->size = 0;
- kfree(rc_tab->scan);
- rc_tab->scan = NULL;
+ ir_free_table(&ir_dev->rc_tab);
ir_unregister_class(input_dev);
static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
{
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+ struct lirc_codec *lirc = &ir_dev->raw->lirc;
int sample;
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
return -EINVAL;
- if (IS_RESET(ev))
+ /* Packet start */
+ if (ev.reset)
return 0;
- IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
- TO_US(ev.duration), TO_STR(ev.pulse));
+ /* Carrier reports */
+ if (ev.carrier_report) {
+ sample = LIRC_FREQUENCY(ev.carrier);
- sample = ev.duration / 1000;
- if (ev.pulse)
- sample |= PULSE_BIT;
+ /* Packet end */
+ } else if (ev.timeout) {
+
+ if (lirc->gap)
+ return 0;
+
+ lirc->gap_start = ktime_get();
+ lirc->gap = true;
+ lirc->gap_duration = ev.duration;
+
+ if (!lirc->send_timeout_reports)
+ return 0;
+
+ sample = LIRC_TIMEOUT(ev.duration / 1000);
+
+ /* Normal sample */
+ } else {
+
+ if (lirc->gap) {
+ int gap_sample;
+
+ lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
+ lirc->gap_start));
+
+ /* Convert to ms and cap by LIRC_VALUE_MASK */
+ do_div(lirc->gap_duration, 1000);
+ lirc->gap_duration = min(lirc->gap_duration,
+ (u64)LIRC_VALUE_MASK);
+
+ gap_sample = LIRC_SPACE(lirc->gap_duration);
+ lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
+ (unsigned char *) &gap_sample);
+ lirc->gap = false;
+ }
+
+ sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
+ LIRC_SPACE(ev.duration / 1000);
+ }
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
(unsigned char *) &sample);
wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
-
return 0;
}
struct ir_input_dev *ir_dev;
int ret = 0;
void *drv_data;
- unsigned long val = 0;
+ __u32 val = 0, tmp;
lirc = lirc_get_pdata(filep);
if (!lirc)
drv_data = ir_dev->props->priv;
if (_IOC_DIR(cmd) & _IOC_WRITE) {
- ret = get_user(val, (unsigned long *)arg);
+ ret = get_user(val, (__u32 *)arg);
if (ret)
return ret;
}
case LIRC_SET_SEND_MODE:
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
return -EINVAL;
- break;
+ return 0;
/* TX settings */
case LIRC_SET_TRANSMITTER_MASK:
- if (ir_dev->props->s_tx_mask)
- ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
- else
+ if (!ir_dev->props->s_tx_mask)
return -EINVAL;
- break;
+
+ return ir_dev->props->s_tx_mask(drv_data, val);
case LIRC_SET_SEND_CARRIER:
- if (ir_dev->props->s_tx_carrier)
- ir_dev->props->s_tx_carrier(drv_data, (u32)val);
- else
+ if (!ir_dev->props->s_tx_carrier)
return -EINVAL;
- break;
+
+ return ir_dev->props->s_tx_carrier(drv_data, val);
case LIRC_SET_SEND_DUTY_CYCLE:
if (!ir_dev->props->s_tx_duty_cycle)
if (val <= 0 || val >= 100)
return -EINVAL;
- ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
- break;
+ return ir_dev->props->s_tx_duty_cycle(drv_data, val);
/* RX settings */
case LIRC_SET_REC_CARRIER:
- if (ir_dev->props->s_rx_carrier_range)
- ret = ir_dev->props->s_rx_carrier_range(
- ir_dev->props->priv,
- ir_dev->raw->lirc.carrier_low, val);
- else
+ if (!ir_dev->props->s_rx_carrier_range)
return -ENOSYS;
- if (!ret)
- ir_dev->raw->lirc.carrier_low = 0;
- break;
+ if (val <= 0)
+ return -EINVAL;
+
+ return ir_dev->props->s_rx_carrier_range(drv_data,
+ ir_dev->raw->lirc.carrier_low, val);
case LIRC_SET_REC_CARRIER_RANGE:
- if (val >= 0)
- ir_dev->raw->lirc.carrier_low = val;
- break;
+ if (val <= 0)
+ return -EINVAL;
+ ir_dev->raw->lirc.carrier_low = val;
+ return 0;
case LIRC_GET_REC_RESOLUTION:
val = ir_dev->props->rx_resolution;
break;
case LIRC_SET_WIDEBAND_RECEIVER:
- if (ir_dev->props->s_learning_mode)
- return ir_dev->props->s_learning_mode(
- ir_dev->props->priv, !!val);
- else
+ if (!ir_dev->props->s_learning_mode)
return -ENOSYS;
+ return ir_dev->props->s_learning_mode(drv_data, !!val);
+
+ case LIRC_SET_MEASURE_CARRIER_MODE:
+ if (!ir_dev->props->s_carrier_report)
+ return -ENOSYS;
+
+ return ir_dev->props->s_carrier_report(drv_data, !!val);
+
/* Generic timeout support */
case LIRC_GET_MIN_TIMEOUT:
if (!ir_dev->props->max_timeout)
break;
case LIRC_SET_REC_TIMEOUT:
- if (val < ir_dev->props->min_timeout ||
- val > ir_dev->props->max_timeout)
- return -EINVAL;
- ir_dev->props->timeout = val * 1000;
+ if (!ir_dev->props->max_timeout)
+ return -ENOSYS;
+
+ tmp = val * 1000;
+
+ if (tmp < ir_dev->props->min_timeout ||
+ tmp > ir_dev->props->max_timeout)
+ return -EINVAL;
+
+ ir_dev->props->timeout = tmp;
+ break;
+
+ case LIRC_SET_REC_TIMEOUT_REPORTS:
+ lirc->send_timeout_reports = !!val;
break;
default:
}
if (_IOC_DIR(cmd) & _IOC_READ)
- ret = put_user(val, (unsigned long *)arg);
+ ret = put_user(val, (__u32 *)arg);
return ret;
}
.owner = THIS_MODULE,
.write = ir_lirc_transmit_ir,
.unlocked_ioctl = ir_lirc_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = ir_lirc_ioctl,
+ #endif
.read = lirc_dev_fop_read,
.poll = lirc_dev_fop_poll,
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
+ .llseek = no_llseek,
};
static int ir_lirc_register(struct input_dev *input_dev)
if (ir_dev->props->s_learning_mode)
features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
+ if (ir_dev->props->s_carrier_report)
+ features |= LIRC_CAN_MEASURE_CARRIER;
+
+
if (ir_dev->props->max_timeout)
features |= LIRC_CAN_SET_REC_TIMEOUT;
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/completion.h>
-#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/unistd.h>
struct task_struct *task;
long jiffies_to_wait;
-
- struct cdev cdev;
};
static DEFINE_MUTEX(lirc_dev_lock);
static struct irctl *irctls[MAX_IRCTL_DEVICES];
+ static struct cdev cdevs[MAX_IRCTL_DEVICES];
/* Only used for sysfs but defined to void otherwise */
static struct class *lirc_class;
/* helper function
* initializes the irctl structure
*/
- static void init_irctl(struct irctl *ir)
+ static void lirc_irctl_init(struct irctl *ir)
{
- dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
- ir->d.name, ir->d.minor);
mutex_init(&ir->irctl_lock);
ir->d.minor = NOPLUG;
}
- static void cleanup(struct irctl *ir)
+ static void lirc_irctl_cleanup(struct irctl *ir)
{
dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
* reads key codes from driver and puts them into buffer
* returns 0 on success
*/
- static int add_to_buf(struct irctl *ir)
+ static int lirc_add_to_buf(struct irctl *ir)
{
if (ir->d.add_to_buf) {
int res = -ENODATA;
}
if (kthread_should_stop())
break;
- if (!add_to_buf(ir))
+ if (!lirc_add_to_buf(ir))
wake_up_interruptible(&ir->buf->wait_poll);
} else {
set_current_state(TASK_INTERRUPTIBLE);
}
- static struct file_operations fops = {
+ static struct file_operations lirc_dev_fops = {
.owner = THIS_MODULE,
.read = lirc_dev_fop_read,
.write = lirc_dev_fop_write,
.poll = lirc_dev_fop_poll,
.unlocked_ioctl = lirc_dev_fop_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = lirc_dev_fop_ioctl,
+ #endif
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
+ .llseek = noop_llseek,
};
static int lirc_cdev_add(struct irctl *ir)
{
int retval;
struct lirc_driver *d = &ir->d;
+ struct cdev *cdev = &cdevs[d->minor];
if (d->fops) {
- cdev_init(&ir->cdev, d->fops);
- ir->cdev.owner = d->owner;
+ cdev_init(cdev, d->fops);
+ cdev->owner = d->owner;
} else {
- cdev_init(&ir->cdev, &fops);
- ir->cdev.owner = THIS_MODULE;
+ cdev_init(cdev, &lirc_dev_fops);
+ cdev->owner = THIS_MODULE;
}
- kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
+ kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
- retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
+ retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
if (retval)
- kobject_put(&ir->cdev.kobj);
+ kobject_put(&cdev->kobj);
return retval;
}
goto out;
}
+ if (!d->dev) {
+ printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__);
+ err = -EINVAL;
+ goto out;
+ }
+
if (MAX_IRCTL_DEVICES <= d->minor) {
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
"\"minor\" must be between 0 and %d (%d)!\n",
err = -ENOMEM;
goto out_lock;
}
- init_irctl(ir);
+ lirc_irctl_init(ir);
irctls[minor] = ir;
d->minor = minor;
d->features = LIRC_CAN_REC_LIRCCODE;
ir->d = *d;
- ir->d.minor = minor;
device_create(lirc_class, ir->d.dev,
MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
int lirc_unregister_driver(int minor)
{
struct irctl *ir;
+ struct cdev *cdev;
if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
- printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
- "\"minor (%d)\" must be between 0 and %d!\n",
- minor, MAX_IRCTL_DEVICES-1);
+ printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
+ "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
return -EBADRQC;
}
ir = irctls[minor];
+ if (!ir) {
+ printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct "
+ "for minor %d!\n", __func__, minor);
+ return -ENOENT;
+ }
+
+ cdev = &cdevs[minor];
mutex_lock(&lirc_dev_lock);
if (ir->d.minor != minor) {
- printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
- "minor (%d) device not registered!", minor);
+ printk(KERN_ERR "lirc_dev: %s: minor (%d) device not "
+ "registered!\n", __func__, minor);
mutex_unlock(&lirc_dev_lock);
return -ENOENT;
}
wake_up_interruptible(&ir->buf->wait_poll);
mutex_lock(&ir->irctl_lock);
ir->d.set_use_dec(ir->d.data);
- module_put(ir->d.owner);
+ module_put(cdev->owner);
mutex_unlock(&ir->irctl_lock);
- cdev_del(&ir->cdev);
} else {
- cleanup(ir);
- cdev_del(&ir->cdev);
+ lirc_irctl_cleanup(ir);
+ cdev_del(cdev);
kfree(ir);
irctls[minor] = NULL;
}
int lirc_dev_fop_open(struct inode *inode, struct file *file)
{
struct irctl *ir;
+ struct cdev *cdev;
int retval = 0;
if (iminor(inode) >= MAX_IRCTL_DEVICES) {
retval = -ENODEV;
goto error;
}
- file->private_data = ir;
dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
goto error;
}
- if (try_module_get(ir->d.owner)) {
- ++ir->open;
+ cdev = &cdevs[iminor(inode)];
+ if (try_module_get(cdev->owner)) {
+ ir->open++;
retval = ir->d.set_use_inc(ir->d.data);
if (retval) {
- module_put(ir->d.owner);
- --ir->open;
+ module_put(cdev->owner);
+ ir->open--;
} else {
lirc_buffer_clear(ir->buf);
}
mutex_unlock(&lirc_dev_lock);
+ nonseekable_open(inode, file);
+
return retval;
}
EXPORT_SYMBOL(lirc_dev_fop_open);
int lirc_dev_fop_close(struct inode *inode, struct file *file)
{
struct irctl *ir = irctls[iminor(inode)];
+ struct cdev *cdev = &cdevs[iminor(inode)];
+
+ if (!ir) {
+ printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+ return -EINVAL;
+ }
dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
WARN_ON(mutex_lock_killable(&lirc_dev_lock));
- --ir->open;
+ ir->open--;
if (ir->attached) {
ir->d.set_use_dec(ir->d.data);
- module_put(ir->d.owner);
+ module_put(cdev->owner);
} else {
- cleanup(ir);
+ lirc_irctl_cleanup(ir);
+ cdev_del(cdev);
irctls[ir->d.minor] = NULL;
kfree(ir);
}
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
unsigned int ret;
+ if (!ir) {
+ printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+ return POLLERR;
+ }
+
dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
if (!ir->attached) {
long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- unsigned long mode;
+ __u32 mode;
int result = 0;
- struct irctl *ir = file->private_data;
+ struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+
+ if (!ir) {
+ printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__);
+ return -ENODEV;
+ }
dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
ir->d.name, ir->d.minor, cmd);
switch (cmd) {
case LIRC_GET_FEATURES:
- result = put_user(ir->d.features, (unsigned long *)arg);
+ result = put_user(ir->d.features, (__u32 *)arg);
break;
case LIRC_GET_REC_MODE:
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
result = put_user(LIRC_REC2MODE
(ir->d.features & LIRC_CAN_REC_MASK),
- (unsigned long *)arg);
+ (__u32 *)arg);
break;
case LIRC_SET_REC_MODE:
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
break;
}
- result = get_user(mode, (unsigned long *)arg);
+ result = get_user(mode, (__u32 *)arg);
if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
result = -EINVAL;
/*
*/
break;
case LIRC_GET_LENGTH:
- result = put_user(ir->d.code_length, (unsigned long *)arg);
+ result = put_user(ir->d.code_length, (__u32 *)arg);
break;
case LIRC_GET_MIN_TIMEOUT:
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
break;
}
- result = put_user(ir->d.min_timeout, (unsigned long *)arg);
+ result = put_user(ir->d.min_timeout, (__u32 *)arg);
break;
case LIRC_GET_MAX_TIMEOUT:
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
break;
}
- result = put_user(ir->d.max_timeout, (unsigned long *)arg);
+ result = put_user(ir->d.max_timeout, (__u32 *)arg);
break;
default:
result = -EINVAL;
loff_t *ppos)
{
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
- unsigned char buf[ir->chunk_size];
+ unsigned char *buf;
int ret = 0, written = 0;
DECLARE_WAITQUEUE(wait, current);
+ if (!ir) {
+ printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+ return -ENODEV;
+ }
+
dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
+ buf = kzalloc(ir->chunk_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
if (mutex_lock_interruptible(&ir->irctl_lock))
return -ERESTARTSYS;
if (!ir->attached) {
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);
{
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+ if (!ir) {
+ printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+ return -ENODEV;
+ }
+
dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
if (!ir->attached)
kthread_stop(fepriv->thread);
- init_MUTEX (&fepriv->sem);
+ sema_init(&fepriv->sem, 1);
fepriv->state = FESTATE_IDLE;
/* paranoia check in case a signal arrived */
.unlocked_ioctl = dvb_generic_ioctl,
.poll = dvb_frontend_poll,
.open = dvb_frontend_open,
- .release = dvb_frontend_release
+ .release = dvb_frontend_release,
+ .llseek = noop_llseek,
};
int dvb_register_frontend(struct dvb_adapter* dvb,
}
fepriv = fe->frontend_priv;
- init_MUTEX (&fepriv->sem);
+ sema_init(&fepriv->sem, 1);
init_waitqueue_head (&fepriv->wait_queue);
init_waitqueue_head (&fepriv->events.wait_queue);
mutex_init(&fepriv->events.mtx);
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
- * the project's page is at http://www.linuxtv.org/dvb/
+ * the project's page is at http://www.linuxtv.org/
*/
.unlocked_ioctl = dvb_generic_ioctl,
.open = dvb_generic_open,
.release = dvb_generic_release,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_osd = {
/* Budgetpatch note:
* Original hardware design by Roberto Deza:
* There is a DVB_Wiki at
- * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
- * where is described this 'DVB TT Budget Patch', on Card Modding:
- * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
- * On the short description there is also a link to a external file,
- * with more details:
- * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
+ * http://www.linuxtv.org/
*
* New software triggering design by Emard that works on
* original Roberto Deza's hardware:
get recognized before the main driver is fully loaded */
saa7146_write(dev, GPIO_CTRL, 0x500000);
- av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
static struct saa7146_extension av7110_extension_driver = {
- .name = "dvb",
+ .name = "av7110",
.flags = SAA7146_USE_I2C_IRQ,
.module = THIS_MODULE,
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
- * the project's page is at http://www.linuxtv.org/dvb/
+ * the project's page is at http://www.linuxtv.org/
*/
#include <linux/types.h>
return -1;
}
while (1) {
- if ((len = dvb_ringbuffer_avail(buf)) < 6)
+ len = dvb_ringbuffer_avail(buf);
+ if (len < 6) {
+ wake_up(&buf->queue);
return -1;
+ }
sync = DVB_RINGBUFFER_PEEK(buf, 0) << 24;
sync |= DVB_RINGBUFFER_PEEK(buf, 1) << 16;
sync |= DVB_RINGBUFFER_PEEK(buf, 2) << 8;
.open = dvb_video_open,
.release = dvb_video_release,
.poll = dvb_video_poll,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_video = {
.open = dvb_audio_open,
.release = dvb_audio_release,
.poll = dvb_audio_poll,
+ .llseek = noop_llseek,
};
static struct dvb_device dvbdev_audio = {
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
- * the project's page is at http://www.linuxtv.org/dvb/
+ * the project's page is at http://www.linuxtv.org/
*/
if (bi->type != BUDGET_FS_ACTIVY)
saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
- budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
-
strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120);
config VIDEO_VIVI
tristate "Virtual Video Driver"
depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
- depends on (FRAMEBUFFER_CONSOLE || STI_CONSOLE) && FONTS
+ depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
select FONT_8x16
select VIDEOBUF_VMALLOC
default n
Check out <file:Documentation/video4linux/w9966.txt> for more
information.
- config VIDEO_CPIA
- tristate "CPiA Video For Linux (DEPRECATED)"
- depends on VIDEO_V4L1
- default n
- ---help---
- This driver is DEPRECATED please use the gspca cpia1 module
- instead. Note that you need atleast version 0.6.4 of libv4l for
- the cpia1 gspca module.
-
- This is the video4linux driver for cameras based on Vision's CPiA
- (Colour Processor Interface ASIC), such as the Creative Labs Video
- Blaster Webcam II. If you have one of these cameras, say Y here
- and select parallel port and/or USB lowlevel support below,
- otherwise say N. This will not work with the Creative Webcam III.
-
- Please read <file:Documentation/video4linux/README.cpia> for more
- information.
-
- This driver is also available as a module (cpia).
-
- config VIDEO_CPIA_PP
- tristate "CPiA Parallel Port Lowlevel Support"
- depends on PARPORT_1284 && VIDEO_CPIA && PARPORT
- help
- This is the lowlevel parallel port support for cameras based on
- Vision's CPiA (Colour Processor Interface ASIC), such as the
- Creative Webcam II. If you have the parallel port version of one
- of these cameras, say Y here, otherwise say N. It is also available
- as a module (cpia_pp).
-
- config VIDEO_CPIA_USB
- tristate "CPiA USB Lowlevel Support"
- depends on VIDEO_CPIA && USB
- help
- This is the lowlevel USB support for cameras based on Vision's CPiA
- (Colour Processor Interface ASIC), such as the Creative Webcam II.
- If you have the USB version of one of these cameras, say Y here,
- otherwise say N. This will not work with the Creative Webcam III.
- It is also available as a module (cpia_usb).
-
source "drivers/media/video/cpia2/Kconfig"
- config VIDEO_SAA5246A
- tristate "SAA5246A, SAA5281 Teletext processor"
- depends on I2C && VIDEO_V4L2
- help
- Support for I2C bus based teletext using the SAA5246A or SAA5281
- chip. Useful only if you live in Europe.
-
- To compile this driver as a module, choose M here: the
- module will be called saa5246a.
-
- config VIDEO_SAA5249
- tristate "SAA5249 Teletext processor"
- depends on I2C && VIDEO_V4L2
- help
- Support for I2C bus based teletext using the SAA5249 chip. At the
- moment this is only useful on some European WinTV cards.
-
- To compile this driver as a module, choose M here: the
- module will be called saa5249.
-
config VIDEO_VINO
tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
Say Y here to build in support for the Vino video input system found
on SGI Indy machines.
- config VIDEO_STRADIS
- tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS
- help
- Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
- driver for PCI. There is a product page at
- <http://www.stradis.com/>.
-
source "drivers/media/video/zoran/Kconfig"
config VIDEO_MEYE
CMOS camera controller. This is the controller found on first-
generation OLPC systems.
+ config VIDEO_SR030PC30
+ tristate "SR030PC30 VGA camera sensor support"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This driver supports SR030PC30 VGA camera from Siliconfile
+
+ config VIDEO_VIA_CAMERA
+ tristate "VIAFB camera controller support"
+ depends on FB_VIA
+ select VIDEOBUF_DMA_SG
+ select VIDEO_OV7670
+ help
+ Driver support for the integrated camera controller in VIA
+ Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems
+ with ov7670 sensors.
+
config SOC_CAMERA
tristate "SoC camera support"
depends on VIDEO_V4L2 && HAS_DMA && I2C
over a bus like PCI or USB. For example some i2c camera connected
directly to the data bus of an SoC.
+ config SOC_CAMERA_IMX074
+ tristate "imx074 support"
+ depends on SOC_CAMERA && I2C
+ help
+ This driver supports IMX074 cameras from Sony
+
config SOC_CAMERA_MT9M001
tristate "mt9m001 support"
depends on SOC_CAMERA && I2C
help
This is a generic SoC camera platform driver, useful for testing
+ config SOC_CAMERA_OV6650
+ tristate "ov6650 sensor support"
+ depends on SOC_CAMERA && I2C
+ ---help---
+ This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor
+
config SOC_CAMERA_OV772X
tristate "ov772x camera support"
depends on SOC_CAMERA && I2C
---help---
This is a v4l2 driver for the SuperH Mobile CEU Interface
+ config VIDEO_OMAP1
+ tristate "OMAP1 Camera Interface driver"
+ depends on VIDEO_DEV && ARCH_OMAP1 && SOC_CAMERA
+ select VIDEOBUF_DMA_CONTIG
+ select VIDEOBUF_DMA_SG
+ ---help---
+ This is a v4l2 driver for the TI OMAP1 camera interface
+
config VIDEO_OMAP2
tristate "OMAP2 Camera Capture Interface driver"
depends on VIDEO_DEV && ARCH_OMAP2
Supported devices are typically found in some Asus laptops,
with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
may be supported by the stk11xx driver, from which this is
- derived, see http://stk11xx.sourceforge.net
+ derived, see <http://sourceforge.net/projects/syntekdriver/>
To compile this driver as a module, choose M here: the
module will be called stkwebcam.
* sensor.
*
* The data sheet for this device can be found at:
- * http://www.marvell.com/products/pcconn/88ALP01.jsp
+ * http://www.marvell.com/products/pc_connectivity/88alp01/
*
* Copyright 2006 One Laptop Per Child Association, Inc.
* Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
+ #include <linux/dmi.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <asm/io.h>
+ #include "ov7670.h"
#include "cafe_ccic-regs.h"
#define CAFE_VERSION 0x000002
/* Current operating parameters */
u32 sensor_type; /* Currently ov7670 only */
struct v4l2_pix_format pix_format;
+ enum v4l2_mbus_pixelcode mbus_code;
/* Locks */
struct mutex s_mutex; /* Access to this structure */
return container_of(dev, struct cafe_camera, v4l2_dev);
}
+ static struct cafe_format_struct {
+ __u8 *desc;
+ __u32 pixelformat;
+ int bpp; /* Bytes per pixel */
+ enum v4l2_mbus_pixelcode mbus_code;
+ } cafe_formats[] = {
+ {
+ .desc = "YUYV 4:2:2",
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
+ .bpp = 2,
+ },
+ {
+ .desc = "RGB 444",
+ .pixelformat = V4L2_PIX_FMT_RGB444,
+ .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
+ .bpp = 2,
+ },
+ {
+ .desc = "RGB 565",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
+ .bpp = 2,
+ },
+ {
+ .desc = "Raw RGB Bayer",
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
+ .bpp = 1
+ },
+ };
+ #define N_CAFE_FMTS ARRAY_SIZE(cafe_formats)
+
+ static struct cafe_format_struct *cafe_find_format(u32 pixelformat)
+ {
+ unsigned i;
+
+ for (i = 0; i < N_CAFE_FMTS; i++)
+ if (cafe_formats[i].pixelformat == pixelformat)
+ return cafe_formats + i;
+ /* Not found? Then return the first format. */
+ return cafe_formats;
+ }
/*
* Start over with DMA buffers - dev_lock needed.
{
unsigned int rval;
unsigned long flags;
- DEFINE_WAIT(the_wait);
spin_lock_irqsave(&cam->dev_lock, flags);
rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
cafe_reg_write(cam, REG_TWSIC1, rval);
spin_unlock_irqrestore(&cam->dev_lock, flags);
+ /* Unfortunately, reading TWSIC1 too soon after sending a command
+ * causes the device to die.
+ * Use a busy-wait because we often send a large quantity of small
+ * commands at-once; using msleep() would cause a lot of context
+ * switches which take longer than 2ms, resulting in a noticable
+ * boot-time and capture-start delays.
+ */
+ mdelay(2);
+
/*
- * Time to wait for the write to complete. THIS IS A RACY
- * WAY TO DO IT, but the sad fact is that reading the TWSIC1
- * register too quickly after starting the operation sends
- * the device into a place that may be kinder and better, but
- * which is absolutely useless for controlling the sensor. In
- * practice we have plenty of time to get into our sleep state
- * before the interrupt hits, and the worst case is that we
- * time out and then see that things completed, so this seems
- * the best way for now.
+ * Another sad fact is that sometimes, commands silently complete but
+ * cafe_smbus_write_done() never becomes aware of this.
+ * This happens at random and appears to possible occur with any
+ * command.
+ * We don't understand why this is. We work around this issue
+ * with the timeout in the wait below, assuming that all commands
+ * complete within the timeout.
*/
- do {
- prepare_to_wait(&cam->smbus_wait, &the_wait,
- TASK_UNINTERRUPTIBLE);
- schedule_timeout(1); /* even 1 jiffy is too long */
- finish_wait(&cam->smbus_wait, &the_wait);
- } while (!cafe_smbus_write_done(cam));
-
- #ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT
wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam),
CAFE_SMBUS_TIMEOUT);
- #endif
+
spin_lock_irqsave(&cam->dev_lock, flags);
rval = cafe_reg_read(cam, REG_TWSIC1);
spin_unlock_irqrestore(&cam->dev_lock, flags);
static int cafe_cam_configure(struct cafe_camera *cam)
{
- struct v4l2_format fmt;
+ struct v4l2_mbus_framefmt mbus_fmt;
int ret;
if (cam->state != S_IDLE)
return -EINVAL;
- fmt.fmt.pix = cam->pix_format;
+ v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code);
ret = sensor_call(cam, core, init, 0);
if (ret == 0)
- ret = sensor_call(cam, video, s_fmt, &fmt);
+ ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt);
/*
* OV7670 does weird things if flip is set *before* format...
*/
/*
* The default format we use until somebody says otherwise.
*/
- static struct v4l2_pix_format cafe_def_pix_format = {
+ static const struct v4l2_pix_format cafe_def_pix_format = {
.width = VGA_WIDTH,
.height = VGA_HEIGHT,
.pixelformat = V4L2_PIX_FMT_YUYV,
.sizeimage = VGA_WIDTH*VGA_HEIGHT*2,
};
+ static const enum v4l2_mbus_pixelcode cafe_def_mbus_code =
+ V4L2_MBUS_FMT_YUYV8_2X8;
+
static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp,
void *priv, struct v4l2_fmtdesc *fmt)
{
- struct cafe_camera *cam = priv;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = sensor_call(cam, video, enum_fmt, fmt);
- mutex_unlock(&cam->s_mutex);
- return ret;
+ if (fmt->index >= N_CAFE_FMTS)
+ return -EINVAL;
+ strlcpy(fmt->description, cafe_formats[fmt->index].desc,
+ sizeof(fmt->description));
+ fmt->pixelformat = cafe_formats[fmt->index].pixelformat;
+ return 0;
}
-
static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_format *fmt)
{
struct cafe_camera *cam = priv;
+ struct cafe_format_struct *f;
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+ struct v4l2_mbus_framefmt mbus_fmt;
int ret;
+ f = cafe_find_format(pix->pixelformat);
+ pix->pixelformat = f->pixelformat;
+ v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
mutex_lock(&cam->s_mutex);
- ret = sensor_call(cam, video, try_fmt, fmt);
+ ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
mutex_unlock(&cam->s_mutex);
+ v4l2_fill_pix_format(pix, &mbus_fmt);
+ pix->bytesperline = pix->width * f->bpp;
+ pix->sizeimage = pix->height * pix->bytesperline;
return ret;
}
struct v4l2_format *fmt)
{
struct cafe_camera *cam = priv;
+ struct cafe_format_struct *f;
int ret;
/*
*/
if (cam->state != S_IDLE || cam->n_sbufs > 0)
return -EBUSY;
+
+ f = cafe_find_format(fmt->fmt.pix.pixelformat);
+
/*
* See if the formatting works in principle.
*/
*/
mutex_lock(&cam->s_mutex);
cam->pix_format = fmt->fmt.pix;
+ cam->mbus_code = f->mbus_code;
+
/*
* Make sure we have appropriate DMA buffers.
*/
return sensor_call(cam, core, g_chip_ident, chip);
}
+ static int cafe_vidioc_enum_framesizes(struct file *filp, void *priv,
+ struct v4l2_frmsizeenum *sizes)
+ {
+ struct cafe_camera *cam = priv;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = sensor_call(cam, video, enum_framesizes, sizes);
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+ }
+
+ static int cafe_vidioc_enum_frameintervals(struct file *filp, void *priv,
+ struct v4l2_frmivalenum *interval)
+ {
+ struct cafe_camera *cam = priv;
+ int ret;
+
+ mutex_lock(&cam->s_mutex);
+ ret = sensor_call(cam, video, enum_frameintervals, interval);
+ mutex_unlock(&cam->s_mutex);
+ return ret;
+ }
+
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int cafe_vidioc_g_register(struct file *file, void *priv,
struct v4l2_dbg_register *reg)
.vidioc_s_ctrl = cafe_vidioc_s_ctrl,
.vidioc_g_parm = cafe_vidioc_g_parm,
.vidioc_s_parm = cafe_vidioc_s_parm,
+ .vidioc_enum_framesizes = cafe_vidioc_enum_framesizes,
+ .vidioc_enum_frameintervals = cafe_vidioc_enum_frameintervals,
.vidioc_g_chip_ident = cafe_vidioc_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = cafe_vidioc_g_register,
* PCI interface stuff.
*/
+ static const struct dmi_system_id olpc_xo1_dmi[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OLPC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1"),
+ },
+ },
+ { }
+ };
+
static int cafe_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
struct cafe_camera *cam;
+ struct ov7670_config sensor_cfg = {
+ /* This controller only does SMBUS */
+ .use_smbus = true,
+
+ /*
+ * Exclude QCIF mode, because it only captures a tiny portion
+ * of the sensor FOV
+ */
+ .min_width = 320,
+ .min_height = 240,
+ };
/*
* Start putting together one of our big camera structures.
init_waitqueue_head(&cam->iowait);
cam->pdev = pdev;
cam->pix_format = cafe_def_pix_format;
+ cam->mbus_code = cafe_def_mbus_code;
INIT_LIST_HEAD(&cam->dev_list);
INIT_LIST_HEAD(&cam->sb_avail);
INIT_LIST_HEAD(&cam->sb_full);
if (ret)
goto out_freeirq;
+ /* Apply XO-1 clock speed */
+ if (dmi_check_system(olpc_xo1_dmi))
+ sensor_cfg.clock_speed = 45;
+
cam->sensor_addr = 0x42;
cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter,
- "ov7670", "ov7670", cam->sensor_addr, NULL);
+ NULL, "ov7670", cam->sensor_addr, NULL);
if (cam->sensor == NULL) {
ret = -ENODEV;
goto out_smbus;
}
+
ret = cafe_cam_init(cam);
if (ret)
goto out_smbus;
* (c) 2008 Steven Toth <stoth@linuxtv.org>
* - CX23885/7/8 support
*
- * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
+ * Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
*
* 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
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct cx23885_buffer),
- fh);
+ fh, NULL);
unlock_kernel();
return 0;
* (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
* - video_ioctl2 conversion
*
- * Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
+ * Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
*
* 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
dprintk( 1, "%s\n", __func__);
- lock_kernel();
+ mutex_lock(&dev->core->lock);
/* Make sure we can acquire the hardware */
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
err = drv->request_acquire(drv);
if(err != 0) {
dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
- unlock_kernel();
+ mutex_unlock(&dev->core->lock);;
return err;
}
}
if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) {
if (drv)
drv->request_release(drv);
- unlock_kernel();
+ mutex_unlock(&dev->core->lock);
return -EINVAL;
}
dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
if (NULL == fh) {
if (drv)
drv->request_release(drv);
- unlock_kernel();
+ mutex_unlock(&dev->core->lock);
return -ENOMEM;
}
file->private_data = fh;
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct cx88_buffer),
- fh);
+ fh, NULL);
/* FIXME: locking against other video device */
cx88_set_scale(dev->core, dev->width, dev->height,
fh->mpegq.field);
- unlock_kernel();
atomic_inc(&dev->core->mpeg_users);
-
+ mutex_unlock(&dev->core->lock);
return 0;
}
videobuf_stop(&fh->mpegq);
videobuf_mmap_free(&fh->mpegq);
+
+ mutex_lock(&dev->core->lock);
file->private_data = NULL;
kfree(fh);
+ mutex_unlock(&dev->core->lock);
/* Make sure we release the hardware */
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
- Visit http://www.mihu.de/linux/saa7146/mxb/
+ Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html
for further details about this card.
This program is free software; you can redistribute it and/or modify
#include "tea6415c.h"
#include "tea6420.h"
- #define I2C_SAA5246A 0x11
#define I2C_SAA7111A 0x24
#define I2C_TDA9840 0x42
#define I2C_TEA6415C 0x43
}
mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "saa7115", "saa7111", I2C_SAA7111A, NULL);
+ NULL, "saa7111", I2C_SAA7111A, NULL);
mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tea6420", "tea6420", I2C_TEA6420_1, NULL);
+ NULL, "tea6420", I2C_TEA6420_1, NULL);
mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tea6420", "tea6420", I2C_TEA6420_2, NULL);
+ NULL, "tea6420", I2C_TEA6420_2, NULL);
mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tea6415c", "tea6415c", I2C_TEA6415C, NULL);
+ NULL, "tea6415c", I2C_TEA6415C, NULL);
mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tda9840", "tda9840", I2C_TDA9840, NULL);
+ NULL, "tda9840", I2C_TDA9840, NULL);
mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "tuner", "tuner", I2C_TUNER, NULL);
- if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
- "saa5246a", "saa5246a", I2C_SAA5246A, NULL)) {
- printk(KERN_INFO "mxb: found teletext decoder\n");
- }
+ NULL, "tuner", I2C_TUNER, NULL);
/* check if all devices are present */
if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
if (height > BUZ_MAX_HEIGHT)
height = BUZ_MAX_HEIGHT;
- /* Check for vaild parameters */
+ /* Check for invalid parameters */
if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT ||
width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {
dprintk(1,
mmap_unlock_and_return:
mutex_unlock(&zr->resource_lock);
- return 0;
+ return res;
}
static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
source "drivers/staging/tm6000/Kconfig"
+ source "drivers/staging/cpia/Kconfig"
+
+ source "drivers/staging/stradis/Kconfig"
+
source "drivers/staging/usbip/Kconfig"
source "drivers/staging/winbond/Kconfig"
source "drivers/staging/xgifb/Kconfig"
-source "drivers/staging/mrst-touchscreen/Kconfig"
-
source "drivers/staging/msm/Kconfig"
source "drivers/staging/lirc/Kconfig"
obj-$(CONFIG_VIDEO_GO7007) += go7007/
obj-$(CONFIG_VIDEO_CX25821) += cx25821/
obj-$(CONFIG_VIDEO_TM6000) += tm6000/
+ obj-$(CONFIG_VIDEO_CPIA) += cpia/
+ obj-$(CONFIG_VIDEO_STRADIS) += stradis/
obj-$(CONFIG_LIRC_STAGING) += lirc/
obj-$(CONFIG_USB_IP_COMMON) += usbip/
obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_TI_ST) += ti-st/
obj-$(CONFIG_ADIS16255) += adis16255/
obj-$(CONFIG_FB_XGI) += xgifb/
-obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
obj-$(CONFIG_MSM_STAGING) += msm/
obj-$(CONFIG_EASYCAP) += easycap/
obj-$(CONFIG_SOLO6X10) += solo6x10/
config VIDEO_CX25821
tristate "Conexant cx25821 support"
depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+ depends on BKL # please fix
select I2C_ALGOBIT
select VIDEO_BTCX
select VIDEO_TVEEPROM
- select VIDEO_IR
+ depends on VIDEO_IR
select VIDEOBUF_DVB
select VIDEOBUF_DMA_SG
select VIDEO_CX25840
config VIDEO_GO7007
tristate "WIS GO7007 MPEG encoder support"
depends on VIDEO_DEV && PCI && I2C && INPUT
+ depends on BKL # please fix
depends on SND
select VIDEOBUF_DMA_SG
- select VIDEO_IR
+ depends on VIDEO_IR
select VIDEO_TUNER
select VIDEO_TVEEPROM
select SND_PCM
static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
int retval = 0;
- unsigned long value = 0;
- unsigned int ivalue;
+ __u32 value = 0;
unsigned long hw_flags;
if (cmd == LIRC_GET_FEATURES)
case LIRC_GET_FEATURES:
case LIRC_GET_SEND_MODE:
case LIRC_GET_REC_MODE:
- retval = put_user(value, (unsigned long *) arg);
+ retval = put_user(value, (__u32 *) arg);
break;
case LIRC_SET_SEND_MODE:
case LIRC_SET_REC_MODE:
- retval = get_user(value, (unsigned long *) arg);
+ retval = get_user(value, (__u32 *) arg);
break;
case LIRC_SET_SEND_CARRIER:
- retval = get_user(ivalue, (unsigned int *) arg);
+ retval = get_user(value, (__u32 *) arg);
if (retval)
return retval;
- ivalue /= 1000;
- if (ivalue > IT87_CIR_FREQ_MAX ||
- ivalue < IT87_CIR_FREQ_MIN)
+ value /= 1000;
+ if (value > IT87_CIR_FREQ_MAX ||
+ value < IT87_CIR_FREQ_MIN)
return -EINVAL;
- it87_freq = ivalue;
+ it87_freq = value;
spin_lock_irqsave(&hardware_lock, hw_flags);
outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) |
.write = lirc_write,
.poll = lirc_poll,
.unlocked_ioctl = lirc_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = lirc_ioctl,
+ #endif
.open = lirc_open,
.release = lirc_close,
+ .llseek = noop_llseek,
};
static int set_use_inc(void *data)
printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
}
- /* SECTION: PNP for ITE8704/18 */
+ /* SECTION: PNP for ITE8704/13/18 */
static const struct pnp_device_id pnp_dev_table[] = {
{"ITE8704", 0},
+ {"ITE8713", 0},
{}
};
static int init_timing_params(unsigned int new_duty_cycle,
unsigned int new_freq)
{
- unsigned long long loops_per_sec, work;
+ __u64 loops_per_sec, work;
duty_cycle = new_duty_cycle;
freq = new_freq;
static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
int result;
- unsigned long value;
- unsigned int ivalue;
+ __u32 value;
switch (cmd) {
case LIRC_GET_SEND_MODE:
result = put_user(LIRC_SEND2MODE
(hardware[type].features&LIRC_CAN_SEND_MASK),
- (unsigned long *) arg);
+ (__u32 *) arg);
if (result)
return result;
break;
if (!(hardware[type].features&LIRC_CAN_SEND_MASK))
return -ENOIOCTLCMD;
- result = get_user(value, (unsigned long *) arg);
+ result = get_user(value, (__u32 *) arg);
if (result)
return result;
/* only LIRC_MODE_PULSE supported */
if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE))
return -ENOIOCTLCMD;
- result = get_user(ivalue, (unsigned int *) arg);
+ result = get_user(value, (__u32 *) arg);
if (result)
return result;
- if (ivalue <= 0 || ivalue > 100)
+ if (value <= 0 || value > 100)
return -EINVAL;
- return init_timing_params(ivalue, freq);
+ return init_timing_params(value, freq);
break;
case LIRC_SET_SEND_CARRIER:
if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER))
return -ENOIOCTLCMD;
- result = get_user(ivalue, (unsigned int *) arg);
+ result = get_user(value, (__u32 *) arg);
if (result)
return result;
- if (ivalue > 500000 || ivalue < 20000)
+ if (value > 500000 || value < 20000)
return -EINVAL;
- return init_timing_params(duty_cycle, ivalue);
+ return init_timing_params(duty_cycle, value);
break;
default:
.owner = THIS_MODULE,
.write = lirc_write,
.unlocked_ioctl = lirc_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = lirc_ioctl,
+ #endif
.read = lirc_dev_fop_read,
.poll = lirc_dev_fop_poll,
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
+ .llseek = no_llseek,
};
static struct lirc_driver driver = {
static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
int retval = 0;
- unsigned long value = 0;
+ __u32 value = 0;
#ifdef LIRC_ON_SA1100
- unsigned int ivalue;
if (cmd == LIRC_GET_FEATURES)
value = LIRC_CAN_SEND_PULSE |
case LIRC_GET_FEATURES:
case LIRC_GET_SEND_MODE:
case LIRC_GET_REC_MODE:
- retval = put_user(value, (unsigned long *) arg);
+ retval = put_user(value, (__u32 *) arg);
break;
case LIRC_SET_SEND_MODE:
case LIRC_SET_REC_MODE:
- retval = get_user(value, (unsigned long *) arg);
+ retval = get_user(value, (__u32 *) arg);
break;
#ifdef LIRC_ON_SA1100
case LIRC_SET_SEND_DUTY_CYCLE:
- retval = get_user(ivalue, (unsigned int *) arg);
+ retval = get_user(value, (__u32 *) arg);
if (retval)
return retval;
- if (ivalue <= 0 || ivalue > 100)
+ if (value <= 0 || value > 100)
return -EINVAL;
- /* (ivalue/100)*(1000000/freq) */
- duty_cycle = ivalue;
+ /* (value/100)*(1000000/freq) */
+ duty_cycle = value;
pulse_width = (unsigned long) duty_cycle*10000/freq;
space_width = (unsigned long) 1000000L/freq-pulse_width;
if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
break;
case LIRC_SET_SEND_CARRIER:
- retval = get_user(ivalue, (unsigned int *) arg);
+ retval = get_user(value, (__u32 *) arg);
if (retval)
return retval;
- if (ivalue > 500000 || ivalue < 20000)
+ if (value > 500000 || value < 20000)
return -EINVAL;
- freq = ivalue;
+ freq = value;
pulse_width = (unsigned long) duty_cycle*10000/freq;
space_width = (unsigned long) 1000000L/freq-pulse_width;
if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
.write = lirc_write,
.poll = lirc_poll,
.unlocked_ioctl = lirc_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = lirc_ioctl,
+ #endif
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
+ .llseek = no_llseek,
};
static int set_use_inc(void *data)
writel(tmp, engine + 0x1C);
}
- if (op != VIA_BITBLT_COLOR)
+ if (op == VIA_BITBLT_FILL) {
+ writel(fg_color, engine + 0x58);
+ } else if (op == VIA_BITBLT_MONO) {
writel(fg_color, engine + 0x4C);
-
- if (op == VIA_BITBLT_MONO)
writel(bg_color, engine + 0x50);
+ }
if (op == VIA_BITBLT_FILL)
ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
return 0;
}
-int viafb_init_engine(struct fb_info *info)
+int viafb_setup_engine(struct fb_info *info)
{
struct viafb_par *viapar = info->par;
void __iomem *engine;
- int highest_reg, i;
- u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
- vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
+ u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
engine = viapar->shared->vdev->engine_mmio;
if (!engine) {
return -ENOMEM;
}
- /* Initialize registers to reset the 2D engine */
- switch (viapar->shared->chip_info.twod_engine) {
- case VIA_2D_ENG_M1:
- highest_reg = 0x5c;
- break;
- default:
- highest_reg = 0x40;
- break;
- }
- for (i = 0; i <= highest_reg; i += 4)
- writel(0x0, engine + i);
-
switch (chip_name) {
case UNICHROME_CLE266:
case UNICHROME_K400:
break;
case UNICHROME_VX800:
case UNICHROME_VX855:
+ case UNICHROME_VX900:
viapar->shared->hw_bitblt = hw_bitblt_2;
break;
default:
viapar->shared->vq_vram_addr = viapar->fbmem_free;
viapar->fbmem_used += VQ_SIZE;
- #if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE)
+ #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
/*
* Set aside a chunk of framebuffer memory for the camera
* driver. Someday this driver probably needs a proper allocator
viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
#endif
+ viafb_reset_engine(viapar);
+ return 0;
+}
+
+void viafb_reset_engine(struct viafb_par *viapar)
+{
+ void __iomem *engine = viapar->shared->vdev->engine_mmio;
+ int highest_reg, i;
+ u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
+ vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
+
+ /* Initialize registers to reset the 2D engine */
+ switch (viapar->shared->chip_info.twod_engine) {
+ case VIA_2D_ENG_M1:
+ highest_reg = 0x5c;
+ break;
+ default:
+ highest_reg = 0x40;
+ break;
+ }
+ for (i = 0; i <= highest_reg; i += 4)
+ writel(0x0, engine + i);
+
/* Init AGP and VQ regs */
switch (chip_name) {
case UNICHROME_K8M890:
case UNICHROME_P4M900:
case UNICHROME_VX800:
case UNICHROME_VX855:
+ case UNICHROME_VX900:
writel(0x00100000, engine + VIA_REG_CR_TRANSET);
writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
case UNICHROME_P4M900:
case UNICHROME_VX800:
case UNICHROME_VX855:
+ case UNICHROME_VX900:
vq_start_low |= 0x20000000;
vq_end_low |= 0x20000000;
vq_high |= 0x20000000;
writel(0x0, engine + VIA_REG_CURSOR_ORG);
writel(0x0, engine + VIA_REG_CURSOR_BG);
writel(0x0, engine + VIA_REG_CURSOR_FG);
- return 0;
+ return;
}
void viafb_show_hw_cursor(struct fb_info *info, int Status)
* The default port config.
*/
static struct via_port_cfg adap_configs[] = {
- [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_OFF, VIASR, 0x26 },
+ [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
[VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
[VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
[VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
EXPORT_SYMBOL_GPL(viafb_irq_disable);
/* ---------------------------------------------------------------------- */
+ /*
+ * Currently, the camera driver is the only user of the DMA code, so we
+ * only compile it in if the camera driver is being built. Chances are,
+ * most viafb systems will not need to have this extra code for a while.
+ * As soon as another user comes long, the ifdef can be removed.
+ */
+ #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
/*
* Access to the DMA engine. This currently provides what the camera
* driver needs (i.e. outgoing only) but is easily expandable if need
return 0;
}
EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
-
+ #endif /* CONFIG_VIDEO_VIA_CAMERA */
/* ---------------------------------------------------------------------- */
/*
static u16 via_function3[] = {
CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
- P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3,
+ P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3,
};
/* Get the BIOS-configured framebuffer size from PCI configuration space
case P4M900_FUNCTION3:
case VX800_FUNCTION3:
case VX855_FUNCTION3:
+ case VX900_FUNCTION3:
/*case CN750_FUNCTION3: */
offset = 0xA0;
break;
* Eventually we want to move away from mapping this
* entire region.
*/
- vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
+ if (vdev->chip_type == UNICHROME_VX900)
+ vdev->fbmem_start = pci_resource_start(vdev->pdev, 2);
+ else
+ vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
if (ret < 0)
goto out_unmap;
},
{
.name = "viafb-i2c",
- }
+ },
+ #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
+ {
+ .name = "viafb-camera",
+ },
+ #endif
};
#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
.driver_data = UNICHROME_VX800 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
.driver_data = UNICHROME_VX855 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID),
+ .driver_data = UNICHROME_VX900 },
{ }
};
MODULE_DEVICE_TABLE(pci, via_pci_table);
.id_table = via_pci_table,
.probe = via_pci_probe,
.remove = __devexit_p(via_pci_remove),
+#ifdef CONFIG_PM
+ .suspend = viafb_suspend,
+ .resume = viafb_resume,
+#endif
};
static int __init via_core_init(void)
header-y += radeonfb.h
header-y += random.h
header-y += raw.h
+header-y += rds.h
header-y += reboot.h
header-y += reiserfs_fs.h
header-y += reiserfs_xattr.h
header-y += vhost.h
header-y += videodev.h
header-y += videodev2.h
- header-y += videotext.h
header-y += virtio_9p.h
header-y += virtio_balloon.h
header-y += virtio_blk.h
#define IR_TYPE_RC6 (1 << 2) /* Philips RC6 protocol */
#define IR_TYPE_JVC (1 << 3) /* JVC protocol */
#define IR_TYPE_SONY (1 << 4) /* Sony12/15/20 protocol */
+ #define IR_TYPE_RC5_SZ (1 << 5) /* RC5 variant used by Streamzap */
#define IR_TYPE_LIRC (1 << 30) /* Pass raw IR to lirc userspace */
#define IR_TYPE_OTHER (1u << 31)
#define IR_TYPE_ALL (IR_TYPE_RC5 | IR_TYPE_NEC | IR_TYPE_RC6 | \
IR_TYPE_JVC | IR_TYPE_SONY | IR_TYPE_LIRC | \
- IR_TYPE_OTHER)
+ IR_TYPE_RC5_SZ | IR_TYPE_OTHER)
struct ir_scancode {
u32 scancode;
unsigned int len; /* Used number of entries */
unsigned int alloc; /* Size of *scan in bytes */
u64 ir_type;
- char *name;
+ const char *name;
spinlock_t lock;
};
/* Names of the several keytables defined in-kernel */
#define RC_MAP_ADSTECH_DVB_T_PCI "rc-adstech-dvb-t-pci"
+ #define RC_MAP_ALINK_DTU_M "rc-alink-dtu-m"
+ #define RC_MAP_ANYSEE "rc-anysee"
#define RC_MAP_APAC_VIEWCOMP "rc-apac-viewcomp"
#define RC_MAP_ASUS_PC39 "rc-asus-pc39"
#define RC_MAP_ATI_TV_WONDER_HD_600 "rc-ati-tv-wonder-hd-600"
#define RC_MAP_AVERMEDIA_DVBT "rc-avermedia-dvbt"
#define RC_MAP_AVERMEDIA_M135A "rc-avermedia-m135a"
#define RC_MAP_AVERMEDIA_M733A_RM_K6 "rc-avermedia-m733a-rm-k6"
+ #define RC_MAP_AVERMEDIA_RM_KS "rc-avermedia-rm-ks"
#define RC_MAP_AVERMEDIA "rc-avermedia"
#define RC_MAP_AVERTV_303 "rc-avertv-303"
+ #define RC_MAP_AZUREWAVE_AD_TU700 "rc-azurewave-ad-tu700"
#define RC_MAP_BEHOLD_COLUMBUS "rc-behold-columbus"
#define RC_MAP_BEHOLD "rc-behold"
#define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old"
#define RC_MAP_CINERGY "rc-cinergy"
#define RC_MAP_DIB0700_NEC_TABLE "rc-dib0700-nec"
#define RC_MAP_DIB0700_RC5_TABLE "rc-dib0700-rc5"
+ #define RC_MAP_DIGITALNOW_TINYTWIN "rc-digitalnow-tinytwin"
+ #define RC_MAP_DIGITTRADE "rc-digittrade"
#define RC_MAP_DM1105_NEC "rc-dm1105-nec"
#define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro"
#define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t"
#define RC_MAP_KAIOMY "rc-kaiomy"
#define RC_MAP_KWORLD_315U "rc-kworld-315u"
#define RC_MAP_KWORLD_PLUS_TV_ANALOG "rc-kworld-plus-tv-analog"
+ #define RC_MAP_LEADTEK_Y04G0051 "rc-leadtek-y04g0051"
#define RC_MAP_LIRC "rc-lirc"
+ #define RC_MAP_LME2510 "rc-lme2510"
#define RC_MAP_MANLI "rc-manli"
+ #define RC_MAP_MSI_DIGIVOX_II "rc-msi-digivox-ii"
+ #define RC_MAP_MSI_DIGIVOX_III "rc-msi-digivox-iii"
#define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus"
#define RC_MAP_MSI_TVANYWHERE "rc-msi-tvanywhere"
#define RC_MAP_NEBULA "rc-nebula"
#define RC_MAP_PURPLETV "rc-purpletv"
#define RC_MAP_PV951 "rc-pv951"
#define RC_MAP_RC5_HAUPPAUGE_NEW "rc-rc5-hauppauge-new"
- #define RC_MAP_RC5_STREAMZAP "rc-rc5-streamzap"
#define RC_MAP_RC5_TV "rc-rc5-tv"
#define RC_MAP_RC6_MCE "rc-rc6-mce"
#define RC_MAP_REAL_AUDIO_220_32_KEYS "rc-real-audio-220-32-keys"
+ #define RC_MAP_STREAMZAP "rc-streamzap"
#define RC_MAP_TBS_NEC "rc-tbs-nec"
#define RC_MAP_TERRATEC_CINERGY_XS "rc-terratec-cinergy-xs"
+ #define RC_MAP_TERRATEC_SLIM "rc-terratec-slim"
#define RC_MAP_TEVII_NEC "rc-tevii-nec"
+ #define RC_MAP_TOTAL_MEDIA_IN_HAND "rc-total-media-in-hand"
+ #define RC_MAP_TREKSTOR "rc-trekstor"
#define RC_MAP_TT_1500 "rc-tt-1500"
+ #define RC_MAP_TWINHAN_VP1027_DVBS "rc-twinhan1027"
#define RC_MAP_VIDEOMATE_S350 "rc-videomate-s350"
#define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr"
#define RC_MAP_WINFAST "rc-winfast"