diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2010-07-31 10:59:23 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-08 22:43:00 -0400 |
commit | e589333f346b58f8da5bb8152e1219c52d375ccc (patch) | |
tree | 4ff05f4f9c5a06c532084ed46b3612ebeec1e21c | |
parent | 4a702ebf61120906696f8366dd2be0653b1643e3 (diff) |
V4L/DVB: IR: extend interfaces to support more device settings
LIRC: add new IOCTL that enables learning mode (wide band receiver)
Still missing features: carrier report & timeout reports.
Will need to pack these into ir_raw_event
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | Documentation/DocBook/v4l/lirc_device_interface.xml | 16 | ||||
-rw-r--r-- | drivers/media/IR/ir-core-priv.h | 1 | ||||
-rw-r--r-- | drivers/media/IR/ir-lirc-codec.c | 112 | ||||
-rw-r--r-- | include/media/ir-core.h | 12 | ||||
-rw-r--r-- | include/media/lirc.h | 5 |
5 files changed, 125 insertions, 21 deletions
diff --git a/Documentation/DocBook/v4l/lirc_device_interface.xml b/Documentation/DocBook/v4l/lirc_device_interface.xml index 0413234023d4..68134c0ab4d1 100644 --- a/Documentation/DocBook/v4l/lirc_device_interface.xml +++ b/Documentation/DocBook/v4l/lirc_device_interface.xml | |||
@@ -229,6 +229,22 @@ on working with the default settings initially.</para> | |||
229 | and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para> | 229 | and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para> |
230 | </listitem> | 230 | </listitem> |
231 | </varlistentry> | 231 | </varlistentry> |
232 | <varlistentry> | ||
233 | <term>LIRC_SET_WIDEBAND_RECEIVER</term> | ||
234 | <listitem> | ||
235 | <para>Some receivers are equipped with special wide band receiver which is intended | ||
236 | to be used to learn output of existing remote. | ||
237 | Calling that ioctl with (1) will enable it, and with (0) disable it. | ||
238 | This might be useful of receivers that have otherwise narrow band receiver | ||
239 | that prevents them to be used with some remotes. | ||
240 | Wide band receiver might also be more precise | ||
241 | On the other hand its disadvantage it usually reduced range of reception. | ||
242 | Note: wide band receiver might be implictly enabled if you enable | ||
243 | carrier reports. In that case it will be disabled as soon as you disable | ||
244 | carrier reports. Trying to disable wide band receiver while carrier | ||
245 | reports are active will do nothing.</para> | ||
246 | </listitem> | ||
247 | </varlistentry> | ||
232 | </variablelist> | 248 | </variablelist> |
233 | 249 | ||
234 | </section> | 250 | </section> |
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index 8053e3b84272..a85a8c7c905a 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h | |||
@@ -79,6 +79,7 @@ struct ir_raw_event_ctrl { | |||
79 | struct lirc_codec { | 79 | struct lirc_codec { |
80 | struct ir_input_dev *ir_dev; | 80 | struct ir_input_dev *ir_dev; |
81 | struct lirc_driver *drv; | 81 | struct lirc_driver *drv; |
82 | int carrier_low; | ||
82 | } lirc; | 83 | } lirc; |
83 | }; | 84 | }; |
84 | 85 | ||
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 8ca01fd67139..77b5946413c0 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c | |||
@@ -46,7 +46,6 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
46 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", | 46 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", |
47 | TO_US(ev.duration), TO_STR(ev.pulse)); | 47 | TO_US(ev.duration), TO_STR(ev.pulse)); |
48 | 48 | ||
49 | |||
50 | sample = ev.duration / 1000; | 49 | sample = ev.duration / 1000; |
51 | if (ev.pulse) | 50 | if (ev.pulse) |
52 | sample |= PULSE_BIT; | 51 | sample |= PULSE_BIT; |
@@ -96,13 +95,14 @@ out: | |||
96 | return ret; | 95 | return ret; |
97 | } | 96 | } |
98 | 97 | ||
99 | static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | 98 | static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, |
99 | unsigned long __user arg) | ||
100 | { | 100 | { |
101 | struct lirc_codec *lirc; | 101 | struct lirc_codec *lirc; |
102 | struct ir_input_dev *ir_dev; | 102 | struct ir_input_dev *ir_dev; |
103 | int ret = 0; | 103 | int ret = 0; |
104 | void *drv_data; | 104 | void *drv_data; |
105 | unsigned long val; | 105 | unsigned long val = 0; |
106 | 106 | ||
107 | lirc = lirc_get_pdata(filep); | 107 | lirc = lirc_get_pdata(filep); |
108 | if (!lirc) | 108 | if (!lirc) |
@@ -114,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar | |||
114 | 114 | ||
115 | drv_data = ir_dev->props->priv; | 115 | drv_data = ir_dev->props->priv; |
116 | 116 | ||
117 | switch (cmd) { | 117 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
118 | case LIRC_SET_TRANSMITTER_MASK: | ||
119 | ret = get_user(val, (unsigned long *)arg); | 118 | ret = get_user(val, (unsigned long *)arg); |
120 | if (ret) | 119 | if (ret) |
121 | return ret; | 120 | return ret; |
121 | } | ||
122 | |||
123 | switch (cmd) { | ||
124 | |||
125 | /* legacy support */ | ||
126 | case LIRC_GET_SEND_MODE: | ||
127 | val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; | ||
128 | break; | ||
129 | |||
130 | case LIRC_SET_SEND_MODE: | ||
131 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) | ||
132 | return -EINVAL; | ||
133 | break; | ||
122 | 134 | ||
123 | if (ir_dev->props && ir_dev->props->s_tx_mask) | 135 | /* TX settings */ |
136 | case LIRC_SET_TRANSMITTER_MASK: | ||
137 | if (ir_dev->props->s_tx_mask) | ||
124 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); | 138 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); |
125 | else | 139 | else |
126 | return -EINVAL; | 140 | return -EINVAL; |
127 | break; | 141 | break; |
128 | 142 | ||
129 | case LIRC_SET_SEND_CARRIER: | 143 | case LIRC_SET_SEND_CARRIER: |
130 | ret = get_user(val, (unsigned long *)arg); | 144 | if (ir_dev->props->s_tx_carrier) |
131 | if (ret) | ||
132 | return ret; | ||
133 | |||
134 | if (ir_dev->props && ir_dev->props->s_tx_carrier) | ||
135 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); | 145 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); |
136 | else | 146 | else |
137 | return -EINVAL; | 147 | return -EINVAL; |
138 | break; | 148 | break; |
139 | 149 | ||
140 | case LIRC_GET_SEND_MODE: | 150 | case LIRC_SET_SEND_DUTY_CYCLE: |
141 | val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; | 151 | if (!ir_dev->props->s_tx_duty_cycle) |
142 | ret = put_user(val, (unsigned long *)arg); | 152 | return -ENOSYS; |
153 | |||
154 | if (val <= 0 || val >= 100) | ||
155 | return -EINVAL; | ||
156 | |||
157 | ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); | ||
143 | break; | 158 | break; |
144 | 159 | ||
145 | case LIRC_SET_SEND_MODE: | 160 | /* RX settings */ |
146 | ret = get_user(val, (unsigned long *)arg); | 161 | case LIRC_SET_REC_CARRIER: |
147 | if (ret) | 162 | if (ir_dev->props->s_rx_carrier_range) |
148 | return ret; | 163 | ret = ir_dev->props->s_rx_carrier_range( |
164 | ir_dev->props->priv, | ||
165 | ir_dev->raw->lirc.carrier_low, val); | ||
166 | else | ||
167 | return -ENOSYS; | ||
149 | 168 | ||
150 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) | 169 | if (!ret) |
170 | ir_dev->raw->lirc.carrier_low = 0; | ||
171 | break; | ||
172 | |||
173 | case LIRC_SET_REC_CARRIER_RANGE: | ||
174 | if (val >= 0) | ||
175 | ir_dev->raw->lirc.carrier_low = val; | ||
176 | break; | ||
177 | |||
178 | |||
179 | case LIRC_GET_REC_RESOLUTION: | ||
180 | val = ir_dev->props->rx_resolution; | ||
181 | break; | ||
182 | |||
183 | case LIRC_SET_WIDEBAND_RECEIVER: | ||
184 | if (ir_dev->props->s_learning_mode) | ||
185 | return ir_dev->props->s_learning_mode( | ||
186 | ir_dev->props->priv, !!val); | ||
187 | else | ||
188 | return -ENOSYS; | ||
189 | |||
190 | /* Generic timeout support */ | ||
191 | case LIRC_GET_MIN_TIMEOUT: | ||
192 | if (!ir_dev->props->max_timeout) | ||
193 | return -ENOSYS; | ||
194 | val = ir_dev->props->min_timeout / 1000; | ||
195 | break; | ||
196 | |||
197 | case LIRC_GET_MAX_TIMEOUT: | ||
198 | if (!ir_dev->props->max_timeout) | ||
199 | return -ENOSYS; | ||
200 | val = ir_dev->props->max_timeout / 1000; | ||
201 | break; | ||
202 | |||
203 | case LIRC_SET_REC_TIMEOUT: | ||
204 | if (val < ir_dev->props->min_timeout || | ||
205 | val > ir_dev->props->max_timeout) | ||
151 | return -EINVAL; | 206 | return -EINVAL; |
207 | ir_dev->props->timeout = val * 1000; | ||
152 | break; | 208 | break; |
153 | 209 | ||
154 | default: | 210 | default: |
155 | return lirc_dev_fop_ioctl(filep, cmd, arg); | 211 | return lirc_dev_fop_ioctl(filep, cmd, arg); |
156 | } | 212 | } |
157 | 213 | ||
214 | if (_IOC_DIR(cmd) & _IOC_READ) | ||
215 | ret = put_user(val, (unsigned long *)arg); | ||
216 | |||
158 | return ret; | 217 | return ret; |
159 | } | 218 | } |
160 | 219 | ||
@@ -200,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev) | |||
200 | 259 | ||
201 | features = LIRC_CAN_REC_MODE2; | 260 | features = LIRC_CAN_REC_MODE2; |
202 | if (ir_dev->props->tx_ir) { | 261 | if (ir_dev->props->tx_ir) { |
262 | |||
203 | features |= LIRC_CAN_SEND_PULSE; | 263 | features |= LIRC_CAN_SEND_PULSE; |
204 | if (ir_dev->props->s_tx_mask) | 264 | if (ir_dev->props->s_tx_mask) |
205 | features |= LIRC_CAN_SET_TRANSMITTER_MASK; | 265 | features |= LIRC_CAN_SET_TRANSMITTER_MASK; |
206 | if (ir_dev->props->s_tx_carrier) | 266 | if (ir_dev->props->s_tx_carrier) |
207 | features |= LIRC_CAN_SET_SEND_CARRIER; | 267 | features |= LIRC_CAN_SET_SEND_CARRIER; |
268 | |||
269 | if (ir_dev->props->s_tx_duty_cycle) | ||
270 | features |= LIRC_CAN_SET_REC_DUTY_CYCLE; | ||
208 | } | 271 | } |
209 | 272 | ||
273 | if (ir_dev->props->s_rx_carrier_range) | ||
274 | features |= LIRC_CAN_SET_REC_CARRIER | | ||
275 | LIRC_CAN_SET_REC_CARRIER_RANGE; | ||
276 | |||
277 | if (ir_dev->props->s_learning_mode) | ||
278 | features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; | ||
279 | |||
280 | if (ir_dev->props->max_timeout) | ||
281 | features |= LIRC_CAN_SET_REC_TIMEOUT; | ||
282 | |||
283 | |||
210 | snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", | 284 | snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", |
211 | ir_dev->driver_name); | 285 | ir_dev->driver_name); |
212 | drv->minor = -1; | 286 | drv->minor = -1; |
diff --git a/include/media/ir-core.h b/include/media/ir-core.h index a781045aeed5..eb7fddf8f607 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h | |||
@@ -44,6 +44,8 @@ enum rc_driver_type { | |||
44 | * @timeout: optional time after which device stops sending data | 44 | * @timeout: optional time after which device stops sending data |
45 | * @min_timeout: minimum timeout supported by device | 45 | * @min_timeout: minimum timeout supported by device |
46 | * @max_timeout: maximum timeout supported by device | 46 | * @max_timeout: maximum timeout supported by device |
47 | * @rx_resolution : resolution (in ns) of input sampler | ||
48 | * @tx_resolution: resolution (in ns) of output sampler | ||
47 | * @priv: driver-specific data, to be used on the callbacks | 49 | * @priv: driver-specific data, to be used on the callbacks |
48 | * @change_protocol: allow changing the protocol used on hardware decoders | 50 | * @change_protocol: allow changing the protocol used on hardware decoders |
49 | * @open: callback to allow drivers to enable polling/irq when IR input device | 51 | * @open: callback to allow drivers to enable polling/irq when IR input device |
@@ -52,9 +54,12 @@ enum rc_driver_type { | |||
52 | * is opened. | 54 | * is opened. |
53 | * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs) | 55 | * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs) |
54 | * @s_tx_carrier: set transmit carrier frequency | 56 | * @s_tx_carrier: set transmit carrier frequency |
57 | * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%) | ||
58 | * @s_rx_carrier: inform driver about carrier it is expected to handle | ||
55 | * @tx_ir: transmit IR | 59 | * @tx_ir: transmit IR |
56 | * @s_idle: optional: enable/disable hardware idle mode, upon which, | 60 | * @s_idle: optional: enable/disable hardware idle mode, upon which, |
57 | * device doesn't interrupt host untill it sees IR data | 61 | device doesn't interrupt host until it sees IR pulses |
62 | * @s_learning_mode: enable wide band receiver used for learning | ||
58 | */ | 63 | */ |
59 | struct ir_dev_props { | 64 | struct ir_dev_props { |
60 | enum rc_driver_type driver_type; | 65 | enum rc_driver_type driver_type; |
@@ -65,6 +70,8 @@ struct ir_dev_props { | |||
65 | u32 min_timeout; | 70 | u32 min_timeout; |
66 | u32 max_timeout; | 71 | u32 max_timeout; |
67 | 72 | ||
73 | u32 rx_resolution; | ||
74 | u32 tx_resolution; | ||
68 | 75 | ||
69 | void *priv; | 76 | void *priv; |
70 | int (*change_protocol)(void *priv, u64 ir_type); | 77 | int (*change_protocol)(void *priv, u64 ir_type); |
@@ -72,8 +79,11 @@ struct ir_dev_props { | |||
72 | void (*close)(void *priv); | 79 | void (*close)(void *priv); |
73 | int (*s_tx_mask)(void *priv, u32 mask); | 80 | int (*s_tx_mask)(void *priv, u32 mask); |
74 | int (*s_tx_carrier)(void *priv, u32 carrier); | 81 | int (*s_tx_carrier)(void *priv, u32 carrier); |
82 | int (*s_tx_duty_cycle)(void *priv, u32 duty_cycle); | ||
83 | int (*s_rx_carrier_range)(void *priv, u32 min, u32 max); | ||
75 | int (*tx_ir)(void *priv, int *txbuf, u32 n); | 84 | int (*tx_ir)(void *priv, int *txbuf, u32 n); |
76 | void (*s_idle)(void *priv, int enable); | 85 | void (*s_idle)(void *priv, int enable); |
86 | int (*s_learning_mode)(void *priv, int enable); | ||
77 | }; | 87 | }; |
78 | 88 | ||
79 | struct ir_input_dev { | 89 | struct ir_input_dev { |
diff --git a/include/media/lirc.h b/include/media/lirc.h index 42c467c50519..6678a169fd9e 100644 --- a/include/media/lirc.h +++ b/include/media/lirc.h | |||
@@ -77,6 +77,7 @@ | |||
77 | #define LIRC_CAN_SET_REC_FILTER 0x08000000 | 77 | #define LIRC_CAN_SET_REC_FILTER 0x08000000 |
78 | 78 | ||
79 | #define LIRC_CAN_MEASURE_CARRIER 0x02000000 | 79 | #define LIRC_CAN_MEASURE_CARRIER 0x02000000 |
80 | #define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000 | ||
80 | 81 | ||
81 | #define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) | 82 | #define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) |
82 | #define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) | 83 | #define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) |
@@ -145,7 +146,7 @@ | |||
145 | * if enabled from the next key press on the driver will send | 146 | * if enabled from the next key press on the driver will send |
146 | * LIRC_MODE2_FREQUENCY packets | 147 | * LIRC_MODE2_FREQUENCY packets |
147 | */ | 148 | */ |
148 | #define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) | 149 | #define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) |
149 | 150 | ||
150 | /* | 151 | /* |
151 | * to set a range use | 152 | * to set a range use |
@@ -162,4 +163,6 @@ | |||
162 | #define LIRC_SETUP_START _IO('i', 0x00000021) | 163 | #define LIRC_SETUP_START _IO('i', 0x00000021) |
163 | #define LIRC_SETUP_END _IO('i', 0x00000022) | 164 | #define LIRC_SETUP_END _IO('i', 0x00000022) |
164 | 165 | ||
166 | #define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32) | ||
167 | |||
165 | #endif | 168 | #endif |