diff options
Diffstat (limited to 'drivers/media/IR/ir-lirc-codec.c')
-rw-r--r-- | drivers/media/IR/ir-lirc-codec.c | 124 |
1 files changed, 100 insertions, 24 deletions
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 3ba482d96c4b..77b5946413c0 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c | |||
@@ -32,6 +32,7 @@ | |||
32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | 32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) |
33 | { | 33 | { |
34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
35 | int sample; | ||
35 | 36 | ||
36 | if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) | 37 | if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) |
37 | return 0; | 38 | return 0; |
@@ -39,18 +40,20 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | |||
39 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) | 40 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) |
40 | return -EINVAL; | 41 | return -EINVAL; |
41 | 42 | ||
43 | if (IS_RESET(ev)) | ||
44 | return 0; | ||
45 | |||
42 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", | 46 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", |
43 | TO_US(ev.duration), TO_STR(ev.pulse)); | 47 | TO_US(ev.duration), TO_STR(ev.pulse)); |
44 | 48 | ||
45 | ir_dev->raw->lirc.lircdata += ev.duration / 1000; | 49 | sample = ev.duration / 1000; |
46 | if (ev.pulse) | 50 | if (ev.pulse) |
47 | ir_dev->raw->lirc.lircdata |= PULSE_BIT; | 51 | sample |= PULSE_BIT; |
48 | 52 | ||
49 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, | 53 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, |
50 | (unsigned char *) &ir_dev->raw->lirc.lircdata); | 54 | (unsigned char *) &sample); |
51 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); | 55 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); |
52 | 56 | ||
53 | ir_dev->raw->lirc.lircdata = 0; | ||
54 | 57 | ||
55 | return 0; | 58 | return 0; |
56 | } | 59 | } |
@@ -92,13 +95,14 @@ out: | |||
92 | return ret; | 95 | return ret; |
93 | } | 96 | } |
94 | 97 | ||
95 | 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) | ||
96 | { | 100 | { |
97 | struct lirc_codec *lirc; | 101 | struct lirc_codec *lirc; |
98 | struct ir_input_dev *ir_dev; | 102 | struct ir_input_dev *ir_dev; |
99 | int ret = 0; | 103 | int ret = 0; |
100 | void *drv_data; | 104 | void *drv_data; |
101 | unsigned long val; | 105 | unsigned long val = 0; |
102 | 106 | ||
103 | lirc = lirc_get_pdata(filep); | 107 | lirc = lirc_get_pdata(filep); |
104 | if (!lirc) | 108 | if (!lirc) |
@@ -110,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar | |||
110 | 114 | ||
111 | drv_data = ir_dev->props->priv; | 115 | drv_data = ir_dev->props->priv; |
112 | 116 | ||
113 | switch (cmd) { | 117 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
114 | case LIRC_SET_TRANSMITTER_MASK: | ||
115 | ret = get_user(val, (unsigned long *)arg); | 118 | ret = get_user(val, (unsigned long *)arg); |
116 | if (ret) | 119 | if (ret) |
117 | return ret; | 120 | return ret; |
121 | } | ||
122 | |||
123 | switch (cmd) { | ||
118 | 124 | ||
119 | if (ir_dev->props && ir_dev->props->s_tx_mask) | 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; | ||
134 | |||
135 | /* TX settings */ | ||
136 | case LIRC_SET_TRANSMITTER_MASK: | ||
137 | if (ir_dev->props->s_tx_mask) | ||
120 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); | 138 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); |
121 | else | 139 | else |
122 | return -EINVAL; | 140 | return -EINVAL; |
123 | break; | 141 | break; |
124 | 142 | ||
125 | case LIRC_SET_SEND_CARRIER: | 143 | case LIRC_SET_SEND_CARRIER: |
126 | ret = get_user(val, (unsigned long *)arg); | 144 | if (ir_dev->props->s_tx_carrier) |
127 | if (ret) | ||
128 | return ret; | ||
129 | |||
130 | if (ir_dev->props && ir_dev->props->s_tx_carrier) | ||
131 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); | 145 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); |
132 | else | 146 | else |
133 | return -EINVAL; | 147 | return -EINVAL; |
134 | break; | 148 | break; |
135 | 149 | ||
136 | case LIRC_GET_SEND_MODE: | 150 | case LIRC_SET_SEND_DUTY_CYCLE: |
137 | val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; | 151 | if (!ir_dev->props->s_tx_duty_cycle) |
138 | 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); | ||
139 | break; | 158 | break; |
140 | 159 | ||
141 | case LIRC_SET_SEND_MODE: | 160 | /* RX settings */ |
142 | ret = get_user(val, (unsigned long *)arg); | 161 | case LIRC_SET_REC_CARRIER: |
143 | if (ret) | 162 | if (ir_dev->props->s_rx_carrier_range) |
144 | 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; | ||
145 | 168 | ||
146 | 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) | ||
147 | return -EINVAL; | 206 | return -EINVAL; |
207 | ir_dev->props->timeout = val * 1000; | ||
148 | break; | 208 | break; |
149 | 209 | ||
150 | default: | 210 | default: |
151 | return lirc_dev_fop_ioctl(filep, cmd, arg); | 211 | return lirc_dev_fop_ioctl(filep, cmd, arg); |
152 | } | 212 | } |
153 | 213 | ||
214 | if (_IOC_DIR(cmd) & _IOC_READ) | ||
215 | ret = put_user(val, (unsigned long *)arg); | ||
216 | |||
154 | return ret; | 217 | return ret; |
155 | } | 218 | } |
156 | 219 | ||
@@ -196,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev) | |||
196 | 259 | ||
197 | features = LIRC_CAN_REC_MODE2; | 260 | features = LIRC_CAN_REC_MODE2; |
198 | if (ir_dev->props->tx_ir) { | 261 | if (ir_dev->props->tx_ir) { |
262 | |||
199 | features |= LIRC_CAN_SEND_PULSE; | 263 | features |= LIRC_CAN_SEND_PULSE; |
200 | if (ir_dev->props->s_tx_mask) | 264 | if (ir_dev->props->s_tx_mask) |
201 | features |= LIRC_CAN_SET_TRANSMITTER_MASK; | 265 | features |= LIRC_CAN_SET_TRANSMITTER_MASK; |
202 | if (ir_dev->props->s_tx_carrier) | 266 | if (ir_dev->props->s_tx_carrier) |
203 | 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; | ||
204 | } | 271 | } |
205 | 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 | |||
206 | snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", | 284 | snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", |
207 | ir_dev->driver_name); | 285 | ir_dev->driver_name); |
208 | drv->minor = -1; | 286 | drv->minor = -1; |
@@ -224,8 +302,6 @@ static int ir_lirc_register(struct input_dev *input_dev) | |||
224 | 302 | ||
225 | ir_dev->raw->lirc.drv = drv; | 303 | ir_dev->raw->lirc.drv = drv; |
226 | ir_dev->raw->lirc.ir_dev = ir_dev; | 304 | ir_dev->raw->lirc.ir_dev = ir_dev; |
227 | ir_dev->raw->lirc.lircdata = PULSE_MASK; | ||
228 | |||
229 | return 0; | 305 | return 0; |
230 | 306 | ||
231 | lirc_register_failed: | 307 | lirc_register_failed: |