Skip to content
Snippets Groups Projects
rc-main.c 36 KiB
Newer Older
 * type in hexadecimal into @buf and returns the size of the buffer.
 *
 * Bits of the filter value corresponding to set bits in the filter mask are
 * compared against input scancodes and non-matching scancodes are discarded.
 *
 * dev->lock is taken to guard against races between device registration,
 * store_filter and show_filter.
 */
static ssize_t show_filter(struct device *device,
			   struct device_attribute *attr,
			   char *buf)
{
	struct rc_dev *dev = to_rc_dev(device);
	struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
	u32 val;

	/* Device is being removed */
	if (!dev)
		return -EINVAL;

	mutex_lock(&dev->lock);
	if (!dev->s_filter)
		val = 0;
	else if (fattr->mask)
		val = dev->scancode_filters[fattr->type].mask;
	else
		val = dev->scancode_filters[fattr->type].data;
	mutex_unlock(&dev->lock);

	return sprintf(buf, "%#x\n", val);
}

/**
 * store_filter() - changes the scancode filter value
 * @device:	the device descriptor
 * @attr:	the device attribute struct
 * @buf:	a pointer to the input buffer
 * @len:	length of the input buffer
 *
 * This routine is for changing a scancode filter value or mask.
 * It is trigged by writing to /sys/class/rc/rc?/[wakeup_]filter[_mask].
 * Returns -EINVAL if an invalid filter value for the current protocol was
 * specified or if scancode filtering is not supported by the driver, otherwise
 * returns @len.
 *
 * Bits of the filter value corresponding to set bits in the filter mask are
 * compared against input scancodes and non-matching scancodes are discarded.
 *
 * dev->lock is taken to guard against races between device registration,
 * store_filter and show_filter.
 */
static ssize_t store_filter(struct device *device,
			    struct device_attribute *attr,
			    const char *buf,
			    size_t count)
{
	struct rc_dev *dev = to_rc_dev(device);
	struct rc_filter_attribute *fattr = to_rc_filter_attr(attr);
	struct rc_scancode_filter local_filter, *filter;
	int ret;
	unsigned long val;

	/* Device is being removed */
	if (!dev)
		return -EINVAL;

	ret = kstrtoul(buf, 0, &val);
	if (ret < 0)
		return ret;

	/* Scancode filter not supported (but still accept 0) */
	if (!dev->s_filter)
		return val ? -EINVAL : count;

	mutex_lock(&dev->lock);

	/* Tell the driver about the new filter */
	filter = &dev->scancode_filters[fattr->type];
	local_filter = *filter;
	if (fattr->mask)
		local_filter.mask = val;
	else
		local_filter.data = val;
	ret = dev->s_filter(dev, fattr->type, &local_filter);
	if (ret < 0)
		goto unlock;

	/* Success, commit the new filter */
	*filter = local_filter;

unlock:
	mutex_unlock(&dev->lock);
	return count;
}

static void rc_dev_release(struct device *device)
{
}

#define ADD_HOTPLUG_VAR(fmt, val...)					\
	do {								\
		int err = add_uevent_var(env, fmt, val);		\
		if (err)						\
			return err;					\
	} while (0)

static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
{
	struct rc_dev *dev = to_rc_dev(device);
	if (!dev || !dev->input_dev)
		return -ENODEV;

	if (dev->rc_map.name)
		ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
	if (dev->driver_name)
		ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name);

	return 0;
}

/*
 * Static device attribute struct with the sysfs attributes for IR's
 */
static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
		   show_protocols, store_protocols);
static RC_FILTER_ATTR(filter, S_IRUGO|S_IWUSR,
		      show_filter, store_filter, RC_FILTER_NORMAL, false);
static RC_FILTER_ATTR(filter_mask, S_IRUGO|S_IWUSR,
		      show_filter, store_filter, RC_FILTER_NORMAL, true);
static RC_FILTER_ATTR(wakeup_filter, S_IRUGO|S_IWUSR,
		      show_filter, store_filter, RC_FILTER_WAKEUP, false);
static RC_FILTER_ATTR(wakeup_filter_mask, S_IRUGO|S_IWUSR,
		      show_filter, store_filter, RC_FILTER_WAKEUP, true);

static struct attribute *rc_dev_attrs[] = {
	&dev_attr_protocols.attr,
	&dev_attr_filter.attr.attr,
	&dev_attr_filter_mask.attr.attr,
	&dev_attr_wakeup_filter.attr.attr,
	&dev_attr_wakeup_filter_mask.attr.attr,
	NULL,
};

static struct attribute_group rc_dev_attr_grp = {
	.attrs	= rc_dev_attrs,
};

static const struct attribute_group *rc_dev_attr_groups[] = {
	&rc_dev_attr_grp,
	NULL
};

static struct device_type rc_dev_type = {
	.groups		= rc_dev_attr_groups,
struct rc_dev *rc_allocate_device(void)
	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return NULL;

	dev->input_dev = input_allocate_device();
	if (!dev->input_dev) {
		kfree(dev);
		return NULL;
	}

	dev->input_dev->getkeycode = ir_getkeycode;
	dev->input_dev->setkeycode = ir_setkeycode;
	input_set_drvdata(dev->input_dev, dev);

	spin_lock_init(&dev->rc_map.lock);
	spin_lock_init(&dev->keylock);
	mutex_init(&dev->lock);
	setup_timer(&dev->timer_keyup, ir_timer_keyup, (unsigned long)dev);
	dev->dev.type = &rc_dev_type;
	dev->dev.class = &rc_class;
	device_initialize(&dev->dev);

	__module_get(THIS_MODULE);
	return dev;
}
EXPORT_SYMBOL_GPL(rc_allocate_device);

