xref: /OK3568_Linux_fs/kernel/drivers/media/rc/lirc_dev.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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