[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20081105194738.19407.31117.stgit@localhost>
Date: Wed, 05 Nov 2008 14:47:38 -0500
From: Jon Smirl <jonsmirl@...il.com>
To: linux-kernel@...r.kernel.org
Subject: [RFC PATCH V4 1/6] Minimal changes to the core input system
Minimal changes to the core input system. The bulk of IR support loads as a module. These changes are passive if the rest of IR isn't loaded.
Jon Smirl
<jonsmirl@...il.com>
---
drivers/input/evdev.c | 55 +++++++++++++++++++++++++++++
drivers/input/input.c | 17 +++++++++
include/linux/input.h | 75 +++++++++++++++++++++++++++++++++++++++
include/linux/mod_devicetable.h | 3 ++
4 files changed, 150 insertions(+), 0 deletions(-)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 1070db3..33a01dc 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -328,6 +328,14 @@ struct ff_effect_compat {
} u;
};
+struct ir_command_compat {
+ __u32 protocol;
+ __u32 device;
+ __u32 command;
+ __u32 transmitters;
+};
+
+
/* Note to the author of this code: did it ever occur to
you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
@@ -432,6 +440,32 @@ static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
return 0;
}
+static int evdev_ir_send_from_user(const char __user *buffer, size_t size,
+ struct ir_command *ir_command)
+{
+ if (COMPAT_TEST) {
+ struct ir_command_compat *compat_ir_command;
+
+ if (size != sizeof(struct ir_command_compat))
+ return -EINVAL;
+
+ compat_ir_command = (struct ir_command_compat *)ir_command;
+
+ if (copy_from_user(compat_ir_command, buffer,
+ sizeof(struct ir_command_compat)))
+ return -EFAULT;
+
+ } else {
+ if (size != sizeof(struct ir_command))
+ return -EINVAL;
+
+ if (copy_from_user(ir_command, buffer, sizeof(struct ir_command)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
#else
static inline size_t evdev_event_size(void)
@@ -469,6 +503,18 @@ static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
return 0;
}
+static int evdev_ir_send_from_user(const char __user *buffer, size_t size,
+ struct ir_command *ir_command)
+{
+ if (size != sizeof(struct ir_command))
+ return -EINVAL;
+
+ if (copy_from_user(ir_command, buffer, sizeof(struct ir_command)))
+ return -EFAULT;
+
+ return 0;
+}
+
#endif /* CONFIG_COMPAT */
static ssize_t evdev_write(struct file *file, const char __user *buffer,
@@ -695,6 +741,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
struct ff_effect effect;
+ struct ir_command ir_command;
int __user *ip = (int __user *)p;
int i, t, u, v;
int error;
@@ -859,6 +906,14 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return 0;
}
+
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOIRSEND)) {
+
+ if (evdev_ir_send_from_user(p, _IOC_SIZE(cmd), &ir_command))
+ return -EFAULT;
+
+ return input_ir_send(dev, &ir_command, file);
+ }
}
}
return -EINVAL;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c13ced3..0a9b15a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -240,6 +240,10 @@ static void input_handle_event(struct input_dev *dev,
case EV_PWR:
disposition = INPUT_PASS_TO_ALL;
break;
+
+ case EV_IR:
+ disposition = INPUT_PASS_TO_ALL;
+ break;
}
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
@@ -693,6 +697,7 @@ static const struct input_device_id *input_match_device(const struct input_devic
MATCH_BIT(sndbit, SND_MAX);
MATCH_BIT(ffbit, FF_MAX);
MATCH_BIT(swbit, SW_MAX);
+ MATCH_BIT(irbit, IR_MAX);
return id;
}
@@ -815,6 +820,8 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
input_seq_print_bitmap(seq, "FF", dev->ffbit, FF_MAX);
if (test_bit(EV_SW, dev->evbit))
input_seq_print_bitmap(seq, "SW", dev->swbit, SW_MAX);
+ if (test_bit(EV_IR, dev->evbit))
+ input_seq_print_bitmap(seq, "IR", dev->irbit, IR_MAX);
seq_putc(seq, '\n');
@@ -992,6 +999,8 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
'f', id->ffbit, 0, FF_MAX);
len += input_print_modalias_bits(buf + len, size - len,
'w', id->swbit, 0, SW_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'i', id->irbit, 0, IR_MAX);
if (add_cr)
len += snprintf(buf + len, max(size - len, 0), "\n");
@@ -1093,6 +1102,7 @@ INPUT_DEV_CAP_ATTR(LED, led);
INPUT_DEV_CAP_ATTR(SND, snd);
INPUT_DEV_CAP_ATTR(FF, ff);
INPUT_DEV_CAP_ATTR(SW, sw);
+INPUT_DEV_CAP_ATTR(IR, ir);
static struct attribute *input_dev_caps_attrs[] = {
&dev_attr_ev.attr,
@@ -1104,6 +1114,7 @@ static struct attribute *input_dev_caps_attrs[] = {
&dev_attr_snd.attr,
&dev_attr_ff.attr,
&dev_attr_sw.attr,
+ &dev_attr_ir.attr,
NULL
};
@@ -1221,6 +1232,8 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
INPUT_ADD_HOTPLUG_BM_VAR("FF=", dev->ffbit, FF_MAX);
if (test_bit(EV_SW, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
+ if (test_bit(EV_IR, dev->evbit))
+ INPUT_ADD_HOTPLUG_BM_VAR("IR=", dev->irbit, IR_MAX);
INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
@@ -1333,6 +1346,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
__set_bit(code, dev->ffbit);
break;
+ case EV_IR:
+ __set_bit(code, dev->irbit);
+ break;
+
case EV_PWR:
/* do nothing */
break;
diff --git a/include/linux/input.h b/include/linux/input.h
index b86fb55..95e385f 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -79,6 +79,8 @@ struct input_absinfo {
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
+#define EVIOIRSEND _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ir_command)) /* send an IR command */
+
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
/*
@@ -97,6 +99,7 @@ struct input_absinfo {
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
+#define EV_IR 0x18
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
@@ -959,6 +962,56 @@ struct ff_effect {
#define FF_MAX 0x7f
#define FF_CNT (FF_MAX+1)
+/*
+ * IR Support
+ */
+
+#define IR_PROTOCOL_RESERVED 0
+#define IR_PROTOCOL_JVC 1
+#define IR_PROTOCOL_NEC 2
+#define IR_PROTOCOL_NOKIA 3
+#define IR_PROTOCOL_SHARP 4
+#define IR_PROTOCOL_SONY_12 5
+#define IR_PROTOCOL_SONY_15 6
+#define IR_PROTOCOL_SONY_20 7
+#define IR_PROTOCOL_PHILIPS_RC5 8
+#define IR_PROTOCOL_PHILIPS_RC6 9
+#define IR_PROTOCOL_PHILIPS_RCMM 10
+#define IR_PROTOCOL_PHILIPS_RECS80 11
+#define IR_PROTOCOL_RCA 12
+#define IR_PROTOCOL_ITT 13
+
+#define IR_PROTOCOL 1
+#define IR_DEVICE 2
+#define IR_COMMAND 3
+
+#define IR_CAP_RECEIVE_BASEBAND 0
+#define IR_CAP_RECEIVE_36K 1
+#define IR_CAP_RECEIVE_38K 2
+#define IR_CAP_RECEIVE_40K 3
+#define IR_CAP_RECEIVE_56K 4
+#define IR_CAP_SEND_BASEBAND 5
+#define IR_CAP_SEND_36K 6
+#define IR_CAP_SEND_38K 7
+#define IR_CAP_SEND_40K 8
+#define IR_CAP_SEND_56K 9
+#define IR_CAP_XMITTER_1 10
+#define IR_CAP_XMITTER_2 11
+#define IR_CAP_XMITTER_3 12
+#define IR_CAP_XMITTER_4 13
+#define IR_CAP_RECEIVE_RAW 14
+#define IR_CAP_SEND_RAW 15
+#define IR_MAX 0x0f
+#define IR_CNT IR_MAX + 1
+
+struct ir_command {
+ __u32 protocol;
+ __u32 device;
+ __u32 command;
+ __u32 transmitters;
+};
+
+
#ifdef __KERNEL__
/*
@@ -986,6 +1039,7 @@ struct ff_effect {
* @sndbit: bitmap of sound effects supported by the device
* @ffbit: bitmap of force feedback effects supported by the device
* @swbit: bitmap of switches present on the device
+ * @irbit: bitmap of capabilies of the IR hardware
* @keycodemax: size of keycode table
* @keycodesize: size of elements in keycode table
* @keycode: map of scancodes to keycodes for this device
@@ -1058,6 +1112,7 @@ struct input_dev {
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
+ unsigned long irbit[BITS_TO_LONGS(IR_CNT)];
unsigned int keycodemax;
unsigned int keycodesize;
@@ -1066,6 +1121,7 @@ struct input_dev {
int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
struct ff_device *ff;
+ struct ir_device *ir;
unsigned int repeat_key;
struct timer_list timer;
@@ -1301,6 +1357,11 @@ static inline void input_report_switch(struct input_dev *dev, unsigned int code,
input_event(dev, EV_SW, code, !!value);
}
+static inline void input_report_ir(struct input_dev *dev, unsigned int code, int value)
+{
+ input_event(dev, EV_IR, code, value);
+}
+
static inline void input_sync(struct input_dev *dev)
{
input_event(dev, EV_SYN, SYN_REPORT, 0);
@@ -1379,5 +1440,19 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file);
int input_ff_create_memless(struct input_dev *dev, void *data,
int (*play_effect)(struct input_dev *, void *, struct ff_effect *));
+/**
+ * IR support functions
+ */
+
+typedef int (*send_func)(void *private, unsigned int *buffer, unsigned int count,
+ unsigned int frequency, unsigned int xmitters);
+
+int input_ir_create(struct input_dev *dev, void *private, send_func send);
+void input_ir_destroy(struct input_dev *dev);
+
+void input_ir_decode(struct input_dev *dev, unsigned int delta, unsigned int bit);
+int input_ir_send(struct input_dev *dev, struct ir_command *ir_command, struct file *file);
+int input_ir_register(struct input_dev *dev);
+
#endif
#endif
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 97b91d1..ea35367 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -293,6 +293,7 @@ struct pcmcia_device_id {
#define INPUT_DEVICE_ID_SND_MAX 0x07
#define INPUT_DEVICE_ID_FF_MAX 0x7f
#define INPUT_DEVICE_ID_SW_MAX 0x0f
+#define INPUT_DEVICE_ID_IR_MAX 0x0f
#define INPUT_DEVICE_ID_MATCH_BUS 1
#define INPUT_DEVICE_ID_MATCH_VENDOR 2
@@ -308,6 +309,7 @@ struct pcmcia_device_id {
#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x0400
#define INPUT_DEVICE_ID_MATCH_FFBIT 0x0800
#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
+#define INPUT_DEVICE_ID_MATCH_IRBIT 0x2000
struct input_device_id {
@@ -327,6 +329,7 @@ struct input_device_id {
kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t irbit[INPUT_DEVICE_ID_IR_MAX / BITS_PER_LONG + 1];
kernel_ulong_t driver_info;
};
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists