1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * LIRC base driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * by Artur Lipowski <alipowski@interia.pl>
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/mutex.h>
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/file.h>
14*4882a593Smuzhiyun #include <linux/idr.h>
15*4882a593Smuzhiyun #include <linux/poll.h>
16*4882a593Smuzhiyun #include <linux/sched.h>
17*4882a593Smuzhiyun #include <linux/wait.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "rc-core-priv.h"
20*4882a593Smuzhiyun #include <uapi/linux/lirc.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define LIRCBUF_SIZE 1024
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static dev_t lirc_base_dev;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* Used to keep track of allocated lirc devices */
27*4882a593Smuzhiyun static DEFINE_IDA(lirc_ida);
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /* Only used for sysfs but defined to void otherwise */
30*4882a593Smuzhiyun static struct class *lirc_class;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /**
33*4882a593Smuzhiyun * lirc_raw_event() - Send raw IR data to lirc to be relayed to userspace
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * @dev: the struct rc_dev descriptor of the device
36*4882a593Smuzhiyun * @ev: the struct ir_raw_event descriptor of the pulse/space
37*4882a593Smuzhiyun */
lirc_raw_event(struct rc_dev * dev,struct ir_raw_event ev)38*4882a593Smuzhiyun void lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun unsigned long flags;
41*4882a593Smuzhiyun struct lirc_fh *fh;
42*4882a593Smuzhiyun int sample;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* Packet start */
45*4882a593Smuzhiyun if (ev.reset) {
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * Userspace expects a long space event before the start of
48*4882a593Smuzhiyun * the signal to use as a sync. This may be done with repeat
49*4882a593Smuzhiyun * packets and normal samples. But if a reset has been sent
50*4882a593Smuzhiyun * then we assume that a long time has passed, so we send a
51*4882a593Smuzhiyun * space with the maximum time value.
52*4882a593Smuzhiyun */
53*4882a593Smuzhiyun sample = LIRC_SPACE(LIRC_VALUE_MASK);
54*4882a593Smuzhiyun dev_dbg(&dev->dev, "delivering reset sync space to lirc_dev\n");
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Carrier reports */
57*4882a593Smuzhiyun } else if (ev.carrier_report) {
58*4882a593Smuzhiyun sample = LIRC_FREQUENCY(ev.carrier);
59*4882a593Smuzhiyun dev_dbg(&dev->dev, "carrier report (freq: %d)\n", sample);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* Packet end */
62*4882a593Smuzhiyun } else if (ev.timeout) {
63*4882a593Smuzhiyun if (dev->gap)
64*4882a593Smuzhiyun return;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun dev->gap_start = ktime_get();
67*4882a593Smuzhiyun dev->gap = true;
68*4882a593Smuzhiyun dev->gap_duration = ev.duration;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun sample = LIRC_TIMEOUT(ev.duration);
71*4882a593Smuzhiyun dev_dbg(&dev->dev, "timeout report (duration: %d)\n", sample);
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* Normal sample */
74*4882a593Smuzhiyun } else {
75*4882a593Smuzhiyun if (dev->gap) {
76*4882a593Smuzhiyun dev->gap_duration += ktime_to_us(ktime_sub(ktime_get(),
77*4882a593Smuzhiyun dev->gap_start));
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /* Cap by LIRC_VALUE_MASK */
80*4882a593Smuzhiyun dev->gap_duration = min_t(u64, dev->gap_duration,
81*4882a593Smuzhiyun LIRC_VALUE_MASK);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun spin_lock_irqsave(&dev->lirc_fh_lock, flags);
84*4882a593Smuzhiyun list_for_each_entry(fh, &dev->lirc_fh, list)
85*4882a593Smuzhiyun kfifo_put(&fh->rawir,
86*4882a593Smuzhiyun LIRC_SPACE(dev->gap_duration));
87*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->lirc_fh_lock, flags);
88*4882a593Smuzhiyun dev->gap = false;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun sample = ev.pulse ? LIRC_PULSE(ev.duration) :
92*4882a593Smuzhiyun LIRC_SPACE(ev.duration);
93*4882a593Smuzhiyun dev_dbg(&dev->dev, "delivering %uus %s to lirc_dev\n",
94*4882a593Smuzhiyun ev.duration, TO_STR(ev.pulse));
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /*
98*4882a593Smuzhiyun * bpf does not care about the gap generated above; that exists
99*4882a593Smuzhiyun * for backwards compatibility
100*4882a593Smuzhiyun */
101*4882a593Smuzhiyun lirc_bpf_run(dev, sample);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun spin_lock_irqsave(&dev->lirc_fh_lock, flags);
104*4882a593Smuzhiyun list_for_each_entry(fh, &dev->lirc_fh, list) {
105*4882a593Smuzhiyun if (LIRC_IS_TIMEOUT(sample) && !fh->send_timeout_reports)
106*4882a593Smuzhiyun continue;
107*4882a593Smuzhiyun if (kfifo_put(&fh->rawir, sample))
108*4882a593Smuzhiyun wake_up_poll(&fh->wait_poll, EPOLLIN | EPOLLRDNORM);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->lirc_fh_lock, flags);
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /**
114*4882a593Smuzhiyun * lirc_scancode_event() - Send scancode data to lirc to be relayed to
115*4882a593Smuzhiyun * userspace. This can be called in atomic context.
116*4882a593Smuzhiyun * @dev: the struct rc_dev descriptor of the device
117*4882a593Smuzhiyun * @lsc: the struct lirc_scancode describing the decoded scancode
118*4882a593Smuzhiyun */
lirc_scancode_event(struct rc_dev * dev,struct lirc_scancode * lsc)119*4882a593Smuzhiyun void lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun unsigned long flags;
122*4882a593Smuzhiyun struct lirc_fh *fh;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun lsc->timestamp = ktime_get_ns();
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun spin_lock_irqsave(&dev->lirc_fh_lock, flags);
127*4882a593Smuzhiyun list_for_each_entry(fh, &dev->lirc_fh, list) {
128*4882a593Smuzhiyun if (kfifo_put(&fh->scancodes, *lsc))
129*4882a593Smuzhiyun wake_up_poll(&fh->wait_poll, EPOLLIN | EPOLLRDNORM);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->lirc_fh_lock, flags);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(lirc_scancode_event);
134*4882a593Smuzhiyun
lirc_open(struct inode * inode,struct file * file)135*4882a593Smuzhiyun static int lirc_open(struct inode *inode, struct file *file)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun struct rc_dev *dev = container_of(inode->i_cdev, struct rc_dev,
138*4882a593Smuzhiyun lirc_cdev);
139*4882a593Smuzhiyun struct lirc_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
140*4882a593Smuzhiyun unsigned long flags;
141*4882a593Smuzhiyun int retval;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (!fh)
144*4882a593Smuzhiyun return -ENOMEM;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun get_device(&dev->dev);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (!dev->registered) {
149*4882a593Smuzhiyun retval = -ENODEV;
150*4882a593Smuzhiyun goto out_fh;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (dev->driver_type == RC_DRIVER_IR_RAW) {
154*4882a593Smuzhiyun if (kfifo_alloc(&fh->rawir, MAX_IR_EVENT_SIZE, GFP_KERNEL)) {
155*4882a593Smuzhiyun retval = -ENOMEM;
156*4882a593Smuzhiyun goto out_fh;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
161*4882a593Smuzhiyun if (kfifo_alloc(&fh->scancodes, 32, GFP_KERNEL)) {
162*4882a593Smuzhiyun retval = -ENOMEM;
163*4882a593Smuzhiyun goto out_rawir;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun fh->send_mode = LIRC_MODE_PULSE;
168*4882a593Smuzhiyun fh->rc = dev;
169*4882a593Smuzhiyun fh->send_timeout_reports = true;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (dev->driver_type == RC_DRIVER_SCANCODE)
172*4882a593Smuzhiyun fh->rec_mode = LIRC_MODE_SCANCODE;
173*4882a593Smuzhiyun else
174*4882a593Smuzhiyun fh->rec_mode = LIRC_MODE_MODE2;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun retval = rc_open(dev);
177*4882a593Smuzhiyun if (retval)
178*4882a593Smuzhiyun goto out_kfifo;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun init_waitqueue_head(&fh->wait_poll);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun file->private_data = fh;
183*4882a593Smuzhiyun spin_lock_irqsave(&dev->lirc_fh_lock, flags);
184*4882a593Smuzhiyun list_add(&fh->list, &dev->lirc_fh);
185*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->lirc_fh_lock, flags);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun stream_open(inode, file);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun return 0;
190*4882a593Smuzhiyun out_kfifo:
191*4882a593Smuzhiyun if (dev->driver_type != RC_DRIVER_IR_RAW_TX)
192*4882a593Smuzhiyun kfifo_free(&fh->scancodes);
193*4882a593Smuzhiyun out_rawir:
194*4882a593Smuzhiyun if (dev->driver_type == RC_DRIVER_IR_RAW)
195*4882a593Smuzhiyun kfifo_free(&fh->rawir);
196*4882a593Smuzhiyun out_fh:
197*4882a593Smuzhiyun kfree(fh);
198*4882a593Smuzhiyun put_device(&dev->dev);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun return retval;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
lirc_close(struct inode * inode,struct file * file)203*4882a593Smuzhiyun static int lirc_close(struct inode *inode, struct file *file)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun struct lirc_fh *fh = file->private_data;
206*4882a593Smuzhiyun struct rc_dev *dev = fh->rc;
207*4882a593Smuzhiyun unsigned long flags;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun spin_lock_irqsave(&dev->lirc_fh_lock, flags);
210*4882a593Smuzhiyun list_del(&fh->list);
211*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->lirc_fh_lock, flags);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (dev->driver_type == RC_DRIVER_IR_RAW)
214*4882a593Smuzhiyun kfifo_free(&fh->rawir);
215*4882a593Smuzhiyun if (dev->driver_type != RC_DRIVER_IR_RAW_TX)
216*4882a593Smuzhiyun kfifo_free(&fh->scancodes);
217*4882a593Smuzhiyun kfree(fh);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun rc_close(dev);
220*4882a593Smuzhiyun put_device(&dev->dev);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun return 0;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
lirc_transmit(struct file * file,const char __user * buf,size_t n,loff_t * ppos)225*4882a593Smuzhiyun static ssize_t lirc_transmit(struct file *file, const char __user *buf,
226*4882a593Smuzhiyun size_t n, loff_t *ppos)
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun struct lirc_fh *fh = file->private_data;
229*4882a593Smuzhiyun struct rc_dev *dev = fh->rc;
230*4882a593Smuzhiyun unsigned int *txbuf;
231*4882a593Smuzhiyun struct ir_raw_event *raw = NULL;
232*4882a593Smuzhiyun ssize_t ret;
233*4882a593Smuzhiyun size_t count;
234*4882a593Smuzhiyun ktime_t start;
235*4882a593Smuzhiyun s64 towait;
236*4882a593Smuzhiyun unsigned int duration = 0; /* signal duration in us */
237*4882a593Smuzhiyun int i;
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun ret = mutex_lock_interruptible(&dev->lock);
240*4882a593Smuzhiyun if (ret)
241*4882a593Smuzhiyun return ret;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (!dev->registered) {
244*4882a593Smuzhiyun ret = -ENODEV;
245*4882a593Smuzhiyun goto out_unlock;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun if (!dev->tx_ir) {
249*4882a593Smuzhiyun ret = -EINVAL;
250*4882a593Smuzhiyun goto out_unlock;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun if (fh->send_mode == LIRC_MODE_SCANCODE) {
254*4882a593Smuzhiyun struct lirc_scancode scan;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun if (n != sizeof(scan)) {
257*4882a593Smuzhiyun ret = -EINVAL;
258*4882a593Smuzhiyun goto out_unlock;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (copy_from_user(&scan, buf, sizeof(scan))) {
262*4882a593Smuzhiyun ret = -EFAULT;
263*4882a593Smuzhiyun goto out_unlock;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun if (scan.flags || scan.keycode || scan.timestamp) {
267*4882a593Smuzhiyun ret = -EINVAL;
268*4882a593Smuzhiyun goto out_unlock;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun /* We only have encoders for 32-bit protocols. */
272*4882a593Smuzhiyun if (scan.scancode > U32_MAX ||
273*4882a593Smuzhiyun !rc_validate_scancode(scan.rc_proto, scan.scancode)) {
274*4882a593Smuzhiyun ret = -EINVAL;
275*4882a593Smuzhiyun goto out_unlock;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL);
279*4882a593Smuzhiyun if (!raw) {
280*4882a593Smuzhiyun ret = -ENOMEM;
281*4882a593Smuzhiyun goto out_unlock;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun ret = ir_raw_encode_scancode(scan.rc_proto, scan.scancode,
285*4882a593Smuzhiyun raw, LIRCBUF_SIZE);
286*4882a593Smuzhiyun if (ret < 0)
287*4882a593Smuzhiyun goto out_kfree_raw;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun count = ret;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL);
292*4882a593Smuzhiyun if (!txbuf) {
293*4882a593Smuzhiyun ret = -ENOMEM;
294*4882a593Smuzhiyun goto out_kfree_raw;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun for (i = 0; i < count; i++)
298*4882a593Smuzhiyun txbuf[i] = raw[i].duration;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun if (dev->s_tx_carrier) {
301*4882a593Smuzhiyun int carrier = ir_raw_encode_carrier(scan.rc_proto);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun if (carrier > 0)
304*4882a593Smuzhiyun dev->s_tx_carrier(dev, carrier);
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun } else {
307*4882a593Smuzhiyun if (n < sizeof(unsigned int) || n % sizeof(unsigned int)) {
308*4882a593Smuzhiyun ret = -EINVAL;
309*4882a593Smuzhiyun goto out_unlock;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun count = n / sizeof(unsigned int);
313*4882a593Smuzhiyun if (count > LIRCBUF_SIZE || count % 2 == 0) {
314*4882a593Smuzhiyun ret = -EINVAL;
315*4882a593Smuzhiyun goto out_unlock;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun txbuf = memdup_user(buf, n);
319*4882a593Smuzhiyun if (IS_ERR(txbuf)) {
320*4882a593Smuzhiyun ret = PTR_ERR(txbuf);
321*4882a593Smuzhiyun goto out_unlock;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun for (i = 0; i < count; i++) {
326*4882a593Smuzhiyun if (txbuf[i] > IR_MAX_DURATION - duration || !txbuf[i]) {
327*4882a593Smuzhiyun ret = -EINVAL;
328*4882a593Smuzhiyun goto out_kfree;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun duration += txbuf[i];
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun start = ktime_get();
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun ret = dev->tx_ir(dev, txbuf, count);
337*4882a593Smuzhiyun if (ret < 0)
338*4882a593Smuzhiyun goto out_kfree;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun kfree(txbuf);
341*4882a593Smuzhiyun kfree(raw);
342*4882a593Smuzhiyun mutex_unlock(&dev->lock);
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /*
345*4882a593Smuzhiyun * The lircd gap calculation expects the write function to
346*4882a593Smuzhiyun * wait for the actual IR signal to be transmitted before
347*4882a593Smuzhiyun * returning.
348*4882a593Smuzhiyun */
349*4882a593Smuzhiyun towait = ktime_us_delta(ktime_add_us(start, duration),
350*4882a593Smuzhiyun ktime_get());
351*4882a593Smuzhiyun if (towait > 0) {
352*4882a593Smuzhiyun set_current_state(TASK_INTERRUPTIBLE);
353*4882a593Smuzhiyun schedule_timeout(usecs_to_jiffies(towait));
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun return n;
357*4882a593Smuzhiyun out_kfree:
358*4882a593Smuzhiyun kfree(txbuf);
359*4882a593Smuzhiyun out_kfree_raw:
360*4882a593Smuzhiyun kfree(raw);
361*4882a593Smuzhiyun out_unlock:
362*4882a593Smuzhiyun mutex_unlock(&dev->lock);
363*4882a593Smuzhiyun return ret;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
lirc_ioctl(struct file * file,unsigned int cmd,unsigned long arg)366*4882a593Smuzhiyun static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun struct lirc_fh *fh = file->private_data;
369*4882a593Smuzhiyun struct rc_dev *dev = fh->rc;
370*4882a593Smuzhiyun u32 __user *argp = (u32 __user *)(arg);
371*4882a593Smuzhiyun u32 val = 0;
372*4882a593Smuzhiyun int ret;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun if (_IOC_DIR(cmd) & _IOC_WRITE) {
375*4882a593Smuzhiyun ret = get_user(val, argp);
376*4882a593Smuzhiyun if (ret)
377*4882a593Smuzhiyun return ret;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun ret = mutex_lock_interruptible(&dev->lock);
381*4882a593Smuzhiyun if (ret)
382*4882a593Smuzhiyun return ret;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun if (!dev->registered) {
385*4882a593Smuzhiyun ret = -ENODEV;
386*4882a593Smuzhiyun goto out;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun switch (cmd) {
390*4882a593Smuzhiyun case LIRC_GET_FEATURES:
391*4882a593Smuzhiyun if (dev->driver_type == RC_DRIVER_SCANCODE)
392*4882a593Smuzhiyun val |= LIRC_CAN_REC_SCANCODE;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun if (dev->driver_type == RC_DRIVER_IR_RAW) {
395*4882a593Smuzhiyun val |= LIRC_CAN_REC_MODE2;
396*4882a593Smuzhiyun if (dev->rx_resolution)
397*4882a593Smuzhiyun val |= LIRC_CAN_GET_REC_RESOLUTION;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun if (dev->tx_ir) {
401*4882a593Smuzhiyun val |= LIRC_CAN_SEND_PULSE;
402*4882a593Smuzhiyun if (dev->s_tx_mask)
403*4882a593Smuzhiyun val |= LIRC_CAN_SET_TRANSMITTER_MASK;
404*4882a593Smuzhiyun if (dev->s_tx_carrier)
405*4882a593Smuzhiyun val |= LIRC_CAN_SET_SEND_CARRIER;
406*4882a593Smuzhiyun if (dev->s_tx_duty_cycle)
407*4882a593Smuzhiyun val |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun if (dev->s_rx_carrier_range)
411*4882a593Smuzhiyun val |= LIRC_CAN_SET_REC_CARRIER |
412*4882a593Smuzhiyun LIRC_CAN_SET_REC_CARRIER_RANGE;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun if (dev->s_learning_mode)
415*4882a593Smuzhiyun val |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (dev->s_carrier_report)
418*4882a593Smuzhiyun val |= LIRC_CAN_MEASURE_CARRIER;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun if (dev->max_timeout)
421*4882a593Smuzhiyun val |= LIRC_CAN_SET_REC_TIMEOUT;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun break;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun /* mode support */
426*4882a593Smuzhiyun case LIRC_GET_REC_MODE:
427*4882a593Smuzhiyun if (dev->driver_type == RC_DRIVER_IR_RAW_TX)
428*4882a593Smuzhiyun ret = -ENOTTY;
429*4882a593Smuzhiyun else
430*4882a593Smuzhiyun val = fh->rec_mode;
431*4882a593Smuzhiyun break;
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun case LIRC_SET_REC_MODE:
434*4882a593Smuzhiyun switch (dev->driver_type) {
435*4882a593Smuzhiyun case RC_DRIVER_IR_RAW_TX:
436*4882a593Smuzhiyun ret = -ENOTTY;
437*4882a593Smuzhiyun break;
438*4882a593Smuzhiyun case RC_DRIVER_SCANCODE:
439*4882a593Smuzhiyun if (val != LIRC_MODE_SCANCODE)
440*4882a593Smuzhiyun ret = -EINVAL;
441*4882a593Smuzhiyun break;
442*4882a593Smuzhiyun case RC_DRIVER_IR_RAW:
443*4882a593Smuzhiyun if (!(val == LIRC_MODE_MODE2 ||
444*4882a593Smuzhiyun val == LIRC_MODE_SCANCODE))
445*4882a593Smuzhiyun ret = -EINVAL;
446*4882a593Smuzhiyun break;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun if (!ret)
450*4882a593Smuzhiyun fh->rec_mode = val;
451*4882a593Smuzhiyun break;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun case LIRC_GET_SEND_MODE:
454*4882a593Smuzhiyun if (!dev->tx_ir)
455*4882a593Smuzhiyun ret = -ENOTTY;
456*4882a593Smuzhiyun else
457*4882a593Smuzhiyun val = fh->send_mode;
458*4882a593Smuzhiyun break;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun case LIRC_SET_SEND_MODE:
461*4882a593Smuzhiyun if (!dev->tx_ir)
462*4882a593Smuzhiyun ret = -ENOTTY;
463*4882a593Smuzhiyun else if (!(val == LIRC_MODE_PULSE || val == LIRC_MODE_SCANCODE))
464*4882a593Smuzhiyun ret = -EINVAL;
465*4882a593Smuzhiyun else
466*4882a593Smuzhiyun fh->send_mode = val;
467*4882a593Smuzhiyun break;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun /* TX settings */
470*4882a593Smuzhiyun case LIRC_SET_TRANSMITTER_MASK:
471*4882a593Smuzhiyun if (!dev->s_tx_mask)
472*4882a593Smuzhiyun ret = -ENOTTY;
473*4882a593Smuzhiyun else
474*4882a593Smuzhiyun ret = dev->s_tx_mask(dev, val);
475*4882a593Smuzhiyun break;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun case LIRC_SET_SEND_CARRIER:
478*4882a593Smuzhiyun if (!dev->s_tx_carrier)
479*4882a593Smuzhiyun ret = -ENOTTY;
480*4882a593Smuzhiyun else
481*4882a593Smuzhiyun ret = dev->s_tx_carrier(dev, val);
482*4882a593Smuzhiyun break;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun case LIRC_SET_SEND_DUTY_CYCLE:
485*4882a593Smuzhiyun if (!dev->s_tx_duty_cycle)
486*4882a593Smuzhiyun ret = -ENOTTY;
487*4882a593Smuzhiyun else if (val <= 0 || val >= 100)
488*4882a593Smuzhiyun ret = -EINVAL;
489*4882a593Smuzhiyun else
490*4882a593Smuzhiyun ret = dev->s_tx_duty_cycle(dev, val);
491*4882a593Smuzhiyun break;
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /* RX settings */
494*4882a593Smuzhiyun case LIRC_SET_REC_CARRIER:
495*4882a593Smuzhiyun if (!dev->s_rx_carrier_range)
496*4882a593Smuzhiyun ret = -ENOTTY;
497*4882a593Smuzhiyun else if (val <= 0)
498*4882a593Smuzhiyun ret = -EINVAL;
499*4882a593Smuzhiyun else
500*4882a593Smuzhiyun ret = dev->s_rx_carrier_range(dev, fh->carrier_low,
501*4882a593Smuzhiyun val);
502*4882a593Smuzhiyun break;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun case LIRC_SET_REC_CARRIER_RANGE:
505*4882a593Smuzhiyun if (!dev->s_rx_carrier_range)
506*4882a593Smuzhiyun ret = -ENOTTY;
507*4882a593Smuzhiyun else if (val <= 0)
508*4882a593Smuzhiyun ret = -EINVAL;
509*4882a593Smuzhiyun else
510*4882a593Smuzhiyun fh->carrier_low = val;
511*4882a593Smuzhiyun break;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun case LIRC_GET_REC_RESOLUTION:
514*4882a593Smuzhiyun if (!dev->rx_resolution)
515*4882a593Smuzhiyun ret = -ENOTTY;
516*4882a593Smuzhiyun else
517*4882a593Smuzhiyun val = dev->rx_resolution;
518*4882a593Smuzhiyun break;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun case LIRC_SET_WIDEBAND_RECEIVER:
521*4882a593Smuzhiyun if (!dev->s_learning_mode)
522*4882a593Smuzhiyun ret = -ENOTTY;
523*4882a593Smuzhiyun else
524*4882a593Smuzhiyun ret = dev->s_learning_mode(dev, !!val);
525*4882a593Smuzhiyun break;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun case LIRC_SET_MEASURE_CARRIER_MODE:
528*4882a593Smuzhiyun if (!dev->s_carrier_report)
529*4882a593Smuzhiyun ret = -ENOTTY;
530*4882a593Smuzhiyun else
531*4882a593Smuzhiyun ret = dev->s_carrier_report(dev, !!val);
532*4882a593Smuzhiyun break;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun /* Generic timeout support */
535*4882a593Smuzhiyun case LIRC_GET_MIN_TIMEOUT:
536*4882a593Smuzhiyun if (!dev->max_timeout)
537*4882a593Smuzhiyun ret = -ENOTTY;
538*4882a593Smuzhiyun else
539*4882a593Smuzhiyun val = dev->min_timeout;
540*4882a593Smuzhiyun break;
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun case LIRC_GET_MAX_TIMEOUT:
543*4882a593Smuzhiyun if (!dev->max_timeout)
544*4882a593Smuzhiyun ret = -ENOTTY;
545*4882a593Smuzhiyun else
546*4882a593Smuzhiyun val = dev->max_timeout;
547*4882a593Smuzhiyun break;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun case LIRC_SET_REC_TIMEOUT:
550*4882a593Smuzhiyun if (!dev->max_timeout) {
551*4882a593Smuzhiyun ret = -ENOTTY;
552*4882a593Smuzhiyun } else {
553*4882a593Smuzhiyun if (val < dev->min_timeout || val > dev->max_timeout)
554*4882a593Smuzhiyun ret = -EINVAL;
555*4882a593Smuzhiyun else if (dev->s_timeout)
556*4882a593Smuzhiyun ret = dev->s_timeout(dev, val);
557*4882a593Smuzhiyun else
558*4882a593Smuzhiyun dev->timeout = val;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun break;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun case LIRC_GET_REC_TIMEOUT:
563*4882a593Smuzhiyun if (!dev->timeout)
564*4882a593Smuzhiyun ret = -ENOTTY;
565*4882a593Smuzhiyun else
566*4882a593Smuzhiyun val = dev->timeout;
567*4882a593Smuzhiyun break;
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun case LIRC_SET_REC_TIMEOUT_REPORTS:
570*4882a593Smuzhiyun if (dev->driver_type != RC_DRIVER_IR_RAW)
571*4882a593Smuzhiyun ret = -ENOTTY;
572*4882a593Smuzhiyun else
573*4882a593Smuzhiyun fh->send_timeout_reports = !!val;
574*4882a593Smuzhiyun break;
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun default:
577*4882a593Smuzhiyun ret = -ENOTTY;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun if (!ret && _IOC_DIR(cmd) & _IOC_READ)
581*4882a593Smuzhiyun ret = put_user(val, argp);
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun out:
584*4882a593Smuzhiyun mutex_unlock(&dev->lock);
585*4882a593Smuzhiyun return ret;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
lirc_poll(struct file * file,struct poll_table_struct * wait)588*4882a593Smuzhiyun static __poll_t lirc_poll(struct file *file, struct poll_table_struct *wait)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun struct lirc_fh *fh = file->private_data;
591*4882a593Smuzhiyun struct rc_dev *rcdev = fh->rc;
592*4882a593Smuzhiyun __poll_t events = 0;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun poll_wait(file, &fh->wait_poll, wait);
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun if (!rcdev->registered) {
597*4882a593Smuzhiyun events = EPOLLHUP | EPOLLERR;
598*4882a593Smuzhiyun } else if (rcdev->driver_type != RC_DRIVER_IR_RAW_TX) {
599*4882a593Smuzhiyun if (fh->rec_mode == LIRC_MODE_SCANCODE &&
600*4882a593Smuzhiyun !kfifo_is_empty(&fh->scancodes))
601*4882a593Smuzhiyun events = EPOLLIN | EPOLLRDNORM;
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun if (fh->rec_mode == LIRC_MODE_MODE2 &&
604*4882a593Smuzhiyun !kfifo_is_empty(&fh->rawir))
605*4882a593Smuzhiyun events = EPOLLIN | EPOLLRDNORM;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun return events;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
lirc_read_mode2(struct file * file,char __user * buffer,size_t length)611*4882a593Smuzhiyun static ssize_t lirc_read_mode2(struct file *file, char __user *buffer,
612*4882a593Smuzhiyun size_t length)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun struct lirc_fh *fh = file->private_data;
615*4882a593Smuzhiyun struct rc_dev *rcdev = fh->rc;
616*4882a593Smuzhiyun unsigned int copied;
617*4882a593Smuzhiyun int ret;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun if (length < sizeof(unsigned int) || length % sizeof(unsigned int))
620*4882a593Smuzhiyun return -EINVAL;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun do {
623*4882a593Smuzhiyun if (kfifo_is_empty(&fh->rawir)) {
624*4882a593Smuzhiyun if (file->f_flags & O_NONBLOCK)
625*4882a593Smuzhiyun return -EAGAIN;
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun ret = wait_event_interruptible(fh->wait_poll,
628*4882a593Smuzhiyun !kfifo_is_empty(&fh->rawir) ||
629*4882a593Smuzhiyun !rcdev->registered);
630*4882a593Smuzhiyun if (ret)
631*4882a593Smuzhiyun return ret;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun if (!rcdev->registered)
635*4882a593Smuzhiyun return -ENODEV;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun ret = mutex_lock_interruptible(&rcdev->lock);
638*4882a593Smuzhiyun if (ret)
639*4882a593Smuzhiyun return ret;
640*4882a593Smuzhiyun ret = kfifo_to_user(&fh->rawir, buffer, length, &copied);
641*4882a593Smuzhiyun mutex_unlock(&rcdev->lock);
642*4882a593Smuzhiyun if (ret)
643*4882a593Smuzhiyun return ret;
644*4882a593Smuzhiyun } while (copied == 0);
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun return copied;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun
lirc_read_scancode(struct file * file,char __user * buffer,size_t length)649*4882a593Smuzhiyun static ssize_t lirc_read_scancode(struct file *file, char __user *buffer,
650*4882a593Smuzhiyun size_t length)
651*4882a593Smuzhiyun {
652*4882a593Smuzhiyun struct lirc_fh *fh = file->private_data;
653*4882a593Smuzhiyun struct rc_dev *rcdev = fh->rc;
654*4882a593Smuzhiyun unsigned int copied;
655*4882a593Smuzhiyun int ret;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (length < sizeof(struct lirc_scancode) ||
658*4882a593Smuzhiyun length % sizeof(struct lirc_scancode))
659*4882a593Smuzhiyun return -EINVAL;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun do {
662*4882a593Smuzhiyun if (kfifo_is_empty(&fh->scancodes)) {
663*4882a593Smuzhiyun if (file->f_flags & O_NONBLOCK)
664*4882a593Smuzhiyun return -EAGAIN;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun ret = wait_event_interruptible(fh->wait_poll,
667*4882a593Smuzhiyun !kfifo_is_empty(&fh->scancodes) ||
668*4882a593Smuzhiyun !rcdev->registered);
669*4882a593Smuzhiyun if (ret)
670*4882a593Smuzhiyun return ret;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun if (!rcdev->registered)
674*4882a593Smuzhiyun return -ENODEV;
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun ret = mutex_lock_interruptible(&rcdev->lock);
677*4882a593Smuzhiyun if (ret)
678*4882a593Smuzhiyun return ret;
679*4882a593Smuzhiyun ret = kfifo_to_user(&fh->scancodes, buffer, length, &copied);
680*4882a593Smuzhiyun mutex_unlock(&rcdev->lock);
681*4882a593Smuzhiyun if (ret)
682*4882a593Smuzhiyun return ret;
683*4882a593Smuzhiyun } while (copied == 0);
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun return copied;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
lirc_read(struct file * file,char __user * buffer,size_t length,loff_t * ppos)688*4882a593Smuzhiyun static ssize_t lirc_read(struct file *file, char __user *buffer, size_t length,
689*4882a593Smuzhiyun loff_t *ppos)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun struct lirc_fh *fh = file->private_data;
692*4882a593Smuzhiyun struct rc_dev *rcdev = fh->rc;
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun if (rcdev->driver_type == RC_DRIVER_IR_RAW_TX)
695*4882a593Smuzhiyun return -EINVAL;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun if (!rcdev->registered)
698*4882a593Smuzhiyun return -ENODEV;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (fh->rec_mode == LIRC_MODE_MODE2)
701*4882a593Smuzhiyun return lirc_read_mode2(file, buffer, length);
702*4882a593Smuzhiyun else /* LIRC_MODE_SCANCODE */
703*4882a593Smuzhiyun return lirc_read_scancode(file, buffer, length);
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun static const struct file_operations lirc_fops = {
707*4882a593Smuzhiyun .owner = THIS_MODULE,
708*4882a593Smuzhiyun .write = lirc_transmit,
709*4882a593Smuzhiyun .unlocked_ioctl = lirc_ioctl,
710*4882a593Smuzhiyun .compat_ioctl = compat_ptr_ioctl,
711*4882a593Smuzhiyun .read = lirc_read,
712*4882a593Smuzhiyun .poll = lirc_poll,
713*4882a593Smuzhiyun .open = lirc_open,
714*4882a593Smuzhiyun .release = lirc_close,
715*4882a593Smuzhiyun .llseek = no_llseek,
716*4882a593Smuzhiyun };
717*4882a593Smuzhiyun
lirc_release_device(struct device * ld)718*4882a593Smuzhiyun static void lirc_release_device(struct device *ld)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun struct rc_dev *rcdev = container_of(ld, struct rc_dev, lirc_dev);
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun put_device(&rcdev->dev);
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun
lirc_register(struct rc_dev * dev)725*4882a593Smuzhiyun int lirc_register(struct rc_dev *dev)
726*4882a593Smuzhiyun {
727*4882a593Smuzhiyun const char *rx_type, *tx_type;
728*4882a593Smuzhiyun int err, minor;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun minor = ida_simple_get(&lirc_ida, 0, RC_DEV_MAX, GFP_KERNEL);
731*4882a593Smuzhiyun if (minor < 0)
732*4882a593Smuzhiyun return minor;
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun device_initialize(&dev->lirc_dev);
735*4882a593Smuzhiyun dev->lirc_dev.class = lirc_class;
736*4882a593Smuzhiyun dev->lirc_dev.parent = &dev->dev;
737*4882a593Smuzhiyun dev->lirc_dev.release = lirc_release_device;
738*4882a593Smuzhiyun dev->lirc_dev.devt = MKDEV(MAJOR(lirc_base_dev), minor);
739*4882a593Smuzhiyun dev_set_name(&dev->lirc_dev, "lirc%d", minor);
740*4882a593Smuzhiyun
741*4882a593Smuzhiyun INIT_LIST_HEAD(&dev->lirc_fh);
742*4882a593Smuzhiyun spin_lock_init(&dev->lirc_fh_lock);
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun cdev_init(&dev->lirc_cdev, &lirc_fops);
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun err = cdev_device_add(&dev->lirc_cdev, &dev->lirc_dev);
747*4882a593Smuzhiyun if (err)
748*4882a593Smuzhiyun goto out_ida;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun get_device(&dev->dev);
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun switch (dev->driver_type) {
753*4882a593Smuzhiyun case RC_DRIVER_SCANCODE:
754*4882a593Smuzhiyun rx_type = "scancode";
755*4882a593Smuzhiyun break;
756*4882a593Smuzhiyun case RC_DRIVER_IR_RAW:
757*4882a593Smuzhiyun rx_type = "raw IR";
758*4882a593Smuzhiyun break;
759*4882a593Smuzhiyun default:
760*4882a593Smuzhiyun rx_type = "no";
761*4882a593Smuzhiyun break;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun if (dev->tx_ir)
765*4882a593Smuzhiyun tx_type = "raw IR";
766*4882a593Smuzhiyun else
767*4882a593Smuzhiyun tx_type = "no";
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun dev_info(&dev->dev, "lirc_dev: driver %s registered at minor = %d, %s receiver, %s transmitter",
770*4882a593Smuzhiyun dev->driver_name, minor, rx_type, tx_type);
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun return 0;
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun out_ida:
775*4882a593Smuzhiyun ida_simple_remove(&lirc_ida, minor);
776*4882a593Smuzhiyun return err;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
lirc_unregister(struct rc_dev * dev)779*4882a593Smuzhiyun void lirc_unregister(struct rc_dev *dev)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun unsigned long flags;
782*4882a593Smuzhiyun struct lirc_fh *fh;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun dev_dbg(&dev->dev, "lirc_dev: driver %s unregistered from minor = %d\n",
785*4882a593Smuzhiyun dev->driver_name, MINOR(dev->lirc_dev.devt));
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun spin_lock_irqsave(&dev->lirc_fh_lock, flags);
788*4882a593Smuzhiyun list_for_each_entry(fh, &dev->lirc_fh, list)
789*4882a593Smuzhiyun wake_up_poll(&fh->wait_poll, EPOLLHUP | EPOLLERR);
790*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->lirc_fh_lock, flags);
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun cdev_device_del(&dev->lirc_cdev, &dev->lirc_dev);
793*4882a593Smuzhiyun ida_simple_remove(&lirc_ida, MINOR(dev->lirc_dev.devt));
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
lirc_dev_init(void)796*4882a593Smuzhiyun int __init lirc_dev_init(void)
797*4882a593Smuzhiyun {
798*4882a593Smuzhiyun int retval;
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun lirc_class = class_create(THIS_MODULE, "lirc");
801*4882a593Smuzhiyun if (IS_ERR(lirc_class)) {
802*4882a593Smuzhiyun pr_err("class_create failed\n");
803*4882a593Smuzhiyun return PTR_ERR(lirc_class);
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun retval = alloc_chrdev_region(&lirc_base_dev, 0, RC_DEV_MAX, "lirc");
807*4882a593Smuzhiyun if (retval) {
808*4882a593Smuzhiyun class_destroy(lirc_class);
809*4882a593Smuzhiyun pr_err("alloc_chrdev_region failed\n");
810*4882a593Smuzhiyun return retval;
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun pr_debug("IR Remote Control driver registered, major %d\n",
814*4882a593Smuzhiyun MAJOR(lirc_base_dev));
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun return 0;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun
lirc_dev_exit(void)819*4882a593Smuzhiyun void __exit lirc_dev_exit(void)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun class_destroy(lirc_class);
822*4882a593Smuzhiyun unregister_chrdev_region(lirc_base_dev, RC_DEV_MAX);
823*4882a593Smuzhiyun }
824*4882a593Smuzhiyun
rc_dev_get_from_fd(int fd)825*4882a593Smuzhiyun struct rc_dev *rc_dev_get_from_fd(int fd)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun struct fd f = fdget(fd);
828*4882a593Smuzhiyun struct lirc_fh *fh;
829*4882a593Smuzhiyun struct rc_dev *dev;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun if (!f.file)
832*4882a593Smuzhiyun return ERR_PTR(-EBADF);
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun if (f.file->f_op != &lirc_fops) {
835*4882a593Smuzhiyun fdput(f);
836*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun fh = f.file->private_data;
840*4882a593Smuzhiyun dev = fh->rc;
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun get_device(&dev->dev);
843*4882a593Smuzhiyun fdput(f);
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun return dev;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun MODULE_ALIAS("lirc_dev");
849