Newer
Older
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 = &ir_input_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)
if (!dev)
return;
if (dev->input_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? */
static atomic_t devno = ATOMIC_INIT(0);
struct rc_map *rc_map;
const char *path;
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 either
* dev->rc_map.rc_type or dev->raw->enabled_protocols before it has
* been initialized.
*/
mutex_lock(&dev->lock);
dev->devno = (unsigned long)(atomic_inc_return(&devno) - 1);
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;
rc = input_register_device(dev->input_dev);
if (rc)
goto out_table;
* 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",
path ? path : "N/A");
kfree(path);
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);
if (rc < 0)
goto out_raw;
}
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_dev:
device_del(&dev->dev);
out_unlock:
mutex_unlock(&dev->lock);
EXPORT_SYMBOL_GPL(rc_register_device);
void rc_unregister_device(struct rc_dev *dev)
if (!dev)
return;
del_timer_sync(&dev->timer_keyup);
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;
device_del(&dev->dev);
rc_free_device(dev);
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(&ir_input_class);
if (rc) {
printk(KERN_ERR "rc_core: unable to register rc class\n");
return rc;
}
rc_map_register(&empty_map);
return 0;
}
static void __exit rc_core_exit(void)
{
class_unregister(&ir_input_class);
rc_map_unregister(&empty_map);
module_init(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");