void rc_free_device(struct rc_dev *dev)
		input_free_device(dev->input_dev);

	put_device(&dev->dev);

	kfree(dev);
	module_put(THIS_MODULE);
}
EXPORT_SYMBOL_GPL(rc_free_device);

int rc_register_device(struct rc_dev *dev)
{
	static bool raw_init = false; /* raw decoders loaded? */
	struct rc_map *rc_map;
	if (!dev || !dev->map_name)
		return -EINVAL;
	rc_map = rc_map_get(dev->map_name);
		rc_map = rc_map_get(RC_MAP_EMPTY);
	if (!rc_map || !rc_map->scan || rc_map->size == 0)
		return -EINVAL;

	set_bit(EV_KEY, dev->input_dev->evbit);
	set_bit(EV_REP, dev->input_dev->evbit);
	set_bit(EV_MSC, dev->input_dev->evbit);
	set_bit(MSC_SCAN, dev->input_dev->mscbit);
	if (dev->open)
		dev->input_dev->open = ir_open;
	if (dev->close)
		dev->input_dev->close = ir_close;

	/*
	 * Take the lock here, as the device sysfs node will appear
	 * when device_add() is called, which may trigger an ir-keytable udev
	 * rule, which will in turn call show_protocols and access
	 * dev->enabled_protocols before it has been initialized.
	do {
		devno = find_first_zero_bit(ir_core_dev_number,
					    IRRCV_NUM_DEVICES);
		/* No free device slots */
		if (devno >= IRRCV_NUM_DEVICES)
			return -ENOMEM;
	} while (test_and_set_bit(devno, ir_core_dev_number));

	dev->devno = devno;
	dev_set_name(&dev->dev, "rc%ld", dev->devno);
	dev_set_drvdata(&dev->dev, dev);
	rc = device_add(&dev->dev);
	if (rc)
	rc = ir_setkeytable(dev, rc_map);
	if (rc)
		goto out_dev;

	dev->input_dev->dev.parent = &dev->dev;
	memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id));
	dev->input_dev->phys = dev->input_phys;
	dev->input_dev->name = dev->input_name;

	/* input_register_device can call ir_open, so unlock mutex here */
	mutex_unlock(&dev->lock);

	rc = input_register_device(dev->input_dev);
Lucas De Marchi's avatar
Lucas De Marchi committed
	 * Default delay of 250ms is too short for some protocols, especially
	 * since the timeout is currently set to 250ms. Increase it to 500ms,
	 * to avoid wrong repetition of the keycodes. Note that this must be
	 * set after the call to input_register_device().
	 */
	dev->input_dev->rep[REP_DELAY] = 500;

	/*
	 * As a repeat event on protocols like RC-5 and NEC take as long as
	 * 110/114ms, using 33ms as a repeat period is not the right thing
	 * to do.
	 */
	dev->input_dev->rep[REP_PERIOD] = 125;

	path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
	printk(KERN_INFO "%s: %s as %s\n",
		dev_name(&dev->dev),
		dev->input_name ? dev->input_name : "Unspecified device",
	if (dev->driver_type == RC_DRIVER_IR_RAW) {
		/* Load raw decoders, if they aren't already */
		if (!raw_init) {
			IR_dprintk(1, "Loading raw decoders\n");
			ir_raw_init();
			raw_init = true;
		}
		rc = ir_raw_event_register(dev);
		if (rc < 0)
			goto out_input;
	}

	if (dev->change_protocol) {
		u64 rc_type = (1 << rc_map->rc_type);
		rc = dev->change_protocol(dev, &rc_type);
		dev->enabled_protocols = rc_type;
	mutex_unlock(&dev->lock);

	IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n",
		   dev->devno,
		   dev->driver_name ? dev->driver_name : "unknown",
		   rc_map->name ? rc_map->name : "unknown",
		   dev->driver_type == RC_DRIVER_IR_RAW ? "raw" : "cooked");


out_raw:
	if (dev->driver_type == RC_DRIVER_IR_RAW)
		ir_raw_event_unregister(dev);
out_input:
	input_unregister_device(dev->input_dev);
	dev->input_dev = NULL;
out_table:
	ir_free_table(&dev->rc_map);
out_unlock:
	mutex_unlock(&dev->lock);
	clear_bit(dev->devno, ir_core_dev_number);
EXPORT_SYMBOL_GPL(rc_register_device);
void rc_unregister_device(struct rc_dev *dev)
	del_timer_sync(&dev->timer_keyup);
	clear_bit(dev->devno, ir_core_dev_number);

	if (dev->driver_type == RC_DRIVER_IR_RAW)
		ir_raw_event_unregister(dev);

	/* Freeing the table should also call the stop callback */
	ir_free_table(&dev->rc_map);
	IR_dprintk(1, "Freed keycode table\n");

	input_unregister_device(dev->input_dev);
	dev->input_dev = NULL;

EXPORT_SYMBOL_GPL(rc_unregister_device);

/*
 * Init/exit code for the module. Basically, creates/removes /sys/class/rc
 */

static int __init rc_core_init(void)
	int rc = class_register(&rc_class);
		printk(KERN_ERR "rc_core: unable to register rc class\n");
	led_trigger_register_simple("rc-feedback", &led_feedback);
	rc_map_register(&empty_map);
static void __exit rc_core_exit(void)
	class_unregister(&rc_class);
	led_trigger_unregister_simple(led_feedback);
	rc_map_unregister(&empty_map);
subsys_initcall(rc_core_init);
module_exit(rc_core_exit);
int rc_core_debug;    /* ir_debug level (0,1,2) */
EXPORT_SYMBOL_GPL(rc_core_debug);
module_param_named(debug, rc_core_debug, int, 0644);

MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_LICENSE("GPL");