2010-07-03 08:06:57 +04:00
|
|
|
/*
|
|
|
|
* LIRC base driver
|
|
|
|
*
|
|
|
|
* by Artur Lipowski <alipowski@interia.pl>
|
|
|
|
* This code is licensed under GNU GPL
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _LINUX_LIRC_DEV_H
|
|
|
|
#define _LINUX_LIRC_DEV_H
|
|
|
|
|
|
|
|
#define BUFLEN 16
|
|
|
|
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/ioctl.h>
|
|
|
|
#include <linux/poll.h>
|
|
|
|
#include <linux/kfifo.h>
|
|
|
|
#include <media/lirc.h>
|
2017-06-25 15:32:36 +03:00
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/cdev.h>
|
2010-07-03 08:06:57 +04:00
|
|
|
|
|
|
|
struct lirc_buffer {
|
|
|
|
wait_queue_head_t wait_poll;
|
|
|
|
spinlock_t fifo_lock;
|
|
|
|
unsigned int chunk_size;
|
|
|
|
unsigned int size; /* in chunks */
|
|
|
|
/* Using chunks instead of bytes pretends to simplify boundary checking
|
|
|
|
* And should allow for some performance fine tunning later */
|
|
|
|
struct kfifo fifo;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline void lirc_buffer_clear(struct lirc_buffer *buf)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
2014-10-29 00:51:01 +03:00
|
|
|
if (kfifo_initialized(&buf->fifo)) {
|
2010-07-03 08:06:57 +04:00
|
|
|
spin_lock_irqsave(&buf->fifo_lock, flags);
|
|
|
|
kfifo_reset(&buf->fifo);
|
|
|
|
spin_unlock_irqrestore(&buf->fifo_lock, flags);
|
|
|
|
} else
|
|
|
|
WARN(1, "calling %s on an uninitialized lirc_buffer\n",
|
|
|
|
__func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int lirc_buffer_init(struct lirc_buffer *buf,
|
|
|
|
unsigned int chunk_size,
|
|
|
|
unsigned int size)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
init_waitqueue_head(&buf->wait_poll);
|
|
|
|
spin_lock_init(&buf->fifo_lock);
|
|
|
|
buf->chunk_size = chunk_size;
|
|
|
|
buf->size = size;
|
|
|
|
ret = kfifo_alloc(&buf->fifo, size * chunk_size, GFP_KERNEL);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void lirc_buffer_free(struct lirc_buffer *buf)
|
|
|
|
{
|
2014-10-29 00:51:01 +03:00
|
|
|
if (kfifo_initialized(&buf->fifo)) {
|
2010-07-03 08:06:57 +04:00
|
|
|
kfifo_free(&buf->fifo);
|
|
|
|
} else
|
|
|
|
WARN(1, "calling %s on an uninitialized lirc_buffer\n",
|
|
|
|
__func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int lirc_buffer_len(struct lirc_buffer *buf)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&buf->fifo_lock, flags);
|
|
|
|
len = kfifo_len(&buf->fifo);
|
|
|
|
spin_unlock_irqrestore(&buf->fifo_lock, flags);
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int lirc_buffer_full(struct lirc_buffer *buf)
|
|
|
|
{
|
|
|
|
return lirc_buffer_len(buf) == buf->size * buf->chunk_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int lirc_buffer_empty(struct lirc_buffer *buf)
|
|
|
|
{
|
|
|
|
return !lirc_buffer_len(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int lirc_buffer_read(struct lirc_buffer *buf,
|
|
|
|
unsigned char *dest)
|
|
|
|
{
|
|
|
|
unsigned int ret = 0;
|
|
|
|
|
|
|
|
if (lirc_buffer_len(buf) >= buf->chunk_size)
|
|
|
|
ret = kfifo_out_locked(&buf->fifo, dest, buf->chunk_size,
|
|
|
|
&buf->fifo_lock);
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
|
|
|
|
unsigned char *orig)
|
|
|
|
{
|
|
|
|
unsigned int ret;
|
|
|
|
|
|
|
|
ret = kfifo_in_locked(&buf->fifo, orig, buf->chunk_size,
|
|
|
|
&buf->fifo_lock);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-10-05 19:35:37 +03:00
|
|
|
/**
|
2017-09-21 22:13:34 +03:00
|
|
|
* struct lirc_dev - represents a LIRC device
|
2015-10-05 19:35:37 +03:00
|
|
|
*
|
2017-09-21 22:13:34 +03:00
|
|
|
* @name: used for logging
|
|
|
|
* @minor: the minor device (/dev/lircX) number for the device
|
|
|
|
* @code_length: length of a remote control key code expressed in bits
|
2015-10-05 19:35:37 +03:00
|
|
|
* @features: lirc compatible hardware features, like LIRC_MODE_RAW,
|
2016-07-17 15:16:57 +03:00
|
|
|
* LIRC_CAN\_\*, as defined at include/media/lirc.h.
|
2017-06-25 15:31:45 +03:00
|
|
|
* @buffer_size: Number of FIFO buffers with @chunk_size size.
|
|
|
|
* Only used if @rbuf is NULL.
|
2015-10-05 19:35:37 +03:00
|
|
|
* @chunk_size: Size of each FIFO buffer.
|
2017-06-25 15:31:45 +03:00
|
|
|
* Only used if @rbuf is NULL.
|
2017-09-21 22:13:34 +03:00
|
|
|
* @data: private per-driver data
|
2017-06-25 15:32:36 +03:00
|
|
|
* @buf: if %NULL, lirc_dev will allocate and manage the buffer,
|
|
|
|
* otherwise allocated by the caller which will
|
2015-10-05 19:35:37 +03:00
|
|
|
* have to write to the buffer by other means, like irq's
|
|
|
|
* (see also lirc_serial.c).
|
2017-06-25 15:32:36 +03:00
|
|
|
* @buf_internal: whether lirc_dev has allocated the read buffer or not
|
2017-09-21 22:13:34 +03:00
|
|
|
* @rdev: &struct rc_dev associated with the device
|
|
|
|
* @fops: &struct file_operations for the device
|
2015-10-05 19:35:37 +03:00
|
|
|
* @owner: the module owning this struct
|
2017-06-25 15:32:36 +03:00
|
|
|
* @attached: if the device is still live
|
|
|
|
* @open: open count for the device's chardev
|
|
|
|
* @mutex: serialises file_operations calls
|
|
|
|
* @dev: &struct device assigned to the device
|
|
|
|
* @cdev: &struct cdev assigned to the device
|
2015-10-05 19:35:37 +03:00
|
|
|
*/
|
2017-09-21 22:13:34 +03:00
|
|
|
struct lirc_dev {
|
2010-07-03 08:06:57 +04:00
|
|
|
char name[40];
|
2017-06-25 15:31:24 +03:00
|
|
|
unsigned int minor;
|
2010-10-09 00:24:21 +04:00
|
|
|
__u32 code_length;
|
|
|
|
__u32 features;
|
2010-07-03 08:06:57 +04:00
|
|
|
|
2017-06-25 15:31:45 +03:00
|
|
|
unsigned int buffer_size; /* in chunks holding one code each */
|
2010-07-03 08:06:57 +04:00
|
|
|
unsigned int chunk_size;
|
2017-06-25 15:32:36 +03:00
|
|
|
struct lirc_buffer *buf;
|
|
|
|
bool buf_internal;
|
2010-07-03 08:06:57 +04:00
|
|
|
|
|
|
|
void *data;
|
[media] media: lirc: Allow lirc dev to talk to rc device
The use case is simple, if any rc device has allowed protocols =
RC_TYPE_LIRC and map_name = RC_MAP_LIRC set, the driver open will be never
called. The reason for this is, all of the key maps except lirc have some
KEYS in there map, so during rc_register_device process these keys are
matched against the input drivers and open is performed, so for the case
of RC_MAP_EMPTY, a vt/keyboard is matched and the driver open is
performed.
In case of lirc, there is no match and result is that there is no open
performed, however the lirc-dev will go ahead and create a /dev/lirc0
node. Now when lircd/mode2 opens this device, no data is available
because the driver was never opened.
Other case pointed by Sean Young, As rc device gets opened via the
input interface. If the input device is never opened (e.g. embedded with
no console) then the rc open is never called and lirc will not work
either. So that's another case.
lirc_dev seems to have no link with actual rc device w.r.t open/close.
This patch adds rc_dev pointer to lirc_driver structure for cases like
this, so that it can do the open/close of the real driver in accordance
to lircd/mode2 open/close.
Without this patch its impossible to open a rc device which has
RC_TYPE_LIRC ad RC_MAP_LIRC set.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
2013-07-22 11:23:07 +04:00
|
|
|
struct rc_dev *rdev;
|
2010-09-30 23:55:07 +04:00
|
|
|
const struct file_operations *fops;
|
2010-07-03 08:06:57 +04:00
|
|
|
struct module *owner;
|
2017-06-25 15:32:36 +03:00
|
|
|
|
|
|
|
bool attached;
|
|
|
|
int open;
|
|
|
|
|
|
|
|
struct mutex mutex; /* protect from simultaneous accesses */
|
|
|
|
|
|
|
|
struct device dev;
|
|
|
|
struct cdev cdev;
|
2010-07-03 08:06:57 +04:00
|
|
|
};
|
|
|
|
|
2017-06-25 15:32:15 +03:00
|
|
|
struct lirc_dev *lirc_allocate_device(void);
|
|
|
|
|
|
|
|
void lirc_free_device(struct lirc_dev *d);
|
|
|
|
|
2017-09-21 22:13:34 +03:00
|
|
|
int lirc_register_device(struct lirc_dev *d);
|
2010-07-03 08:06:57 +04:00
|
|
|
|
2017-09-21 22:13:34 +03:00
|
|
|
void lirc_unregister_device(struct lirc_dev *d);
|
2010-07-03 08:06:57 +04:00
|
|
|
|
2017-06-25 15:31:40 +03:00
|
|
|
/* Must be called in the open fop before lirc_get_pdata() can be used */
|
|
|
|
void lirc_init_pdata(struct inode *inode, struct file *file);
|
|
|
|
|
2017-09-21 22:13:34 +03:00
|
|
|
/* Returns the private data stored in the lirc_dev
|
2010-07-03 08:06:57 +04:00
|
|
|
* associated with the given device file pointer.
|
|
|
|
*/
|
|
|
|
void *lirc_get_pdata(struct file *file);
|
|
|
|
|
|
|
|
/* default file operations
|
|
|
|
* used by drivers if they override only some operations
|
|
|
|
*/
|
|
|
|
int lirc_dev_fop_open(struct inode *inode, struct file *file);
|
|
|
|
int lirc_dev_fop_close(struct inode *inode, struct file *file);
|
|
|
|
unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait);
|
2010-08-02 22:43:35 +04:00
|
|
|
long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
2010-11-17 08:13:39 +03:00
|
|
|
ssize_t lirc_dev_fop_read(struct file *file, char __user *buffer, size_t length,
|
2010-07-03 08:06:57 +04:00
|
|
|
loff_t *ppos);
|
|
|
|
#endif
|