From 945cdfa2c99e2a3f5ead11519ba11ed1df2dd5c1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 11 Mar 2010 12:41:56 -0300 Subject: V4L/DVB: ir: use a real device instead of a virtual class Change the ir-sysfs approach to create irrcv0 as a device, instead of using class_dev. Also, change the way input is registered, in order to make its parent to be the irrcv device. Due to this change, now the event device is created under /sys/class/ir/irrcv class: /sys/class/irrcv/irrcv0/ |-- current_protocol |-- device -> ../../../1-3 |-- input9 | |-- capabilities | | |-- abs ... Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 10 +----- drivers/media/IR/ir-sysfs.c | 78 +++++++++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 33 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index bfca26d51827..af1f4d7fb910 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -449,22 +449,15 @@ int ir_input_register(struct input_dev *input_dev, input_dev->setkeycode = ir_setkeycode; input_set_drvdata(input_dev, ir_dev); - rc = input_register_device(input_dev); - if (rc < 0) - goto err; - rc = ir_register_class(input_dev); - if (rc < 0) { - input_unregister_device(input_dev); + if (rc < 0) goto err; - } return 0; err: kfree(rc_tab->scan); kfree(ir_dev); - input_set_drvdata(input_dev, NULL); return rc; } EXPORT_SYMBOL_GPL(ir_input_register); @@ -493,7 +486,6 @@ void ir_input_unregister(struct input_dev *dev) ir_unregister_class(dev); kfree(ir_dev); - input_unregister_device(dev); } EXPORT_SYMBOL_GPL(ir_input_unregister); diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index e14e6c486b52..59bd388be8d7 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -23,7 +23,15 @@ static unsigned long ir_core_dev_number; /* class for /sys/class/irrcv */ -static struct class *ir_input_class; +static char *ir_devnode(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "irrcv/%s", dev_name(dev)); +} + +struct class ir_input_class = { + .name = "irrcv", + .devnode = ir_devnode, +}; /** * show_protocol() - shows the current IR protocol @@ -129,6 +137,20 @@ static struct attribute *ir_dev_attrs[] = { NULL, }; +static struct attribute_group ir_dev_attr_grp = { + .attrs = ir_dev_attrs, +}; + +static const struct attribute_group *ir_dev_attr_groups[] = { + &ir_dev_attr_grp, + NULL +}; + +static struct device_type ir_dev_type = { + .groups = ir_dev_attr_groups, +}; + + /** * ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv? * @input_dev: the struct input_dev descriptor of the device @@ -138,7 +160,7 @@ static struct attribute *ir_dev_attrs[] = { int ir_register_class(struct input_dev *input_dev) { int rc; - struct kobject *kobj; + const char *path; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); int devno = find_first_zero_bit(&ir_core_dev_number, @@ -147,19 +169,31 @@ int ir_register_class(struct input_dev *input_dev) if (unlikely(devno < 0)) return devno; - ir_dev->attr.attrs = ir_dev_attrs; - ir_dev->class_dev = device_create(ir_input_class, NULL, - input_dev->dev.devt, ir_dev, - "irrcv%d", devno); - kobj = &ir_dev->class_dev->kobj; - - printk(KERN_WARNING "Creating IR device %s\n", kobject_name(kobj)); - rc = sysfs_create_group(kobj, &ir_dev->attr); - if (unlikely(rc < 0)) { - device_destroy(ir_input_class, input_dev->dev.devt); - return -ENOMEM; + ir_dev->dev.type = &ir_dev_type; + ir_dev->dev.class = &ir_input_class; + ir_dev->dev.parent = input_dev->dev.parent; + dev_set_name(&ir_dev->dev, "irrcv%d", devno); + rc = device_register(&ir_dev->dev); + if (rc) + return rc; + + + input_dev->dev.parent = &ir_dev->dev; + rc = input_register_device(input_dev); + if (rc < 0) { + device_del(&ir_dev->dev); + return rc; } + __module_get(THIS_MODULE); + + path = kobject_get_path(&input_dev->dev.kobj, GFP_KERNEL); + printk(KERN_INFO "%s: %s associated with sysfs %s\n", + dev_name(&ir_dev->dev), + input_dev->name ? input_dev->name : "Unspecified device", + path ? path : "N/A"); + kfree(path); + ir_dev->devno = devno; set_bit(devno, &ir_core_dev_number); @@ -176,16 +210,12 @@ int ir_register_class(struct input_dev *input_dev) void ir_unregister_class(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct kobject *kobj; clear_bit(ir_dev->devno, &ir_core_dev_number); + input_unregister_device(input_dev); + device_del(&ir_dev->dev); - kobj = &ir_dev->class_dev->kobj; - - sysfs_remove_group(kobj, &ir_dev->attr); - device_destroy(ir_input_class, input_dev->dev.devt); - - kfree(ir_dev->attr.name); + module_put(THIS_MODULE); } /* @@ -194,10 +224,10 @@ void ir_unregister_class(struct input_dev *input_dev) static int __init ir_core_init(void) { - ir_input_class = class_create(THIS_MODULE, "irrcv"); - if (IS_ERR(ir_input_class)) { + int rc = class_register(&ir_input_class); + if (rc) { printk(KERN_ERR "ir_core: unable to register irrcv class\n"); - return PTR_ERR(ir_input_class); + return rc; } return 0; @@ -205,7 +235,7 @@ static int __init ir_core_init(void) static void __exit ir_core_exit(void) { - class_destroy(ir_input_class); + class_unregister(&ir_input_class); } module_init(ir_core_init); -- cgit v1.2.3 From 2915e5ef35d103a5ecae15d9ecc614fcd0dc48f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Mar 2010 11:40:13 -0300 Subject: V4L/DVB: ir-core: Add a macro to properly create IR tables Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keymaps.c | 455 ++++++++---------------------------------- 1 file changed, 81 insertions(+), 374 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index 0efdefe75f32..dfc777b78dea 100644 --- a/drivers/media/IR/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c @@ -28,16 +28,28 @@ #include #include + +/* + * The usage of tables with just the command part is deprecated. + * All new IR keytables should contain address+command and need + * to define the proper IR_TYPE (IR_TYPE_RC5/IR_TYPE_NEC). + * The deprecated tables should use IR_TYPE_UNKNOWN + */ +#define IR_TABLE(irname, type, tabname) \ +struct ir_scancode_table tabname ## _table = { \ + .scan = tabname, \ + .size = ARRAY_SIZE(tabname), \ + .ir_type = type, \ + .name = #irname, \ +}; \ +EXPORT_SYMBOL_GPL(tabname ## _table) + + /* empty keytable, can be used as placeholder for not-yet created keytables */ static struct ir_scancode ir_codes_empty[] = { { 0x2a, KEY_COFFEE }, }; - -struct ir_scancode_table ir_codes_empty_table = { - .scan = ir_codes_empty, - .size = ARRAY_SIZE(ir_codes_empty), -}; -EXPORT_SYMBOL_GPL(ir_codes_empty_table); +IR_TABLE(empty, IR_TYPE_UNKNOWN, ir_codes_empty); /* Michal Majchrowicz */ static struct ir_scancode ir_codes_proteus_2309[] = { @@ -68,12 +80,7 @@ static struct ir_scancode ir_codes_proteus_2309[] = { { 0x1e, KEY_VOLUMEUP }, /* volume + */ { 0x14, KEY_F1 }, }; - -struct ir_scancode_table ir_codes_proteus_2309_table = { - .scan = ir_codes_proteus_2309, - .size = ARRAY_SIZE(ir_codes_proteus_2309), -}; -EXPORT_SYMBOL_GPL(ir_codes_proteus_2309_table); +IR_TABLE(proteus_2309, IR_TYPE_UNKNOWN, ir_codes_proteus_2309); /* Matt Jesson */ static struct ir_scancode ir_codes_avermedia_m135a[] = { @@ -168,12 +170,7 @@ static struct ir_scancode ir_codes_avermedia_m135a[] = { { 0x18, KEY_PLAY }, { 0x1b, KEY_STOP }, }; - -struct ir_scancode_table ir_codes_avermedia_m135a_table = { - .scan = ir_codes_avermedia_m135a, - .size = ARRAY_SIZE(ir_codes_avermedia_m135a), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a_table); +IR_TABLE(avermedia_m135a, IR_TYPE_UNKNOWN, ir_codes_avermedia_m135a); /* Oldrich Jedlicka */ static struct ir_scancode ir_codes_avermedia_cardbus[] = { @@ -232,12 +229,7 @@ static struct ir_scancode ir_codes_avermedia_cardbus[] = { { 0x42, KEY_CHANNELDOWN }, /* Channel down */ { 0x43, KEY_CHANNELUP }, /* Channel up */ }; - -struct ir_scancode_table ir_codes_avermedia_cardbus_table = { - .scan = ir_codes_avermedia_cardbus, - .size = ARRAY_SIZE(ir_codes_avermedia_cardbus), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus_table); +IR_TABLE(avermedia_cardbus, IR_TYPE_UNKNOWN, ir_codes_avermedia_cardbus); /* Attila Kondoros */ static struct ir_scancode ir_codes_apac_viewcomp[] = { @@ -279,12 +271,7 @@ static struct ir_scancode ir_codes_apac_viewcomp[] = { { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ }; - -struct ir_scancode_table ir_codes_apac_viewcomp_table = { - .scan = ir_codes_apac_viewcomp, - .size = ARRAY_SIZE(ir_codes_apac_viewcomp), -}; -EXPORT_SYMBOL_GPL(ir_codes_apac_viewcomp_table); +IR_TABLE(apac_viewcomp, IR_TYPE_UNKNOWN, ir_codes_apac_viewcomp); /* ---------------------------------------------------------------------- */ @@ -331,12 +318,7 @@ static struct ir_scancode ir_codes_pixelview[] = { { 0x1d, KEY_REFRESH }, /* reset */ { 0x18, KEY_MUTE }, /* mute/unmute */ }; - -struct ir_scancode_table ir_codes_pixelview_table = { - .scan = ir_codes_pixelview, - .size = ARRAY_SIZE(ir_codes_pixelview), -}; -EXPORT_SYMBOL_GPL(ir_codes_pixelview_table); +IR_TABLE(pixelview, IR_TYPE_UNKNOWN, ir_codes_pixelview); /* Mauro Carvalho Chehab @@ -381,12 +363,7 @@ static struct ir_scancode ir_codes_pixelview_new[] = { { 0x31, KEY_TV }, { 0x34, KEY_RADIO }, }; - -struct ir_scancode_table ir_codes_pixelview_new_table = { - .scan = ir_codes_pixelview_new, - .size = ARRAY_SIZE(ir_codes_pixelview_new), -}; -EXPORT_SYMBOL_GPL(ir_codes_pixelview_new_table); +IR_TABLE(pixelview_new, IR_TYPE_UNKNOWN, ir_codes_pixelview_new); static struct ir_scancode ir_codes_nebula[] = { { 0x00, KEY_0 }, @@ -445,12 +422,7 @@ static struct ir_scancode ir_codes_nebula[] = { { 0x35, KEY_PHONE }, { 0x36, KEY_PC }, }; - -struct ir_scancode_table ir_codes_nebula_table = { - .scan = ir_codes_nebula, - .size = ARRAY_SIZE(ir_codes_nebula), -}; -EXPORT_SYMBOL_GPL(ir_codes_nebula_table); +IR_TABLE(nebula, IR_TYPE_UNKNOWN, ir_codes_nebula); /* DigitalNow DNTV Live DVB-T Remote */ static struct ir_scancode ir_codes_dntv_live_dvb_t[] = { @@ -490,12 +462,7 @@ static struct ir_scancode ir_codes_dntv_live_dvb_t[] = { { 0x1e, KEY_CHANNELDOWN }, { 0x1f, KEY_VOLUMEDOWN }, }; - -struct ir_scancode_table ir_codes_dntv_live_dvb_t_table = { - .scan = ir_codes_dntv_live_dvb_t, - .size = ARRAY_SIZE(ir_codes_dntv_live_dvb_t), -}; -EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvb_t_table); +IR_TABLE(dntv_live_dvb_t, IR_TYPE_UNKNOWN, ir_codes_dntv_live_dvb_t); /* ---------------------------------------------------------------------- */ @@ -547,12 +514,7 @@ static struct ir_scancode ir_codes_iodata_bctv7e[] = { { 0x61, KEY_FASTFORWARD }, /* forward >> */ { 0x01, KEY_NEXT }, /* skip >| */ }; - -struct ir_scancode_table ir_codes_iodata_bctv7e_table = { - .scan = ir_codes_iodata_bctv7e, - .size = ARRAY_SIZE(ir_codes_iodata_bctv7e), -}; -EXPORT_SYMBOL_GPL(ir_codes_iodata_bctv7e_table); +IR_TABLE(iodata_bctv7e, IR_TYPE_UNKNOWN, ir_codes_iodata_bctv7e); /* ---------------------------------------------------------------------- */ @@ -605,12 +567,7 @@ static struct ir_scancode ir_codes_adstech_dvb_t_pci[] = { { 0x15, KEY_VOLUMEUP }, { 0x1c, KEY_VOLUMEDOWN }, }; - -struct ir_scancode_table ir_codes_adstech_dvb_t_pci_table = { - .scan = ir_codes_adstech_dvb_t_pci, - .size = ARRAY_SIZE(ir_codes_adstech_dvb_t_pci), -}; -EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci_table); +IR_TABLE(adstech_dvb_t_pci, IR_TYPE_UNKNOWN, ir_codes_adstech_dvb_t_pci); /* ---------------------------------------------------------------------- */ @@ -644,12 +601,7 @@ static struct ir_scancode ir_codes_msi_tvanywhere[] = { { 0x1e, KEY_CHANNELDOWN }, { 0x1f, KEY_VOLUMEDOWN }, }; - -struct ir_scancode_table ir_codes_msi_tvanywhere_table = { - .scan = ir_codes_msi_tvanywhere, - .size = ARRAY_SIZE(ir_codes_msi_tvanywhere), -}; -EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_table); +IR_TABLE(msi_tvanywhere, IR_TYPE_UNKNOWN, ir_codes_msi_tvanywhere); /* ---------------------------------------------------------------------- */ @@ -738,12 +690,7 @@ static struct ir_scancode ir_codes_msi_tvanywhere_plus[] = { { 0x0c, KEY_FASTFORWARD }, /* >> */ { 0x1d, KEY_RESTART }, /* Reset */ }; - -struct ir_scancode_table ir_codes_msi_tvanywhere_plus_table = { - .scan = ir_codes_msi_tvanywhere_plus, - .size = ARRAY_SIZE(ir_codes_msi_tvanywhere_plus), -}; -EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus_table); +IR_TABLE(msi_tvanywhere_plus, IR_TYPE_UNKNOWN, ir_codes_msi_tvanywhere_plus); /* ---------------------------------------------------------------------- */ @@ -791,12 +738,7 @@ static struct ir_scancode ir_codes_cinergy_1400[] = { { 0x48, KEY_STOP }, { 0x5c, KEY_NEXT }, }; - -struct ir_scancode_table ir_codes_cinergy_1400_table = { - .scan = ir_codes_cinergy_1400, - .size = ARRAY_SIZE(ir_codes_cinergy_1400), -}; -EXPORT_SYMBOL_GPL(ir_codes_cinergy_1400_table); +IR_TABLE(cinergy_1400, IR_TYPE_UNKNOWN, ir_codes_cinergy_1400); /* ---------------------------------------------------------------------- */ @@ -845,12 +787,7 @@ static struct ir_scancode ir_codes_avertv_303[] = { { 0x13, KEY_DOWN }, { 0x1b, KEY_UP }, }; - -struct ir_scancode_table ir_codes_avertv_303_table = { - .scan = ir_codes_avertv_303, - .size = ARRAY_SIZE(ir_codes_avertv_303), -}; -EXPORT_SYMBOL_GPL(ir_codes_avertv_303_table); +IR_TABLE(avertv_303, IR_TYPE_UNKNOWN, ir_codes_avertv_303); /* ---------------------------------------------------------------------- */ @@ -911,12 +848,7 @@ static struct ir_scancode ir_codes_dntv_live_dvbt_pro[] = { { 0x5c, KEY_YELLOW }, { 0x5d, KEY_BLUE }, }; - -struct ir_scancode_table ir_codes_dntv_live_dvbt_pro_table = { - .scan = ir_codes_dntv_live_dvbt_pro, - .size = ARRAY_SIZE(ir_codes_dntv_live_dvbt_pro), -}; -EXPORT_SYMBOL_GPL(ir_codes_dntv_live_dvbt_pro_table); +IR_TABLE(dntv_live_dvbt_pro, IR_TYPE_UNKNOWN, ir_codes_dntv_live_dvbt_pro); static struct ir_scancode ir_codes_em_terratec[] = { { 0x01, KEY_CHANNEL }, @@ -948,12 +880,7 @@ static struct ir_scancode ir_codes_em_terratec[] = { { 0x1e, KEY_STOP }, { 0x40, KEY_ZOOM }, }; - -struct ir_scancode_table ir_codes_em_terratec_table = { - .scan = ir_codes_em_terratec, - .size = ARRAY_SIZE(ir_codes_em_terratec), -}; -EXPORT_SYMBOL_GPL(ir_codes_em_terratec_table); +IR_TABLE(em_terratec, IR_TYPE_UNKNOWN, ir_codes_em_terratec); static struct ir_scancode ir_codes_pinnacle_grey[] = { { 0x3a, KEY_0 }, @@ -1005,12 +932,7 @@ static struct ir_scancode ir_codes_pinnacle_grey[] = { { 0x2a, KEY_MEDIA }, { 0x18, KEY_EPG }, }; - -struct ir_scancode_table ir_codes_pinnacle_grey_table = { - .scan = ir_codes_pinnacle_grey, - .size = ARRAY_SIZE(ir_codes_pinnacle_grey), -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey_table); +IR_TABLE(pinnacle_grey, IR_TYPE_UNKNOWN, ir_codes_pinnacle_grey); static struct ir_scancode ir_codes_flyvideo[] = { { 0x0f, KEY_0 }, @@ -1043,12 +965,7 @@ static struct ir_scancode ir_codes_flyvideo[] = { { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ }; - -struct ir_scancode_table ir_codes_flyvideo_table = { - .scan = ir_codes_flyvideo, - .size = ARRAY_SIZE(ir_codes_flyvideo), -}; -EXPORT_SYMBOL_GPL(ir_codes_flyvideo_table); +IR_TABLE(flyvideo, IR_TYPE_UNKNOWN, ir_codes_flyvideo); static struct ir_scancode ir_codes_flydvb[] = { { 0x01, KEY_ZOOM }, /* Full Screen */ @@ -1088,12 +1005,7 @@ static struct ir_scancode ir_codes_flydvb[] = { { 0x11, KEY_STOP }, /* Stop */ { 0x0e, KEY_NEXT }, /* End >>| */ }; - -struct ir_scancode_table ir_codes_flydvb_table = { - .scan = ir_codes_flydvb, - .size = ARRAY_SIZE(ir_codes_flydvb), -}; -EXPORT_SYMBOL_GPL(ir_codes_flydvb_table); +IR_TABLE(flydvb, IR_TYPE_UNKNOWN, ir_codes_flydvb); static struct ir_scancode ir_codes_cinergy[] = { { 0x00, KEY_0 }, @@ -1134,12 +1046,7 @@ static struct ir_scancode ir_codes_cinergy[] = { { 0x22, KEY_PAUSE }, { 0x23, KEY_STOP }, }; - -struct ir_scancode_table ir_codes_cinergy_table = { - .scan = ir_codes_cinergy, - .size = ARRAY_SIZE(ir_codes_cinergy), -}; -EXPORT_SYMBOL_GPL(ir_codes_cinergy_table); +IR_TABLE(cinergy, IR_TYPE_UNKNOWN, ir_codes_cinergy); /* Alfons Geser * updates from Job D. R. Borges */ @@ -1197,12 +1104,7 @@ static struct ir_scancode ir_codes_eztv[] = { { 0x13, KEY_ENTER }, /* enter */ { 0x21, KEY_DOT }, /* . (decimal dot) */ }; - -struct ir_scancode_table ir_codes_eztv_table = { - .scan = ir_codes_eztv, - .size = ARRAY_SIZE(ir_codes_eztv), -}; -EXPORT_SYMBOL_GPL(ir_codes_eztv_table); +IR_TABLE(eztv, IR_TYPE_UNKNOWN, ir_codes_eztv); /* Alex Hermann */ static struct ir_scancode ir_codes_avermedia[] = { @@ -1250,12 +1152,7 @@ static struct ir_scancode ir_codes_avermedia[] = { { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ }; - -struct ir_scancode_table ir_codes_avermedia_table = { - .scan = ir_codes_avermedia, - .size = ARRAY_SIZE(ir_codes_avermedia), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_table); +IR_TABLE(avermedia, IR_TYPE_UNKNOWN, ir_codes_avermedia); static struct ir_scancode ir_codes_videomate_tv_pvr[] = { { 0x14, KEY_MUTE }, @@ -1305,12 +1202,7 @@ static struct ir_scancode ir_codes_videomate_tv_pvr[] = { { 0x20, KEY_LANGUAGE }, { 0x21, KEY_SLEEP }, }; - -struct ir_scancode_table ir_codes_videomate_tv_pvr_table = { - .scan = ir_codes_videomate_tv_pvr, - .size = ARRAY_SIZE(ir_codes_videomate_tv_pvr), -}; -EXPORT_SYMBOL_GPL(ir_codes_videomate_tv_pvr_table); +IR_TABLE(videomate_tv_pvr, IR_TYPE_UNKNOWN, ir_codes_videomate_tv_pvr); /* Michael Tokarev http://www.corpit.ru/mjt/beholdTV/remote_control.jpg @@ -1407,12 +1299,7 @@ static struct ir_scancode ir_codes_manli[] = { /* 0x1d unused ? */ }; - -struct ir_scancode_table ir_codes_manli_table = { - .scan = ir_codes_manli, - .size = ARRAY_SIZE(ir_codes_manli), -}; -EXPORT_SYMBOL_GPL(ir_codes_manli_table); +IR_TABLE(manli, IR_TYPE_UNKNOWN, ir_codes_manli); /* Mike Baikov */ static struct ir_scancode ir_codes_gotview7135[] = { @@ -1453,12 +1340,7 @@ static struct ir_scancode ir_codes_gotview7135[] = { { 0x1e, KEY_TIME }, /* TIMESHIFT */ { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ }; - -struct ir_scancode_table ir_codes_gotview7135_table = { - .scan = ir_codes_gotview7135, - .size = ARRAY_SIZE(ir_codes_gotview7135), -}; -EXPORT_SYMBOL_GPL(ir_codes_gotview7135_table); +IR_TABLE(gotview7135, IR_TYPE_UNKNOWN, ir_codes_gotview7135); static struct ir_scancode ir_codes_purpletv[] = { { 0x03, KEY_POWER }, @@ -1502,12 +1384,7 @@ static struct ir_scancode ir_codes_purpletv[] = { { 0x42, KEY_REWIND }, /* Backward ? */ }; - -struct ir_scancode_table ir_codes_purpletv_table = { - .scan = ir_codes_purpletv, - .size = ARRAY_SIZE(ir_codes_purpletv), -}; -EXPORT_SYMBOL_GPL(ir_codes_purpletv_table); +IR_TABLE(purpletv, IR_TYPE_UNKNOWN, ir_codes_purpletv); /* Mapping for the 28 key remote control as seen at http://www.sednacomputer.com/photo/cardbus-tv.jpg @@ -1549,12 +1426,7 @@ static struct ir_scancode ir_codes_pctv_sedna[] = { { 0x17, KEY_DIGITS }, /* Plus */ { 0x1f, KEY_PLAY }, /* Play */ }; - -struct ir_scancode_table ir_codes_pctv_sedna_table = { - .scan = ir_codes_pctv_sedna, - .size = ARRAY_SIZE(ir_codes_pctv_sedna), -}; -EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna_table); +IR_TABLE(pctv_sedna, IR_TYPE_UNKNOWN, ir_codes_pctv_sedna); /* Mark Phalan */ static struct ir_scancode ir_codes_pv951[] = { @@ -1594,12 +1466,7 @@ static struct ir_scancode ir_codes_pv951[] = { { 0x14, KEY_EQUAL }, /* SYNC */ { 0x1c, KEY_MEDIA }, /* PC/TV */ }; - -struct ir_scancode_table ir_codes_pv951_table = { - .scan = ir_codes_pv951, - .size = ARRAY_SIZE(ir_codes_pv951), -}; -EXPORT_SYMBOL_GPL(ir_codes_pv951_table); +IR_TABLE(pv951, IR_TYPE_UNKNOWN, ir_codes_pv951); /* generic RC5 keytable */ /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ @@ -1642,12 +1509,7 @@ static struct ir_scancode ir_codes_rc5_tv[] = { { 0x3d, KEY_SUSPEND }, /* system standby */ }; - -struct ir_scancode_table ir_codes_rc5_tv_table = { - .scan = ir_codes_rc5_tv, - .size = ARRAY_SIZE(ir_codes_rc5_tv), -}; -EXPORT_SYMBOL_GPL(ir_codes_rc5_tv_table); +IR_TABLE(rc5_tv, IR_TYPE_UNKNOWN, ir_codes_rc5_tv); /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ static struct ir_scancode ir_codes_winfast[] = { @@ -1711,12 +1573,7 @@ static struct ir_scancode ir_codes_winfast[] = { { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ }; - -struct ir_scancode_table ir_codes_winfast_table = { - .scan = ir_codes_winfast, - .size = ARRAY_SIZE(ir_codes_winfast), -}; -EXPORT_SYMBOL_GPL(ir_codes_winfast_table); +IR_TABLE(winfast, IR_TYPE_UNKNOWN, ir_codes_winfast); static struct ir_scancode ir_codes_pinnacle_color[] = { { 0x59, KEY_MUTE }, @@ -1773,12 +1630,7 @@ static struct ir_scancode ir_codes_pinnacle_color[] = { { 0x74, KEY_CHANNEL }, { 0x0a, KEY_BACKSPACE }, }; - -struct ir_scancode_table ir_codes_pinnacle_color_table = { - .scan = ir_codes_pinnacle_color, - .size = ARRAY_SIZE(ir_codes_pinnacle_color), -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color_table); +IR_TABLE(pinnacle_color, IR_TYPE_UNKNOWN, ir_codes_pinnacle_color); /* Hauppauge: the newer, gray remotes (seems there are multiple * slightly different versions), shipped with cx88+ivtv cards. @@ -1840,12 +1692,7 @@ static struct ir_scancode ir_codes_hauppauge_new[] = { { 0x3c, KEY_ZOOM }, /* full */ { 0x3d, KEY_POWER }, /* system power (green button) */ }; - -struct ir_scancode_table ir_codes_hauppauge_new_table = { - .scan = ir_codes_hauppauge_new, - .size = ARRAY_SIZE(ir_codes_hauppauge_new), -}; -EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table); +IR_TABLE(hauppauge_new, IR_TYPE_UNKNOWN, ir_codes_hauppauge_new); static struct ir_scancode ir_codes_npgtech[] = { { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ @@ -1888,12 +1735,7 @@ static struct ir_scancode ir_codes_npgtech[] = { { 0x10, KEY_POWER }, }; - -struct ir_scancode_table ir_codes_npgtech_table = { - .scan = ir_codes_npgtech, - .size = ARRAY_SIZE(ir_codes_npgtech), -}; -EXPORT_SYMBOL_GPL(ir_codes_npgtech_table); +IR_TABLE(npgtech, IR_TYPE_UNKNOWN, ir_codes_npgtech); /* Norwood Micro (non-Pro) TV Tuner By Peter Naulls @@ -1940,12 +1782,7 @@ static struct ir_scancode ir_codes_norwood[] = { { 0x34, KEY_RADIO }, /* FM */ { 0x65, KEY_POWER }, /* Computer power */ }; - -struct ir_scancode_table ir_codes_norwood_table = { - .scan = ir_codes_norwood, - .size = ARRAY_SIZE(ir_codes_norwood), -}; -EXPORT_SYMBOL_GPL(ir_codes_norwood_table); +IR_TABLE(norwood, IR_TYPE_UNKNOWN, ir_codes_norwood); /* From reading the following remotes: * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 @@ -1999,12 +1836,7 @@ static struct ir_scancode ir_codes_budget_ci_old[] = { { 0x3d, KEY_POWER2 }, { 0x3e, KEY_TUNER }, }; - -struct ir_scancode_table ir_codes_budget_ci_old_table = { - .scan = ir_codes_budget_ci_old, - .size = ARRAY_SIZE(ir_codes_budget_ci_old), -}; -EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old_table); +IR_TABLE(budget_ci_old, IR_TYPE_UNKNOWN, ir_codes_budget_ci_old); /* * Marc Fargas @@ -2057,13 +1889,7 @@ static struct ir_scancode ir_codes_asus_pc39[] = { { 0x3d, KEY_MUTE }, /* mute */ { 0x01, KEY_DVD }, /* dvd */ }; - -struct ir_scancode_table ir_codes_asus_pc39_table = { - .scan = ir_codes_asus_pc39, - .size = ARRAY_SIZE(ir_codes_asus_pc39), -}; -EXPORT_SYMBOL_GPL(ir_codes_asus_pc39_table); - +IR_TABLE(asus_pc39, IR_TYPE_UNKNOWN, ir_codes_asus_pc39); /* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons Juan Pablo Sormani */ @@ -2137,12 +1963,7 @@ static struct ir_scancode ir_codes_encore_enltv[] = { { 0x47, KEY_YELLOW }, /* AP3 */ { 0x57, KEY_BLUE }, /* AP4 */ }; - -struct ir_scancode_table ir_codes_encore_enltv_table = { - .scan = ir_codes_encore_enltv, - .size = ARRAY_SIZE(ir_codes_encore_enltv), -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_table); +IR_TABLE(encore_enltv, IR_TYPE_UNKNOWN, ir_codes_encore_enltv); /* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton Mauro Carvalho Chehab */ @@ -2194,12 +2015,7 @@ static struct ir_scancode ir_codes_encore_enltv2[] = { { 0x7d, KEY_FORWARD }, { 0x79, KEY_STOP }, }; - -struct ir_scancode_table ir_codes_encore_enltv2_table = { - .scan = ir_codes_encore_enltv2, - .size = ARRAY_SIZE(ir_codes_encore_enltv2), -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv2_table); +IR_TABLE(encore_enltv2, IR_TYPE_UNKNOWN, ir_codes_encore_enltv2); /* for the Technotrend 1500 bundled remotes (grey and black): */ static struct ir_scancode ir_codes_tt_1500[] = { @@ -2243,12 +2059,7 @@ static struct ir_scancode ir_codes_tt_1500[] = { { 0x3e, KEY_PAUSE }, { 0x3f, KEY_FORWARD }, }; - -struct ir_scancode_table ir_codes_tt_1500_table = { - .scan = ir_codes_tt_1500, - .size = ARRAY_SIZE(ir_codes_tt_1500), -}; -EXPORT_SYMBOL_GPL(ir_codes_tt_1500_table); +IR_TABLE(tt_1500, IR_TYPE_UNKNOWN, ir_codes_tt_1500); /* DViCO FUSION HDTV MCE remote */ static struct ir_scancode ir_codes_fusionhdtv_mce[] = { @@ -2308,12 +2119,7 @@ static struct ir_scancode ir_codes_fusionhdtv_mce[] = { { 0x01, KEY_RECORD }, { 0x4e, KEY_POWER }, }; - -struct ir_scancode_table ir_codes_fusionhdtv_mce_table = { - .scan = ir_codes_fusionhdtv_mce, - .size = ARRAY_SIZE(ir_codes_fusionhdtv_mce), -}; -EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce_table); +IR_TABLE(fusionhdtv_mce, IR_TYPE_UNKNOWN, ir_codes_fusionhdtv_mce); /* Pinnacle PCTV HD 800i mini remote */ static struct ir_scancode ir_codes_pinnacle_pctv_hd[] = { @@ -2348,12 +2154,7 @@ static struct ir_scancode ir_codes_pinnacle_pctv_hd[] = { { 0x36, KEY_RECORD }, { 0x3f, KEY_EPG }, /* Labeled "?" */ }; - -struct ir_scancode_table ir_codes_pinnacle_pctv_hd_table = { - .scan = ir_codes_pinnacle_pctv_hd, - .size = ARRAY_SIZE(ir_codes_pinnacle_pctv_hd), -}; -EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd_table); +IR_TABLE(pinnacle_pctv_hd, IR_TYPE_UNKNOWN, ir_codes_pinnacle_pctv_hd); /* * Igor Kuznetsov @@ -2456,12 +2257,7 @@ static struct ir_scancode ir_codes_behold[] = { { 0x5c, KEY_CAMERA }, }; - -struct ir_scancode_table ir_codes_behold_table = { - .scan = ir_codes_behold, - .size = ARRAY_SIZE(ir_codes_behold), -}; -EXPORT_SYMBOL_GPL(ir_codes_behold_table); +IR_TABLE(behold, IR_TYPE_UNKNOWN, ir_codes_behold); /* Beholder Intl. Ltd. 2008 * Dmitry Belimov d.belimov@google.com @@ -2531,12 +2327,7 @@ static struct ir_scancode ir_codes_behold_columbus[] = { { 0x1A, KEY_NEXT }, }; - -struct ir_scancode_table ir_codes_behold_columbus_table = { - .scan = ir_codes_behold_columbus, - .size = ARRAY_SIZE(ir_codes_behold_columbus), -}; -EXPORT_SYMBOL_GPL(ir_codes_behold_columbus_table); +IR_TABLE(behold_columbus, IR_TYPE_UNKNOWN, ir_codes_behold_columbus); /* * Remote control for the Genius TVGO A11MCE @@ -2582,12 +2373,7 @@ static struct ir_scancode ir_codes_genius_tvgo_a11mce[] = { { 0x13, KEY_YELLOW }, { 0x50, KEY_BLUE }, }; - -struct ir_scancode_table ir_codes_genius_tvgo_a11mce_table = { - .scan = ir_codes_genius_tvgo_a11mce, - .size = ARRAY_SIZE(ir_codes_genius_tvgo_a11mce), -}; -EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce_table); +IR_TABLE(genius_tvgo_a11mce, IR_TYPE_UNKNOWN, ir_codes_genius_tvgo_a11mce); /* * Remote control for Powercolor Real Angel 330 @@ -2630,12 +2416,7 @@ static struct ir_scancode ir_codes_powercolor_real_angel[] = { { 0x14, KEY_RADIO }, /* FM radio */ { 0x25, KEY_POWER }, /* power */ }; - -struct ir_scancode_table ir_codes_powercolor_real_angel_table = { - .scan = ir_codes_powercolor_real_angel, - .size = ARRAY_SIZE(ir_codes_powercolor_real_angel), -}; -EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel_table); +IR_TABLE(powercolor_real_angel, IR_TYPE_UNKNOWN, ir_codes_powercolor_real_angel); /* Kworld Plus TV Analog Lite PCI IR Mauro Carvalho Chehab @@ -2696,11 +2477,7 @@ static struct ir_scancode ir_codes_kworld_plus_tv_analog[] = { { 0x18, KEY_RED}, /* B */ { 0x23, KEY_GREEN}, /* C */ }; -struct ir_scancode_table ir_codes_kworld_plus_tv_analog_table = { - .scan = ir_codes_kworld_plus_tv_analog, - .size = ARRAY_SIZE(ir_codes_kworld_plus_tv_analog), -}; -EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog_table); +IR_TABLE(kworld_plus_tv_analog, IR_TYPE_UNKNOWN, ir_codes_kworld_plus_tv_analog); /* Kaiomy TVnPC U2 Mauro Carvalho Chehab @@ -2749,11 +2526,7 @@ static struct ir_scancode ir_codes_kaiomy[] = { { 0x1e, KEY_YELLOW}, { 0x1f, KEY_BLUE}, }; -struct ir_scancode_table ir_codes_kaiomy_table = { - .scan = ir_codes_kaiomy, - .size = ARRAY_SIZE(ir_codes_kaiomy), -}; -EXPORT_SYMBOL_GPL(ir_codes_kaiomy_table); +IR_TABLE(kaiomy, IR_TYPE_UNKNOWN, ir_codes_kaiomy); static struct ir_scancode ir_codes_avermedia_a16d[] = { { 0x20, KEY_LIST}, @@ -2791,11 +2564,7 @@ static struct ir_scancode ir_codes_avermedia_a16d[] = { { 0x08, KEY_EPG}, { 0x2a, KEY_MENU}, }; -struct ir_scancode_table ir_codes_avermedia_a16d_table = { - .scan = ir_codes_avermedia_a16d, - .size = ARRAY_SIZE(ir_codes_avermedia_a16d), -}; -EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d_table); +IR_TABLE(avermedia_a16d, IR_TYPE_UNKNOWN, ir_codes_avermedia_a16d); /* Encore ENLTV-FM v5.3 Mauro Carvalho Chehab @@ -2838,11 +2607,7 @@ static struct ir_scancode ir_codes_encore_enltv_fm53[] = { { 0x0c, KEY_ZOOM}, /* hide pannel */ { 0x47, KEY_SLEEP}, /* shutdown */ }; -struct ir_scancode_table ir_codes_encore_enltv_fm53_table = { - .scan = ir_codes_encore_enltv_fm53, - .size = ARRAY_SIZE(ir_codes_encore_enltv_fm53), -}; -EXPORT_SYMBOL_GPL(ir_codes_encore_enltv_fm53_table); +IR_TABLE(encore_enltv_fm53, IR_TYPE_UNKNOWN, ir_codes_encore_enltv_fm53); /* Zogis Real Audio 220 - 32 keys IR */ static struct ir_scancode ir_codes_real_audio_220_32_keys[] = { @@ -2882,11 +2647,7 @@ static struct ir_scancode ir_codes_real_audio_220_32_keys[] = { { 0x19, KEY_CAMERA}, /* Snapshot */ }; -struct ir_scancode_table ir_codes_real_audio_220_32_keys_table = { - .scan = ir_codes_real_audio_220_32_keys, - .size = ARRAY_SIZE(ir_codes_real_audio_220_32_keys), -}; -EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys_table); +IR_TABLE(real_audio_220_32_keys, IR_TYPE_UNKNOWN, ir_codes_real_audio_220_32_keys); /* ATI TV Wonder HD 600 USB Devin Heitmueller @@ -2917,11 +2678,7 @@ static struct ir_scancode ir_codes_ati_tv_wonder_hd_600[] = { { 0x16, KEY_MUTE}, { 0x17, KEY_VOLUMEDOWN}, }; -struct ir_scancode_table ir_codes_ati_tv_wonder_hd_600_table = { - .scan = ir_codes_ati_tv_wonder_hd_600, - .size = ARRAY_SIZE(ir_codes_ati_tv_wonder_hd_600), -}; -EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600_table); +IR_TABLE(ati_tv_wonder_hd_600, IR_TYPE_UNKNOWN, ir_codes_ati_tv_wonder_hd_600); /* DVBWorld remotes Igor M. Liplianin @@ -2959,11 +2716,7 @@ static struct ir_scancode ir_codes_dm1105_nec[] = { { 0x1e, KEY_TV}, /* tvmode */ { 0x1b, KEY_B}, /* recall */ }; -struct ir_scancode_table ir_codes_dm1105_nec_table = { - .scan = ir_codes_dm1105_nec, - .size = ARRAY_SIZE(ir_codes_dm1105_nec), -}; -EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec_table); +IR_TABLE(dm1105_nec, IR_TYPE_UNKNOWN, ir_codes_dm1105_nec); static struct ir_scancode ir_codes_tevii_nec[] = { { 0x0a, KEY_POWER2}, @@ -3014,11 +2767,7 @@ static struct ir_scancode ir_codes_tevii_nec[] = { { 0x56, KEY_MODE}, { 0x58, KEY_SWITCHVIDEOMODE}, }; -struct ir_scancode_table ir_codes_tevii_nec_table = { - .scan = ir_codes_tevii_nec, - .size = ARRAY_SIZE(ir_codes_tevii_nec), -}; -EXPORT_SYMBOL_GPL(ir_codes_tevii_nec_table); +IR_TABLE(tevii_nec, IR_TYPE_UNKNOWN, ir_codes_tevii_nec); static struct ir_scancode ir_codes_tbs_nec[] = { { 0x04, KEY_POWER2}, /*power*/ @@ -3054,11 +2803,7 @@ static struct ir_scancode ir_codes_tbs_nec[] = { { 0x00, KEY_PREVIOUS}, { 0x1b, KEY_MODE}, }; -struct ir_scancode_table ir_codes_tbs_nec_table = { - .scan = ir_codes_tbs_nec, - .size = ARRAY_SIZE(ir_codes_tbs_nec), -}; -EXPORT_SYMBOL_GPL(ir_codes_tbs_nec_table); +IR_TABLE(tbs_nec, IR_TYPE_UNKNOWN, ir_codes_tbs_nec); /* Terratec Cinergy Hybrid T USB XS Devin Heitmueller @@ -3112,11 +2857,7 @@ static struct ir_scancode ir_codes_terratec_cinergy_xs[] = { { 0x4f, KEY_FASTFORWARD}, { 0x5c, KEY_NEXT}, }; -struct ir_scancode_table ir_codes_terratec_cinergy_xs_table = { - .scan = ir_codes_terratec_cinergy_xs, - .size = ARRAY_SIZE(ir_codes_terratec_cinergy_xs), -}; -EXPORT_SYMBOL_GPL(ir_codes_terratec_cinergy_xs_table); +IR_TABLE(terratec_cinergy_xs, IR_TYPE_UNKNOWN, ir_codes_terratec_cinergy_xs); /* EVGA inDtube Devin Heitmueller @@ -3139,11 +2880,7 @@ static struct ir_scancode ir_codes_evga_indtube[] = { { 0x1f, KEY_NEXT}, { 0x13, KEY_CAMERA}, }; -struct ir_scancode_table ir_codes_evga_indtube_table = { - .scan = ir_codes_evga_indtube, - .size = ARRAY_SIZE(ir_codes_evga_indtube), -}; -EXPORT_SYMBOL_GPL(ir_codes_evga_indtube_table); +IR_TABLE(evga_indtube, IR_TYPE_UNKNOWN, ir_codes_evga_indtube); static struct ir_scancode ir_codes_videomate_s350[] = { { 0x00, KEY_TV}, @@ -3191,11 +2928,7 @@ static struct ir_scancode ir_codes_videomate_s350[] = { { 0x11, KEY_ENTER}, { 0x20, KEY_TEXT}, }; -struct ir_scancode_table ir_codes_videomate_s350_table = { - .scan = ir_codes_videomate_s350, - .size = ARRAY_SIZE(ir_codes_videomate_s350), -}; -EXPORT_SYMBOL_GPL(ir_codes_videomate_s350_table); +IR_TABLE(videomate_s350, IR_TYPE_UNKNOWN, ir_codes_videomate_s350); /* GADMEI UTV330+ RM008Z remote Shine Liu @@ -3238,11 +2971,7 @@ static struct ir_scancode ir_codes_gadmei_rm008z[] = { { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ { 0x15, KEY_ENTER}, /* OK */ }; -struct ir_scancode_table ir_codes_gadmei_rm008z_table = { - .scan = ir_codes_gadmei_rm008z, - .size = ARRAY_SIZE(ir_codes_gadmei_rm008z), -}; -EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table); +IR_TABLE(gadmei_rm008z, IR_TYPE_UNKNOWN, ir_codes_gadmei_rm008z); /************************************************************* * COMPLETE SCANCODE TABLES @@ -3313,13 +3042,7 @@ static struct ir_scancode ir_codes_rc5_hauppauge_new[] = { { 0x1e3c, KEY_ZOOM }, /* full */ { 0x1e3d, KEY_POWER }, /* system power (green button) */ }; - -struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = { - .scan = ir_codes_rc5_hauppauge_new, - .size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new), - .ir_type = IR_TYPE_RC5, -}; -EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table); +IR_TABLE(rc5_hauppauge_new, IR_TYPE_RC5, ir_codes_rc5_hauppauge_new); /* Terratec Cinergy Hybrid T USB XS FM Mauro Carvalho Chehab @@ -3386,13 +3109,7 @@ static struct ir_scancode ir_codes_nec_terratec_cinergy_xs[] = { { 0x144f, KEY_FASTFORWARD}, { 0x145c, KEY_NEXT}, }; -struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = { - .scan = ir_codes_nec_terratec_cinergy_xs, - .size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs), - .ir_type = IR_TYPE_NEC, -}; -EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table); - +IR_TABLE(nec_terratec_cinergy_xs, IR_TYPE_NEC, ir_codes_nec_terratec_cinergy_xs); /* Leadtek Winfast TV USB II Deluxe remote Magnus Alm @@ -3436,11 +3153,7 @@ static struct ir_scancode ir_codes_winfast_usbii_deluxe[] = { { 0x63, KEY_ENTER}, /* ENTER */ }; -struct ir_scancode_table ir_codes_winfast_usbii_deluxe_table = { - .scan = ir_codes_winfast_usbii_deluxe, - .size = ARRAY_SIZE(ir_codes_winfast_usbii_deluxe), -}; -EXPORT_SYMBOL_GPL(ir_codes_winfast_usbii_deluxe_table); +IR_TABLE(winfast_usbii_deluxe, IR_TYPE_UNKNOWN, ir_codes_winfast_usbii_deluxe); /* Kworld 315U */ @@ -3485,10 +3198,4 @@ static struct ir_scancode ir_codes_kworld_315u[] = { { 0x611e, KEY_YELLOW }, { 0x611f, KEY_BLUE }, }; - -struct ir_scancode_table ir_codes_kworld_315u_table = { - .scan = ir_codes_kworld_315u, - .size = ARRAY_SIZE(ir_codes_kworld_315u), - .ir_type = IR_TYPE_NEC, -}; -EXPORT_SYMBOL_GPL(ir_codes_kworld_315u_table); +IR_TABLE(kworld_315u, IR_TYPE_NEC, ir_codes_kworld_315u); -- cgit v1.2.3 From 9c89a181a09eaafca5fc638c3b7ce1620227f60a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Mar 2010 11:50:17 -0300 Subject: V4L/DVB: ir-core: Export IR name via uevent Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 1 + drivers/media/IR/ir-sysfs.c | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index af1f4d7fb910..6db3ff74659b 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -419,6 +419,7 @@ int ir_input_register(struct input_dev *input_dev, spin_lock_init(&ir_dev->rc_tab.lock); + ir_dev->rc_tab.name = rc_tab->name; ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * sizeof(struct ir_scancode), GFP_KERNEL); diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 59bd388be8d7..6d63657b5685 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -126,6 +126,24 @@ static ssize_t store_protocol(struct device *d, return len; } + +#define ADD_HOTPLUG_VAR(fmt, val...) \ + do { \ + int err = add_uevent_var(env, fmt, val); \ + if (err) \ + return err; \ + } while (0) + +static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(device); + + if (ir_dev->rc_tab.name) + ADD_HOTPLUG_VAR("NAME=\"%s\"", ir_dev->rc_tab.name); + + return 0; +} + /* * Static device attribute struct with the sysfs attributes for IR's */ @@ -148,9 +166,9 @@ static const struct attribute_group *ir_dev_attr_groups[] = { static struct device_type ir_dev_type = { .groups = ir_dev_attr_groups, + .uevent = ir_dev_uevent, }; - /** * ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv? * @input_dev: the struct input_dev descriptor of the device @@ -173,6 +191,7 @@ int ir_register_class(struct input_dev *input_dev) ir_dev->dev.class = &ir_input_class; ir_dev->dev.parent = input_dev->dev.parent; dev_set_name(&ir_dev->dev, "irrcv%d", devno); + dev_set_drvdata(&ir_dev->dev, ir_dev); rc = device_register(&ir_dev->dev); if (rc) return rc; @@ -187,8 +206,8 @@ int ir_register_class(struct input_dev *input_dev) __module_get(THIS_MODULE); - path = kobject_get_path(&input_dev->dev.kobj, GFP_KERNEL); - printk(KERN_INFO "%s: %s associated with sysfs %s\n", + path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL); + printk(KERN_INFO "%s: %s as %s\n", dev_name(&ir_dev->dev), input_dev->name ? input_dev->name : "Unspecified device", path ? path : "N/A"); -- cgit v1.2.3 From 727e625cc2c114e449a78f851b0c12edac897a83 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 12 Mar 2010 21:18:14 -0300 Subject: V4L/DVB: ir-core: export driver name used by IR via uevent Now, both driver and keytable names are exported to userspace. This will help userspace to decide when a table need to be replaced by another one. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 7 ++++++- drivers/media/IR/ir-sysfs.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 6db3ff74659b..73fe4bec83bc 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -404,7 +404,8 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); */ int ir_input_register(struct input_dev *input_dev, const struct ir_scancode_table *rc_tab, - const struct ir_dev_props *props) + const struct ir_dev_props *props, + const char *driver_name) { struct ir_input_dev *ir_dev; struct ir_scancode *keymap = rc_tab->scan; @@ -419,6 +420,10 @@ int ir_input_register(struct input_dev *input_dev, spin_lock_init(&ir_dev->rc_tab.lock); + ir_dev->driver_name = kmalloc(strlen(driver_name) + 1, GFP_KERNEL); + if (!ir_dev->driver_name) + return -ENOMEM; + strcpy(ir_dev->driver_name, driver_name); ir_dev->rc_tab.name = rc_tab->name; ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 6d63657b5685..0592515a19f8 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -140,6 +140,8 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) if (ir_dev->rc_tab.name) ADD_HOTPLUG_VAR("NAME=\"%s\"", ir_dev->rc_tab.name); + if (ir_dev->driver_name) + ADD_HOTPLUG_VAR("DRV_NAME=\"%s\"", ir_dev->driver_name); return 0; } -- cgit v1.2.3 From ecf6e72da31f951aed4618e422de62a72a1d76c6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Mar 2010 00:17:58 -0300 Subject: V4L/DVB: ir-core: be less pedantic with RC protocol name Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 0592515a19f8..253e66999f18 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -93,7 +93,7 @@ static ssize_t store_protocol(struct device *d, buf = strsep((char **) &data, "\n"); - if (!strcasecmp(buf, "rc-5")) + if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) ir_type = IR_TYPE_RC5; else if (!strcasecmp(buf, "pd")) ir_type = IR_TYPE_PD; -- cgit v1.2.3 From d152b8b62421c441bea4eb5d92e9d1b4883fd201 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Mar 2010 00:23:30 -0300 Subject: V4L/DVB: saa7134: use a full scancode table for M135A Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keymaps.c | 100 +++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 49 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index dfc777b78dea..55e7acd7209c 100644 --- a/drivers/media/IR/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c @@ -122,55 +122,57 @@ static struct ir_scancode ir_codes_avermedia_dvbt[] = { }; IR_TABLE(avermedia_dvbt, IR_TYPE_UNKNOWN, ir_codes_avermedia_dvbt); -/* Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_avermedia_m135a[] = { - { 0x00, KEY_POWER2 }, - { 0x2e, KEY_DOT }, /* '.' */ - { 0x01, KEY_MODE }, /* TV/FM */ - - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - { 0x11, KEY_0 }, - - { 0x13, KEY_RIGHT }, /* -> */ - { 0x12, KEY_LEFT }, /* <- */ - - { 0x17, KEY_SLEEP }, /* Capturar Imagem */ - { 0x10, KEY_SHUFFLE }, /* Amostra */ - - /* FIXME: The keys bellow aren't ok */ - - { 0x43, KEY_CHANNELUP }, - { 0x42, KEY_CHANNELDOWN }, - { 0x1f, KEY_VOLUMEUP }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x0c, KEY_ENTER }, - - { 0x14, KEY_MUTE }, - { 0x08, KEY_AUDIO }, - - { 0x03, KEY_TEXT }, - { 0x04, KEY_EPG }, - { 0x2b, KEY_TV2 }, /* TV2 */ - - { 0x1d, KEY_RED }, - { 0x1c, KEY_YELLOW }, - { 0x41, KEY_GREEN }, - { 0x40, KEY_BLUE }, - - { 0x1a, KEY_PLAYPAUSE }, - { 0x19, KEY_RECORD }, - { 0x18, KEY_PLAY }, - { 0x1b, KEY_STOP }, -}; -IR_TABLE(avermedia_m135a, IR_TYPE_UNKNOWN, ir_codes_avermedia_m135a); +/* + * Avermedia M135A with IR model RM-JX + * The same codes exist on both Positivo (BR) and original IR + * Mauro Carvalho Chehab + */ +static struct ir_scancode ir_codes_avermedia_m135a_rm_jx[] = { + { 0x0200, KEY_POWER2 }, + { 0x022e, KEY_DOT }, /* '.' */ + { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ + + { 0x0205, KEY_1 }, + { 0x0206, KEY_2 }, + { 0x0207, KEY_3 }, + { 0x0209, KEY_4 }, + { 0x020a, KEY_5 }, + { 0x020b, KEY_6 }, + { 0x020d, KEY_7 }, + { 0x020e, KEY_8 }, + { 0x020f, KEY_9 }, + { 0x0211, KEY_0 }, + + { 0x0213, KEY_RIGHT }, /* -> or L */ + { 0x0212, KEY_LEFT }, /* <- or R */ + + { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ + { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ + + { 0x0303, KEY_CHANNELUP }, + { 0x0302, KEY_CHANNELDOWN }, + { 0x021f, KEY_VOLUMEUP }, + { 0x021e, KEY_VOLUMEDOWN }, + { 0x020c, KEY_ENTER }, /* Full Screen */ + + { 0x0214, KEY_MUTE }, + { 0x0208, KEY_AUDIO }, + + { 0x0203, KEY_TEXT }, /* Teletext */ + { 0x0204, KEY_EPG }, + { 0x022b, KEY_TV2 }, /* TV2 or PIP */ + + { 0x021d, KEY_RED }, + { 0x021c, KEY_YELLOW }, + { 0x0301, KEY_GREEN }, + { 0x0300, KEY_BLUE }, + + { 0x021a, KEY_PLAYPAUSE }, + { 0x0219, KEY_RECORD }, + { 0x0218, KEY_PLAY }, + { 0x021b, KEY_STOP }, +}; +IR_TABLE(aver-m135a-RM-JX, IR_TYPE_NEC, ir_codes_avermedia_m135a_rm_jx); /* Oldrich Jedlicka */ static struct ir_scancode ir_codes_avermedia_cardbus[] = { -- cgit v1.2.3 From a3572c34da8dacc78a629211a91cf34e9b408701 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 20 Mar 2010 20:59:44 -0300 Subject: V4L/DVB: ir-core: Add logic to decode IR protocols at the IR core Adds a method to pass IR raw pulse/code events into ir-core. This is needed in order to support LIRC. It also helps to move common code from the drivers into the core. In order to allow testing, it implements a simple NEC protocol decoder at ir-nec-decoder.c file. The logic is about the same used at saa7134 driver that handles Avermedia M135A and Encore FM53 boards. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Makefile | 2 +- drivers/media/IR/ir-nec-decoder.c | 131 ++++++++++++++++++++++++++++++++++++++ drivers/media/IR/ir-raw-event.c | 117 ++++++++++++++++++++++++++++++++++ 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 drivers/media/IR/ir-nec-decoder.c create mode 100644 drivers/media/IR/ir-raw-event.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 171890e7a41d..18794c7b0ea6 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,5 +1,5 @@ ir-common-objs := ir-functions.o ir-keymaps.o -ir-core-objs := ir-keytable.o ir-sysfs.o +ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o ir-nec-decoder.o obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c new file mode 100644 index 000000000000..16360eb4055b --- /dev/null +++ b/drivers/media/IR/ir-nec-decoder.c @@ -0,0 +1,131 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* Start time: 4.5 ms */ +#define MIN_START_TIME 3900000 +#define MAX_START_TIME 5100000 + +/* Pulse time: 560 us */ +#define MIN_PULSE_TIME 460000 +#define MAX_PULSE_TIME 660000 + +/* Bit 1 space time: 2.25ms-560 us */ +#define MIN_BIT1_TIME 1490000 +#define MAX_BIT1_TIME 1890000 + +/* Bit 0 space time: 1.12ms-560 us */ +#define MIN_BIT0_TIME 360000 +#define MAX_BIT0_TIME 760000 + + +/** Decode NEC pulsecode. This code can take up to 76.5 ms to run. + Unfortunately, using IRQ to decode pulse didn't work, since it uses + a pulse train of 38KHz. This means one pulse on each 52 us +*/ + +int ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len) +{ + int i, count = -1; + int ircode = 0, not_code = 0; +#if 0 + /* Needed only after porting the event code to the decoder */ + struct ir_input_dev *ir = input_get_drvdata(input_dev); +#endif + + /* Be sure that the first event is an start one and is a pulse */ + for (i = 0; i < len; i++) { + if (evs[i].type & (IR_START_EVENT | IR_PULSE)) + break; + } + i++; /* First event doesn't contain data */ + + if (i >= len) + return 0; + + /* First space should have 4.5 ms otherwise is not NEC protocol */ + if ((evs[i].delta.tv_nsec < MIN_START_TIME) | + (evs[i].delta.tv_nsec > MAX_START_TIME) | + (evs[i].type != IR_SPACE)) + goto err; + + /* + * FIXME: need to implement the repeat sequence + */ + + count = 0; + for (i++; i < len; i++) { + int bit; + + if ((evs[i].delta.tv_nsec < MIN_PULSE_TIME) | + (evs[i].delta.tv_nsec > MAX_PULSE_TIME) | + (evs[i].type != IR_PULSE)) + goto err; + + if (++i >= len) + goto err; + if (evs[i].type != IR_SPACE) + goto err; + + if ((evs[i].delta.tv_nsec > MIN_BIT1_TIME) && + (evs[i].delta.tv_nsec < MAX_BIT1_TIME)) + bit = 1; + else if ((evs[i].delta.tv_nsec > MIN_BIT0_TIME) && + (evs[i].delta.tv_nsec < MAX_BIT0_TIME)) + bit = 0; + else + goto err; + + if (bit) { + int shift = count; + /* Address first, then command */ + if (shift < 8) { + shift += 8; + ircode |= 1 << shift; + } else if (shift < 16) { + not_code |= 1 << shift; + } else if (shift < 24) { + shift -= 16; + ircode |= 1 << shift; + } else { + shift -= 24; + not_code |= 1 << shift; + } + } + if (++count == 32) + break; + } + + /* + * Fixme: may need to accept Extended NEC protocol? + */ + if ((ircode & ~not_code) != ircode) { + IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n", + ircode, not_code); + return -EINVAL; + } + + IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); + + return ircode; +err: + IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n", + count, (evs[i].delta.tv_nsec + 500) / 1000); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(ir_nec_decode); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c new file mode 100644 index 000000000000..9c71ac858923 --- /dev/null +++ b/drivers/media/IR/ir-raw-event.c @@ -0,0 +1,117 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* Define the max number of bit transitions per IR keycode */ +#define MAX_IR_EVENT_SIZE 256 + +int ir_raw_event_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + int rc, size; + + ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); + + size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; + size = roundup_pow_of_two(size); + + rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); + + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_register); + +void ir_raw_event_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + + if (!ir->raw) + return; + + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; +} +EXPORT_SYMBOL_GPL(ir_raw_event_unregister); + +int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + struct timespec ts; + struct ir_raw_event event; + int rc; + + if (!ir->raw) + return -EINVAL; + + event.type = type; + event.delta.tv_sec = 0; + event.delta.tv_nsec = 0; + + ktime_get_ts(&ts); + + if (timespec_equal(&ir->raw->last_event, &event.delta)) + event.type |= IR_START_EVENT; + else + event.delta = timespec_sub(ts, ir->raw->last_event); + + memcpy(&ir->raw->last_event, &ts, sizeof(ts)); + + if (event.delta.tv_sec) { + event.type |= IR_START_EVENT; + event.delta.tv_sec = 0; + event.delta.tv_nsec = 0; + } + + kfifo_in(&ir->raw->kfifo, &event, sizeof(event)); + + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store); + +int ir_raw_event_handle(struct input_dev *input_dev) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + int rc; + struct ir_raw_event *evs; + int len, i; + + /* + * Store the events into a temporary buffer. This allows calling more than + * one decoder to deal with the received data + */ + len = kfifo_len(&ir->raw->kfifo) / sizeof(*evs); + if (!len) + return 0; + evs = kmalloc(len * sizeof(*evs), GFP_ATOMIC); + + for (i = 0; i < len; i++) { + rc = kfifo_out(&ir->raw->kfifo, &evs[i], sizeof(*evs)); + if (rc != sizeof(*evs)) { + IR_dprintk(1, "overflow error: received %d instead of %zd\n", + rc, sizeof(*evs)); + return -EINVAL; + } + IR_dprintk(2, "event type %d, time before event: %07luus\n", + evs[i].type, (evs[i].delta.tv_nsec + 500) / 1000); + } + + rc = ir_nec_decode(input_dev, evs, len); + + kfree(evs); + + return rc; +} +EXPORT_SYMBOL_GPL(ir_raw_event_handle); -- cgit v1.2.3 From 6660de568d164e4eda6617dadcb999c96e62203f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Mar 2010 12:15:16 -0300 Subject: V4L/DVB: ir-core: add two functions to report keyup/keydown events Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 57 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 73fe4bec83bc..e59290febf81 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -365,7 +365,7 @@ static int ir_setkeycode(struct input_dev *dev, * * This routine is used by the input routines when a key is pressed at the * IR. The scancode is received and needs to be converted into a keycode. - * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the + * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the * corresponding keycode from the table. */ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) @@ -391,6 +391,61 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) } EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); +/** + * ir_keyup() - generates input event to cleanup a key press + * @input_dev: the struct input_dev descriptor of the device + * + * This routine is used by the input routines when a key is pressed at the + * IR. It reports a keyup input event via input_report_key(). + */ +void ir_keyup(struct input_dev *dev) +{ + struct ir_input_dev *ir = input_get_drvdata(dev); + + if (!ir->keypressed) + return; + + input_report_key(dev, ir->keycode, 0); + input_sync(dev); + ir->keypressed = 0; +} +EXPORT_SYMBOL_GPL(ir_keyup); + +/** + * ir_keydown() - generates input event for a key press + * @input_dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * + * This routine is used by the input routines when a key is pressed at the + * IR. It gets the keycode for a scancode and reports an input event via + * input_report_key(). + */ +void ir_keydown(struct input_dev *dev, int scancode) +{ + struct ir_input_dev *ir = input_get_drvdata(dev); + + u32 keycode = ir_g_keycode_from_table(dev, scancode); + + /* If already sent a keydown, do a keyup */ + if (ir->keypressed) + ir_keyup(dev); + + if (KEY_RESERVED == keycode) + return; + + ir->keycode = keycode; + ir->keypressed = 1; + + IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", + dev->name, keycode, scancode); + + input_report_key(dev, ir->keycode, 1); + input_sync(dev); + +} +EXPORT_SYMBOL_GPL(ir_keydown); + + /** * ir_input_register() - sets the IR keycode table and add the handlers * for keymap table get/set -- cgit v1.2.3 From ada39630c758c5c3098f4fc1361103ea2bc1afe0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Mar 2010 12:24:24 -0300 Subject: V4L/DVB: ir-core/saa7134: Move ir keyup/keydown code to the ir-core Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 90 +++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 32 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 16360eb4055b..a58c717ec6b0 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -30,37 +30,35 @@ #define MIN_BIT0_TIME 360000 #define MAX_BIT0_TIME 760000 - -/** Decode NEC pulsecode. This code can take up to 76.5 ms to run. - Unfortunately, using IRQ to decode pulse didn't work, since it uses - a pulse train of 38KHz. This means one pulse on each 52 us -*/ - -int ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *evs, - int len) +/** + * __ir_nec_decode() - Decode one NEC pulsecode + * @input_dev: the struct input_dev descriptor of the device + * @evs: event array with type/duration of pulse/space + * @len: length of the array + * @pos: position to start seeking for a code + * This function returns the decoded ircode or -EINVAL if no pulse got decoded + */ +static int __ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len, int *pos) { - int i, count = -1; + int count = -1; int ircode = 0, not_code = 0; -#if 0 - /* Needed only after porting the event code to the decoder */ - struct ir_input_dev *ir = input_get_drvdata(input_dev); -#endif /* Be sure that the first event is an start one and is a pulse */ - for (i = 0; i < len; i++) { - if (evs[i].type & (IR_START_EVENT | IR_PULSE)) + for (; *pos < len; (*pos)++) { + if (evs[*pos].type & (IR_START_EVENT | IR_PULSE)) break; } - i++; /* First event doesn't contain data */ + (*pos)++; /* First event doesn't contain data */ - if (i >= len) + if (*pos >= len) return 0; /* First space should have 4.5 ms otherwise is not NEC protocol */ - if ((evs[i].delta.tv_nsec < MIN_START_TIME) | - (evs[i].delta.tv_nsec > MAX_START_TIME) | - (evs[i].type != IR_SPACE)) + if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) | + (evs[*pos].delta.tv_nsec > MAX_START_TIME) | + (evs[*pos].type != IR_SPACE)) goto err; /* @@ -68,24 +66,24 @@ int ir_nec_decode(struct input_dev *input_dev, */ count = 0; - for (i++; i < len; i++) { + for ((*pos)++; *pos < len; (*pos)++) { int bit; - if ((evs[i].delta.tv_nsec < MIN_PULSE_TIME) | - (evs[i].delta.tv_nsec > MAX_PULSE_TIME) | - (evs[i].type != IR_PULSE)) + if ((evs[*pos].delta.tv_nsec < MIN_PULSE_TIME) | + (evs[*pos].delta.tv_nsec > MAX_PULSE_TIME) | + (evs[*pos].type != IR_PULSE)) goto err; - if (++i >= len) + if (++*pos >= len) goto err; - if (evs[i].type != IR_SPACE) + if (evs[*pos].type != IR_SPACE) goto err; - if ((evs[i].delta.tv_nsec > MIN_BIT1_TIME) && - (evs[i].delta.tv_nsec < MAX_BIT1_TIME)) + if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) && + (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME)) bit = 1; - else if ((evs[i].delta.tv_nsec > MIN_BIT0_TIME) && - (evs[i].delta.tv_nsec < MAX_BIT0_TIME)) + else if ((evs[*pos].delta.tv_nsec > MIN_BIT0_TIME) && + (evs[*pos].delta.tv_nsec < MAX_BIT0_TIME)) bit = 0; else goto err; @@ -120,12 +118,40 @@ int ir_nec_decode(struct input_dev *input_dev, } IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); + ir_keydown(input_dev, ircode); + ir_keyup(input_dev); return ircode; err: IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n", - count, (evs[i].delta.tv_nsec + 500) / 1000); + count, (evs[*pos].delta.tv_nsec + 500) / 1000); return -EINVAL; } + +/** + * __ir_nec_decode() - Decodes all NEC pulsecodes on a given array + * @input_dev: the struct input_dev descriptor of the device + * @evs: event array with type/duration of pulse/space + * @len: length of the array + * This function returns the number of decoded pulses or -EINVAL if no + * pulse got decoded + */ +int ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len) +{ + int pos = 0; + int rc = 0; + + while (pos < len) { + if (__ir_nec_decode(input_dev, evs, len, &pos) >= 0) + rc++; + } + + if (!rc) + return -EINVAL; + return rc; +} + EXPORT_SYMBOL_GPL(ir_nec_decode); -- cgit v1.2.3 From 9f1547829a6f39fe6b2da22653dff40502f3d568 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 21 Mar 2010 13:00:55 -0300 Subject: V4L/DVB: saa7134: don't wait too much to generate an IR event on raw_decode At raw_decode mode, the key is processed after the end of a timer. The previous code resets the timer every time something is received at the IR port. While this works fine with IR's that don't implement repeat, like Avermedia RM-JX IR, it keeps waiting until keydown, on IR's that implement NEC repeat command, like the Terratec yellow. The solution is to change the behaviour to do the timeout after the first received data. The timeout is currently set to 15 ms, as it works fine with NEC protcocol. It may need some adjustments to support other protocols and to better handle spurious detections that may happen with some IR sensors. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 1 + drivers/media/IR/ir-nec-decoder.c | 122 ++++++++++++++++++++++++++------------ drivers/media/IR/ir-raw-event.c | 14 +++++ 3 files changed, 98 insertions(+), 39 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index e59290febf81..fcb0f0cb1fe1 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -405,6 +405,7 @@ void ir_keyup(struct input_dev *dev) if (!ir->keypressed) return; + IR_dprintk(1, "keyup key 0x%04x\n", ir->keycode); input_report_key(dev, ir->keycode, 0); input_sync(dev); ir->keypressed = 0; diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index a58c717ec6b0..104482a6991e 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -14,21 +14,51 @@ #include -/* Start time: 4.5 ms */ -#define MIN_START_TIME 3900000 -#define MAX_START_TIME 5100000 +/* Start time: 4.5 ms + 560 us of the next pulse */ +#define MIN_START_TIME (3900000 + 560000) +#define MAX_START_TIME (5100000 + 560000) -/* Pulse time: 560 us */ -#define MIN_PULSE_TIME 460000 -#define MAX_PULSE_TIME 660000 +/* Bit 1 time: 2.25ms us */ +#define MIN_BIT1_TIME 2050000 +#define MAX_BIT1_TIME 2450000 -/* Bit 1 space time: 2.25ms-560 us */ -#define MIN_BIT1_TIME 1490000 -#define MAX_BIT1_TIME 1890000 +/* Bit 0 time: 1.12ms us */ +#define MIN_BIT0_TIME 920000 +#define MAX_BIT0_TIME 1320000 -/* Bit 0 space time: 1.12ms-560 us */ -#define MIN_BIT0_TIME 360000 -#define MAX_BIT0_TIME 760000 +/* Total IR code is 110 ms, including the 9 ms for the start pulse */ +#define MAX_NEC_TIME 4000000 + +/* Total IR code is 110 ms, including the 9 ms for the start pulse */ +#define MIN_REPEAT_TIME 99000000 +#define MAX_REPEAT_TIME 112000000 + +/* Repeat time: 2.25ms us */ +#define MIN_REPEAT_START_TIME 2050000 +#define MAX_REPEAT_START_TIME 3000000 + +#define REPEAT_TIME 240 /* ms */ + +/** is_repeat - Check if it is a NEC repeat event + * @input_dev: the struct input_dev descriptor of the device + * @pos: the position of the first event + * @len: the length of the buffer + */ +static int is_repeat(struct ir_raw_event *evs, int len, int pos) +{ + if ((evs[pos].delta.tv_nsec < MIN_REPEAT_START_TIME) || + (evs[pos].delta.tv_nsec > MAX_REPEAT_START_TIME)) + return 0; + + if (++pos >= len) + return 0; + + if ((evs[pos].delta.tv_nsec < MIN_REPEAT_TIME) || + (evs[pos].delta.tv_nsec > MAX_REPEAT_TIME)) + return 0; + + return 1; +} /** * __ir_nec_decode() - Decode one NEC pulsecode @@ -36,49 +66,59 @@ * @evs: event array with type/duration of pulse/space * @len: length of the array * @pos: position to start seeking for a code - * This function returns the decoded ircode or -EINVAL if no pulse got decoded + * This function returns -EINVAL if no pulse got decoded, + * 0 if buffer is empty and 1 if one keycode were handled. */ static int __ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event *evs, int len, int *pos) { + struct ir_input_dev *ir = input_get_drvdata(input_dev); int count = -1; int ircode = 0, not_code = 0; /* Be sure that the first event is an start one and is a pulse */ for (; *pos < len; (*pos)++) { - if (evs[*pos].type & (IR_START_EVENT | IR_PULSE)) + /* Very long delays are considered as start events */ + if (evs[*pos].delta.tv_nsec > MAX_NEC_TIME) break; - } - (*pos)++; /* First event doesn't contain data */ + if (evs[*pos].type & IR_START_EVENT) + break; + IR_dprintk(1, "%luus: Spurious NEC %s\n", + (evs[*pos].delta.tv_nsec + 500) / 1000, + (evs[*pos].type & IR_SPACE) ? "space" : "pulse"); + } if (*pos >= len) return 0; - /* First space should have 4.5 ms otherwise is not NEC protocol */ - if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) | - (evs[*pos].delta.tv_nsec > MAX_START_TIME) | - (evs[*pos].type != IR_SPACE)) + (*pos)++; /* First event doesn't contain data */ + + if (evs[*pos].type != IR_PULSE) goto err; - /* - * FIXME: need to implement the repeat sequence - */ + /* Check if it is a NEC repeat event */ + if (is_repeat(evs, len, *pos)) { + *pos += 2; + if (ir->keypressed) { + mod_timer(&ir->raw->timer_keyup, + jiffies + msecs_to_jiffies(REPEAT_TIME)); + IR_dprintk(1, "NEC repeat event\n"); + return 1; + } else { + IR_dprintk(1, "missing NEC repeat event\n"); + return 0; + } + } + + /* First space should have 4.5 ms otherwise is not NEC protocol */ + if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) || + (evs[*pos].delta.tv_nsec > MAX_START_TIME)) + goto err; count = 0; for ((*pos)++; *pos < len; (*pos)++) { int bit; - - if ((evs[*pos].delta.tv_nsec < MIN_PULSE_TIME) | - (evs[*pos].delta.tv_nsec > MAX_PULSE_TIME) | - (evs[*pos].type != IR_PULSE)) - goto err; - - if (++*pos >= len) - goto err; - if (evs[*pos].type != IR_SPACE) - goto err; - if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) && (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME)) bit = 1; @@ -107,6 +147,7 @@ static int __ir_nec_decode(struct input_dev *input_dev, if (++count == 32) break; } + *pos++; /* * Fixme: may need to accept Extended NEC protocol? @@ -119,12 +160,15 @@ static int __ir_nec_decode(struct input_dev *input_dev, IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); ir_keydown(input_dev, ircode); - ir_keyup(input_dev); + mod_timer(&ir->raw->timer_keyup, + jiffies + msecs_to_jiffies(REPEAT_TIME)); - return ircode; + return 1; err: - IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n", - count, (evs[*pos].delta.tv_nsec + 500) / 1000); + IR_dprintk(1, "NEC decoded failed at bit %d (%s) while decoding %luus time\n", + count, + (evs[*pos].type & IR_SPACE) ? "space" : "pulse", + (evs[*pos].delta.tv_nsec + 500) / 1000); return -EINVAL; } @@ -145,7 +189,7 @@ int ir_nec_decode(struct input_dev *input_dev, int rc = 0; while (pos < len) { - if (__ir_nec_decode(input_dev, evs, len, &pos) >= 0) + if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) rc++; } diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 9c71ac858923..0ae55433cef9 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -17,6 +17,13 @@ /* Define the max number of bit transitions per IR keycode */ #define MAX_IR_EVENT_SIZE 256 +static void ir_keyup_timer(unsigned long data) +{ + struct input_dev *input_dev = (struct input_dev *)data; + + ir_keyup(input_dev); +} + int ir_raw_event_register(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); @@ -27,6 +34,11 @@ int ir_raw_event_register(struct input_dev *input_dev) size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; size = roundup_pow_of_two(size); + init_timer(&ir->raw->timer_keyup); + ir->raw->timer_keyup.function = ir_keyup_timer; + ir->raw->timer_keyup.data = (unsigned long)input_dev; + set_bit(EV_REP, input_dev->evbit); + rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); return rc; @@ -40,6 +52,8 @@ void ir_raw_event_unregister(struct input_dev *input_dev) if (!ir->raw) return; + del_timer_sync(&ir->raw->timer_keyup); + kfifo_free(&ir->raw->kfifo); kfree(ir->raw); ir->raw = NULL; -- cgit v1.2.3 From 995187bed30c0545e8da88372e9807da0a85911e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 24 Mar 2010 20:47:53 -0300 Subject: V4L/DVB: ir-core: dynamically load the compiled IR protocols Instead of hardcoding the protocols into ir-core, add a register interface for the IR protocol decoders, and convert ir-nec-decoder into a client of ir-core. With this approach, it is possible to dynamically load the needed IR protocols, and to add a RAW IR interface module, registered as one IR raw protocol decoder. This patch opens a way to register a lirc_dev interface to work as an userspace IR protocol decoder. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 9 +++++++ drivers/media/IR/Makefile | 3 ++- drivers/media/IR/ir-nec-decoder.c | 35 +++++++++++++++++++----- drivers/media/IR/ir-raw-event.c | 57 ++++++++++++++++++++++++++++++++++++++- drivers/media/IR/ir-sysfs.c | 7 +++-- 5 files changed, 101 insertions(+), 10 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 4dde7d180a32..de410d46ae26 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -7,3 +7,12 @@ config VIDEO_IR tristate depends on IR_CORE default IR_CORE + +config IR_NEC_DECODER + tristate "Enable IR raw decoder for NEC protocol" + depends on IR_CORE + default y + + ---help--- + Enable this option if you have IR with NEC protocol, and + if the IR is decoded in software diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 18794c7b0ea6..6140b2712c8a 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,5 +1,6 @@ ir-common-objs := ir-functions.o ir-keymaps.o -ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o ir-nec-decoder.o +ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o +obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 104482a6991e..c9a986dd57fd 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -1,4 +1,4 @@ -/* ir-raw-event.c - handle IR Pulse/Space event +/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol * * Copyright (C) 2010 by Mauro Carvalho Chehab * @@ -147,7 +147,7 @@ static int __ir_nec_decode(struct input_dev *input_dev, if (++count == 32) break; } - *pos++; + (*pos)++; /* * Fixme: may need to accept Extended NEC protocol? @@ -181,9 +181,9 @@ err: * This function returns the number of decoded pulses or -EINVAL if no * pulse got decoded */ -int ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *evs, - int len) +static int ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len) { int pos = 0; int rc = 0; @@ -198,4 +198,27 @@ int ir_nec_decode(struct input_dev *input_dev, return rc; } -EXPORT_SYMBOL_GPL(ir_nec_decode); +static struct ir_raw_handler nec_handler = { + .decode = ir_nec_decode, +}; + +static int __init ir_nec_decode_init(void) +{ + ir_raw_handler_register(&nec_handler); + + printk(KERN_INFO "IR NEC protocol handler initialized\n"); + return 0; +} + +static void __exit ir_nec_decode_exit(void) +{ + ir_raw_handler_unregister(&nec_handler); +} + +module_init(ir_nec_decode_init); +module_exit(ir_nec_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("NEC IR protocol decoder"); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 0ae55433cef9..3eae128400ea 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -13,10 +13,18 @@ */ #include +#include /* Define the max number of bit transitions per IR keycode */ #define MAX_IR_EVENT_SIZE 256 +/* Used to handle IR raw handler extensions */ +static LIST_HEAD(ir_raw_handler_list); +static DEFINE_MUTEX(ir_raw_handler_lock); + +/* Used to load the decoders */ +static struct work_struct wq_load; + static void ir_keyup_timer(unsigned long data) { struct input_dev *input_dev = (struct input_dev *)data; @@ -101,6 +109,7 @@ int ir_raw_event_handle(struct input_dev *input_dev) int rc; struct ir_raw_event *evs; int len, i; + struct ir_raw_handler *ir_raw_handler; /* * Store the events into a temporary buffer. This allows calling more than @@ -122,10 +131,56 @@ int ir_raw_event_handle(struct input_dev *input_dev) evs[i].type, (evs[i].delta.tv_nsec + 500) / 1000); } - rc = ir_nec_decode(input_dev, evs, len); + /* + * Call all ir decoders. This allows decoding the same event with + * more than one protocol handler. + * FIXME: better handle the returned code: does it make sense to use + * other decoders, if the first one already handled the IR? + */ + list_for_each_entry(ir_raw_handler, &ir_raw_handler_list, list) { + rc = ir_raw_handler->decode(input_dev, evs, len); + } kfree(evs); return rc; } EXPORT_SYMBOL_GPL(ir_raw_event_handle); + +/* + * Extension interface - used to register the IR decoders + */ + +int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) +{ + mutex_lock(&ir_raw_handler_lock); + list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); + mutex_unlock(&ir_raw_handler_lock); + return 0; +} +EXPORT_SYMBOL(ir_raw_handler_register); + +void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) +{ + mutex_lock(&ir_raw_handler_lock); + list_del(&ir_raw_handler->list); + mutex_unlock(&ir_raw_handler_lock); +} +EXPORT_SYMBOL(ir_raw_handler_unregister); + +static void init_decoders(struct work_struct *work) +{ + /* Load the decoder modules */ + + load_nec_decode(); + + /* If needed, we may later add some init code. In this case, + it is needed to change the CONFIG_MODULE test at ir-core.h + */ +} + +void ir_raw_init(void) +{ + INIT_WORK(&wq_load, init_decoders); + schedule_work(&wq_load); +} \ No newline at end of file diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 253e66999f18..2279d5594b05 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -1,6 +1,6 @@ /* ir-register.c - handle IR scancode->keycode tables * - * Copyright (C) 2009 by Mauro Carvalho Chehab + * Copyright (C) 2009-2010 by Mauro Carvalho Chehab * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ static char *ir_devnode(struct device *dev, mode_t *mode) return kasprintf(GFP_KERNEL, "irrcv/%s", dev_name(dev)); } -struct class ir_input_class = { +static struct class ir_input_class = { .name = "irrcv", .devnode = ir_devnode, }; @@ -251,6 +251,9 @@ static int __init ir_core_init(void) return rc; } + /* Initialize/load the decoders that will be used */ + ir_raw_init(); + return 0; } -- cgit v1.2.3 From 93c312ff21b0a53e701a45741887208297646a1a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 25 Mar 2010 21:13:43 -0300 Subject: V4L/DVB: ir-core: prepare to add more operations for ir decoders Some decoders and a lirc_dev interface may need some other operations to work. For example: IR device register/unregister and ir_keydown events may need to be tracked. As some operations can occur in interrupt time, and a lock is needed to prevent un-registering a decode while decoding a key, the lock needed to be convert into a spin lock. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 6 +--- drivers/media/IR/ir-raw-event.c | 71 ++++++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 18 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index c9a986dd57fd..cb57cc287734 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -178,8 +178,7 @@ err: * @input_dev: the struct input_dev descriptor of the device * @evs: event array with type/duration of pulse/space * @len: length of the array - * This function returns the number of decoded pulses or -EINVAL if no - * pulse got decoded + * This function returns the number of decoded pulses */ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event *evs, @@ -192,9 +191,6 @@ static int ir_nec_decode(struct input_dev *input_dev, if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) rc++; } - - if (!rc) - return -EINVAL; return rc; } diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 3eae128400ea..11f23f4491b2 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -14,13 +14,41 @@ #include #include +#include /* Define the max number of bit transitions per IR keycode */ #define MAX_IR_EVENT_SIZE 256 /* Used to handle IR raw handler extensions */ static LIST_HEAD(ir_raw_handler_list); -static DEFINE_MUTEX(ir_raw_handler_lock); +static spinlock_t ir_raw_handler_lock; + +/** + * RUN_DECODER() - runs an operation on all IR decoders + * @ops: IR raw handler operation to be called + * @arg: arguments to be passed to the callback + * + * Calls ir_raw_handler::ops for all registered IR handlers. It prevents + * new decode addition/removal while running, by locking ir_raw_handler_lock + * mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum + * of the return codes. + */ +#define RUN_DECODER(ops, ...) ({ \ + struct ir_raw_handler *_ir_raw_handler; \ + int _sumrc = 0, _rc; \ + spin_lock(&ir_raw_handler_lock); \ + list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \ + if (_ir_raw_handler->ops) { \ + _rc = _ir_raw_handler->ops(__VA_ARGS__); \ + if (_rc < 0) \ + break; \ + _sumrc += _rc; \ + } \ + } \ + spin_unlock(&ir_raw_handler_lock); \ + _sumrc; \ +}) + /* Used to load the decoders */ static struct work_struct wq_load; @@ -38,6 +66,8 @@ int ir_raw_event_register(struct input_dev *input_dev) int rc, size; ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); + if (!ir->raw) + return -ENOMEM; size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; size = roundup_pow_of_two(size); @@ -48,6 +78,19 @@ int ir_raw_event_register(struct input_dev *input_dev) set_bit(EV_REP, input_dev->evbit); rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); + if (rc < 0) { + kfree(ir->raw); + ir->raw = NULL; + return rc; + } + + rc = RUN_DECODER(raw_register, input_dev); + if (rc < 0) { + kfifo_free(&ir->raw->kfifo); + kfree(ir->raw); + ir->raw = NULL; + return rc; + } return rc; } @@ -62,6 +105,8 @@ void ir_raw_event_unregister(struct input_dev *input_dev) del_timer_sync(&ir->raw->timer_keyup); + RUN_DECODER(raw_unregister, input_dev); + kfifo_free(&ir->raw->kfifo); kfree(ir->raw); ir->raw = NULL; @@ -109,7 +154,6 @@ int ir_raw_event_handle(struct input_dev *input_dev) int rc; struct ir_raw_event *evs; int len, i; - struct ir_raw_handler *ir_raw_handler; /* * Store the events into a temporary buffer. This allows calling more than @@ -133,13 +177,10 @@ int ir_raw_event_handle(struct input_dev *input_dev) /* * Call all ir decoders. This allows decoding the same event with - * more than one protocol handler. - * FIXME: better handle the returned code: does it make sense to use - * other decoders, if the first one already handled the IR? + * more than one protocol handler. It returns the number of keystrokes + * sent to the event interface */ - list_for_each_entry(ir_raw_handler, &ir_raw_handler_list, list) { - rc = ir_raw_handler->decode(input_dev, evs, len); - } + rc = RUN_DECODER(decode, input_dev, evs, len); kfree(evs); @@ -153,18 +194,18 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle); int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) { - mutex_lock(&ir_raw_handler_lock); + spin_lock(&ir_raw_handler_lock); list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); - mutex_unlock(&ir_raw_handler_lock); + spin_unlock(&ir_raw_handler_lock); return 0; } EXPORT_SYMBOL(ir_raw_handler_register); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) { - mutex_lock(&ir_raw_handler_lock); + spin_lock(&ir_raw_handler_lock); list_del(&ir_raw_handler->list); - mutex_unlock(&ir_raw_handler_lock); + spin_unlock(&ir_raw_handler_lock); } EXPORT_SYMBOL(ir_raw_handler_unregister); @@ -181,6 +222,10 @@ static void init_decoders(struct work_struct *work) void ir_raw_init(void) { + spin_lock_init(&ir_raw_handler_lock); + +#ifdef MODULE INIT_WORK(&wq_load, init_decoders); schedule_work(&wq_load); -} \ No newline at end of file +#endif +} -- cgit v1.2.3 From 20d5f116ec777c9c7ce5b74f0d17ee1d01a0d833 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 25 Mar 2010 23:49:46 -0300 Subject: V4L/DVB: ir-nec-decoder: Add sysfs node to enable/disable per irrcv With the help of raw_register/raw_unregister, adds a sysfs group associated with the decoder, inside the corresponding irrcv node. Writing 1 to nec_decoder/enabled enables the decoder, while writing 0 disables it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 133 +++++++++++++++++++++++++++++++++++++- drivers/media/IR/ir-raw-event.c | 2 +- 2 files changed, 133 insertions(+), 2 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index cb57cc287734..83a9912722f4 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -39,6 +39,85 @@ #define REPEAT_TIME 240 /* ms */ +/* Used to register nec_decoder clients */ +static LIST_HEAD(decoder_list); +static spinlock_t decoder_lock; + +struct decoder_data { + struct list_head list; + struct ir_input_dev *ir_dev; + int enabled:1; +}; + + +/** + * get_decoder_data() - gets decoder data + * @input_dev: input device + * + * Returns the struct decoder_data that corresponds to a device + */ + +static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) +{ + struct decoder_data *data = NULL; + + spin_lock(&decoder_lock); + list_for_each_entry(data, &decoder_list, list) { + if (data->ir_dev == ir_dev) + break; + } + spin_unlock(&decoder_lock); + return data; +} + +static ssize_t store_enabled(struct device *d, + struct device_attribute *mattr, + const char *buf, + size_t len) +{ + unsigned long value; + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (strict_strtoul(buf, 10, &value) || value > 1) + return -EINVAL; + + data->enabled = value; + + return len; +} + +static ssize_t show_enabled(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (data->enabled) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); + +static struct attribute *decoder_attributes[] = { + &dev_attr_enabled.attr, + NULL +}; + +static struct attribute_group decoder_attribute_group = { + .name = "nec_decoder", + .attrs = decoder_attributes, +}; + + /** is_repeat - Check if it is a NEC repeat event * @input_dev: the struct input_dev descriptor of the device * @pos: the position of the first event @@ -184,9 +263,15 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event *evs, int len) { + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct decoder_data *data; int pos = 0; int rc = 0; + data = get_decoder_data(ir_dev); + if (!data || !data->enabled) + return 0; + while (pos < len) { if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) rc++; @@ -194,8 +279,54 @@ static int ir_nec_decode(struct input_dev *input_dev, return rc; } +static int ir_nec_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct decoder_data *data; + int rc; + + rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); + if (rc < 0) + return rc; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + return -ENOMEM; + } + + data->ir_dev = ir_dev; + data->enabled = 1; + + spin_lock(&decoder_lock); + list_add_tail(&data->list, &decoder_list); + spin_unlock(&decoder_lock); + + return 0; +} + +static int ir_nec_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + static struct decoder_data *data; + + data = get_decoder_data(ir_dev); + if (!data) + return 0; + + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + + spin_lock(&decoder_lock); + list_del(&data->list); + spin_unlock(&decoder_lock); + + return 0; +} + static struct ir_raw_handler nec_handler = { - .decode = ir_nec_decode, + .decode = ir_nec_decode, + .raw_register = ir_nec_register, + .raw_unregister = ir_nec_unregister, }; static int __init ir_nec_decode_init(void) diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 11f23f4491b2..371d88e5a586 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -223,7 +223,7 @@ static void init_decoders(struct work_struct *work) void ir_raw_init(void) { spin_lock_init(&ir_raw_handler_lock); - + #ifdef MODULE INIT_WORK(&wq_load, init_decoders); schedule_work(&wq_load); -- cgit v1.2.3 From e202c15b4209f05fe109dd396463a524f4c2d3d8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 26 Mar 2010 22:45:16 -0300 Subject: V4L/DVB: ir-core: rename sysfs remote controller class from ir to rc IR is an alias for Infrared Remote, while RC is an alias for Remote Controller. While currently all implementations are with Infrared Remote Controller, this subsystem is not meant to be used only by IR type of RC's. So, as discussed on both linux-media and linux-input, the better is to rename the subsystem as Remote Controller. While, currently, the only application that uses the /sys/class/irrcv is ir-keytable application, and its sysfs support works only with the current linux-next code, it is still possible to change the userspace API without the risk of breaking applications. So, better to rename this sooner than later. Later patches will be needed to rename the files and to move them away from drivers/media, but this is not a critical issue. So, for now, let's just change the name of the sysfs class/nodes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 2279d5594b05..36dfe51aad92 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -22,14 +22,14 @@ /* bit array to represent IR sysfs device number */ static unsigned long ir_core_dev_number; -/* class for /sys/class/irrcv */ +/* class for /sys/class/rc */ static char *ir_devnode(struct device *dev, mode_t *mode) { - return kasprintf(GFP_KERNEL, "irrcv/%s", dev_name(dev)); + return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev)); } static struct class ir_input_class = { - .name = "irrcv", + .name = "rc", .devnode = ir_devnode, }; @@ -40,7 +40,7 @@ static struct class ir_input_class = { * @buf: a pointer to the output buffer * * This routine is a callback routine for input read the IR protocol type. - * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. + * it is trigged by reading /sys/class/rc/rcrcv?/current_protocol. * It returns the protocol name, as understood by the driver. */ static ssize_t show_protocol(struct device *d, @@ -75,7 +75,7 @@ static ssize_t show_protocol(struct device *d, * @len: length of the input buffer * * This routine is a callback routine for changing the IR protocol type. - * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. + * it is trigged by reading /sys/class/rc/rcrcv?/current_protocol. * It changes the IR the protocol name, if the IR type is recognized * by the driver. * If an unknown protocol name is used, returns -EINVAL. @@ -172,7 +172,7 @@ static struct device_type ir_dev_type = { }; /** - * ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv? + * ir_register_class() - creates the sysfs for /sys/class/rc/rcrcv? * @input_dev: the struct input_dev descriptor of the device * * This routine is used to register the syfs code for IR class @@ -192,7 +192,7 @@ int ir_register_class(struct input_dev *input_dev) ir_dev->dev.type = &ir_dev_type; ir_dev->dev.class = &ir_input_class; ir_dev->dev.parent = input_dev->dev.parent; - dev_set_name(&ir_dev->dev, "irrcv%d", devno); + dev_set_name(&ir_dev->dev, "rcrcv%d", devno); dev_set_drvdata(&ir_dev->dev, ir_dev); rc = device_register(&ir_dev->dev); if (rc) @@ -223,7 +223,7 @@ int ir_register_class(struct input_dev *input_dev) /** * ir_unregister_class() - removes the sysfs for sysfs for - * /sys/class/irrcv/irrcv? + * /sys/class/rc/rcrcv? * @input_dev: the struct input_dev descriptor of the device * * This routine is used to unregister the syfs code for IR class @@ -240,14 +240,14 @@ void ir_unregister_class(struct input_dev *input_dev) } /* - * Init/exit code for the module. Basically, creates/removes /sys/class/irrcv + * Init/exit code for the module. Basically, creates/removes /sys/class/rc */ static int __init ir_core_init(void) { int rc = class_register(&ir_input_class); if (rc) { - printk(KERN_ERR "ir_core: unable to register irrcv class\n"); + printk(KERN_ERR "ir_core: unable to register rc class\n"); return rc; } -- cgit v1.2.3 From 716aab44df8bb9bdf16abea9013890274329b61f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 31 Mar 2010 14:40:35 -0300 Subject: V4L/DVB: ir-core: Add callbacks for input/evdev open/close on IR core Especially when IR needs to do polling, it generates lots of wakeups per second. This makes no sense, if the input event device is closed. Adds a callback handler to the IR hardware driver, to allow registering an open/close ops. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index fcb0f0cb1fe1..99cad829a18a 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -446,6 +446,19 @@ void ir_keydown(struct input_dev *dev, int scancode) } EXPORT_SYMBOL_GPL(ir_keydown); +static int ir_open(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + return ir_dev->props->open(ir_dev->props->priv); +} + +static void ir_close(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + ir_dev->props->close(ir_dev->props->priv); +} /** * ir_input_register() - sets the IR keycode table and add the handlers @@ -495,6 +508,10 @@ int ir_input_register(struct input_dev *input_dev, ir_copy_table(&ir_dev->rc_tab, rc_tab); ir_dev->props = props; + if (props && props->open) + input_dev->open = ir_open; + if (props && props->close) + input_dev->close = ir_close; /* set the bits for the keys */ IR_dprintk(1, "key map size: %d\n", rc_tab->size); -- cgit v1.2.3 From dce4a3e3b228fd31bcfd2d84e673bc08b553e6cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 1 Apr 2010 22:23:38 -0300 Subject: V4L/DVB: ir-common: Use macros to define the keytables The usage of macros ensures that the proper namespace is being used by all tables. It also makes easier to associate a keytable with the name used inside the drivers. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keymaps.c | 265 ++++++++++++++++++++---------------------- 1 file changed, 128 insertions(+), 137 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index 55e7acd7209c..1ba928516cd2 100644 --- a/drivers/media/IR/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c @@ -35,24 +35,15 @@ * to define the proper IR_TYPE (IR_TYPE_RC5/IR_TYPE_NEC). * The deprecated tables should use IR_TYPE_UNKNOWN */ -#define IR_TABLE(irname, type, tabname) \ -struct ir_scancode_table tabname ## _table = { \ - .scan = tabname, \ - .size = ARRAY_SIZE(tabname), \ - .ir_type = type, \ - .name = #irname, \ -}; \ -EXPORT_SYMBOL_GPL(tabname ## _table) - /* empty keytable, can be used as placeholder for not-yet created keytables */ -static struct ir_scancode ir_codes_empty[] = { +static struct ir_scancode empty[] = { { 0x2a, KEY_COFFEE }, }; -IR_TABLE(empty, IR_TYPE_UNKNOWN, ir_codes_empty); +DEFINE_LEGACY_IR_KEYTABLE(empty); /* Michal Majchrowicz */ -static struct ir_scancode ir_codes_proteus_2309[] = { +static struct ir_scancode proteus_2309[] = { /* numeric */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, @@ -80,10 +71,10 @@ static struct ir_scancode ir_codes_proteus_2309[] = { { 0x1e, KEY_VOLUMEUP }, /* volume + */ { 0x14, KEY_F1 }, }; -IR_TABLE(proteus_2309, IR_TYPE_UNKNOWN, ir_codes_proteus_2309); +DEFINE_LEGACY_IR_KEYTABLE(proteus_2309); /* Matt Jesson */ -static struct ir_scancode ir_codes_avermedia_m135a_rm_jx[] = { +static struct ir_scancode avermedia_m135a_rm_jx[] = { { 0x0200, KEY_POWER2 }, { 0x022e, KEY_DOT }, /* '.' */ { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ @@ -172,10 +163,10 @@ static struct ir_scancode ir_codes_avermedia_m135a_rm_jx[] = { { 0x0218, KEY_PLAY }, { 0x021b, KEY_STOP }, }; -IR_TABLE(aver-m135a-RM-JX, IR_TYPE_NEC, ir_codes_avermedia_m135a_rm_jx); +DEFINE_IR_KEYTABLE(avermedia_m135a_rm_jx, IR_TYPE_NEC); /* Oldrich Jedlicka */ -static struct ir_scancode ir_codes_avermedia_cardbus[] = { +static struct ir_scancode avermedia_cardbus[] = { { 0x00, KEY_POWER }, { 0x01, KEY_TUNER }, /* TV/FM */ { 0x03, KEY_TEXT }, /* Teletext */ @@ -231,10 +222,10 @@ static struct ir_scancode ir_codes_avermedia_cardbus[] = { { 0x42, KEY_CHANNELDOWN }, /* Channel down */ { 0x43, KEY_CHANNELUP }, /* Channel up */ }; -IR_TABLE(avermedia_cardbus, IR_TYPE_UNKNOWN, ir_codes_avermedia_cardbus); +DEFINE_LEGACY_IR_KEYTABLE(avermedia_cardbus); /* Attila Kondoros */ -static struct ir_scancode ir_codes_apac_viewcomp[] = { +static struct ir_scancode apac_viewcomp[] = { { 0x01, KEY_1 }, { 0x02, KEY_2 }, @@ -273,11 +264,11 @@ static struct ir_scancode ir_codes_apac_viewcomp[] = { { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ }; -IR_TABLE(apac_viewcomp, IR_TYPE_UNKNOWN, ir_codes_apac_viewcomp); +DEFINE_LEGACY_IR_KEYTABLE(apac_viewcomp); /* ---------------------------------------------------------------------- */ -static struct ir_scancode ir_codes_pixelview[] = { +static struct ir_scancode pixelview[] = { { 0x1e, KEY_POWER }, /* power */ { 0x07, KEY_MEDIA }, /* source */ @@ -320,13 +311,13 @@ static struct ir_scancode ir_codes_pixelview[] = { { 0x1d, KEY_REFRESH }, /* reset */ { 0x18, KEY_MUTE }, /* mute/unmute */ }; -IR_TABLE(pixelview, IR_TYPE_UNKNOWN, ir_codes_pixelview); +DEFINE_LEGACY_IR_KEYTABLE(pixelview); /* Mauro Carvalho Chehab present on PV MPEG 8000GT */ -static struct ir_scancode ir_codes_pixelview_new[] = { +static struct ir_scancode pixelview_new[] = { { 0x3c, KEY_TIME }, /* Timeshift */ { 0x12, KEY_POWER }, @@ -365,9 +356,9 @@ static struct ir_scancode ir_codes_pixelview_new[] = { { 0x31, KEY_TV }, { 0x34, KEY_RADIO }, }; -IR_TABLE(pixelview_new, IR_TYPE_UNKNOWN, ir_codes_pixelview_new); +DEFINE_LEGACY_IR_KEYTABLE(pixelview_new); -static struct ir_scancode ir_codes_nebula[] = { +static struct ir_scancode nebula[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, @@ -424,10 +415,10 @@ static struct ir_scancode ir_codes_nebula[] = { { 0x35, KEY_PHONE }, { 0x36, KEY_PC }, }; -IR_TABLE(nebula, IR_TYPE_UNKNOWN, ir_codes_nebula); +DEFINE_LEGACY_IR_KEYTABLE(nebula); /* DigitalNow DNTV Live DVB-T Remote */ -static struct ir_scancode ir_codes_dntv_live_dvb_t[] = { +static struct ir_scancode dntv_live_dvb_t[] = { { 0x00, KEY_ESC }, /* 'go up a level?' */ /* Keys 0 to 9 */ { 0x0a, KEY_0 }, @@ -464,12 +455,12 @@ static struct ir_scancode ir_codes_dntv_live_dvb_t[] = { { 0x1e, KEY_CHANNELDOWN }, { 0x1f, KEY_VOLUMEDOWN }, }; -IR_TABLE(dntv_live_dvb_t, IR_TYPE_UNKNOWN, ir_codes_dntv_live_dvb_t); +DEFINE_LEGACY_IR_KEYTABLE(dntv_live_dvb_t); /* ---------------------------------------------------------------------- */ /* IO-DATA BCTV7E Remote */ -static struct ir_scancode ir_codes_iodata_bctv7e[] = { +static struct ir_scancode iodata_bctv7e[] = { { 0x40, KEY_TV }, { 0x20, KEY_RADIO }, /* FM */ { 0x60, KEY_EPG }, @@ -516,12 +507,12 @@ static struct ir_scancode ir_codes_iodata_bctv7e[] = { { 0x61, KEY_FASTFORWARD }, /* forward >> */ { 0x01, KEY_NEXT }, /* skip >| */ }; -IR_TABLE(iodata_bctv7e, IR_TYPE_UNKNOWN, ir_codes_iodata_bctv7e); +DEFINE_LEGACY_IR_KEYTABLE(iodata_bctv7e); /* ---------------------------------------------------------------------- */ /* ADS Tech Instant TV DVB-T PCI Remote */ -static struct ir_scancode ir_codes_adstech_dvb_t_pci[] = { +static struct ir_scancode adstech_dvb_t_pci[] = { /* Keys 0 to 9 */ { 0x4d, KEY_0 }, { 0x57, KEY_1 }, @@ -569,13 +560,13 @@ static struct ir_scancode ir_codes_adstech_dvb_t_pci[] = { { 0x15, KEY_VOLUMEUP }, { 0x1c, KEY_VOLUMEDOWN }, }; -IR_TABLE(adstech_dvb_t_pci, IR_TYPE_UNKNOWN, ir_codes_adstech_dvb_t_pci); +DEFINE_LEGACY_IR_KEYTABLE(adstech_dvb_t_pci); /* ---------------------------------------------------------------------- */ /* MSI TV@nywhere MASTER remote */ -static struct ir_scancode ir_codes_msi_tvanywhere[] = { +static struct ir_scancode msi_tvanywhere[] = { /* Keys 0 to 9 */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, @@ -603,7 +594,7 @@ static struct ir_scancode ir_codes_msi_tvanywhere[] = { { 0x1e, KEY_CHANNELDOWN }, { 0x1f, KEY_VOLUMEDOWN }, }; -IR_TABLE(msi_tvanywhere, IR_TYPE_UNKNOWN, ir_codes_msi_tvanywhere); +DEFINE_LEGACY_IR_KEYTABLE(msi_tvanywhere); /* ---------------------------------------------------------------------- */ @@ -622,7 +613,7 @@ IR_TABLE(msi_tvanywhere, IR_TYPE_UNKNOWN, ir_codes_msi_tvanywhere); */ -static struct ir_scancode ir_codes_msi_tvanywhere_plus[] = { +static struct ir_scancode msi_tvanywhere_plus[] = { /* ---- Remote Button Layout ---- @@ -692,12 +683,12 @@ static struct ir_scancode ir_codes_msi_tvanywhere_plus[] = { { 0x0c, KEY_FASTFORWARD }, /* >> */ { 0x1d, KEY_RESTART }, /* Reset */ }; -IR_TABLE(msi_tvanywhere_plus, IR_TYPE_UNKNOWN, ir_codes_msi_tvanywhere_plus); +DEFINE_LEGACY_IR_KEYTABLE(msi_tvanywhere_plus); /* ---------------------------------------------------------------------- */ /* Cinergy 1400 DVB-T */ -static struct ir_scancode ir_codes_cinergy_1400[] = { +static struct ir_scancode cinergy_1400[] = { { 0x01, KEY_POWER }, { 0x02, KEY_1 }, { 0x03, KEY_2 }, @@ -740,12 +731,12 @@ static struct ir_scancode ir_codes_cinergy_1400[] = { { 0x48, KEY_STOP }, { 0x5c, KEY_NEXT }, }; -IR_TABLE(cinergy_1400, IR_TYPE_UNKNOWN, ir_codes_cinergy_1400); +DEFINE_LEGACY_IR_KEYTABLE(cinergy_1400); /* ---------------------------------------------------------------------- */ /* AVERTV STUDIO 303 Remote */ -static struct ir_scancode ir_codes_avertv_303[] = { +static struct ir_scancode avertv_303[] = { { 0x2a, KEY_1 }, { 0x32, KEY_2 }, { 0x3a, KEY_3 }, @@ -789,12 +780,12 @@ static struct ir_scancode ir_codes_avertv_303[] = { { 0x13, KEY_DOWN }, { 0x1b, KEY_UP }, }; -IR_TABLE(avertv_303, IR_TYPE_UNKNOWN, ir_codes_avertv_303); +DEFINE_LEGACY_IR_KEYTABLE(avertv_303); /* ---------------------------------------------------------------------- */ /* DigitalNow DNTV Live! DVB-T Pro Remote */ -static struct ir_scancode ir_codes_dntv_live_dvbt_pro[] = { +static struct ir_scancode dntv_live_dvbt_pro[] = { { 0x16, KEY_POWER }, { 0x5b, KEY_HOME }, @@ -850,9 +841,9 @@ static struct ir_scancode ir_codes_dntv_live_dvbt_pro[] = { { 0x5c, KEY_YELLOW }, { 0x5d, KEY_BLUE }, }; -IR_TABLE(dntv_live_dvbt_pro, IR_TYPE_UNKNOWN, ir_codes_dntv_live_dvbt_pro); +DEFINE_LEGACY_IR_KEYTABLE(dntv_live_dvbt_pro); -static struct ir_scancode ir_codes_em_terratec[] = { +static struct ir_scancode em_terratec[] = { { 0x01, KEY_CHANNEL }, { 0x02, KEY_SELECT }, { 0x03, KEY_MUTE }, @@ -882,9 +873,9 @@ static struct ir_scancode ir_codes_em_terratec[] = { { 0x1e, KEY_STOP }, { 0x40, KEY_ZOOM }, }; -IR_TABLE(em_terratec, IR_TYPE_UNKNOWN, ir_codes_em_terratec); +DEFINE_LEGACY_IR_KEYTABLE(em_terratec); -static struct ir_scancode ir_codes_pinnacle_grey[] = { +static struct ir_scancode pinnacle_grey[] = { { 0x3a, KEY_0 }, { 0x31, KEY_1 }, { 0x32, KEY_2 }, @@ -934,9 +925,9 @@ static struct ir_scancode ir_codes_pinnacle_grey[] = { { 0x2a, KEY_MEDIA }, { 0x18, KEY_EPG }, }; -IR_TABLE(pinnacle_grey, IR_TYPE_UNKNOWN, ir_codes_pinnacle_grey); +DEFINE_LEGACY_IR_KEYTABLE(pinnacle_grey); -static struct ir_scancode ir_codes_flyvideo[] = { +static struct ir_scancode flyvideo[] = { { 0x0f, KEY_0 }, { 0x03, KEY_1 }, { 0x04, KEY_2 }, @@ -967,9 +958,9 @@ static struct ir_scancode ir_codes_flyvideo[] = { { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ }; -IR_TABLE(flyvideo, IR_TYPE_UNKNOWN, ir_codes_flyvideo); +DEFINE_LEGACY_IR_KEYTABLE(flyvideo); -static struct ir_scancode ir_codes_flydvb[] = { +static struct ir_scancode flydvb[] = { { 0x01, KEY_ZOOM }, /* Full Screen */ { 0x00, KEY_POWER }, /* Power */ @@ -1007,9 +998,9 @@ static struct ir_scancode ir_codes_flydvb[] = { { 0x11, KEY_STOP }, /* Stop */ { 0x0e, KEY_NEXT }, /* End >>| */ }; -IR_TABLE(flydvb, IR_TYPE_UNKNOWN, ir_codes_flydvb); +DEFINE_LEGACY_IR_KEYTABLE(flydvb); -static struct ir_scancode ir_codes_cinergy[] = { +static struct ir_scancode cinergy[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, @@ -1048,11 +1039,11 @@ static struct ir_scancode ir_codes_cinergy[] = { { 0x22, KEY_PAUSE }, { 0x23, KEY_STOP }, }; -IR_TABLE(cinergy, IR_TYPE_UNKNOWN, ir_codes_cinergy); +DEFINE_LEGACY_IR_KEYTABLE(cinergy); /* Alfons Geser * updates from Job D. R. Borges */ -static struct ir_scancode ir_codes_eztv[] = { +static struct ir_scancode eztv[] = { { 0x12, KEY_POWER }, { 0x01, KEY_TV }, /* DVR */ { 0x15, KEY_DVD }, /* DVD */ @@ -1106,10 +1097,10 @@ static struct ir_scancode ir_codes_eztv[] = { { 0x13, KEY_ENTER }, /* enter */ { 0x21, KEY_DOT }, /* . (decimal dot) */ }; -IR_TABLE(eztv, IR_TYPE_UNKNOWN, ir_codes_eztv); +DEFINE_LEGACY_IR_KEYTABLE(eztv); /* Alex Hermann */ -static struct ir_scancode ir_codes_avermedia[] = { +static struct ir_scancode avermedia[] = { { 0x28, KEY_1 }, { 0x18, KEY_2 }, { 0x38, KEY_3 }, @@ -1154,9 +1145,9 @@ static struct ir_scancode ir_codes_avermedia[] = { { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ }; -IR_TABLE(avermedia, IR_TYPE_UNKNOWN, ir_codes_avermedia); +DEFINE_LEGACY_IR_KEYTABLE(avermedia); -static struct ir_scancode ir_codes_videomate_tv_pvr[] = { +static struct ir_scancode videomate_tv_pvr[] = { { 0x14, KEY_MUTE }, { 0x24, KEY_ZOOM }, @@ -1204,7 +1195,7 @@ static struct ir_scancode ir_codes_videomate_tv_pvr[] = { { 0x20, KEY_LANGUAGE }, { 0x21, KEY_SLEEP }, }; -IR_TABLE(videomate_tv_pvr, IR_TYPE_UNKNOWN, ir_codes_videomate_tv_pvr); +DEFINE_LEGACY_IR_KEYTABLE(videomate_tv_pvr); /* Michael Tokarev http://www.corpit.ru/mjt/beholdTV/remote_control.jpg @@ -1215,7 +1206,7 @@ IR_TABLE(videomate_tv_pvr, IR_TYPE_UNKNOWN, ir_codes_videomate_tv_pvr); the button labels (several variants when appropriate) helps to descide which keycodes to assign to the buttons. */ -static struct ir_scancode ir_codes_manli[] = { +static struct ir_scancode manli[] = { /* 0x1c 0x12 * * FUNCTION POWER * @@ -1301,10 +1292,10 @@ static struct ir_scancode ir_codes_manli[] = { /* 0x1d unused ? */ }; -IR_TABLE(manli, IR_TYPE_UNKNOWN, ir_codes_manli); +DEFINE_LEGACY_IR_KEYTABLE(manli); /* Mike Baikov */ -static struct ir_scancode ir_codes_gotview7135[] = { +static struct ir_scancode gotview7135[] = { { 0x11, KEY_POWER }, { 0x35, KEY_TV }, @@ -1342,9 +1333,9 @@ static struct ir_scancode ir_codes_gotview7135[] = { { 0x1e, KEY_TIME }, /* TIMESHIFT */ { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ }; -IR_TABLE(gotview7135, IR_TYPE_UNKNOWN, ir_codes_gotview7135); +DEFINE_LEGACY_IR_KEYTABLE(gotview7135); -static struct ir_scancode ir_codes_purpletv[] = { +static struct ir_scancode purpletv[] = { { 0x03, KEY_POWER }, { 0x6f, KEY_MUTE }, { 0x10, KEY_BACKSPACE }, /* Recall */ @@ -1386,13 +1377,13 @@ static struct ir_scancode ir_codes_purpletv[] = { { 0x42, KEY_REWIND }, /* Backward ? */ }; -IR_TABLE(purpletv, IR_TYPE_UNKNOWN, ir_codes_purpletv); +DEFINE_LEGACY_IR_KEYTABLE(purpletv); /* Mapping for the 28 key remote control as seen at http://www.sednacomputer.com/photo/cardbus-tv.jpg Pavel Mihaylov Also for the remote bundled with Kozumi KTV-01C card */ -static struct ir_scancode ir_codes_pctv_sedna[] = { +static struct ir_scancode pctv_sedna[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, @@ -1428,10 +1419,10 @@ static struct ir_scancode ir_codes_pctv_sedna[] = { { 0x17, KEY_DIGITS }, /* Plus */ { 0x1f, KEY_PLAY }, /* Play */ }; -IR_TABLE(pctv_sedna, IR_TYPE_UNKNOWN, ir_codes_pctv_sedna); +DEFINE_LEGACY_IR_KEYTABLE(pctv_sedna); /* Mark Phalan */ -static struct ir_scancode ir_codes_pv951[] = { +static struct ir_scancode pv951[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, @@ -1468,12 +1459,12 @@ static struct ir_scancode ir_codes_pv951[] = { { 0x14, KEY_EQUAL }, /* SYNC */ { 0x1c, KEY_MEDIA }, /* PC/TV */ }; -IR_TABLE(pv951, IR_TYPE_UNKNOWN, ir_codes_pv951); +DEFINE_LEGACY_IR_KEYTABLE(pv951); /* generic RC5 keytable */ /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ /* used by old (black) Hauppauge remotes */ -static struct ir_scancode ir_codes_rc5_tv[] = { +static struct ir_scancode rc5_tv[] = { /* Keys 0 to 9 */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, @@ -1511,10 +1502,10 @@ static struct ir_scancode ir_codes_rc5_tv[] = { { 0x3d, KEY_SUSPEND }, /* system standby */ }; -IR_TABLE(rc5_tv, IR_TYPE_UNKNOWN, ir_codes_rc5_tv); +DEFINE_LEGACY_IR_KEYTABLE(rc5_tv); /* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ -static struct ir_scancode ir_codes_winfast[] = { +static struct ir_scancode winfast[] = { /* Keys 0 to 9 */ { 0x12, KEY_0 }, { 0x05, KEY_1 }, @@ -1575,9 +1566,9 @@ static struct ir_scancode ir_codes_winfast[] = { { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ }; -IR_TABLE(winfast, IR_TYPE_UNKNOWN, ir_codes_winfast); +DEFINE_LEGACY_IR_KEYTABLE(winfast); -static struct ir_scancode ir_codes_pinnacle_color[] = { +static struct ir_scancode pinnacle_color[] = { { 0x59, KEY_MUTE }, { 0x4a, KEY_POWER }, @@ -1632,12 +1623,12 @@ static struct ir_scancode ir_codes_pinnacle_color[] = { { 0x74, KEY_CHANNEL }, { 0x0a, KEY_BACKSPACE }, }; -IR_TABLE(pinnacle_color, IR_TYPE_UNKNOWN, ir_codes_pinnacle_color); +DEFINE_LEGACY_IR_KEYTABLE(pinnacle_color); /* Hauppauge: the newer, gray remotes (seems there are multiple * slightly different versions), shipped with cx88+ivtv cards. * almost rc5 coding, but some non-standard keys */ -static struct ir_scancode ir_codes_hauppauge_new[] = { +static struct ir_scancode hauppauge_new[] = { /* Keys 0 to 9 */ { 0x00, KEY_0 }, { 0x01, KEY_1 }, @@ -1694,9 +1685,9 @@ static struct ir_scancode ir_codes_hauppauge_new[] = { { 0x3c, KEY_ZOOM }, /* full */ { 0x3d, KEY_POWER }, /* system power (green button) */ }; -IR_TABLE(hauppauge_new, IR_TYPE_UNKNOWN, ir_codes_hauppauge_new); +DEFINE_LEGACY_IR_KEYTABLE(hauppauge_new); -static struct ir_scancode ir_codes_npgtech[] = { +static struct ir_scancode npgtech[] = { { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ { 0x2a, KEY_FRONT }, @@ -1737,12 +1728,12 @@ static struct ir_scancode ir_codes_npgtech[] = { { 0x10, KEY_POWER }, }; -IR_TABLE(npgtech, IR_TYPE_UNKNOWN, ir_codes_npgtech); +DEFINE_LEGACY_IR_KEYTABLE(npgtech); /* Norwood Micro (non-Pro) TV Tuner By Peter Naulls Key comments are the functions given in the manual */ -static struct ir_scancode ir_codes_norwood[] = { +static struct ir_scancode norwood[] = { /* Keys 0 to 9 */ { 0x20, KEY_0 }, { 0x21, KEY_1 }, @@ -1784,14 +1775,14 @@ static struct ir_scancode ir_codes_norwood[] = { { 0x34, KEY_RADIO }, /* FM */ { 0x65, KEY_POWER }, /* Computer power */ }; -IR_TABLE(norwood, IR_TYPE_UNKNOWN, ir_codes_norwood); +DEFINE_LEGACY_IR_KEYTABLE(norwood); /* From reading the following remotes: * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 * Hauppauge (from NOVA-CI-s box product) * This is a "middle of the road" approach, differences are noted */ -static struct ir_scancode ir_codes_budget_ci_old[] = { +static struct ir_scancode budget_ci_old[] = { { 0x00, KEY_0 }, { 0x01, KEY_1 }, { 0x02, KEY_2 }, @@ -1838,14 +1829,14 @@ static struct ir_scancode ir_codes_budget_ci_old[] = { { 0x3d, KEY_POWER2 }, { 0x3e, KEY_TUNER }, }; -IR_TABLE(budget_ci_old, IR_TYPE_UNKNOWN, ir_codes_budget_ci_old); +DEFINE_LEGACY_IR_KEYTABLE(budget_ci_old); /* * Marc Fargas * this is the remote control that comes with the asus p7131 * which has a label saying is "Model PC-39" */ -static struct ir_scancode ir_codes_asus_pc39[] = { +static struct ir_scancode asus_pc39[] = { /* Keys 0 to 9 */ { 0x15, KEY_0 }, { 0x29, KEY_1 }, @@ -1891,11 +1882,11 @@ static struct ir_scancode ir_codes_asus_pc39[] = { { 0x3d, KEY_MUTE }, /* mute */ { 0x01, KEY_DVD }, /* dvd */ }; -IR_TABLE(asus_pc39, IR_TYPE_UNKNOWN, ir_codes_asus_pc39); +DEFINE_LEGACY_IR_KEYTABLE(asus_pc39); /* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons Juan Pablo Sormani */ -static struct ir_scancode ir_codes_encore_enltv[] = { +static struct ir_scancode encore_enltv[] = { /* Power button does nothing, neither in Windows app, although it sends data (used for BIOS wakeup?) */ @@ -1965,11 +1956,11 @@ static struct ir_scancode ir_codes_encore_enltv[] = { { 0x47, KEY_YELLOW }, /* AP3 */ { 0x57, KEY_BLUE }, /* AP4 */ }; -IR_TABLE(encore_enltv, IR_TYPE_UNKNOWN, ir_codes_encore_enltv); +DEFINE_LEGACY_IR_KEYTABLE(encore_enltv); /* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_encore_enltv2[] = { +static struct ir_scancode encore_enltv2[] = { { 0x4c, KEY_POWER2 }, { 0x4a, KEY_TUNER }, { 0x40, KEY_1 }, @@ -2017,10 +2008,10 @@ static struct ir_scancode ir_codes_encore_enltv2[] = { { 0x7d, KEY_FORWARD }, { 0x79, KEY_STOP }, }; -IR_TABLE(encore_enltv2, IR_TYPE_UNKNOWN, ir_codes_encore_enltv2); +DEFINE_LEGACY_IR_KEYTABLE(encore_enltv2); /* for the Technotrend 1500 bundled remotes (grey and black): */ -static struct ir_scancode ir_codes_tt_1500[] = { +static struct ir_scancode tt_1500[] = { { 0x01, KEY_POWER }, { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ { 0x03, KEY_1 }, @@ -2061,10 +2052,10 @@ static struct ir_scancode ir_codes_tt_1500[] = { { 0x3e, KEY_PAUSE }, { 0x3f, KEY_FORWARD }, }; -IR_TABLE(tt_1500, IR_TYPE_UNKNOWN, ir_codes_tt_1500); +DEFINE_LEGACY_IR_KEYTABLE(tt_1500); /* DViCO FUSION HDTV MCE remote */ -static struct ir_scancode ir_codes_fusionhdtv_mce[] = { +static struct ir_scancode fusionhdtv_mce[] = { { 0x0b, KEY_1 }, { 0x17, KEY_2 }, @@ -2121,10 +2112,10 @@ static struct ir_scancode ir_codes_fusionhdtv_mce[] = { { 0x01, KEY_RECORD }, { 0x4e, KEY_POWER }, }; -IR_TABLE(fusionhdtv_mce, IR_TYPE_UNKNOWN, ir_codes_fusionhdtv_mce); +DEFINE_LEGACY_IR_KEYTABLE(fusionhdtv_mce); /* Pinnacle PCTV HD 800i mini remote */ -static struct ir_scancode ir_codes_pinnacle_pctv_hd[] = { +static struct ir_scancode pinnacle_pctv_hd[] = { { 0x0f, KEY_1 }, { 0x15, KEY_2 }, @@ -2156,7 +2147,7 @@ static struct ir_scancode ir_codes_pinnacle_pctv_hd[] = { { 0x36, KEY_RECORD }, { 0x3f, KEY_EPG }, /* Labeled "?" */ }; -IR_TABLE(pinnacle_pctv_hd, IR_TYPE_UNKNOWN, ir_codes_pinnacle_pctv_hd); +DEFINE_LEGACY_IR_KEYTABLE(pinnacle_pctv_hd); /* * Igor Kuznetsov @@ -2169,7 +2160,7 @@ IR_TABLE(pinnacle_pctv_hd, IR_TYPE_UNKNOWN, ir_codes_pinnacle_pctv_hd); * the button labels (several variants when appropriate) * helps to descide which keycodes to assign to the buttons. */ -static struct ir_scancode ir_codes_behold[] = { +static struct ir_scancode behold[] = { /* 0x1c 0x12 * * TV/FM POWER * @@ -2259,7 +2250,7 @@ static struct ir_scancode ir_codes_behold[] = { { 0x5c, KEY_CAMERA }, }; -IR_TABLE(behold, IR_TYPE_UNKNOWN, ir_codes_behold); +DEFINE_LEGACY_IR_KEYTABLE(behold); /* Beholder Intl. Ltd. 2008 * Dmitry Belimov d.belimov@google.com @@ -2269,7 +2260,7 @@ IR_TABLE(behold, IR_TYPE_UNKNOWN, ir_codes_behold); * the button labels (several variants when appropriate) * helps to descide which keycodes to assign to the buttons. */ -static struct ir_scancode ir_codes_behold_columbus[] = { +static struct ir_scancode behold_columbus[] = { /* 0x13 0x11 0x1C 0x12 * * Mute Source TV/FM Power * @@ -2329,13 +2320,13 @@ static struct ir_scancode ir_codes_behold_columbus[] = { { 0x1A, KEY_NEXT }, }; -IR_TABLE(behold_columbus, IR_TYPE_UNKNOWN, ir_codes_behold_columbus); +DEFINE_LEGACY_IR_KEYTABLE(behold_columbus); /* * Remote control for the Genius TVGO A11MCE * Adrian Pardini */ -static struct ir_scancode ir_codes_genius_tvgo_a11mce[] = { +static struct ir_scancode genius_tvgo_a11mce[] = { /* Keys 0 to 9 */ { 0x48, KEY_0 }, { 0x09, KEY_1 }, @@ -2375,13 +2366,13 @@ static struct ir_scancode ir_codes_genius_tvgo_a11mce[] = { { 0x13, KEY_YELLOW }, { 0x50, KEY_BLUE }, }; -IR_TABLE(genius_tvgo_a11mce, IR_TYPE_UNKNOWN, ir_codes_genius_tvgo_a11mce); +DEFINE_LEGACY_IR_KEYTABLE(genius_tvgo_a11mce); /* * Remote control for Powercolor Real Angel 330 * Daniel Fraga */ -static struct ir_scancode ir_codes_powercolor_real_angel[] = { +static struct ir_scancode powercolor_real_angel[] = { { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ { 0x00, KEY_0 }, @@ -2418,12 +2409,12 @@ static struct ir_scancode ir_codes_powercolor_real_angel[] = { { 0x14, KEY_RADIO }, /* FM radio */ { 0x25, KEY_POWER }, /* power */ }; -IR_TABLE(powercolor_real_angel, IR_TYPE_UNKNOWN, ir_codes_powercolor_real_angel); +DEFINE_LEGACY_IR_KEYTABLE(powercolor_real_angel); /* Kworld Plus TV Analog Lite PCI IR Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_kworld_plus_tv_analog[] = { +static struct ir_scancode kworld_plus_tv_analog[] = { { 0x0c, KEY_PROG1 }, /* Kworld key */ { 0x16, KEY_CLOSECD }, /* -> ) */ { 0x1d, KEY_POWER2 }, @@ -2479,12 +2470,12 @@ static struct ir_scancode ir_codes_kworld_plus_tv_analog[] = { { 0x18, KEY_RED}, /* B */ { 0x23, KEY_GREEN}, /* C */ }; -IR_TABLE(kworld_plus_tv_analog, IR_TYPE_UNKNOWN, ir_codes_kworld_plus_tv_analog); +DEFINE_LEGACY_IR_KEYTABLE(kworld_plus_tv_analog); /* Kaiomy TVnPC U2 Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_kaiomy[] = { +static struct ir_scancode kaiomy[] = { { 0x43, KEY_POWER2}, { 0x01, KEY_LIST}, { 0x0b, KEY_ZOOM}, @@ -2528,9 +2519,9 @@ static struct ir_scancode ir_codes_kaiomy[] = { { 0x1e, KEY_YELLOW}, { 0x1f, KEY_BLUE}, }; -IR_TABLE(kaiomy, IR_TYPE_UNKNOWN, ir_codes_kaiomy); +DEFINE_LEGACY_IR_KEYTABLE(kaiomy); -static struct ir_scancode ir_codes_avermedia_a16d[] = { +static struct ir_scancode avermedia_a16d[] = { { 0x20, KEY_LIST}, { 0x00, KEY_POWER}, { 0x28, KEY_1}, @@ -2566,12 +2557,12 @@ static struct ir_scancode ir_codes_avermedia_a16d[] = { { 0x08, KEY_EPG}, { 0x2a, KEY_MENU}, }; -IR_TABLE(avermedia_a16d, IR_TYPE_UNKNOWN, ir_codes_avermedia_a16d); +DEFINE_LEGACY_IR_KEYTABLE(avermedia_a16d); /* Encore ENLTV-FM v5.3 Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_encore_enltv_fm53[] = { +static struct ir_scancode encore_enltv_fm53[] = { { 0x10, KEY_POWER2}, { 0x06, KEY_MUTE}, @@ -2609,10 +2600,10 @@ static struct ir_scancode ir_codes_encore_enltv_fm53[] = { { 0x0c, KEY_ZOOM}, /* hide pannel */ { 0x47, KEY_SLEEP}, /* shutdown */ }; -IR_TABLE(encore_enltv_fm53, IR_TYPE_UNKNOWN, ir_codes_encore_enltv_fm53); +DEFINE_LEGACY_IR_KEYTABLE(encore_enltv_fm53); /* Zogis Real Audio 220 - 32 keys IR */ -static struct ir_scancode ir_codes_real_audio_220_32_keys[] = { +static struct ir_scancode real_audio_220_32_keys[] = { { 0x1c, KEY_RADIO}, { 0x12, KEY_POWER2}, @@ -2649,12 +2640,12 @@ static struct ir_scancode ir_codes_real_audio_220_32_keys[] = { { 0x19, KEY_CAMERA}, /* Snapshot */ }; -IR_TABLE(real_audio_220_32_keys, IR_TYPE_UNKNOWN, ir_codes_real_audio_220_32_keys); +DEFINE_LEGACY_IR_KEYTABLE(real_audio_220_32_keys); /* ATI TV Wonder HD 600 USB Devin Heitmueller */ -static struct ir_scancode ir_codes_ati_tv_wonder_hd_600[] = { +static struct ir_scancode ati_tv_wonder_hd_600[] = { { 0x00, KEY_RECORD}, /* Row 1 */ { 0x01, KEY_PLAYPAUSE}, { 0x02, KEY_STOP}, @@ -2680,12 +2671,12 @@ static struct ir_scancode ir_codes_ati_tv_wonder_hd_600[] = { { 0x16, KEY_MUTE}, { 0x17, KEY_VOLUMEDOWN}, }; -IR_TABLE(ati_tv_wonder_hd_600, IR_TYPE_UNKNOWN, ir_codes_ati_tv_wonder_hd_600); +DEFINE_LEGACY_IR_KEYTABLE(ati_tv_wonder_hd_600); /* DVBWorld remotes Igor M. Liplianin */ -static struct ir_scancode ir_codes_dm1105_nec[] = { +static struct ir_scancode dm1105_nec[] = { { 0x0a, KEY_POWER2}, /* power */ { 0x0c, KEY_MUTE}, /* mute */ { 0x11, KEY_1}, @@ -2718,9 +2709,9 @@ static struct ir_scancode ir_codes_dm1105_nec[] = { { 0x1e, KEY_TV}, /* tvmode */ { 0x1b, KEY_B}, /* recall */ }; -IR_TABLE(dm1105_nec, IR_TYPE_UNKNOWN, ir_codes_dm1105_nec); +DEFINE_LEGACY_IR_KEYTABLE(dm1105_nec); -static struct ir_scancode ir_codes_tevii_nec[] = { +static struct ir_scancode tevii_nec[] = { { 0x0a, KEY_POWER2}, { 0x0c, KEY_MUTE}, { 0x11, KEY_1}, @@ -2769,9 +2760,9 @@ static struct ir_scancode ir_codes_tevii_nec[] = { { 0x56, KEY_MODE}, { 0x58, KEY_SWITCHVIDEOMODE}, }; -IR_TABLE(tevii_nec, IR_TYPE_UNKNOWN, ir_codes_tevii_nec); +DEFINE_LEGACY_IR_KEYTABLE(tevii_nec); -static struct ir_scancode ir_codes_tbs_nec[] = { +static struct ir_scancode tbs_nec[] = { { 0x04, KEY_POWER2}, /*power*/ { 0x14, KEY_MUTE}, /*mute*/ { 0x07, KEY_1}, @@ -2805,12 +2796,12 @@ static struct ir_scancode ir_codes_tbs_nec[] = { { 0x00, KEY_PREVIOUS}, { 0x1b, KEY_MODE}, }; -IR_TABLE(tbs_nec, IR_TYPE_UNKNOWN, ir_codes_tbs_nec); +DEFINE_LEGACY_IR_KEYTABLE(tbs_nec); /* Terratec Cinergy Hybrid T USB XS Devin Heitmueller */ -static struct ir_scancode ir_codes_terratec_cinergy_xs[] = { +static struct ir_scancode terratec_cinergy_xs[] = { { 0x41, KEY_HOME}, { 0x01, KEY_POWER}, { 0x42, KEY_MENU}, @@ -2859,12 +2850,12 @@ static struct ir_scancode ir_codes_terratec_cinergy_xs[] = { { 0x4f, KEY_FASTFORWARD}, { 0x5c, KEY_NEXT}, }; -IR_TABLE(terratec_cinergy_xs, IR_TYPE_UNKNOWN, ir_codes_terratec_cinergy_xs); +DEFINE_LEGACY_IR_KEYTABLE(terratec_cinergy_xs); /* EVGA inDtube Devin Heitmueller */ -static struct ir_scancode ir_codes_evga_indtube[] = { +static struct ir_scancode evga_indtube[] = { { 0x12, KEY_POWER}, { 0x02, KEY_MODE}, /* TV */ { 0x14, KEY_MUTE}, @@ -2882,9 +2873,9 @@ static struct ir_scancode ir_codes_evga_indtube[] = { { 0x1f, KEY_NEXT}, { 0x13, KEY_CAMERA}, }; -IR_TABLE(evga_indtube, IR_TYPE_UNKNOWN, ir_codes_evga_indtube); +DEFINE_LEGACY_IR_KEYTABLE(evga_indtube); -static struct ir_scancode ir_codes_videomate_s350[] = { +static struct ir_scancode videomate_s350[] = { { 0x00, KEY_TV}, { 0x01, KEY_DVD}, { 0x04, KEY_RECORD}, @@ -2930,12 +2921,12 @@ static struct ir_scancode ir_codes_videomate_s350[] = { { 0x11, KEY_ENTER}, { 0x20, KEY_TEXT}, }; -IR_TABLE(videomate_s350, IR_TYPE_UNKNOWN, ir_codes_videomate_s350); +DEFINE_LEGACY_IR_KEYTABLE(videomate_s350); /* GADMEI UTV330+ RM008Z remote Shine Liu */ -static struct ir_scancode ir_codes_gadmei_rm008z[] = { +static struct ir_scancode gadmei_rm008z[] = { { 0x14, KEY_POWER2}, /* POWER OFF */ { 0x0c, KEY_MUTE}, /* MUTE */ @@ -2973,7 +2964,7 @@ static struct ir_scancode ir_codes_gadmei_rm008z[] = { { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ { 0x15, KEY_ENTER}, /* OK */ }; -IR_TABLE(gadmei_rm008z, IR_TYPE_UNKNOWN, ir_codes_gadmei_rm008z); +DEFINE_LEGACY_IR_KEYTABLE(gadmei_rm008z); /************************************************************* * COMPLETE SCANCODE TABLES @@ -2987,7 +2978,7 @@ IR_TABLE(gadmei_rm008z, IR_TYPE_UNKNOWN, ir_codes_gadmei_rm008z); * * This table contains the complete RC5 code, instead of just the data part */ -static struct ir_scancode ir_codes_rc5_hauppauge_new[] = { +static struct ir_scancode rc5_hauppauge_new[] = { /* Keys 0 to 9 */ { 0x1e00, KEY_0 }, { 0x1e01, KEY_1 }, @@ -3044,12 +3035,12 @@ static struct ir_scancode ir_codes_rc5_hauppauge_new[] = { { 0x1e3c, KEY_ZOOM }, /* full */ { 0x1e3d, KEY_POWER }, /* system power (green button) */ }; -IR_TABLE(rc5_hauppauge_new, IR_TYPE_RC5, ir_codes_rc5_hauppauge_new); +DEFINE_IR_KEYTABLE(rc5_hauppauge_new, IR_TYPE_RC5); /* Terratec Cinergy Hybrid T USB XS FM Mauro Carvalho Chehab */ -static struct ir_scancode ir_codes_nec_terratec_cinergy_xs[] = { +static struct ir_scancode nec_terratec_cinergy_xs[] = { { 0x1441, KEY_HOME}, { 0x1401, KEY_POWER2}, @@ -3111,12 +3102,12 @@ static struct ir_scancode ir_codes_nec_terratec_cinergy_xs[] = { { 0x144f, KEY_FASTFORWARD}, { 0x145c, KEY_NEXT}, }; -IR_TABLE(nec_terratec_cinergy_xs, IR_TYPE_NEC, ir_codes_nec_terratec_cinergy_xs); +DEFINE_IR_KEYTABLE(nec_terratec_cinergy_xs, IR_TYPE_NEC); /* Leadtek Winfast TV USB II Deluxe remote Magnus Alm */ -static struct ir_scancode ir_codes_winfast_usbii_deluxe[] = { +static struct ir_scancode winfast_usbii_deluxe[] = { { 0x62, KEY_0}, { 0x75, KEY_1}, { 0x76, KEY_2}, @@ -3155,11 +3146,11 @@ static struct ir_scancode ir_codes_winfast_usbii_deluxe[] = { { 0x63, KEY_ENTER}, /* ENTER */ }; -IR_TABLE(winfast_usbii_deluxe, IR_TYPE_UNKNOWN, ir_codes_winfast_usbii_deluxe); +DEFINE_LEGACY_IR_KEYTABLE(winfast_usbii_deluxe); /* Kworld 315U */ -static struct ir_scancode ir_codes_kworld_315u[] = { +static struct ir_scancode kworld_315u[] = { { 0x6143, KEY_POWER }, { 0x6101, KEY_TUNER }, /* source */ { 0x610b, KEY_ZOOM }, @@ -3200,4 +3191,4 @@ static struct ir_scancode ir_codes_kworld_315u[] = { { 0x611e, KEY_YELLOW }, { 0x611f, KEY_BLUE }, }; -IR_TABLE(kworld_315u, IR_TYPE_NEC, ir_codes_kworld_315u); +DEFINE_IR_KEYTABLE(kworld_315u, IR_TYPE_NEC); -- cgit v1.2.3 From 77b7422d48cda9b8e5dabb7f4bc056861c5ed4fe Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 1 Apr 2010 22:43:29 -0300 Subject: V4L/DVB: ir-common: move IR tables from ir-keymaps.c to a separate file Instead of having one big file with lots of keytables, create one include file for each IR keymap. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keymaps.c | 3171 +---------------------------------------- 1 file changed, 11 insertions(+), 3160 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c index 1ba928516cd2..eb2553192789 100644 --- a/drivers/media/IR/ir-keymaps.c +++ b/drivers/media/IR/ir-keymaps.c @@ -17,3178 +17,29 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define IR_KEYMAPS + /* * NOTICE FOR DEVELOPERS: * The IR mappings should be as close as possible to what's * specified at: * http://linuxtv.org/wiki/index.php/Remote_Controllers - */ -#include - -#include -#include - - -/* + * * The usage of tables with just the command part is deprecated. * All new IR keytables should contain address+command and need * to define the proper IR_TYPE (IR_TYPE_RC5/IR_TYPE_NEC). * The deprecated tables should use IR_TYPE_UNKNOWN */ +#include -/* empty keytable, can be used as placeholder for not-yet created keytables */ -static struct ir_scancode empty[] = { - { 0x2a, KEY_COFFEE }, -}; -DEFINE_LEGACY_IR_KEYTABLE(empty); - -/* Michal Majchrowicz */ -static struct ir_scancode proteus_2309[] = { - /* numeric */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x5c, KEY_POWER }, /* power */ - { 0x20, KEY_ZOOM }, /* full screen */ - { 0x0f, KEY_BACKSPACE }, /* recall */ - { 0x1b, KEY_ENTER }, /* mute */ - { 0x41, KEY_RECORD }, /* record */ - { 0x43, KEY_STOP }, /* stop */ - { 0x16, KEY_S }, - { 0x1a, KEY_POWER2 }, /* off */ - { 0x2e, KEY_RED }, - { 0x1f, KEY_CHANNELDOWN }, /* channel - */ - { 0x1c, KEY_CHANNELUP }, /* channel + */ - { 0x10, KEY_VOLUMEDOWN }, /* volume - */ - { 0x1e, KEY_VOLUMEUP }, /* volume + */ - { 0x14, KEY_F1 }, -}; -DEFINE_LEGACY_IR_KEYTABLE(proteus_2309); - -/* Matt Jesson >' */ - { 0x3a, KEY_RECORD }, /* 'capture' */ - { 0x0a, KEY_MUTE }, /* 'mute' */ - { 0x2c, KEY_RECORD }, /* 'record' */ - { 0x1c, KEY_PAUSE }, /* 'pause' */ - { 0x3c, KEY_STOP }, /* 'stop' */ - { 0x0c, KEY_PLAY }, /* 'play' */ - { 0x2e, KEY_RED }, /* 'red' */ - { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */ - { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */ - { 0x21, KEY_GREEN }, /* 'green' */ - { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */ - { 0x31, KEY_CHANNELUP }, /* 'channel +' */ - { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */ - { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ -}; -DEFINE_LEGACY_IR_KEYTABLE(avermedia_dvbt); - -/* - * Avermedia M135A with IR model RM-JX - * The same codes exist on both Positivo (BR) and original IR - * Mauro Carvalho Chehab - */ -static struct ir_scancode avermedia_m135a_rm_jx[] = { - { 0x0200, KEY_POWER2 }, - { 0x022e, KEY_DOT }, /* '.' */ - { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ - - { 0x0205, KEY_1 }, - { 0x0206, KEY_2 }, - { 0x0207, KEY_3 }, - { 0x0209, KEY_4 }, - { 0x020a, KEY_5 }, - { 0x020b, KEY_6 }, - { 0x020d, KEY_7 }, - { 0x020e, KEY_8 }, - { 0x020f, KEY_9 }, - { 0x0211, KEY_0 }, - - { 0x0213, KEY_RIGHT }, /* -> or L */ - { 0x0212, KEY_LEFT }, /* <- or R */ - - { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ - { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ - - { 0x0303, KEY_CHANNELUP }, - { 0x0302, KEY_CHANNELDOWN }, - { 0x021f, KEY_VOLUMEUP }, - { 0x021e, KEY_VOLUMEDOWN }, - { 0x020c, KEY_ENTER }, /* Full Screen */ - - { 0x0214, KEY_MUTE }, - { 0x0208, KEY_AUDIO }, - - { 0x0203, KEY_TEXT }, /* Teletext */ - { 0x0204, KEY_EPG }, - { 0x022b, KEY_TV2 }, /* TV2 or PIP */ - - { 0x021d, KEY_RED }, - { 0x021c, KEY_YELLOW }, - { 0x0301, KEY_GREEN }, - { 0x0300, KEY_BLUE }, - - { 0x021a, KEY_PLAYPAUSE }, - { 0x0219, KEY_RECORD }, - { 0x0218, KEY_PLAY }, - { 0x021b, KEY_STOP }, -}; -DEFINE_IR_KEYTABLE(avermedia_m135a_rm_jx, IR_TYPE_NEC); - -/* Oldrich Jedlicka */ -static struct ir_scancode avermedia_cardbus[] = { - { 0x00, KEY_POWER }, - { 0x01, KEY_TUNER }, /* TV/FM */ - { 0x03, KEY_TEXT }, /* Teletext */ - { 0x04, KEY_EPG }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x08, KEY_AUDIO }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0c, KEY_ZOOM }, /* Full screen */ - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - { 0x10, KEY_PAGEUP }, /* 16-CH PREV */ - { 0x11, KEY_0 }, - { 0x12, KEY_INFO }, - { 0x13, KEY_AGAIN }, /* CH RTN - channel return */ - { 0x14, KEY_MUTE }, - { 0x15, KEY_EDIT }, /* Autoscan */ - { 0x17, KEY_SAVE }, /* Screenshot */ - { 0x18, KEY_PLAYPAUSE }, - { 0x19, KEY_RECORD }, - { 0x1a, KEY_PLAY }, - { 0x1b, KEY_STOP }, - { 0x1c, KEY_FASTFORWARD }, - { 0x1d, KEY_REWIND }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x1f, KEY_VOLUMEUP }, - { 0x22, KEY_SLEEP }, /* Sleep */ - { 0x23, KEY_ZOOM }, /* Aspect */ - { 0x26, KEY_SCREEN }, /* Pos */ - { 0x27, KEY_ANGLE }, /* Size */ - { 0x28, KEY_SELECT }, /* Select */ - { 0x29, KEY_BLUE }, /* Blue/Picture */ - { 0x2a, KEY_BACKSPACE }, /* Back */ - { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ - { 0x2c, KEY_DOWN }, - { 0x2e, KEY_DOT }, - { 0x2f, KEY_TV }, /* Live TV */ - { 0x32, KEY_LEFT }, - { 0x33, KEY_CLEAR }, /* Clear */ - { 0x35, KEY_RED }, /* Red/TV */ - { 0x36, KEY_UP }, - { 0x37, KEY_HOME }, /* Home */ - { 0x39, KEY_GREEN }, /* Green/Video */ - { 0x3d, KEY_YELLOW }, /* Yellow/Music */ - { 0x3e, KEY_OK }, /* Ok */ - { 0x3f, KEY_RIGHT }, - { 0x40, KEY_NEXT }, /* Next */ - { 0x41, KEY_PREVIOUS }, /* Previous */ - { 0x42, KEY_CHANNELDOWN }, /* Channel down */ - { 0x43, KEY_CHANNELUP }, /* Channel up */ -}; -DEFINE_LEGACY_IR_KEYTABLE(avermedia_cardbus); - -/* Attila Kondoros */ -static struct ir_scancode apac_viewcomp[] = { - - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x00, KEY_0 }, - { 0x17, KEY_LAST }, /* +100 */ - { 0x0a, KEY_LIST }, /* recall */ - - - { 0x1c, KEY_TUNER }, /* TV/FM */ - { 0x15, KEY_SEARCH }, /* scan */ - { 0x12, KEY_POWER }, /* power */ - { 0x1f, KEY_VOLUMEDOWN }, /* vol up */ - { 0x1b, KEY_VOLUMEUP }, /* vol down */ - { 0x1e, KEY_CHANNELDOWN }, /* chn up */ - { 0x1a, KEY_CHANNELUP }, /* chn down */ - - { 0x11, KEY_VIDEO }, /* video */ - { 0x0f, KEY_ZOOM }, /* full screen */ - { 0x13, KEY_MUTE }, /* mute/unmute */ - { 0x10, KEY_TEXT }, /* min */ - - { 0x0d, KEY_STOP }, /* freeze */ - { 0x0e, KEY_RECORD }, /* record */ - { 0x1d, KEY_PLAYPAUSE }, /* stop */ - { 0x19, KEY_PLAY }, /* play */ - - { 0x16, KEY_GOTO }, /* osd */ - { 0x14, KEY_REFRESH }, /* default */ - { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ - { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ -}; -DEFINE_LEGACY_IR_KEYTABLE(apac_viewcomp); - -/* ---------------------------------------------------------------------- */ - -static struct ir_scancode pixelview[] = { - - { 0x1e, KEY_POWER }, /* power */ - { 0x07, KEY_MEDIA }, /* source */ - { 0x1c, KEY_SEARCH }, /* scan */ - - - { 0x03, KEY_TUNER }, /* TV/FM */ - - { 0x00, KEY_RECORD }, - { 0x08, KEY_STOP }, - { 0x11, KEY_PLAY }, - - { 0x1a, KEY_PLAYPAUSE }, /* freeze */ - { 0x19, KEY_ZOOM }, /* zoom */ - { 0x0f, KEY_TEXT }, /* min */ - - { 0x01, KEY_1 }, - { 0x0b, KEY_2 }, - { 0x1b, KEY_3 }, - { 0x05, KEY_4 }, - { 0x09, KEY_5 }, - { 0x15, KEY_6 }, - { 0x06, KEY_7 }, - { 0x0a, KEY_8 }, - { 0x12, KEY_9 }, - { 0x02, KEY_0 }, - { 0x10, KEY_LAST }, /* +100 */ - { 0x13, KEY_LIST }, /* recall */ - - { 0x1f, KEY_CHANNELUP }, /* chn down */ - { 0x17, KEY_CHANNELDOWN }, /* chn up */ - { 0x16, KEY_VOLUMEUP }, /* vol down */ - { 0x14, KEY_VOLUMEDOWN }, /* vol up */ - - { 0x04, KEY_KPMINUS }, /* <<< */ - { 0x0e, KEY_SETUP }, /* function */ - { 0x0c, KEY_KPPLUS }, /* >>> */ - - { 0x0d, KEY_GOTO }, /* mts */ - { 0x1d, KEY_REFRESH }, /* reset */ - { 0x18, KEY_MUTE }, /* mute/unmute */ -}; -DEFINE_LEGACY_IR_KEYTABLE(pixelview); - -/* - Mauro Carvalho Chehab - present on PV MPEG 8000GT - */ -static struct ir_scancode pixelview_new[] = { - { 0x3c, KEY_TIME }, /* Timeshift */ - { 0x12, KEY_POWER }, - - { 0x3d, KEY_1 }, - { 0x38, KEY_2 }, - { 0x18, KEY_3 }, - { 0x35, KEY_4 }, - { 0x39, KEY_5 }, - { 0x15, KEY_6 }, - { 0x36, KEY_7 }, - { 0x3a, KEY_8 }, - { 0x1e, KEY_9 }, - { 0x3e, KEY_0 }, - - { 0x1c, KEY_AGAIN }, /* LOOP */ - { 0x3f, KEY_MEDIA }, /* Source */ - { 0x1f, KEY_LAST }, /* +100 */ - { 0x1b, KEY_MUTE }, - - { 0x17, KEY_CHANNELDOWN }, - { 0x16, KEY_CHANNELUP }, - { 0x10, KEY_VOLUMEUP }, - { 0x14, KEY_VOLUMEDOWN }, - { 0x13, KEY_ZOOM }, - - { 0x19, KEY_CAMERA }, /* SNAPSHOT */ - { 0x1a, KEY_SEARCH }, /* scan */ - - { 0x37, KEY_REWIND }, /* << */ - { 0x32, KEY_RECORD }, /* o (red) */ - { 0x33, KEY_FORWARD }, /* >> */ - { 0x11, KEY_STOP }, /* square */ - { 0x3b, KEY_PLAY }, /* > */ - { 0x30, KEY_PLAYPAUSE }, /* || */ - - { 0x31, KEY_TV }, - { 0x34, KEY_RADIO }, -}; -DEFINE_LEGACY_IR_KEYTABLE(pixelview_new); - -static struct ir_scancode nebula[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0a, KEY_TV }, - { 0x0b, KEY_AUX }, - { 0x0c, KEY_DVD }, - { 0x0d, KEY_POWER }, - { 0x0e, KEY_MHP }, /* labelled 'Picture' */ - { 0x0f, KEY_AUDIO }, - { 0x10, KEY_INFO }, - { 0x11, KEY_F13 }, /* 16:9 */ - { 0x12, KEY_F14 }, /* 14:9 */ - { 0x13, KEY_EPG }, - { 0x14, KEY_EXIT }, - { 0x15, KEY_MENU }, - { 0x16, KEY_UP }, - { 0x17, KEY_DOWN }, - { 0x18, KEY_LEFT }, - { 0x19, KEY_RIGHT }, - { 0x1a, KEY_ENTER }, - { 0x1b, KEY_CHANNELUP }, - { 0x1c, KEY_CHANNELDOWN }, - { 0x1d, KEY_VOLUMEUP }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x1f, KEY_RED }, - { 0x20, KEY_GREEN }, - { 0x21, KEY_YELLOW }, - { 0x22, KEY_BLUE }, - { 0x23, KEY_SUBTITLE }, - { 0x24, KEY_F15 }, /* AD */ - { 0x25, KEY_TEXT }, - { 0x26, KEY_MUTE }, - { 0x27, KEY_REWIND }, - { 0x28, KEY_STOP }, - { 0x29, KEY_PLAY }, - { 0x2a, KEY_FASTFORWARD }, - { 0x2b, KEY_F16 }, /* chapter */ - { 0x2c, KEY_PAUSE }, - { 0x2d, KEY_PLAY }, - { 0x2e, KEY_RECORD }, - { 0x2f, KEY_F17 }, /* picture in picture */ - { 0x30, KEY_KPPLUS }, /* zoom in */ - { 0x31, KEY_KPMINUS }, /* zoom out */ - { 0x32, KEY_F18 }, /* capture */ - { 0x33, KEY_F19 }, /* web */ - { 0x34, KEY_EMAIL }, - { 0x35, KEY_PHONE }, - { 0x36, KEY_PC }, -}; -DEFINE_LEGACY_IR_KEYTABLE(nebula); - -/* DigitalNow DNTV Live DVB-T Remote */ -static struct ir_scancode dntv_live_dvb_t[] = { - { 0x00, KEY_ESC }, /* 'go up a level?' */ - /* Keys 0 to 9 */ - { 0x0a, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0b, KEY_TUNER }, /* tv/fm */ - { 0x0c, KEY_SEARCH }, /* scan */ - { 0x0d, KEY_STOP }, - { 0x0e, KEY_PAUSE }, - { 0x0f, KEY_LIST }, /* source */ - - { 0x10, KEY_MUTE }, - { 0x11, KEY_REWIND }, /* backward << */ - { 0x12, KEY_POWER }, - { 0x13, KEY_CAMERA }, /* snap */ - { 0x14, KEY_AUDIO }, /* stereo */ - { 0x15, KEY_CLEAR }, /* reset */ - { 0x16, KEY_PLAY }, - { 0x17, KEY_ENTER }, - { 0x18, KEY_ZOOM }, /* full screen */ - { 0x19, KEY_FASTFORWARD }, /* forward >> */ - { 0x1a, KEY_CHANNELUP }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1c, KEY_INFO }, /* preview */ - { 0x1d, KEY_RECORD }, /* record */ - { 0x1e, KEY_CHANNELDOWN }, - { 0x1f, KEY_VOLUMEDOWN }, -}; -DEFINE_LEGACY_IR_KEYTABLE(dntv_live_dvb_t); - -/* ---------------------------------------------------------------------- */ - -/* IO-DATA BCTV7E Remote */ -static struct ir_scancode iodata_bctv7e[] = { - { 0x40, KEY_TV }, - { 0x20, KEY_RADIO }, /* FM */ - { 0x60, KEY_EPG }, - { 0x00, KEY_POWER }, - - /* Keys 0 to 9 */ - { 0x44, KEY_0 }, /* 10 */ - { 0x50, KEY_1 }, - { 0x30, KEY_2 }, - { 0x70, KEY_3 }, - { 0x48, KEY_4 }, - { 0x28, KEY_5 }, - { 0x68, KEY_6 }, - { 0x58, KEY_7 }, - { 0x38, KEY_8 }, - { 0x78, KEY_9 }, - - { 0x10, KEY_L }, /* Live */ - { 0x08, KEY_TIME }, /* Time Shift */ - - { 0x18, KEY_PLAYPAUSE }, /* Play */ - - { 0x24, KEY_ENTER }, /* 11 */ - { 0x64, KEY_ESC }, /* 12 */ - { 0x04, KEY_M }, /* Multi */ - - { 0x54, KEY_VIDEO }, - { 0x34, KEY_CHANNELUP }, - { 0x74, KEY_VOLUMEUP }, - { 0x14, KEY_MUTE }, - - { 0x4c, KEY_VCR }, /* SVIDEO */ - { 0x2c, KEY_CHANNELDOWN }, - { 0x6c, KEY_VOLUMEDOWN }, - { 0x0c, KEY_ZOOM }, - - { 0x5c, KEY_PAUSE }, - { 0x3c, KEY_RED }, /* || (red) */ - { 0x7c, KEY_RECORD }, /* recording */ - { 0x1c, KEY_STOP }, - - { 0x41, KEY_REWIND }, /* backward << */ - { 0x21, KEY_PLAY }, - { 0x61, KEY_FASTFORWARD }, /* forward >> */ - { 0x01, KEY_NEXT }, /* skip >| */ -}; -DEFINE_LEGACY_IR_KEYTABLE(iodata_bctv7e); - -/* ---------------------------------------------------------------------- */ - -/* ADS Tech Instant TV DVB-T PCI Remote */ -static struct ir_scancode adstech_dvb_t_pci[] = { - /* Keys 0 to 9 */ - { 0x4d, KEY_0 }, - { 0x57, KEY_1 }, - { 0x4f, KEY_2 }, - { 0x53, KEY_3 }, - { 0x56, KEY_4 }, - { 0x4e, KEY_5 }, - { 0x5e, KEY_6 }, - { 0x54, KEY_7 }, - { 0x4c, KEY_8 }, - { 0x5c, KEY_9 }, - - { 0x5b, KEY_POWER }, - { 0x5f, KEY_MUTE }, - { 0x55, KEY_GOTO }, - { 0x5d, KEY_SEARCH }, - { 0x17, KEY_EPG }, /* Guide */ - { 0x1f, KEY_MENU }, - { 0x0f, KEY_UP }, - { 0x46, KEY_DOWN }, - { 0x16, KEY_LEFT }, - { 0x1e, KEY_RIGHT }, - { 0x0e, KEY_SELECT }, /* Enter */ - { 0x5a, KEY_INFO }, - { 0x52, KEY_EXIT }, - { 0x59, KEY_PREVIOUS }, - { 0x51, KEY_NEXT }, - { 0x58, KEY_REWIND }, - { 0x50, KEY_FORWARD }, - { 0x44, KEY_PLAYPAUSE }, - { 0x07, KEY_STOP }, - { 0x1b, KEY_RECORD }, - { 0x13, KEY_TUNER }, /* Live */ - { 0x0a, KEY_A }, - { 0x12, KEY_B }, - { 0x03, KEY_PROG1 }, /* 1 */ - { 0x01, KEY_PROG2 }, /* 2 */ - { 0x00, KEY_PROG3 }, /* 3 */ - { 0x06, KEY_DVD }, - { 0x48, KEY_AUX }, /* Photo */ - { 0x40, KEY_VIDEO }, - { 0x19, KEY_AUDIO }, /* Music */ - { 0x0b, KEY_CHANNELUP }, - { 0x08, KEY_CHANNELDOWN }, - { 0x15, KEY_VOLUMEUP }, - { 0x1c, KEY_VOLUMEDOWN }, -}; -DEFINE_LEGACY_IR_KEYTABLE(adstech_dvb_t_pci); - -/* ---------------------------------------------------------------------- */ - -/* MSI TV@nywhere MASTER remote */ - -static struct ir_scancode msi_tvanywhere[] = { - /* Keys 0 to 9 */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0c, KEY_MUTE }, - { 0x0f, KEY_SCREEN }, /* Full Screen */ - { 0x10, KEY_FN }, /* Funtion */ - { 0x11, KEY_TIME }, /* Time shift */ - { 0x12, KEY_POWER }, - { 0x13, KEY_MEDIA }, /* MTS */ - { 0x14, KEY_SLOW }, - { 0x16, KEY_REWIND }, /* backward << */ - { 0x17, KEY_ENTER }, /* Return */ - { 0x18, KEY_FASTFORWARD }, /* forward >> */ - { 0x1a, KEY_CHANNELUP }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1e, KEY_CHANNELDOWN }, - { 0x1f, KEY_VOLUMEDOWN }, -}; -DEFINE_LEGACY_IR_KEYTABLE(msi_tvanywhere); - -/* ---------------------------------------------------------------------- */ - -/* - Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card - is marked "KS003". The controller is I2C at address 0x30, but does not seem - to respond to probes until a read is performed from a valid device. - I don't know why... - - Note: This remote may be of similar or identical design to the - Pixelview remote (?). The raw codes and duplicate button codes - appear to be the same. - - Henry Wong - Some changes to formatting and keycodes by Mark Schultz - -*/ - -static struct ir_scancode msi_tvanywhere_plus[] = { - -/* ---- Remote Button Layout ---- - - POWER SOURCE SCAN MUTE - TV/FM 1 2 3 - |> 4 5 6 - <| 7 8 9 - ^^UP 0 + RECALL - vvDN RECORD STOP PLAY - - MINIMIZE ZOOM - - CH+ - VOL- VOL+ - CH- - - SNAPSHOT MTS - - << FUNC >> RESET -*/ - - { 0x01, KEY_1 }, /* 1 */ - { 0x0b, KEY_2 }, /* 2 */ - { 0x1b, KEY_3 }, /* 3 */ - { 0x05, KEY_4 }, /* 4 */ - { 0x09, KEY_5 }, /* 5 */ - { 0x15, KEY_6 }, /* 6 */ - { 0x06, KEY_7 }, /* 7 */ - { 0x0a, KEY_8 }, /* 8 */ - { 0x12, KEY_9 }, /* 9 */ - { 0x02, KEY_0 }, /* 0 */ - { 0x10, KEY_KPPLUS }, /* + */ - { 0x13, KEY_AGAIN }, /* Recall */ - - { 0x1e, KEY_POWER }, /* Power */ - { 0x07, KEY_TUNER }, /* Source */ - { 0x1c, KEY_SEARCH }, /* Scan */ - { 0x18, KEY_MUTE }, /* Mute */ - - { 0x03, KEY_RADIO }, /* TV/FM */ - /* The next four keys are duplicates that appear to send the - same IR code as Ch+, Ch-, >>, and << . The raw code assigned - to them is the actual code + 0x20 - they will never be - detected as such unless some way is discovered to distinguish - these buttons from those that have the same code. */ - { 0x3f, KEY_RIGHT }, /* |> and Ch+ */ - { 0x37, KEY_LEFT }, /* <| and Ch- */ - { 0x2c, KEY_UP }, /* ^^Up and >> */ - { 0x24, KEY_DOWN }, /* vvDn and << */ - - { 0x00, KEY_RECORD }, /* Record */ - { 0x08, KEY_STOP }, /* Stop */ - { 0x11, KEY_PLAY }, /* Play */ - - { 0x0f, KEY_CLOSE }, /* Minimize */ - { 0x19, KEY_ZOOM }, /* Zoom */ - { 0x1a, KEY_CAMERA }, /* Snapshot */ - { 0x0d, KEY_LANGUAGE }, /* MTS */ - - { 0x14, KEY_VOLUMEDOWN }, /* Vol- */ - { 0x16, KEY_VOLUMEUP }, /* Vol+ */ - { 0x17, KEY_CHANNELDOWN }, /* Ch- */ - { 0x1f, KEY_CHANNELUP }, /* Ch+ */ - - { 0x04, KEY_REWIND }, /* << */ - { 0x0e, KEY_MENU }, /* Function */ - { 0x0c, KEY_FASTFORWARD }, /* >> */ - { 0x1d, KEY_RESTART }, /* Reset */ -}; -DEFINE_LEGACY_IR_KEYTABLE(msi_tvanywhere_plus); - -/* ---------------------------------------------------------------------- */ - -/* Cinergy 1400 DVB-T */ -static struct ir_scancode cinergy_1400[] = { - { 0x01, KEY_POWER }, - { 0x02, KEY_1 }, - { 0x03, KEY_2 }, - { 0x04, KEY_3 }, - { 0x05, KEY_4 }, - { 0x06, KEY_5 }, - { 0x07, KEY_6 }, - { 0x08, KEY_7 }, - { 0x09, KEY_8 }, - { 0x0a, KEY_9 }, - { 0x0c, KEY_0 }, - - { 0x0b, KEY_VIDEO }, - { 0x0d, KEY_REFRESH }, - { 0x0e, KEY_SELECT }, - { 0x0f, KEY_EPG }, - { 0x10, KEY_UP }, - { 0x11, KEY_LEFT }, - { 0x12, KEY_OK }, - { 0x13, KEY_RIGHT }, - { 0x14, KEY_DOWN }, - { 0x15, KEY_TEXT }, - { 0x16, KEY_INFO }, - - { 0x17, KEY_RED }, - { 0x18, KEY_GREEN }, - { 0x19, KEY_YELLOW }, - { 0x1a, KEY_BLUE }, - - { 0x1b, KEY_CHANNELUP }, - { 0x1c, KEY_VOLUMEUP }, - { 0x1d, KEY_MUTE }, - { 0x1e, KEY_VOLUMEDOWN }, - { 0x1f, KEY_CHANNELDOWN }, - - { 0x40, KEY_PAUSE }, - { 0x4c, KEY_PLAY }, - { 0x58, KEY_RECORD }, - { 0x54, KEY_PREVIOUS }, - { 0x48, KEY_STOP }, - { 0x5c, KEY_NEXT }, -}; -DEFINE_LEGACY_IR_KEYTABLE(cinergy_1400); - -/* ---------------------------------------------------------------------- */ - -/* AVERTV STUDIO 303 Remote */ -static struct ir_scancode avertv_303[] = { - { 0x2a, KEY_1 }, - { 0x32, KEY_2 }, - { 0x3a, KEY_3 }, - { 0x4a, KEY_4 }, - { 0x52, KEY_5 }, - { 0x5a, KEY_6 }, - { 0x6a, KEY_7 }, - { 0x72, KEY_8 }, - { 0x7a, KEY_9 }, - { 0x0e, KEY_0 }, - - { 0x02, KEY_POWER }, - { 0x22, KEY_VIDEO }, - { 0x42, KEY_AUDIO }, - { 0x62, KEY_ZOOM }, - { 0x0a, KEY_TV }, - { 0x12, KEY_CD }, - { 0x1a, KEY_TEXT }, - - { 0x16, KEY_SUBTITLE }, - { 0x1e, KEY_REWIND }, - { 0x06, KEY_PRINT }, - - { 0x2e, KEY_SEARCH }, - { 0x36, KEY_SLEEP }, - { 0x3e, KEY_SHUFFLE }, - { 0x26, KEY_MUTE }, - - { 0x4e, KEY_RECORD }, - { 0x56, KEY_PAUSE }, - { 0x5e, KEY_STOP }, - { 0x46, KEY_PLAY }, - - { 0x6e, KEY_RED }, - { 0x0b, KEY_GREEN }, - { 0x66, KEY_YELLOW }, - { 0x03, KEY_BLUE }, - - { 0x76, KEY_LEFT }, - { 0x7e, KEY_RIGHT }, - { 0x13, KEY_DOWN }, - { 0x1b, KEY_UP }, -}; -DEFINE_LEGACY_IR_KEYTABLE(avertv_303); - -/* ---------------------------------------------------------------------- */ - -/* DigitalNow DNTV Live! DVB-T Pro Remote */ -static struct ir_scancode dntv_live_dvbt_pro[] = { - { 0x16, KEY_POWER }, - { 0x5b, KEY_HOME }, - - { 0x55, KEY_TV }, /* live tv */ - { 0x58, KEY_TUNER }, /* digital Radio */ - { 0x5a, KEY_RADIO }, /* FM radio */ - { 0x59, KEY_DVD }, /* dvd menu */ - { 0x03, KEY_1 }, - { 0x01, KEY_2 }, - { 0x06, KEY_3 }, - { 0x09, KEY_4 }, - { 0x1d, KEY_5 }, - { 0x1f, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x19, KEY_8 }, - { 0x1b, KEY_9 }, - { 0x0c, KEY_CANCEL }, - { 0x15, KEY_0 }, - { 0x4a, KEY_CLEAR }, - { 0x13, KEY_BACK }, - { 0x00, KEY_TAB }, - { 0x4b, KEY_UP }, - { 0x4e, KEY_LEFT }, - { 0x4f, KEY_OK }, - { 0x52, KEY_RIGHT }, - { 0x51, KEY_DOWN }, - { 0x1e, KEY_VOLUMEUP }, - { 0x0a, KEY_VOLUMEDOWN }, - { 0x02, KEY_CHANNELDOWN }, - { 0x05, KEY_CHANNELUP }, - { 0x11, KEY_RECORD }, - { 0x14, KEY_PLAY }, - { 0x4c, KEY_PAUSE }, - { 0x1a, KEY_STOP }, - { 0x40, KEY_REWIND }, - { 0x12, KEY_FASTFORWARD }, - { 0x41, KEY_PREVIOUSSONG }, /* replay |< */ - { 0x42, KEY_NEXTSONG }, /* skip >| */ - { 0x54, KEY_CAMERA }, /* capture */ - { 0x50, KEY_LANGUAGE }, /* sap */ - { 0x47, KEY_TV2 }, /* pip */ - { 0x4d, KEY_SCREEN }, - { 0x43, KEY_SUBTITLE }, - { 0x10, KEY_MUTE }, - { 0x49, KEY_AUDIO }, /* l/r */ - { 0x07, KEY_SLEEP }, - { 0x08, KEY_VIDEO }, /* a/v */ - { 0x0e, KEY_PREVIOUS }, /* recall */ - { 0x45, KEY_ZOOM }, /* zoom + */ - { 0x46, KEY_ANGLE }, /* zoom - */ - { 0x56, KEY_RED }, - { 0x57, KEY_GREEN }, - { 0x5c, KEY_YELLOW }, - { 0x5d, KEY_BLUE }, -}; -DEFINE_LEGACY_IR_KEYTABLE(dntv_live_dvbt_pro); - -static struct ir_scancode em_terratec[] = { - { 0x01, KEY_CHANNEL }, - { 0x02, KEY_SELECT }, - { 0x03, KEY_MUTE }, - { 0x04, KEY_POWER }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x08, KEY_CHANNELUP }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0c, KEY_CHANNELDOWN }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_0 }, - { 0x12, KEY_MENU }, - { 0x13, KEY_PRINT }, - { 0x14, KEY_VOLUMEDOWN }, - { 0x16, KEY_PAUSE }, - { 0x18, KEY_RECORD }, - { 0x19, KEY_REWIND }, - { 0x1a, KEY_PLAY }, - { 0x1b, KEY_FORWARD }, - { 0x1c, KEY_BACKSPACE }, - { 0x1e, KEY_STOP }, - { 0x40, KEY_ZOOM }, -}; -DEFINE_LEGACY_IR_KEYTABLE(em_terratec); - -static struct ir_scancode pinnacle_grey[] = { - { 0x3a, KEY_0 }, - { 0x31, KEY_1 }, - { 0x32, KEY_2 }, - { 0x33, KEY_3 }, - { 0x34, KEY_4 }, - { 0x35, KEY_5 }, - { 0x36, KEY_6 }, - { 0x37, KEY_7 }, - { 0x38, KEY_8 }, - { 0x39, KEY_9 }, - - { 0x2f, KEY_POWER }, - - { 0x2e, KEY_P }, - { 0x1f, KEY_L }, - { 0x2b, KEY_I }, - - { 0x2d, KEY_SCREEN }, - { 0x1e, KEY_ZOOM }, - { 0x1b, KEY_VOLUMEUP }, - { 0x0f, KEY_VOLUMEDOWN }, - { 0x17, KEY_CHANNELUP }, - { 0x1c, KEY_CHANNELDOWN }, - { 0x25, KEY_INFO }, - - { 0x3c, KEY_MUTE }, - - { 0x3d, KEY_LEFT }, - { 0x3b, KEY_RIGHT }, - - { 0x3f, KEY_UP }, - { 0x3e, KEY_DOWN }, - { 0x1a, KEY_ENTER }, - - { 0x1d, KEY_MENU }, - { 0x19, KEY_AGAIN }, - { 0x16, KEY_PREVIOUSSONG }, - { 0x13, KEY_NEXTSONG }, - { 0x15, KEY_PAUSE }, - { 0x0e, KEY_REWIND }, - { 0x0d, KEY_PLAY }, - { 0x0b, KEY_STOP }, - { 0x07, KEY_FORWARD }, - { 0x27, KEY_RECORD }, - { 0x26, KEY_TUNER }, - { 0x29, KEY_TEXT }, - { 0x2a, KEY_MEDIA }, - { 0x18, KEY_EPG }, -}; -DEFINE_LEGACY_IR_KEYTABLE(pinnacle_grey); - -static struct ir_scancode flyvideo[] = { - { 0x0f, KEY_0 }, - { 0x03, KEY_1 }, - { 0x04, KEY_2 }, - { 0x05, KEY_3 }, - { 0x07, KEY_4 }, - { 0x08, KEY_5 }, - { 0x09, KEY_6 }, - { 0x0b, KEY_7 }, - { 0x0c, KEY_8 }, - { 0x0d, KEY_9 }, - - { 0x0e, KEY_MODE }, /* Air/Cable */ - { 0x11, KEY_VIDEO }, /* Video */ - { 0x15, KEY_AUDIO }, /* Audio */ - { 0x00, KEY_POWER }, /* Power */ - { 0x18, KEY_TUNER }, /* AV Source */ - { 0x02, KEY_ZOOM }, /* Fullscreen */ - { 0x1a, KEY_LANGUAGE }, /* Stereo */ - { 0x1b, KEY_MUTE }, /* Mute */ - { 0x14, KEY_VOLUMEUP }, /* Volume + */ - { 0x17, KEY_VOLUMEDOWN },/* Volume - */ - { 0x12, KEY_CHANNELUP },/* Channel + */ - { 0x13, KEY_CHANNELDOWN },/* Channel - */ - { 0x06, KEY_AGAIN }, /* Recall */ - { 0x10, KEY_ENTER }, /* Enter */ - - { 0x19, KEY_BACK }, /* Rewind ( <<< ) */ - { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ - { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ -}; -DEFINE_LEGACY_IR_KEYTABLE(flyvideo); - -static struct ir_scancode flydvb[] = { - { 0x01, KEY_ZOOM }, /* Full Screen */ - { 0x00, KEY_POWER }, /* Power */ - - { 0x03, KEY_1 }, - { 0x04, KEY_2 }, - { 0x05, KEY_3 }, - { 0x07, KEY_4 }, - { 0x08, KEY_5 }, - { 0x09, KEY_6 }, - { 0x0b, KEY_7 }, - { 0x0c, KEY_8 }, - { 0x0d, KEY_9 }, - { 0x06, KEY_AGAIN }, /* Recall */ - { 0x0f, KEY_0 }, - { 0x10, KEY_MUTE }, /* Mute */ - { 0x02, KEY_RADIO }, /* TV/Radio */ - { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */ - - { 0x14, KEY_VOLUMEUP }, /* VOL+ */ - { 0x17, KEY_VOLUMEDOWN }, /* VOL- */ - { 0x12, KEY_CHANNELUP }, /* CH+ */ - { 0x13, KEY_CHANNELDOWN }, /* CH- */ - { 0x1d, KEY_ENTER }, /* Enter */ - - { 0x1a, KEY_MODE }, /* PIP */ - { 0x18, KEY_TUNER }, /* Source */ - - { 0x1e, KEY_RECORD }, /* Record/Pause */ - { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ - { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */ - { 0x19, KEY_BACK }, /* Rewind << */ - { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */ - { 0x1f, KEY_FORWARD }, /* Forward >> */ - { 0x16, KEY_PREVIOUS }, /* Back |<< */ - { 0x11, KEY_STOP }, /* Stop */ - { 0x0e, KEY_NEXT }, /* End >>| */ -}; -DEFINE_LEGACY_IR_KEYTABLE(flydvb); - -static struct ir_scancode cinergy[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0a, KEY_POWER }, - { 0x0b, KEY_PROG1 }, /* app */ - { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ - { 0x0d, KEY_CHANNELUP }, /* channel */ - { 0x0e, KEY_CHANNELDOWN }, /* channel- */ - { 0x0f, KEY_VOLUMEUP }, - { 0x10, KEY_VOLUMEDOWN }, - { 0x11, KEY_TUNER }, /* AV */ - { 0x12, KEY_NUMLOCK }, /* -/-- */ - { 0x13, KEY_AUDIO }, /* audio */ - { 0x14, KEY_MUTE }, - { 0x15, KEY_UP }, - { 0x16, KEY_DOWN }, - { 0x17, KEY_LEFT }, - { 0x18, KEY_RIGHT }, - { 0x19, BTN_LEFT, }, - { 0x1a, BTN_RIGHT, }, - { 0x1b, KEY_WWW }, /* text */ - { 0x1c, KEY_REWIND }, - { 0x1d, KEY_FORWARD }, - { 0x1e, KEY_RECORD }, - { 0x1f, KEY_PLAY }, - { 0x20, KEY_PREVIOUSSONG }, - { 0x21, KEY_NEXTSONG }, - { 0x22, KEY_PAUSE }, - { 0x23, KEY_STOP }, -}; -DEFINE_LEGACY_IR_KEYTABLE(cinergy); - -/* Alfons Geser - * updates from Job D. R. Borges */ -static struct ir_scancode eztv[] = { - { 0x12, KEY_POWER }, - { 0x01, KEY_TV }, /* DVR */ - { 0x15, KEY_DVD }, /* DVD */ - { 0x17, KEY_AUDIO }, /* music */ - /* DVR mode / DVD mode / music mode */ - - { 0x1b, KEY_MUTE }, /* mute */ - { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */ - { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */ - { 0x16, KEY_ZOOM }, /* full screen */ - { 0x1c, KEY_VIDEO }, /* video source / eject / delall */ - { 0x1d, KEY_RESTART }, /* playback / angle / del */ - { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */ - { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */ - - { 0x31, KEY_HELP }, /* help */ - { 0x32, KEY_MODE }, /* num/memo */ - { 0x33, KEY_ESC }, /* cancel */ - - { 0x0c, KEY_UP }, /* up */ - { 0x10, KEY_DOWN }, /* down */ - { 0x08, KEY_LEFT }, /* left */ - { 0x04, KEY_RIGHT }, /* right */ - { 0x03, KEY_SELECT }, /* select */ - - { 0x1f, KEY_REWIND }, /* rewind */ - { 0x20, KEY_PLAYPAUSE },/* play/pause */ - { 0x29, KEY_FORWARD }, /* forward */ - { 0x14, KEY_AGAIN }, /* repeat */ - { 0x2b, KEY_RECORD }, /* recording */ - { 0x2c, KEY_STOP }, /* stop */ - { 0x2d, KEY_PLAY }, /* play */ - { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */ - - { 0x00, KEY_0 }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - - { 0x2a, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x18, KEY_CHANNELUP },/* CH.tracking up */ - { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */ - - { 0x13, KEY_ENTER }, /* enter */ - { 0x21, KEY_DOT }, /* . (decimal dot) */ -}; -DEFINE_LEGACY_IR_KEYTABLE(eztv); - -/* Alex Hermann */ -static struct ir_scancode avermedia[] = { - { 0x28, KEY_1 }, - { 0x18, KEY_2 }, - { 0x38, KEY_3 }, - { 0x24, KEY_4 }, - { 0x14, KEY_5 }, - { 0x34, KEY_6 }, - { 0x2c, KEY_7 }, - { 0x1c, KEY_8 }, - { 0x3c, KEY_9 }, - { 0x22, KEY_0 }, - - { 0x20, KEY_TV }, /* TV/FM */ - { 0x10, KEY_CD }, /* CD */ - { 0x30, KEY_TEXT }, /* TELETEXT */ - { 0x00, KEY_POWER }, /* POWER */ - - { 0x08, KEY_VIDEO }, /* VIDEO */ - { 0x04, KEY_AUDIO }, /* AUDIO */ - { 0x0c, KEY_ZOOM }, /* FULL SCREEN */ - - { 0x12, KEY_SUBTITLE }, /* DISPLAY */ - { 0x32, KEY_REWIND }, /* LOOP */ - { 0x02, KEY_PRINT }, /* PREVIEW */ - - { 0x2a, KEY_SEARCH }, /* AUTOSCAN */ - { 0x1a, KEY_SLEEP }, /* FREEZE */ - { 0x3a, KEY_CAMERA }, /* SNAPSHOT */ - { 0x0a, KEY_MUTE }, /* MUTE */ - - { 0x26, KEY_RECORD }, /* RECORD */ - { 0x16, KEY_PAUSE }, /* PAUSE */ - { 0x36, KEY_STOP }, /* STOP */ - { 0x06, KEY_PLAY }, /* PLAY */ - - { 0x2e, KEY_RED }, /* RED */ - { 0x21, KEY_GREEN }, /* GREEN */ - { 0x0e, KEY_YELLOW }, /* YELLOW */ - { 0x01, KEY_BLUE }, /* BLUE */ - - { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */ - { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */ - { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ - { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ -}; -DEFINE_LEGACY_IR_KEYTABLE(avermedia); - -static struct ir_scancode videomate_tv_pvr[] = { - { 0x14, KEY_MUTE }, - { 0x24, KEY_ZOOM }, - - { 0x01, KEY_DVD }, - { 0x23, KEY_RADIO }, - { 0x00, KEY_TV }, - - { 0x0a, KEY_REWIND }, - { 0x08, KEY_PLAYPAUSE }, - { 0x0f, KEY_FORWARD }, - - { 0x02, KEY_PREVIOUS }, - { 0x07, KEY_STOP }, - { 0x06, KEY_NEXT }, - - { 0x0c, KEY_UP }, - { 0x0e, KEY_DOWN }, - { 0x0b, KEY_LEFT }, - { 0x0d, KEY_RIGHT }, - { 0x11, KEY_OK }, - - { 0x03, KEY_MENU }, - { 0x09, KEY_SETUP }, - { 0x05, KEY_VIDEO }, - { 0x22, KEY_CHANNEL }, - - { 0x12, KEY_VOLUMEUP }, - { 0x15, KEY_VOLUMEDOWN }, - { 0x10, KEY_CHANNELUP }, - { 0x13, KEY_CHANNELDOWN }, - - { 0x04, KEY_RECORD }, - - { 0x16, KEY_1 }, - { 0x17, KEY_2 }, - { 0x18, KEY_3 }, - { 0x19, KEY_4 }, - { 0x1a, KEY_5 }, - { 0x1b, KEY_6 }, - { 0x1c, KEY_7 }, - { 0x1d, KEY_8 }, - { 0x1e, KEY_9 }, - { 0x1f, KEY_0 }, - - { 0x20, KEY_LANGUAGE }, - { 0x21, KEY_SLEEP }, -}; -DEFINE_LEGACY_IR_KEYTABLE(videomate_tv_pvr); - -/* Michael Tokarev - http://www.corpit.ru/mjt/beholdTV/remote_control.jpg - keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at - least, and probably other cards too. - The "ascii-art picture" below (in comments, first row - is the keycode in hex, and subsequent row(s) shows - the button labels (several variants when appropriate) - helps to descide which keycodes to assign to the buttons. - */ -static struct ir_scancode manli[] = { - - /* 0x1c 0x12 * - * FUNCTION POWER * - * FM (|) * - * */ - { 0x1c, KEY_RADIO }, /*XXX*/ - { 0x12, KEY_POWER }, - - /* 0x01 0x02 0x03 * - * 1 2 3 * - * * - * 0x04 0x05 0x06 * - * 4 5 6 * - * * - * 0x07 0x08 0x09 * - * 7 8 9 * - * */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - /* 0x0a 0x00 0x17 * - * RECALL 0 +100 * - * PLUS * - * */ - { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */ - { 0x00, KEY_0 }, - { 0x17, KEY_DIGITS }, /*XXX*/ - - /* 0x14 0x10 * - * MENU INFO * - * OSD */ - { 0x14, KEY_MENU }, - { 0x10, KEY_INFO }, - - /* 0x0b * - * Up * - * * - * 0x18 0x16 0x0c * - * Left Ok Right * - * * - * 0x015 * - * Down * - * */ - { 0x0b, KEY_UP }, - { 0x18, KEY_LEFT }, - { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */ - { 0x0c, KEY_RIGHT }, - { 0x15, KEY_DOWN }, - - /* 0x11 0x0d * - * TV/AV MODE * - * SOURCE STEREO * - * */ - { 0x11, KEY_TV }, /*XXX*/ - { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */ - - /* 0x0f 0x1b 0x1a * - * AUDIO Vol+ Chan+ * - * TIMESHIFT??? * - * * - * 0x0e 0x1f 0x1e * - * SLEEP Vol- Chan- * - * */ - { 0x0f, KEY_AUDIO }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1a, KEY_CHANNELUP }, - { 0x0e, KEY_TIME }, - { 0x1f, KEY_VOLUMEDOWN }, - { 0x1e, KEY_CHANNELDOWN }, - - /* 0x13 0x19 * - * MUTE SNAPSHOT* - * */ - { 0x13, KEY_MUTE }, - { 0x19, KEY_CAMERA }, - - /* 0x1d unused ? */ -}; -DEFINE_LEGACY_IR_KEYTABLE(manli); - -/* Mike Baikov */ -static struct ir_scancode gotview7135[] = { - - { 0x11, KEY_POWER }, - { 0x35, KEY_TV }, - { 0x1b, KEY_0 }, - { 0x29, KEY_1 }, - { 0x19, KEY_2 }, - { 0x39, KEY_3 }, - { 0x1f, KEY_4 }, - { 0x2c, KEY_5 }, - { 0x21, KEY_6 }, - { 0x24, KEY_7 }, - { 0x18, KEY_8 }, - { 0x2b, KEY_9 }, - { 0x3b, KEY_AGAIN }, /* LOOP */ - { 0x06, KEY_AUDIO }, - { 0x31, KEY_PRINT }, /* PREVIEW */ - { 0x3e, KEY_VIDEO }, - { 0x10, KEY_CHANNELUP }, - { 0x20, KEY_CHANNELDOWN }, - { 0x0c, KEY_VOLUMEDOWN }, - { 0x28, KEY_VOLUMEUP }, - { 0x08, KEY_MUTE }, - { 0x26, KEY_SEARCH }, /* SCAN */ - { 0x3f, KEY_CAMERA }, /* SNAPSHOT */ - { 0x12, KEY_RECORD }, - { 0x32, KEY_STOP }, - { 0x3c, KEY_PLAY }, - { 0x1d, KEY_REWIND }, - { 0x2d, KEY_PAUSE }, - { 0x0d, KEY_FORWARD }, - { 0x05, KEY_ZOOM }, /*FULL*/ - - { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */ - { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */ - { 0x1e, KEY_TIME }, /* TIMESHIFT */ - { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ -}; -DEFINE_LEGACY_IR_KEYTABLE(gotview7135); - -static struct ir_scancode purpletv[] = { - { 0x03, KEY_POWER }, - { 0x6f, KEY_MUTE }, - { 0x10, KEY_BACKSPACE }, /* Recall */ - - { 0x11, KEY_0 }, - { 0x04, KEY_1 }, - { 0x05, KEY_2 }, - { 0x06, KEY_3 }, - { 0x08, KEY_4 }, - { 0x09, KEY_5 }, - { 0x0a, KEY_6 }, - { 0x0c, KEY_7 }, - { 0x0d, KEY_8 }, - { 0x0e, KEY_9 }, - { 0x12, KEY_DOT }, /* 100+ */ - - { 0x07, KEY_VOLUMEUP }, - { 0x0b, KEY_VOLUMEDOWN }, - { 0x1a, KEY_KPPLUS }, - { 0x18, KEY_KPMINUS }, - { 0x15, KEY_UP }, - { 0x1d, KEY_DOWN }, - { 0x0f, KEY_CHANNELUP }, - { 0x13, KEY_CHANNELDOWN }, - { 0x48, KEY_ZOOM }, - - { 0x1b, KEY_VIDEO }, /* Video source */ - { 0x1f, KEY_CAMERA }, /* Snapshot */ - { 0x49, KEY_LANGUAGE }, /* MTS Select */ - { 0x19, KEY_SEARCH }, /* Auto Scan */ - - { 0x4b, KEY_RECORD }, - { 0x46, KEY_PLAY }, - { 0x45, KEY_PAUSE }, /* Pause */ - { 0x44, KEY_STOP }, - { 0x43, KEY_TIME }, /* Time Shift */ - { 0x17, KEY_CHANNEL }, /* SURF CH */ - { 0x40, KEY_FORWARD }, /* Forward ? */ - { 0x42, KEY_REWIND }, /* Backward ? */ - -}; -DEFINE_LEGACY_IR_KEYTABLE(purpletv); - -/* Mapping for the 28 key remote control as seen at - http://www.sednacomputer.com/photo/cardbus-tv.jpg - Pavel Mihaylov - Also for the remote bundled with Kozumi KTV-01C card */ -static struct ir_scancode pctv_sedna[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0a, KEY_AGAIN }, /* Recall */ - { 0x0b, KEY_CHANNELUP }, - { 0x0c, KEY_VOLUMEUP }, - { 0x0d, KEY_MODE }, /* Stereo */ - { 0x0e, KEY_STOP }, - { 0x0f, KEY_PREVIOUSSONG }, - { 0x10, KEY_ZOOM }, - { 0x11, KEY_TUNER }, /* Source */ - { 0x12, KEY_POWER }, - { 0x13, KEY_MUTE }, - { 0x15, KEY_CHANNELDOWN }, - { 0x18, KEY_VOLUMEDOWN }, - { 0x19, KEY_CAMERA }, /* Snapshot */ - { 0x1a, KEY_NEXTSONG }, - { 0x1b, KEY_TIME }, /* Time Shift */ - { 0x1c, KEY_RADIO }, /* FM Radio */ - { 0x1d, KEY_RECORD }, - { 0x1e, KEY_PAUSE }, - /* additional codes for Kozumi's remote */ - { 0x14, KEY_INFO }, /* OSD */ - { 0x16, KEY_OK }, /* OK */ - { 0x17, KEY_DIGITS }, /* Plus */ - { 0x1f, KEY_PLAY }, /* Play */ -}; -DEFINE_LEGACY_IR_KEYTABLE(pctv_sedna); - -/* Mark Phalan */ -static struct ir_scancode pv951[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x12, KEY_POWER }, - { 0x10, KEY_MUTE }, - { 0x1f, KEY_VOLUMEDOWN }, - { 0x1b, KEY_VOLUMEUP }, - { 0x1a, KEY_CHANNELUP }, - { 0x1e, KEY_CHANNELDOWN }, - { 0x0e, KEY_PAGEUP }, - { 0x1d, KEY_PAGEDOWN }, - { 0x13, KEY_SOUND }, - - { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */ - { 0x16, KEY_SUBTITLE }, /* CC */ - { 0x0d, KEY_TEXT }, /* TTX */ - { 0x0b, KEY_TV }, /* AIR/CBL */ - { 0x11, KEY_PC }, /* PC/TV */ - { 0x17, KEY_OK }, /* CH RTN */ - { 0x19, KEY_MODE }, /* FUNC */ - { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ - - /* Not sure what to do with these ones! */ - { 0x0f, KEY_SELECT }, /* SOURCE */ - { 0x0a, KEY_KPPLUS }, /* +100 */ - { 0x14, KEY_EQUAL }, /* SYNC */ - { 0x1c, KEY_MEDIA }, /* PC/TV */ -}; -DEFINE_LEGACY_IR_KEYTABLE(pv951); - -/* generic RC5 keytable */ -/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ -/* used by old (black) Hauppauge remotes */ -static struct ir_scancode rc5_tv[] = { - /* Keys 0 to 9 */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ - { 0x0c, KEY_POWER }, /* standby */ - { 0x0d, KEY_MUTE }, /* mute / demute */ - { 0x0f, KEY_TV }, /* display */ - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x12, KEY_BRIGHTNESSUP }, - { 0x13, KEY_BRIGHTNESSDOWN }, - { 0x1e, KEY_SEARCH }, /* search + */ - { 0x20, KEY_CHANNELUP }, /* channel / program + */ - { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x22, KEY_CHANNEL }, /* alt / channel */ - { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ - { 0x26, KEY_SLEEP }, /* sleeptimer */ - { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ - { 0x30, KEY_PAUSE }, - { 0x32, KEY_REWIND }, - { 0x33, KEY_GOTO }, - { 0x35, KEY_PLAY }, - { 0x36, KEY_STOP }, - { 0x37, KEY_RECORD }, /* recording */ - { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ - { 0x3d, KEY_SUSPEND }, /* system standby */ - -}; -DEFINE_LEGACY_IR_KEYTABLE(rc5_tv); - -/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ -static struct ir_scancode winfast[] = { - /* Keys 0 to 9 */ - { 0x12, KEY_0 }, - { 0x05, KEY_1 }, - { 0x06, KEY_2 }, - { 0x07, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0a, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x0d, KEY_7 }, - { 0x0e, KEY_8 }, - { 0x0f, KEY_9 }, - - { 0x00, KEY_POWER }, - { 0x1b, KEY_AUDIO }, /* Audio Source */ - { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ - { 0x1e, KEY_VIDEO }, /* Video Source */ - { 0x16, KEY_INFO }, /* Display information */ - { 0x04, KEY_VOLUMEUP }, - { 0x08, KEY_VOLUMEDOWN }, - { 0x0c, KEY_CHANNELUP }, - { 0x10, KEY_CHANNELDOWN }, - { 0x03, KEY_ZOOM }, /* fullscreen */ - { 0x1f, KEY_TEXT }, /* closed caption/teletext */ - { 0x20, KEY_SLEEP }, - { 0x29, KEY_CLEAR }, /* boss key */ - { 0x14, KEY_MUTE }, - { 0x2b, KEY_RED }, - { 0x2c, KEY_GREEN }, - { 0x2d, KEY_YELLOW }, - { 0x2e, KEY_BLUE }, - { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ - { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ - { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ - { 0x21, KEY_DOT }, - { 0x13, KEY_ENTER }, - { 0x11, KEY_LAST }, /* Recall (last channel */ - { 0x22, KEY_PREVIOUS }, - { 0x23, KEY_PLAYPAUSE }, - { 0x24, KEY_NEXT }, - { 0x25, KEY_TIME }, /* Time Shifting */ - { 0x26, KEY_STOP }, - { 0x27, KEY_RECORD }, - { 0x28, KEY_SAVE }, /* Screenshot */ - { 0x2f, KEY_MENU }, - { 0x30, KEY_CANCEL }, - { 0x31, KEY_CHANNEL }, /* Channel Surf */ - { 0x32, KEY_SUBTITLE }, - { 0x33, KEY_LANGUAGE }, - { 0x34, KEY_REWIND }, - { 0x35, KEY_FASTFORWARD }, - { 0x36, KEY_TV }, - { 0x37, KEY_RADIO }, /* FM */ - { 0x38, KEY_DVD }, - - { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ - { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ - { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ - { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ - { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ -}; -DEFINE_LEGACY_IR_KEYTABLE(winfast); - -static struct ir_scancode pinnacle_color[] = { - { 0x59, KEY_MUTE }, - { 0x4a, KEY_POWER }, - - { 0x18, KEY_TEXT }, - { 0x26, KEY_TV }, - { 0x3d, KEY_PRINT }, - - { 0x48, KEY_RED }, - { 0x04, KEY_GREEN }, - { 0x11, KEY_YELLOW }, - { 0x00, KEY_BLUE }, - - { 0x2d, KEY_VOLUMEUP }, - { 0x1e, KEY_VOLUMEDOWN }, - - { 0x49, KEY_MENU }, - - { 0x16, KEY_CHANNELUP }, - { 0x17, KEY_CHANNELDOWN }, - - { 0x20, KEY_UP }, - { 0x21, KEY_DOWN }, - { 0x22, KEY_LEFT }, - { 0x23, KEY_RIGHT }, - { 0x0d, KEY_SELECT }, - - { 0x08, KEY_BACK }, - { 0x07, KEY_REFRESH }, - - { 0x2f, KEY_ZOOM }, - { 0x29, KEY_RECORD }, - - { 0x4b, KEY_PAUSE }, - { 0x4d, KEY_REWIND }, - { 0x2e, KEY_PLAY }, - { 0x4e, KEY_FORWARD }, - { 0x53, KEY_PREVIOUS }, - { 0x4c, KEY_STOP }, - { 0x54, KEY_NEXT }, - - { 0x69, KEY_0 }, - { 0x6a, KEY_1 }, - { 0x6b, KEY_2 }, - { 0x6c, KEY_3 }, - { 0x6d, KEY_4 }, - { 0x6e, KEY_5 }, - { 0x6f, KEY_6 }, - { 0x70, KEY_7 }, - { 0x71, KEY_8 }, - { 0x72, KEY_9 }, - - { 0x74, KEY_CHANNEL }, - { 0x0a, KEY_BACKSPACE }, -}; -DEFINE_LEGACY_IR_KEYTABLE(pinnacle_color); - -/* Hauppauge: the newer, gray remotes (seems there are multiple - * slightly different versions), shipped with cx88+ivtv cards. - * almost rc5 coding, but some non-standard keys */ -static struct ir_scancode hauppauge_new[] = { - /* Keys 0 to 9 */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ - { 0x0b, KEY_RED }, /* red button */ - { 0x0c, KEY_RADIO }, - { 0x0d, KEY_MENU }, - { 0x0e, KEY_SUBTITLE }, /* also the # key */ - { 0x0f, KEY_MUTE }, - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x12, KEY_PREVIOUS }, /* previous channel */ - { 0x14, KEY_UP }, - { 0x15, KEY_DOWN }, - { 0x16, KEY_LEFT }, - { 0x17, KEY_RIGHT }, - { 0x18, KEY_VIDEO }, /* Videos */ - { 0x19, KEY_AUDIO }, /* Music */ - /* 0x1a: Pictures - presume this means - "Multimedia Home Platform" - - no "PICTURES" key in input.h - */ - { 0x1a, KEY_MHP }, - - { 0x1b, KEY_EPG }, /* Guide */ - { 0x1c, KEY_TV }, - { 0x1e, KEY_NEXTSONG }, /* skip >| */ - { 0x1f, KEY_EXIT }, /* back/exit */ - { 0x20, KEY_CHANNELUP }, /* channel / program + */ - { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x22, KEY_CHANNEL }, /* source (old black remote) */ - { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ - { 0x25, KEY_ENTER }, /* OK */ - { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ - { 0x29, KEY_BLUE }, /* blue key */ - { 0x2e, KEY_GREEN }, /* green button */ - { 0x30, KEY_PAUSE }, /* pause */ - { 0x32, KEY_REWIND }, /* backward << */ - { 0x34, KEY_FASTFORWARD }, /* forward >> */ - { 0x35, KEY_PLAY }, - { 0x36, KEY_STOP }, - { 0x37, KEY_RECORD }, /* recording */ - { 0x38, KEY_YELLOW }, /* yellow key */ - { 0x3b, KEY_SELECT }, /* top right button */ - { 0x3c, KEY_ZOOM }, /* full */ - { 0x3d, KEY_POWER }, /* system power (green button) */ -}; -DEFINE_LEGACY_IR_KEYTABLE(hauppauge_new); - -static struct ir_scancode npgtech[] = { - { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ - { 0x2a, KEY_FRONT }, - - { 0x3e, KEY_1 }, - { 0x02, KEY_2 }, - { 0x06, KEY_3 }, - { 0x0a, KEY_4 }, - { 0x0e, KEY_5 }, - { 0x12, KEY_6 }, - { 0x16, KEY_7 }, - { 0x1a, KEY_8 }, - { 0x1e, KEY_9 }, - { 0x3a, KEY_0 }, - { 0x22, KEY_NUMLOCK }, /* -/-- */ - { 0x20, KEY_REFRESH }, - - { 0x03, KEY_BRIGHTNESSDOWN }, - { 0x28, KEY_AUDIO }, - { 0x3c, KEY_CHANNELUP }, - { 0x3f, KEY_VOLUMEDOWN }, - { 0x2e, KEY_MUTE }, - { 0x3b, KEY_VOLUMEUP }, - { 0x00, KEY_CHANNELDOWN }, - { 0x07, KEY_BRIGHTNESSUP }, - { 0x2c, KEY_TEXT }, - - { 0x37, KEY_RECORD }, - { 0x17, KEY_PLAY }, - { 0x13, KEY_PAUSE }, - { 0x26, KEY_STOP }, - { 0x18, KEY_FASTFORWARD }, - { 0x14, KEY_REWIND }, - { 0x33, KEY_ZOOM }, - { 0x32, KEY_KEYBOARD }, - { 0x30, KEY_GOTO }, /* Pointing arrow */ - { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */ - { 0x0b, KEY_RADIO }, - { 0x10, KEY_POWER }, - -}; -DEFINE_LEGACY_IR_KEYTABLE(npgtech); - -/* Norwood Micro (non-Pro) TV Tuner - By Peter Naulls - Key comments are the functions given in the manual */ -static struct ir_scancode norwood[] = { - /* Keys 0 to 9 */ - { 0x20, KEY_0 }, - { 0x21, KEY_1 }, - { 0x22, KEY_2 }, - { 0x23, KEY_3 }, - { 0x24, KEY_4 }, - { 0x25, KEY_5 }, - { 0x26, KEY_6 }, - { 0x27, KEY_7 }, - { 0x28, KEY_8 }, - { 0x29, KEY_9 }, - - { 0x78, KEY_TUNER }, /* Video Source */ - { 0x2c, KEY_EXIT }, /* Open/Close software */ - { 0x2a, KEY_SELECT }, /* 2 Digit Select */ - { 0x69, KEY_AGAIN }, /* Recall */ - - { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */ - { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */ - { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */ - { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */ - - { 0x2d, KEY_MUTE }, /* Mute */ - { 0x30, KEY_VOLUMEUP }, /* Volume up */ - { 0x31, KEY_VOLUMEDOWN }, /* Volume down */ - { 0x60, KEY_CHANNELUP }, /* Channel up */ - { 0x61, KEY_CHANNELDOWN }, /* Channel down */ - - { 0x3f, KEY_RECORD }, /* Record */ - { 0x37, KEY_PLAY }, /* Play */ - { 0x36, KEY_PAUSE }, /* Pause */ - { 0x2b, KEY_STOP }, /* Stop */ - { 0x67, KEY_FASTFORWARD }, /* Foward */ - { 0x66, KEY_REWIND }, /* Rewind */ - { 0x3e, KEY_SEARCH }, /* Auto Scan */ - { 0x2e, KEY_CAMERA }, /* Capture Video */ - { 0x6d, KEY_MENU }, /* Show/Hide Control */ - { 0x2f, KEY_ZOOM }, /* Full Screen */ - { 0x34, KEY_RADIO }, /* FM */ - { 0x65, KEY_POWER }, /* Computer power */ -}; -DEFINE_LEGACY_IR_KEYTABLE(norwood); - -/* From reading the following remotes: - * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 - * Hauppauge (from NOVA-CI-s box product) - * This is a "middle of the road" approach, differences are noted - */ -static struct ir_scancode budget_ci_old[] = { - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0a, KEY_ENTER }, - { 0x0b, KEY_RED }, - { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */ - { 0x0d, KEY_MUTE }, - { 0x0f, KEY_A }, /* TV on Hauppauge */ - { 0x10, KEY_VOLUMEUP }, - { 0x11, KEY_VOLUMEDOWN }, - { 0x14, KEY_B }, - { 0x1c, KEY_UP }, - { 0x1d, KEY_DOWN }, - { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */ - { 0x1f, KEY_BREAK }, - { 0x20, KEY_CHANNELUP }, - { 0x21, KEY_CHANNELDOWN }, - { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */ - { 0x24, KEY_RESTART }, - { 0x25, KEY_OK }, - { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */ - { 0x28, KEY_ENTER }, /* VCR mode on Zenith */ - { 0x29, KEY_PAUSE }, - { 0x2b, KEY_RIGHT }, - { 0x2c, KEY_LEFT }, - { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */ - { 0x30, KEY_SLOW }, - { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */ - { 0x32, KEY_REWIND }, - { 0x34, KEY_FASTFORWARD }, - { 0x35, KEY_PLAY }, - { 0x36, KEY_STOP }, - { 0x37, KEY_RECORD }, - { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */ - { 0x3a, KEY_C }, - { 0x3c, KEY_EXIT }, - { 0x3d, KEY_POWER2 }, - { 0x3e, KEY_TUNER }, -}; -DEFINE_LEGACY_IR_KEYTABLE(budget_ci_old); - -/* - * Marc Fargas - * this is the remote control that comes with the asus p7131 - * which has a label saying is "Model PC-39" - */ -static struct ir_scancode asus_pc39[] = { - /* Keys 0 to 9 */ - { 0x15, KEY_0 }, - { 0x29, KEY_1 }, - { 0x2d, KEY_2 }, - { 0x2b, KEY_3 }, - { 0x09, KEY_4 }, - { 0x0d, KEY_5 }, - { 0x0b, KEY_6 }, - { 0x31, KEY_7 }, - { 0x35, KEY_8 }, - { 0x33, KEY_9 }, - - { 0x3e, KEY_RADIO }, /* radio */ - { 0x03, KEY_MENU }, /* dvd/menu */ - { 0x2a, KEY_VOLUMEUP }, - { 0x19, KEY_VOLUMEDOWN }, - { 0x37, KEY_UP }, - { 0x3b, KEY_DOWN }, - { 0x27, KEY_LEFT }, - { 0x2f, KEY_RIGHT }, - { 0x25, KEY_VIDEO }, /* video */ - { 0x39, KEY_AUDIO }, /* music */ - - { 0x21, KEY_TV }, /* tv */ - { 0x1d, KEY_EXIT }, /* back */ - { 0x0a, KEY_CHANNELUP }, /* channel / program + */ - { 0x1b, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x1a, KEY_ENTER }, /* enter */ - - { 0x06, KEY_PAUSE }, /* play/pause */ - { 0x1e, KEY_PREVIOUS }, /* rew */ - { 0x26, KEY_NEXT }, /* forward */ - { 0x0e, KEY_REWIND }, /* backward << */ - { 0x3a, KEY_FASTFORWARD }, /* forward >> */ - { 0x36, KEY_STOP }, - { 0x2e, KEY_RECORD }, /* recording */ - { 0x16, KEY_POWER }, /* the button that reads "close" */ - - { 0x11, KEY_ZOOM }, /* full screen */ - { 0x13, KEY_MACRO }, /* recall */ - { 0x23, KEY_HOME }, /* home */ - { 0x05, KEY_PVR }, /* picture */ - { 0x3d, KEY_MUTE }, /* mute */ - { 0x01, KEY_DVD }, /* dvd */ -}; -DEFINE_LEGACY_IR_KEYTABLE(asus_pc39); - -/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons - Juan Pablo Sormani */ -static struct ir_scancode encore_enltv[] = { - - /* Power button does nothing, neither in Windows app, - although it sends data (used for BIOS wakeup?) */ - { 0x0d, KEY_MUTE }, - - { 0x1e, KEY_TV }, - { 0x00, KEY_VIDEO }, - { 0x01, KEY_AUDIO }, /* music */ - { 0x02, KEY_MHP }, /* picture */ - - { 0x1f, KEY_1 }, - { 0x03, KEY_2 }, - { 0x04, KEY_3 }, - { 0x05, KEY_4 }, - { 0x1c, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x1d, KEY_9 }, - { 0x0a, KEY_0 }, - - { 0x09, KEY_LIST }, /* -/-- */ - { 0x0b, KEY_LAST }, /* recall */ - - { 0x14, KEY_HOME }, /* win start menu */ - { 0x15, KEY_EXIT }, /* exit */ - { 0x16, KEY_CHANNELUP }, /* UP */ - { 0x12, KEY_CHANNELDOWN }, /* DOWN */ - { 0x0c, KEY_VOLUMEUP }, /* RIGHT */ - { 0x17, KEY_VOLUMEDOWN }, /* LEFT */ - - { 0x18, KEY_ENTER }, /* OK */ - - { 0x0e, KEY_ESC }, - { 0x13, KEY_CYCLEWINDOWS }, /* desktop */ - { 0x11, KEY_TAB }, - { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */ - - { 0x1a, KEY_MENU }, - { 0x1b, KEY_ZOOM }, /* fullscreen */ - { 0x44, KEY_TIME }, /* time shift */ - { 0x40, KEY_MODE }, /* source */ - - { 0x5a, KEY_RECORD }, - { 0x42, KEY_PLAY }, /* play/pause */ - { 0x45, KEY_STOP }, - { 0x43, KEY_CAMERA }, /* camera icon */ - - { 0x48, KEY_REWIND }, - { 0x4a, KEY_FASTFORWARD }, - { 0x49, KEY_PREVIOUS }, - { 0x4b, KEY_NEXT }, - - { 0x4c, KEY_FAVORITES }, /* tv wall */ - { 0x4d, KEY_SOUND }, /* DVD sound */ - { 0x4e, KEY_LANGUAGE }, /* DVD lang */ - { 0x4f, KEY_TEXT }, /* DVD text */ - - { 0x50, KEY_SLEEP }, /* shutdown */ - { 0x51, KEY_MODE }, /* stereo > main */ - { 0x52, KEY_SELECT }, /* stereo > sap */ - { 0x53, KEY_PROG1 }, /* teletext */ - - - { 0x59, KEY_RED }, /* AP1 */ - { 0x41, KEY_GREEN }, /* AP2 */ - { 0x47, KEY_YELLOW }, /* AP3 */ - { 0x57, KEY_BLUE }, /* AP4 */ -}; -DEFINE_LEGACY_IR_KEYTABLE(encore_enltv); - -/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton - Mauro Carvalho Chehab */ -static struct ir_scancode encore_enltv2[] = { - { 0x4c, KEY_POWER2 }, - { 0x4a, KEY_TUNER }, - { 0x40, KEY_1 }, - { 0x60, KEY_2 }, - { 0x50, KEY_3 }, - { 0x70, KEY_4 }, - { 0x48, KEY_5 }, - { 0x68, KEY_6 }, - { 0x58, KEY_7 }, - { 0x78, KEY_8 }, - { 0x44, KEY_9 }, - { 0x54, KEY_0 }, - - { 0x64, KEY_LAST }, /* +100 */ - { 0x4e, KEY_AGAIN }, /* Recall */ - - { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ - { 0x5e, KEY_MENU }, - { 0x56, KEY_SCREEN }, - { 0x7a, KEY_SETUP }, - - { 0x46, KEY_MUTE }, - { 0x5c, KEY_MODE }, /* Stereo */ - { 0x74, KEY_INFO }, - { 0x7c, KEY_CLEAR }, - - { 0x55, KEY_UP }, - { 0x49, KEY_DOWN }, - { 0x7e, KEY_LEFT }, - { 0x59, KEY_RIGHT }, - { 0x6a, KEY_ENTER }, - - { 0x42, KEY_VOLUMEUP }, - { 0x62, KEY_VOLUMEDOWN }, - { 0x52, KEY_CHANNELUP }, - { 0x72, KEY_CHANNELDOWN }, - - { 0x41, KEY_RECORD }, - { 0x51, KEY_CAMERA }, /* Snapshot */ - { 0x75, KEY_TIME }, /* Timeshift */ - { 0x71, KEY_TV2 }, /* PIP */ - - { 0x45, KEY_REWIND }, - { 0x6f, KEY_PAUSE }, - { 0x7d, KEY_FORWARD }, - { 0x79, KEY_STOP }, -}; -DEFINE_LEGACY_IR_KEYTABLE(encore_enltv2); - -/* for the Technotrend 1500 bundled remotes (grey and black): */ -static struct ir_scancode tt_1500[] = { - { 0x01, KEY_POWER }, - { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ - { 0x03, KEY_1 }, - { 0x04, KEY_2 }, - { 0x05, KEY_3 }, - { 0x06, KEY_4 }, - { 0x07, KEY_5 }, - { 0x08, KEY_6 }, - { 0x09, KEY_7 }, - { 0x0a, KEY_8 }, - { 0x0b, KEY_9 }, - { 0x0c, KEY_0 }, - { 0x0d, KEY_UP }, - { 0x0e, KEY_LEFT }, - { 0x0f, KEY_OK }, - { 0x10, KEY_RIGHT }, - { 0x11, KEY_DOWN }, - { 0x12, KEY_INFO }, - { 0x13, KEY_EXIT }, - { 0x14, KEY_RED }, - { 0x15, KEY_GREEN }, - { 0x16, KEY_YELLOW }, - { 0x17, KEY_BLUE }, - { 0x18, KEY_MUTE }, - { 0x19, KEY_TEXT }, - { 0x1a, KEY_MODE }, /* ? TV/Radio */ - { 0x21, KEY_OPTION }, - { 0x22, KEY_EPG }, - { 0x23, KEY_CHANNELUP }, - { 0x24, KEY_CHANNELDOWN }, - { 0x25, KEY_VOLUMEUP }, - { 0x26, KEY_VOLUMEDOWN }, - { 0x27, KEY_SETUP }, - { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ - { 0x3b, KEY_PLAY }, - { 0x3c, KEY_STOP }, - { 0x3d, KEY_REWIND }, - { 0x3e, KEY_PAUSE }, - { 0x3f, KEY_FORWARD }, -}; -DEFINE_LEGACY_IR_KEYTABLE(tt_1500); - -/* DViCO FUSION HDTV MCE remote */ -static struct ir_scancode fusionhdtv_mce[] = { - - { 0x0b, KEY_1 }, - { 0x17, KEY_2 }, - { 0x1b, KEY_3 }, - { 0x07, KEY_4 }, - { 0x50, KEY_5 }, - { 0x54, KEY_6 }, - { 0x48, KEY_7 }, - { 0x4c, KEY_8 }, - { 0x58, KEY_9 }, - { 0x03, KEY_0 }, - - { 0x5e, KEY_OK }, - { 0x51, KEY_UP }, - { 0x53, KEY_DOWN }, - { 0x5b, KEY_LEFT }, - { 0x5f, KEY_RIGHT }, - - { 0x02, KEY_TV }, /* Labeled DTV on remote */ - { 0x0e, KEY_MP3 }, - { 0x1a, KEY_DVD }, - { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */ - { 0x16, KEY_SETUP }, - { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */ - { 0x0a, KEY_EPG }, /* Labeled Guide on remote */ - - { 0x49, KEY_BACK }, - { 0x59, KEY_INFO }, /* Labeled MORE on remote */ - { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */ - { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */ - - { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */ - { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */ - { 0x42, KEY_ENTER }, /* Labeled START with a green - MS windows logo on remote */ - - { 0x15, KEY_VOLUMEUP }, - { 0x05, KEY_VOLUMEDOWN }, - { 0x11, KEY_CHANNELUP }, - { 0x09, KEY_CHANNELDOWN }, - - { 0x52, KEY_CAMERA }, - { 0x5a, KEY_TUNER }, - { 0x19, KEY_OPEN }, - - { 0x13, KEY_MODE }, /* 4:3 16:9 select */ - { 0x1f, KEY_ZOOM }, - - { 0x43, KEY_REWIND }, - { 0x47, KEY_PLAYPAUSE }, - { 0x4f, KEY_FASTFORWARD }, - { 0x57, KEY_MUTE }, - { 0x0d, KEY_STOP }, - { 0x01, KEY_RECORD }, - { 0x4e, KEY_POWER }, -}; -DEFINE_LEGACY_IR_KEYTABLE(fusionhdtv_mce); - -/* Pinnacle PCTV HD 800i mini remote */ -static struct ir_scancode pinnacle_pctv_hd[] = { - - { 0x0f, KEY_1 }, - { 0x15, KEY_2 }, - { 0x10, KEY_3 }, - { 0x18, KEY_4 }, - { 0x1b, KEY_5 }, - { 0x1e, KEY_6 }, - { 0x11, KEY_7 }, - { 0x21, KEY_8 }, - { 0x12, KEY_9 }, - { 0x27, KEY_0 }, - - { 0x24, KEY_ZOOM }, - { 0x2a, KEY_SUBTITLE }, - - { 0x00, KEY_MUTE }, - { 0x01, KEY_ENTER }, /* Pinnacle Logo */ - { 0x39, KEY_POWER }, - - { 0x03, KEY_VOLUMEUP }, - { 0x09, KEY_VOLUMEDOWN }, - { 0x06, KEY_CHANNELUP }, - { 0x0c, KEY_CHANNELDOWN }, - - { 0x2d, KEY_REWIND }, - { 0x30, KEY_PLAYPAUSE }, - { 0x33, KEY_FASTFORWARD }, - { 0x3c, KEY_STOP }, - { 0x36, KEY_RECORD }, - { 0x3f, KEY_EPG }, /* Labeled "?" */ -}; -DEFINE_LEGACY_IR_KEYTABLE(pinnacle_pctv_hd); - -/* - * Igor Kuznetsov - * Andrey J. Melnikov - * - * Keytable is used by BeholdTV 60x series, M6 series at - * least, and probably other cards too. - * The "ascii-art picture" below (in comments, first row - * is the keycode in hex, and subsequent row(s) shows - * the button labels (several variants when appropriate) - * helps to descide which keycodes to assign to the buttons. - */ -static struct ir_scancode behold[] = { - - /* 0x1c 0x12 * - * TV/FM POWER * - * */ - { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ - { 0x12, KEY_POWER }, - - /* 0x01 0x02 0x03 * - * 1 2 3 * - * * - * 0x04 0x05 0x06 * - * 4 5 6 * - * * - * 0x07 0x08 0x09 * - * 7 8 9 * - * */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - - /* 0x0a 0x00 0x17 * - * RECALL 0 MODE * - * */ - { 0x0a, KEY_AGAIN }, - { 0x00, KEY_0 }, - { 0x17, KEY_MODE }, - - /* 0x14 0x10 * - * ASPECT FULLSCREEN * - * */ - { 0x14, KEY_SCREEN }, - { 0x10, KEY_ZOOM }, - - /* 0x0b * - * Up * - * * - * 0x18 0x16 0x0c * - * Left Ok Right * - * * - * 0x015 * - * Down * - * */ - { 0x0b, KEY_CHANNELUP }, - { 0x18, KEY_VOLUMEDOWN }, - { 0x16, KEY_OK }, /* XXX KEY_ENTER */ - { 0x0c, KEY_VOLUMEUP }, - { 0x15, KEY_CHANNELDOWN }, - - /* 0x11 0x0d * - * MUTE INFO * - * */ - { 0x11, KEY_MUTE }, - { 0x0d, KEY_INFO }, - - /* 0x0f 0x1b 0x1a * - * RECORD PLAY/PAUSE STOP * - * * - * 0x0e 0x1f 0x1e * - *TELETEXT AUDIO SOURCE * - * RED YELLOW * - * */ - { 0x0f, KEY_RECORD }, - { 0x1b, KEY_PLAYPAUSE }, - { 0x1a, KEY_STOP }, - { 0x0e, KEY_TEXT }, - { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ - { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ - - /* 0x1d 0x13 0x19 * - * SLEEP PREVIEW DVB * - * GREEN BLUE * - * */ - { 0x1d, KEY_SLEEP }, - { 0x13, KEY_GREEN }, - { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ - - /* 0x58 0x5c * - * FREEZE SNAPSHOT * - * */ - { 0x58, KEY_SLOW }, - { 0x5c, KEY_CAMERA }, - -}; -DEFINE_LEGACY_IR_KEYTABLE(behold); - -/* Beholder Intl. Ltd. 2008 - * Dmitry Belimov d.belimov@google.com - * Keytable is used by BeholdTV Columbus - * The "ascii-art picture" below (in comments, first row - * is the keycode in hex, and subsequent row(s) shows - * the button labels (several variants when appropriate) - * helps to descide which keycodes to assign to the buttons. - */ -static struct ir_scancode behold_columbus[] = { - - /* 0x13 0x11 0x1C 0x12 * - * Mute Source TV/FM Power * - * */ - - { 0x13, KEY_MUTE }, - { 0x11, KEY_PROPS }, - { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ - { 0x12, KEY_POWER }, - - /* 0x01 0x02 0x03 0x0D * - * 1 2 3 Stereo * - * * - * 0x04 0x05 0x06 0x19 * - * 4 5 6 Snapshot * - * * - * 0x07 0x08 0x09 0x10 * - * 7 8 9 Zoom * - * */ - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x0D, KEY_SETUP }, /* Setup key */ - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x19, KEY_CAMERA }, /* Snapshot key */ - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x10, KEY_ZOOM }, - - /* 0x0A 0x00 0x0B 0x0C * - * RECALL 0 ChannelUp VolumeUp * - * */ - { 0x0A, KEY_AGAIN }, - { 0x00, KEY_0 }, - { 0x0B, KEY_CHANNELUP }, - { 0x0C, KEY_VOLUMEUP }, - - /* 0x1B 0x1D 0x15 0x18 * - * Timeshift Record ChannelDown VolumeDown * - * */ - - { 0x1B, KEY_TIME }, - { 0x1D, KEY_RECORD }, - { 0x15, KEY_CHANNELDOWN }, - { 0x18, KEY_VOLUMEDOWN }, - - /* 0x0E 0x1E 0x0F 0x1A * - * Stop Pause Previouse Next * - * */ - - { 0x0E, KEY_STOP }, - { 0x1E, KEY_PAUSE }, - { 0x0F, KEY_PREVIOUS }, - { 0x1A, KEY_NEXT }, - -}; -DEFINE_LEGACY_IR_KEYTABLE(behold_columbus); - -/* - * Remote control for the Genius TVGO A11MCE - * Adrian Pardini - */ -static struct ir_scancode genius_tvgo_a11mce[] = { - /* Keys 0 to 9 */ - { 0x48, KEY_0 }, - { 0x09, KEY_1 }, - { 0x1d, KEY_2 }, - { 0x1f, KEY_3 }, - { 0x19, KEY_4 }, - { 0x1b, KEY_5 }, - { 0x11, KEY_6 }, - { 0x17, KEY_7 }, - { 0x12, KEY_8 }, - { 0x16, KEY_9 }, - - { 0x54, KEY_RECORD }, /* recording */ - { 0x06, KEY_MUTE }, /* mute */ - { 0x10, KEY_POWER }, - { 0x40, KEY_LAST }, /* recall */ - { 0x4c, KEY_CHANNELUP }, /* channel / program + */ - { 0x00, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x0d, KEY_VOLUMEUP }, - { 0x15, KEY_VOLUMEDOWN }, - { 0x4d, KEY_OK }, /* also labeled as Pause */ - { 0x1c, KEY_ZOOM }, /* full screen and Stop*/ - { 0x02, KEY_MODE }, /* AV Source or Rewind*/ - { 0x04, KEY_LIST }, /* -/-- */ - /* small arrows above numbers */ - { 0x1a, KEY_NEXT }, /* also Fast Forward */ - { 0x0e, KEY_PREVIOUS }, /* also Rewind */ - /* these are in a rather non standard layout and have - an alternate name written */ - { 0x1e, KEY_UP }, /* Video Setting */ - { 0x0a, KEY_DOWN }, /* Video Default */ - { 0x05, KEY_CAMERA }, /* Snapshot */ - { 0x0c, KEY_RIGHT }, /* Hide Panel */ - /* Four buttons without label */ - { 0x49, KEY_RED }, - { 0x0b, KEY_GREEN }, - { 0x13, KEY_YELLOW }, - { 0x50, KEY_BLUE }, -}; -DEFINE_LEGACY_IR_KEYTABLE(genius_tvgo_a11mce); - -/* - * Remote control for Powercolor Real Angel 330 - * Daniel Fraga - */ -static struct ir_scancode powercolor_real_angel[] = { - { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ - { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ - { 0x00, KEY_0 }, - { 0x01, KEY_1 }, - { 0x02, KEY_2 }, - { 0x03, KEY_3 }, - { 0x04, KEY_4 }, - { 0x05, KEY_5 }, - { 0x06, KEY_6 }, - { 0x07, KEY_7 }, - { 0x08, KEY_8 }, - { 0x09, KEY_9 }, - { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */ - { 0x29, KEY_PREVIOUS }, /* previous channel */ - { 0x12, KEY_BRIGHTNESSUP }, - { 0x13, KEY_BRIGHTNESSDOWN }, - { 0x2b, KEY_MODE }, /* stereo/mono */ - { 0x2c, KEY_TEXT }, /* teletext */ - { 0x20, KEY_CHANNELUP }, /* channel up */ - { 0x21, KEY_CHANNELDOWN }, /* channel down */ - { 0x10, KEY_VOLUMEUP }, /* volume up */ - { 0x11, KEY_VOLUMEDOWN }, /* volume down */ - { 0x0d, KEY_MUTE }, - { 0x1f, KEY_RECORD }, - { 0x17, KEY_PLAY }, - { 0x16, KEY_PAUSE }, - { 0x0b, KEY_STOP }, - { 0x27, KEY_FASTFORWARD }, - { 0x26, KEY_REWIND }, - { 0x1e, KEY_SEARCH }, /* autoscan */ - { 0x0e, KEY_CAMERA }, /* snapshot */ - { 0x2d, KEY_SETUP }, - { 0x0f, KEY_SCREEN }, /* full screen */ - { 0x14, KEY_RADIO }, /* FM radio */ - { 0x25, KEY_POWER }, /* power */ -}; -DEFINE_LEGACY_IR_KEYTABLE(powercolor_real_angel); - -/* Kworld Plus TV Analog Lite PCI IR - Mauro Carvalho Chehab - */ -static struct ir_scancode kworld_plus_tv_analog[] = { - { 0x0c, KEY_PROG1 }, /* Kworld key */ - { 0x16, KEY_CLOSECD }, /* -> ) */ - { 0x1d, KEY_POWER2 }, - - { 0x00, KEY_1 }, - { 0x01, KEY_2 }, - { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */ - { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */ - { 0x04, KEY_5 }, - { 0x05, KEY_6 }, - { 0x06, KEY_7 }, - { 0x07, KEY_8 }, - { 0x08, KEY_9 }, - { 0x0a, KEY_0 }, - - { 0x09, KEY_AGAIN }, - { 0x14, KEY_MUTE }, - - { 0x20, KEY_UP }, - { 0x21, KEY_DOWN }, - { 0x0b, KEY_ENTER }, - - { 0x10, KEY_CHANNELUP }, - { 0x11, KEY_CHANNELDOWN }, - - /* Couldn't map key left/key right since those - conflict with '3' and '4' scancodes - I dunno what the original driver does - */ - - { 0x13, KEY_VOLUMEUP }, - { 0x12, KEY_VOLUMEDOWN }, - - /* The lower part of the IR - There are several duplicated keycodes there. - Most of them conflict with digits. - Add mappings just to the unused scancodes. - Somehow, the original driver has a way to know, - but this doesn't seem to be on some GPIO. - Also, it is not related to the time between keyup - and keydown. - */ - { 0x19, KEY_TIME}, /* Timeshift */ - { 0x1a, KEY_STOP}, - { 0x1b, KEY_RECORD}, - - { 0x22, KEY_TEXT}, - - { 0x15, KEY_AUDIO}, /* ((*)) */ - { 0x0f, KEY_ZOOM}, - { 0x1c, KEY_CAMERA}, /* snapshot */ - - { 0x18, KEY_RED}, /* B */ - { 0x23, KEY_GREEN}, /* C */ -}; -DEFINE_LEGACY_IR_KEYTABLE(kworld_plus_tv_analog); - -/* Kaiomy TVnPC U2 - Mauro Carvalho Chehab - */ -static struct ir_scancode kaiomy[] = { - { 0x43, KEY_POWER2}, - { 0x01, KEY_LIST}, - { 0x0b, KEY_ZOOM}, - { 0x03, KEY_POWER}, - - { 0x04, KEY_1}, - { 0x08, KEY_2}, - { 0x02, KEY_3}, - - { 0x0f, KEY_4}, - { 0x05, KEY_5}, - { 0x06, KEY_6}, - - { 0x0c, KEY_7}, - { 0x0d, KEY_8}, - { 0x0a, KEY_9}, - - { 0x11, KEY_0}, - - { 0x09, KEY_CHANNELUP}, - { 0x07, KEY_CHANNELDOWN}, - - { 0x0e, KEY_VOLUMEUP}, - { 0x13, KEY_VOLUMEDOWN}, - - { 0x10, KEY_HOME}, - { 0x12, KEY_ENTER}, - - { 0x14, KEY_RECORD}, - { 0x15, KEY_STOP}, - { 0x16, KEY_PLAY}, - { 0x17, KEY_MUTE}, - - { 0x18, KEY_UP}, - { 0x19, KEY_DOWN}, - { 0x1a, KEY_LEFT}, - { 0x1b, KEY_RIGHT}, - - { 0x1c, KEY_RED}, - { 0x1d, KEY_GREEN}, - { 0x1e, KEY_YELLOW}, - { 0x1f, KEY_BLUE}, -}; -DEFINE_LEGACY_IR_KEYTABLE(kaiomy); - -static struct ir_scancode avermedia_a16d[] = { - { 0x20, KEY_LIST}, - { 0x00, KEY_POWER}, - { 0x28, KEY_1}, - { 0x18, KEY_2}, - { 0x38, KEY_3}, - { 0x24, KEY_4}, - { 0x14, KEY_5}, - { 0x34, KEY_6}, - { 0x2c, KEY_7}, - { 0x1c, KEY_8}, - { 0x3c, KEY_9}, - { 0x12, KEY_SUBTITLE}, - { 0x22, KEY_0}, - { 0x32, KEY_REWIND}, - { 0x3a, KEY_SHUFFLE}, - { 0x02, KEY_PRINT}, - { 0x11, KEY_CHANNELDOWN}, - { 0x31, KEY_CHANNELUP}, - { 0x0c, KEY_ZOOM}, - { 0x1e, KEY_VOLUMEDOWN}, - { 0x3e, KEY_VOLUMEUP}, - { 0x0a, KEY_MUTE}, - { 0x04, KEY_AUDIO}, - { 0x26, KEY_RECORD}, - { 0x06, KEY_PLAY}, - { 0x36, KEY_STOP}, - { 0x16, KEY_PAUSE}, - { 0x2e, KEY_REWIND}, - { 0x0e, KEY_FASTFORWARD}, - { 0x30, KEY_TEXT}, - { 0x21, KEY_GREEN}, - { 0x01, KEY_BLUE}, - { 0x08, KEY_EPG}, - { 0x2a, KEY_MENU}, -}; -DEFINE_LEGACY_IR_KEYTABLE(avermedia_a16d); - -/* Encore ENLTV-FM v5.3 - Mauro Carvalho Chehab - */ -static struct ir_scancode encore_enltv_fm53[] = { - { 0x10, KEY_POWER2}, - { 0x06, KEY_MUTE}, - - { 0x09, KEY_1}, - { 0x1d, KEY_2}, - { 0x1f, KEY_3}, - { 0x19, KEY_4}, - { 0x1b, KEY_5}, - { 0x11, KEY_6}, - { 0x17, KEY_7}, - { 0x12, KEY_8}, - { 0x16, KEY_9}, - { 0x48, KEY_0}, - - { 0x04, KEY_LIST}, /* -/-- */ - { 0x40, KEY_LAST}, /* recall */ - - { 0x02, KEY_MODE}, /* TV/AV */ - { 0x05, KEY_CAMERA}, /* SNAPSHOT */ - - { 0x4c, KEY_CHANNELUP}, /* UP */ - { 0x00, KEY_CHANNELDOWN}, /* DOWN */ - { 0x0d, KEY_VOLUMEUP}, /* RIGHT */ - { 0x15, KEY_VOLUMEDOWN}, /* LEFT */ - { 0x49, KEY_ENTER}, /* OK */ - - { 0x54, KEY_RECORD}, - { 0x4d, KEY_PLAY}, /* pause */ - - { 0x1e, KEY_MENU}, /* video setting */ - { 0x0e, KEY_RIGHT}, /* <- */ - { 0x1a, KEY_LEFT}, /* -> */ - - { 0x0a, KEY_CLEAR}, /* video default */ - { 0x0c, KEY_ZOOM}, /* hide pannel */ - { 0x47, KEY_SLEEP}, /* shutdown */ -}; -DEFINE_LEGACY_IR_KEYTABLE(encore_enltv_fm53); - -/* Zogis Real Audio 220 - 32 keys IR */ -static struct ir_scancode real_audio_220_32_keys[] = { - { 0x1c, KEY_RADIO}, - { 0x12, KEY_POWER2}, - - { 0x01, KEY_1}, - { 0x02, KEY_2}, - { 0x03, KEY_3}, - { 0x04, KEY_4}, - { 0x05, KEY_5}, - { 0x06, KEY_6}, - { 0x07, KEY_7}, - { 0x08, KEY_8}, - { 0x09, KEY_9}, - { 0x00, KEY_0}, - - { 0x0c, KEY_VOLUMEUP}, - { 0x18, KEY_VOLUMEDOWN}, - { 0x0b, KEY_CHANNELUP}, - { 0x15, KEY_CHANNELDOWN}, - { 0x16, KEY_ENTER}, - - { 0x11, KEY_LIST}, /* Source */ - { 0x0d, KEY_AUDIO}, /* stereo */ - - { 0x0f, KEY_PREVIOUS}, /* Prev */ - { 0x1b, KEY_TIME}, /* Timeshift */ - { 0x1a, KEY_NEXT}, /* Next */ - - { 0x0e, KEY_STOP}, - { 0x1f, KEY_PLAY}, - { 0x1e, KEY_PLAYPAUSE}, /* Pause */ - - { 0x1d, KEY_RECORD}, - { 0x13, KEY_MUTE}, - { 0x19, KEY_CAMERA}, /* Snapshot */ - -}; -DEFINE_LEGACY_IR_KEYTABLE(real_audio_220_32_keys); - -/* ATI TV Wonder HD 600 USB - Devin Heitmueller - */ -static struct ir_scancode ati_tv_wonder_hd_600[] = { - { 0x00, KEY_RECORD}, /* Row 1 */ - { 0x01, KEY_PLAYPAUSE}, - { 0x02, KEY_STOP}, - { 0x03, KEY_POWER}, - { 0x04, KEY_PREVIOUS}, /* Row 2 */ - { 0x05, KEY_REWIND}, - { 0x06, KEY_FORWARD}, - { 0x07, KEY_NEXT}, - { 0x08, KEY_EPG}, /* Row 3 */ - { 0x09, KEY_HOME}, - { 0x0a, KEY_MENU}, - { 0x0b, KEY_CHANNELUP}, - { 0x0c, KEY_BACK}, /* Row 4 */ - { 0x0d, KEY_UP}, - { 0x0e, KEY_INFO}, - { 0x0f, KEY_CHANNELDOWN}, - { 0x10, KEY_LEFT}, /* Row 5 */ - { 0x11, KEY_SELECT}, - { 0x12, KEY_RIGHT}, - { 0x13, KEY_VOLUMEUP}, - { 0x14, KEY_LAST}, /* Row 6 */ - { 0x15, KEY_DOWN}, - { 0x16, KEY_MUTE}, - { 0x17, KEY_VOLUMEDOWN}, -}; -DEFINE_LEGACY_IR_KEYTABLE(ati_tv_wonder_hd_600); - -/* DVBWorld remotes - Igor M. Liplianin - */ -static struct ir_scancode dm1105_nec[] = { - { 0x0a, KEY_POWER2}, /* power */ - { 0x0c, KEY_MUTE}, /* mute */ - { 0x11, KEY_1}, - { 0x12, KEY_2}, - { 0x13, KEY_3}, - { 0x14, KEY_4}, - { 0x15, KEY_5}, - { 0x16, KEY_6}, - { 0x17, KEY_7}, - { 0x18, KEY_8}, - { 0x19, KEY_9}, - { 0x10, KEY_0}, - { 0x1c, KEY_CHANNELUP}, /* ch+ */ - { 0x0f, KEY_CHANNELDOWN}, /* ch- */ - { 0x1a, KEY_VOLUMEUP}, /* vol+ */ - { 0x0e, KEY_VOLUMEDOWN}, /* vol- */ - { 0x04, KEY_RECORD}, /* rec */ - { 0x09, KEY_CHANNEL}, /* fav */ - { 0x08, KEY_BACKSPACE}, /* rewind */ - { 0x07, KEY_FASTFORWARD}, /* fast */ - { 0x0b, KEY_PAUSE}, /* pause */ - { 0x02, KEY_ESC}, /* cancel */ - { 0x03, KEY_TAB}, /* tab */ - { 0x00, KEY_UP}, /* up */ - { 0x1f, KEY_ENTER}, /* ok */ - { 0x01, KEY_DOWN}, /* down */ - { 0x05, KEY_RECORD}, /* cap */ - { 0x06, KEY_STOP}, /* stop */ - { 0x40, KEY_ZOOM}, /* full */ - { 0x1e, KEY_TV}, /* tvmode */ - { 0x1b, KEY_B}, /* recall */ -}; -DEFINE_LEGACY_IR_KEYTABLE(dm1105_nec); - -static struct ir_scancode tevii_nec[] = { - { 0x0a, KEY_POWER2}, - { 0x0c, KEY_MUTE}, - { 0x11, KEY_1}, - { 0x12, KEY_2}, - { 0x13, KEY_3}, - { 0x14, KEY_4}, - { 0x15, KEY_5}, - { 0x16, KEY_6}, - { 0x17, KEY_7}, - { 0x18, KEY_8}, - { 0x19, KEY_9}, - { 0x10, KEY_0}, - { 0x1c, KEY_MENU}, - { 0x0f, KEY_VOLUMEDOWN}, - { 0x1a, KEY_LAST}, - { 0x0e, KEY_OPEN}, - { 0x04, KEY_RECORD}, - { 0x09, KEY_VOLUMEUP}, - { 0x08, KEY_CHANNELUP}, - { 0x07, KEY_PVR}, - { 0x0b, KEY_TIME}, - { 0x02, KEY_RIGHT}, - { 0x03, KEY_LEFT}, - { 0x00, KEY_UP}, - { 0x1f, KEY_OK}, - { 0x01, KEY_DOWN}, - { 0x05, KEY_TUNER}, - { 0x06, KEY_CHANNELDOWN}, - { 0x40, KEY_PLAYPAUSE}, - { 0x1e, KEY_REWIND}, - { 0x1b, KEY_FAVORITES}, - { 0x1d, KEY_BACK}, - { 0x4d, KEY_FASTFORWARD}, - { 0x44, KEY_EPG}, - { 0x4c, KEY_INFO}, - { 0x41, KEY_AB}, - { 0x43, KEY_AUDIO}, - { 0x45, KEY_SUBTITLE}, - { 0x4a, KEY_LIST}, - { 0x46, KEY_F1}, - { 0x47, KEY_F2}, - { 0x5e, KEY_F3}, - { 0x5c, KEY_F4}, - { 0x52, KEY_F5}, - { 0x5a, KEY_F6}, - { 0x56, KEY_MODE}, - { 0x58, KEY_SWITCHVIDEOMODE}, -}; -DEFINE_LEGACY_IR_KEYTABLE(tevii_nec); - -static struct ir_scancode tbs_nec[] = { - { 0x04, KEY_POWER2}, /*power*/ - { 0x14, KEY_MUTE}, /*mute*/ - { 0x07, KEY_1}, - { 0x06, KEY_2}, - { 0x05, KEY_3}, - { 0x0b, KEY_4}, - { 0x0a, KEY_5}, - { 0x09, KEY_6}, - { 0x0f, KEY_7}, - { 0x0e, KEY_8}, - { 0x0d, KEY_9}, - { 0x12, KEY_0}, - { 0x16, KEY_CHANNELUP}, /*ch+*/ - { 0x11, KEY_CHANNELDOWN},/*ch-*/ - { 0x13, KEY_VOLUMEUP}, /*vol+*/ - { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ - { 0x03, KEY_RECORD}, /*rec*/ - { 0x18, KEY_PAUSE}, /*pause*/ - { 0x19, KEY_OK}, /*ok*/ - { 0x1a, KEY_CAMERA}, /* snapshot */ - { 0x01, KEY_UP}, - { 0x10, KEY_LEFT}, - { 0x02, KEY_RIGHT}, - { 0x08, KEY_DOWN}, - { 0x15, KEY_FAVORITES}, - { 0x17, KEY_SUBTITLE}, - { 0x1d, KEY_ZOOM}, - { 0x1f, KEY_EXIT}, - { 0x1e, KEY_MENU}, - { 0x1c, KEY_EPG}, - { 0x00, KEY_PREVIOUS}, - { 0x1b, KEY_MODE}, -}; -DEFINE_LEGACY_IR_KEYTABLE(tbs_nec); - -/* Terratec Cinergy Hybrid T USB XS - Devin Heitmueller - */ -static struct ir_scancode terratec_cinergy_xs[] = { - { 0x41, KEY_HOME}, - { 0x01, KEY_POWER}, - { 0x42, KEY_MENU}, - { 0x02, KEY_1}, - { 0x03, KEY_2}, - { 0x04, KEY_3}, - { 0x43, KEY_SUBTITLE}, - { 0x05, KEY_4}, - { 0x06, KEY_5}, - { 0x07, KEY_6}, - { 0x44, KEY_TEXT}, - { 0x08, KEY_7}, - { 0x09, KEY_8}, - { 0x0a, KEY_9}, - { 0x45, KEY_DELETE}, - { 0x0b, KEY_TUNER}, - { 0x0c, KEY_0}, - { 0x0d, KEY_MODE}, - { 0x46, KEY_TV}, - { 0x47, KEY_DVD}, - { 0x49, KEY_VIDEO}, - { 0x4b, KEY_AUX}, - { 0x10, KEY_UP}, - { 0x11, KEY_LEFT}, - { 0x12, KEY_OK}, - { 0x13, KEY_RIGHT}, - { 0x14, KEY_DOWN}, - { 0x0f, KEY_EPG}, - { 0x16, KEY_INFO}, - { 0x4d, KEY_BACKSPACE}, - { 0x1c, KEY_VOLUMEUP}, - { 0x4c, KEY_PLAY}, - { 0x1b, KEY_CHANNELUP}, - { 0x1e, KEY_VOLUMEDOWN}, - { 0x1d, KEY_MUTE}, - { 0x1f, KEY_CHANNELDOWN}, - { 0x17, KEY_RED}, - { 0x18, KEY_GREEN}, - { 0x19, KEY_YELLOW}, - { 0x1a, KEY_BLUE}, - { 0x58, KEY_RECORD}, - { 0x48, KEY_STOP}, - { 0x40, KEY_PAUSE}, - { 0x54, KEY_LAST}, - { 0x4e, KEY_REWIND}, - { 0x4f, KEY_FASTFORWARD}, - { 0x5c, KEY_NEXT}, -}; -DEFINE_LEGACY_IR_KEYTABLE(terratec_cinergy_xs); - -/* EVGA inDtube - Devin Heitmueller - */ -static struct ir_scancode evga_indtube[] = { - { 0x12, KEY_POWER}, - { 0x02, KEY_MODE}, /* TV */ - { 0x14, KEY_MUTE}, - { 0x1a, KEY_CHANNELUP}, - { 0x16, KEY_TV2}, /* PIP */ - { 0x1d, KEY_VOLUMEUP}, - { 0x05, KEY_CHANNELDOWN}, - { 0x0f, KEY_PLAYPAUSE}, - { 0x19, KEY_VOLUMEDOWN}, - { 0x1c, KEY_REWIND}, - { 0x0d, KEY_RECORD}, - { 0x18, KEY_FORWARD}, - { 0x1e, KEY_PREVIOUS}, - { 0x1b, KEY_STOP}, - { 0x1f, KEY_NEXT}, - { 0x13, KEY_CAMERA}, -}; -DEFINE_LEGACY_IR_KEYTABLE(evga_indtube); - -static struct ir_scancode videomate_s350[] = { - { 0x00, KEY_TV}, - { 0x01, KEY_DVD}, - { 0x04, KEY_RECORD}, - { 0x05, KEY_VIDEO}, /* TV/Video */ - { 0x07, KEY_STOP}, - { 0x08, KEY_PLAYPAUSE}, - { 0x0a, KEY_REWIND}, - { 0x0f, KEY_FASTFORWARD}, - { 0x10, KEY_CHANNELUP}, - { 0x12, KEY_VOLUMEUP}, - { 0x13, KEY_CHANNELDOWN}, - { 0x14, KEY_MUTE}, - { 0x15, KEY_VOLUMEDOWN}, - { 0x16, KEY_1}, - { 0x17, KEY_2}, - { 0x18, KEY_3}, - { 0x19, KEY_4}, - { 0x1a, KEY_5}, - { 0x1b, KEY_6}, - { 0x1c, KEY_7}, - { 0x1d, KEY_8}, - { 0x1e, KEY_9}, - { 0x1f, KEY_0}, - { 0x21, KEY_SLEEP}, - { 0x24, KEY_ZOOM}, - { 0x25, KEY_LAST}, /* Recall */ - { 0x26, KEY_SUBTITLE}, /* CC */ - { 0x27, KEY_LANGUAGE}, /* MTS */ - { 0x29, KEY_CHANNEL}, /* SURF */ - { 0x2b, KEY_A}, - { 0x2c, KEY_B}, - { 0x2f, KEY_CAMERA}, /* Snapshot */ - { 0x23, KEY_RADIO}, - { 0x02, KEY_PREVIOUSSONG}, - { 0x06, KEY_NEXTSONG}, - { 0x03, KEY_EPG}, - { 0x09, KEY_SETUP}, - { 0x22, KEY_BACKSPACE}, - { 0x0c, KEY_UP}, - { 0x0e, KEY_DOWN}, - { 0x0b, KEY_LEFT}, - { 0x0d, KEY_RIGHT}, - { 0x11, KEY_ENTER}, - { 0x20, KEY_TEXT}, -}; -DEFINE_LEGACY_IR_KEYTABLE(videomate_s350); - -/* GADMEI UTV330+ RM008Z remote - Shine Liu - */ -static struct ir_scancode gadmei_rm008z[] = { - { 0x14, KEY_POWER2}, /* POWER OFF */ - { 0x0c, KEY_MUTE}, /* MUTE */ - - { 0x18, KEY_TV}, /* TV */ - { 0x0e, KEY_VIDEO}, /* AV */ - { 0x0b, KEY_AUDIO}, /* SV */ - { 0x0f, KEY_RADIO}, /* FM */ - - { 0x00, KEY_1}, - { 0x01, KEY_2}, - { 0x02, KEY_3}, - { 0x03, KEY_4}, - { 0x04, KEY_5}, - { 0x05, KEY_6}, - { 0x06, KEY_7}, - { 0x07, KEY_8}, - { 0x08, KEY_9}, - { 0x09, KEY_0}, - { 0x0a, KEY_INFO}, /* OSD */ - { 0x1c, KEY_BACKSPACE}, /* LAST */ - - { 0x0d, KEY_PLAY}, /* PLAY */ - { 0x1e, KEY_CAMERA}, /* SNAPSHOT */ - { 0x1a, KEY_RECORD}, /* RECORD */ - { 0x17, KEY_STOP}, /* STOP */ - - { 0x1f, KEY_UP}, /* UP */ - { 0x44, KEY_DOWN}, /* DOWN */ - { 0x46, KEY_TAB}, /* BACK */ - { 0x4a, KEY_ZOOM}, /* FULLSECREEN */ - - { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */ - { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ - { 0x12, KEY_CHANNELUP}, /* CHANNELUP */ - { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ - { 0x15, KEY_ENTER}, /* OK */ -}; -DEFINE_LEGACY_IR_KEYTABLE(gadmei_rm008z); - -/************************************************************* - * COMPLETE SCANCODE TABLES - * Instead of just a partial scancode, the tables bellow - * contains the complete scancode and the receiver protocol - *************************************************************/ +#include +#include /* - * Hauppauge:the newer, gray remotes (seems there are multiple - * slightly different versions), shipped with cx88+ivtv cards. - * - * This table contains the complete RC5 code, instead of just the data part - */ -static struct ir_scancode rc5_hauppauge_new[] = { - /* Keys 0 to 9 */ - { 0x1e00, KEY_0 }, - { 0x1e01, KEY_1 }, - { 0x1e02, KEY_2 }, - { 0x1e03, KEY_3 }, - { 0x1e04, KEY_4 }, - { 0x1e05, KEY_5 }, - { 0x1e06, KEY_6 }, - { 0x1e07, KEY_7 }, - { 0x1e08, KEY_8 }, - { 0x1e09, KEY_9 }, - - { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ - { 0x1e0b, KEY_RED }, /* red button */ - { 0x1e0c, KEY_RADIO }, - { 0x1e0d, KEY_MENU }, - { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ - { 0x1e0f, KEY_MUTE }, - { 0x1e10, KEY_VOLUMEUP }, - { 0x1e11, KEY_VOLUMEDOWN }, - { 0x1e12, KEY_PREVIOUS }, /* previous channel */ - { 0x1e14, KEY_UP }, - { 0x1e15, KEY_DOWN }, - { 0x1e16, KEY_LEFT }, - { 0x1e17, KEY_RIGHT }, - { 0x1e18, KEY_VIDEO }, /* Videos */ - { 0x1e19, KEY_AUDIO }, /* Music */ - /* 0x1e1a: Pictures - presume this means - "Multimedia Home Platform" - - no "PICTURES" key in input.h - */ - { 0x1e1a, KEY_MHP }, - - { 0x1e1b, KEY_EPG }, /* Guide */ - { 0x1e1c, KEY_TV }, - { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ - { 0x1e1f, KEY_EXIT }, /* back/exit */ - { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ - { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ - { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ - { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ - { 0x1e25, KEY_ENTER }, /* OK */ - { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ - { 0x1e29, KEY_BLUE }, /* blue key */ - { 0x1e2e, KEY_GREEN }, /* green button */ - { 0x1e30, KEY_PAUSE }, /* pause */ - { 0x1e32, KEY_REWIND }, /* backward << */ - { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ - { 0x1e35, KEY_PLAY }, - { 0x1e36, KEY_STOP }, - { 0x1e37, KEY_RECORD }, /* recording */ - { 0x1e38, KEY_YELLOW }, /* yellow key */ - { 0x1e3b, KEY_SELECT }, /* top right button */ - { 0x1e3c, KEY_ZOOM }, /* full */ - { 0x1e3d, KEY_POWER }, /* system power (green button) */ -}; -DEFINE_IR_KEYTABLE(rc5_hauppauge_new, IR_TYPE_RC5); - -/* Terratec Cinergy Hybrid T USB XS FM - Mauro Carvalho Chehab + * All keytables got moved to include/media/keytables directory. + * This file is still needed - at least for now, as their data is + * dynamically inserted here by the media/ir-common.h, due to the + * #define IR_KEYMAPS line, at the beginning of this file. The + * plans are to get rid of this file completely in a near future. */ -static struct ir_scancode nec_terratec_cinergy_xs[] = { - { 0x1441, KEY_HOME}, - { 0x1401, KEY_POWER2}, - - { 0x1442, KEY_MENU}, /* DVD menu */ - { 0x1443, KEY_SUBTITLE}, - { 0x1444, KEY_TEXT}, /* Teletext */ - { 0x1445, KEY_DELETE}, - - { 0x1402, KEY_1}, - { 0x1403, KEY_2}, - { 0x1404, KEY_3}, - { 0x1405, KEY_4}, - { 0x1406, KEY_5}, - { 0x1407, KEY_6}, - { 0x1408, KEY_7}, - { 0x1409, KEY_8}, - { 0x140a, KEY_9}, - { 0x140c, KEY_0}, - - { 0x140b, KEY_TUNER}, /* AV */ - { 0x140d, KEY_MODE}, /* A.B */ - - { 0x1446, KEY_TV}, - { 0x1447, KEY_DVD}, - { 0x1449, KEY_VIDEO}, - { 0x144a, KEY_RADIO}, /* Music */ - { 0x144b, KEY_CAMERA}, /* PIC */ - - { 0x1410, KEY_UP}, - { 0x1411, KEY_LEFT}, - { 0x1412, KEY_OK}, - { 0x1413, KEY_RIGHT}, - { 0x1414, KEY_DOWN}, - - { 0x140f, KEY_EPG}, - { 0x1416, KEY_INFO}, - { 0x144d, KEY_BACKSPACE}, - - { 0x141c, KEY_VOLUMEUP}, - { 0x141e, KEY_VOLUMEDOWN}, - - { 0x144c, KEY_PLAY}, - { 0x141d, KEY_MUTE}, - - { 0x141b, KEY_CHANNELUP}, - { 0x141f, KEY_CHANNELDOWN}, - - { 0x1417, KEY_RED}, - { 0x1418, KEY_GREEN}, - { 0x1419, KEY_YELLOW}, - { 0x141a, KEY_BLUE}, - - { 0x1458, KEY_RECORD}, - { 0x1448, KEY_STOP}, - { 0x1440, KEY_PAUSE}, - - { 0x1454, KEY_LAST}, - { 0x144e, KEY_REWIND}, - { 0x144f, KEY_FASTFORWARD}, - { 0x145c, KEY_NEXT}, -}; -DEFINE_IR_KEYTABLE(nec_terratec_cinergy_xs, IR_TYPE_NEC); - -/* Leadtek Winfast TV USB II Deluxe remote - Magnus Alm - */ -static struct ir_scancode winfast_usbii_deluxe[] = { - { 0x62, KEY_0}, - { 0x75, KEY_1}, - { 0x76, KEY_2}, - { 0x77, KEY_3}, - { 0x79, KEY_4}, - { 0x7a, KEY_5}, - { 0x7b, KEY_6}, - { 0x7d, KEY_7}, - { 0x7e, KEY_8}, - { 0x7f, KEY_9}, - - { 0x38, KEY_CAMERA}, /* SNAPSHOT */ - { 0x37, KEY_RECORD}, /* RECORD */ - { 0x35, KEY_TIME}, /* TIMESHIFT */ - - { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ - { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ - { 0x64, KEY_MUTE}, /* MUTE */ - - { 0x21, KEY_CHANNEL}, /* SURF */ - { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ - { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ - { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ - - { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ - - { 0x70, KEY_POWER2}, /* TV ON/OFF */ - - { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ - { 0x3a, KEY_NEW}, /* PIP */ - { 0x73, KEY_ZOOM}, /* FULLSECREEN */ - - { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ - - { 0x31, KEY_DOT}, /* '.' */ - { 0x63, KEY_ENTER}, /* ENTER */ - -}; -DEFINE_LEGACY_IR_KEYTABLE(winfast_usbii_deluxe); - -/* Kworld 315U - */ -static struct ir_scancode kworld_315u[] = { - { 0x6143, KEY_POWER }, - { 0x6101, KEY_TUNER }, /* source */ - { 0x610b, KEY_ZOOM }, - { 0x6103, KEY_POWER2 }, /* shutdown */ - - { 0x6104, KEY_1 }, - { 0x6108, KEY_2 }, - { 0x6102, KEY_3 }, - { 0x6109, KEY_CHANNELUP }, - - { 0x610f, KEY_4 }, - { 0x6105, KEY_5 }, - { 0x6106, KEY_6 }, - { 0x6107, KEY_CHANNELDOWN }, - - { 0x610c, KEY_7 }, - { 0x610d, KEY_8 }, - { 0x610a, KEY_9 }, - { 0x610e, KEY_VOLUMEUP }, - - { 0x6110, KEY_LAST }, - { 0x6111, KEY_0 }, - { 0x6112, KEY_ENTER }, - { 0x6113, KEY_VOLUMEDOWN }, - - { 0x6114, KEY_RECORD }, - { 0x6115, KEY_STOP }, - { 0x6116, KEY_PLAY }, - { 0x6117, KEY_MUTE }, - - { 0x6118, KEY_UP }, - { 0x6119, KEY_DOWN }, - { 0x611a, KEY_LEFT }, - { 0x611b, KEY_RIGHT }, - { 0x611c, KEY_RED }, - { 0x611d, KEY_GREEN }, - { 0x611e, KEY_YELLOW }, - { 0x611f, KEY_BLUE }, -}; -DEFINE_IR_KEYTABLE(kworld_315u, IR_TYPE_NEC); -- cgit v1.2.3 From 9ce50c1a5faad80cf6100ea4e8970416ee3b8b59 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 2 Apr 2010 02:33:35 -0300 Subject: V4L/DVB: ir-core: Add support for RC map code register Instead of having all RC tables hardcoded on one file with all tables there, add infrastructure for registering and dynamically load the table(s) when needed. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Makefile | 2 +- drivers/media/IR/rc-map.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 drivers/media/IR/rc-map.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 6140b2712c8a..3a4f590d0bbb 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,5 +1,5 @@ ir-common-objs := ir-functions.o ir-keymaps.o -ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o +ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c new file mode 100644 index 000000000000..aa269f5ef3fe --- /dev/null +++ b/drivers/media/IR/rc-map.c @@ -0,0 +1,75 @@ +/* ir-raw-event.c - handle IR Pulse/Space event + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +/* Used to handle IR raw handler extensions */ +static LIST_HEAD(rc_map_list); +static spinlock_t rc_map_lock; + + +static struct rc_keymap *seek_rc_map(const char *name) +{ + struct rc_keymap *map = NULL; + + spin_lock(&rc_map_lock); + list_for_each_entry(map, &rc_map_list, list) { + if (!strcmp(name, map->map.name)) + break; + } + spin_unlock(&rc_map_lock); + + return map; +} + +struct ir_scancode_table *get_rc_map(const char *name) +{ + int rc = 0; + + struct rc_keymap *map; + + map = seek_rc_map(name); +#ifdef MODULE + if (!map) { + rc = request_module("name"); + if (rc < 0) + return NULL; + + map = seek_rc_map(name); + } +#endif + if (!map) + return NULL; + + return &map->map; +} +EXPORT_SYMBOL_GPL(get_rc_map); + +int ir_register_map(struct rc_keymap *map) +{ + spin_lock(&rc_map_lock); + list_add_tail(&map->list, &rc_map_list); + spin_unlock(&rc_map_lock); + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_handler_register); + +void ir_unregister_map(struct rc_keymap *map) +{ + spin_lock(&rc_map_lock); + list_del(&map->list); + spin_unlock(&rc_map_lock); +} +EXPORT_SYMBOL_GPL(ir_raw_handler_unregister); -- cgit v1.2.3 From 6686fa6917caaaaf3d595df6accedb87607517c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 2 Apr 2010 03:05:46 -0300 Subject: V4L/DVB: Break Remote Controller keymaps into modules The original Remote Controller approach were very messy: a big file, that were part of ir-common kernel module, containing 64 different RC keymap tables, used by the V4L/DVB drivers. Better to break each RC keymap table into a separate module, registering them into rc core on a process similar to the fs/nls tables. As an userspace program is now in charge of loading those tables, adds an option to allow the complete removal of those tables from kernelspace. Yet, on embedded devices like Set Top Boxes and TV sets, maybe the only available input device is the IR. So, we should keep allowing the usage of in-kernel tables, but a latter patch should change the default to 'n', after giving some time for distros to add the v4l-utils with the ir-keytable program, to allow the table load via userspace. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 2 + drivers/media/IR/keymaps/Kconfig | 15 +++ drivers/media/IR/keymaps/Makefile | 64 ++++++++++ drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c | 89 +++++++++++++ drivers/media/IR/keymaps/rc-apac-viewcomp.c | 80 ++++++++++++ drivers/media/IR/keymaps/rc-asus-pc39.c | 91 +++++++++++++ drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c | 69 ++++++++++ drivers/media/IR/keymaps/rc-avermedia-a16d.c | 75 +++++++++++ drivers/media/IR/keymaps/rc-avermedia-cardbus.c | 97 ++++++++++++++ drivers/media/IR/keymaps/rc-avermedia-dvbt.c | 78 ++++++++++++ .../media/IR/keymaps/rc-avermedia-m135a-rm-jx.c | 90 +++++++++++++ drivers/media/IR/keymaps/rc-avermedia.c | 86 +++++++++++++ drivers/media/IR/keymaps/rc-avertv-303.c | 85 +++++++++++++ drivers/media/IR/keymaps/rc-behold-columbus.c | 108 ++++++++++++++++ drivers/media/IR/keymaps/rc-behold.c | 141 +++++++++++++++++++++ drivers/media/IR/keymaps/rc-budget-ci-old.c | 92 ++++++++++++++ drivers/media/IR/keymaps/rc-cinergy-1400.c | 84 ++++++++++++ drivers/media/IR/keymaps/rc-cinergy.c | 78 ++++++++++++ drivers/media/IR/keymaps/rc-dm1105-nec.c | 76 +++++++++++ drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c | 78 ++++++++++++ drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c | 97 ++++++++++++++ drivers/media/IR/keymaps/rc-em-terratec.c | 69 ++++++++++ drivers/media/IR/keymaps/rc-empty.c | 44 +++++++ drivers/media/IR/keymaps/rc-encore-enltv-fm53.c | 81 ++++++++++++ drivers/media/IR/keymaps/rc-encore-enltv.c | 112 ++++++++++++++++ drivers/media/IR/keymaps/rc-encore-enltv2.c | 90 +++++++++++++ drivers/media/IR/keymaps/rc-evga-indtube.c | 61 +++++++++ drivers/media/IR/keymaps/rc-eztv.c | 96 ++++++++++++++ drivers/media/IR/keymaps/rc-flydvb.c | 77 +++++++++++ drivers/media/IR/keymaps/rc-flyvideo.c | 70 ++++++++++ drivers/media/IR/keymaps/rc-fusionhdtv-mce.c | 98 ++++++++++++++ drivers/media/IR/keymaps/rc-gadmei-rm008z.c | 81 ++++++++++++ drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c | 84 ++++++++++++ drivers/media/IR/keymaps/rc-gotview7135.c | 79 ++++++++++++ drivers/media/IR/keymaps/rc-hauppauge-new.c | 100 +++++++++++++++ drivers/media/IR/keymaps/rc-iodata-bctv7e.c | 88 +++++++++++++ drivers/media/IR/keymaps/rc-kaiomy.c | 87 +++++++++++++ drivers/media/IR/keymaps/rc-kworld-315u.c | 83 ++++++++++++ .../media/IR/keymaps/rc-kworld-plus-tv-analog.c | 99 +++++++++++++++ drivers/media/IR/keymaps/rc-manli.c | 135 ++++++++++++++++++++ drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c | 123 ++++++++++++++++++ drivers/media/IR/keymaps/rc-msi-tvanywhere.c | 69 ++++++++++ drivers/media/IR/keymaps/rc-nebula.c | 96 ++++++++++++++ .../media/IR/keymaps/rc-nec-terratec-cinergy-xs.c | 105 +++++++++++++++ drivers/media/IR/keymaps/rc-norwood.c | 85 +++++++++++++ drivers/media/IR/keymaps/rc-npgtech.c | 80 ++++++++++++ drivers/media/IR/keymaps/rc-pctv-sedna.c | 80 ++++++++++++ drivers/media/IR/keymaps/rc-pinnacle-color.c | 94 ++++++++++++++ drivers/media/IR/keymaps/rc-pinnacle-grey.c | 89 +++++++++++++ drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c | 73 +++++++++++ drivers/media/IR/keymaps/rc-pixelview-new.c | 83 ++++++++++++ drivers/media/IR/keymaps/rc-pixelview.c | 82 ++++++++++++ .../media/IR/keymaps/rc-powercolor-real-angel.c | 81 ++++++++++++ drivers/media/IR/keymaps/rc-proteus-2309.c | 69 ++++++++++ drivers/media/IR/keymaps/rc-purpletv.c | 81 ++++++++++++ drivers/media/IR/keymaps/rc-pv951.c | 78 ++++++++++++ drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c | 103 +++++++++++++++ drivers/media/IR/keymaps/rc-rc5-tv.c | 81 ++++++++++++ .../media/IR/keymaps/rc-real-audio-220-32-keys.c | 78 ++++++++++++ drivers/media/IR/keymaps/rc-tbs-nec.c | 73 +++++++++++ drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c | 92 ++++++++++++++ drivers/media/IR/keymaps/rc-tevii-nec.c | 88 +++++++++++++ drivers/media/IR/keymaps/rc-tt-1500.c | 82 ++++++++++++ drivers/media/IR/keymaps/rc-videomate-s350.c | 85 +++++++++++++ drivers/media/IR/keymaps/rc-videomate-tv-pvr.c | 87 +++++++++++++ drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c | 82 ++++++++++++ drivers/media/IR/keymaps/rc-winfast.c | 102 +++++++++++++++ drivers/media/IR/rc-map.c | 4 +- 68 files changed, 5632 insertions(+), 2 deletions(-) create mode 100644 drivers/media/IR/keymaps/Kconfig create mode 100644 drivers/media/IR/keymaps/Makefile create mode 100644 drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c create mode 100644 drivers/media/IR/keymaps/rc-apac-viewcomp.c create mode 100644 drivers/media/IR/keymaps/rc-asus-pc39.c create mode 100644 drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c create mode 100644 drivers/media/IR/keymaps/rc-avermedia-a16d.c create mode 100644 drivers/media/IR/keymaps/rc-avermedia-cardbus.c create mode 100644 drivers/media/IR/keymaps/rc-avermedia-dvbt.c create mode 100644 drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c create mode 100644 drivers/media/IR/keymaps/rc-avermedia.c create mode 100644 drivers/media/IR/keymaps/rc-avertv-303.c create mode 100644 drivers/media/IR/keymaps/rc-behold-columbus.c create mode 100644 drivers/media/IR/keymaps/rc-behold.c create mode 100644 drivers/media/IR/keymaps/rc-budget-ci-old.c create mode 100644 drivers/media/IR/keymaps/rc-cinergy-1400.c create mode 100644 drivers/media/IR/keymaps/rc-cinergy.c create mode 100644 drivers/media/IR/keymaps/rc-dm1105-nec.c create mode 100644 drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c create mode 100644 drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c create mode 100644 drivers/media/IR/keymaps/rc-em-terratec.c create mode 100644 drivers/media/IR/keymaps/rc-empty.c create mode 100644 drivers/media/IR/keymaps/rc-encore-enltv-fm53.c create mode 100644 drivers/media/IR/keymaps/rc-encore-enltv.c create mode 100644 drivers/media/IR/keymaps/rc-encore-enltv2.c create mode 100644 drivers/media/IR/keymaps/rc-evga-indtube.c create mode 100644 drivers/media/IR/keymaps/rc-eztv.c create mode 100644 drivers/media/IR/keymaps/rc-flydvb.c create mode 100644 drivers/media/IR/keymaps/rc-flyvideo.c create mode 100644 drivers/media/IR/keymaps/rc-fusionhdtv-mce.c create mode 100644 drivers/media/IR/keymaps/rc-gadmei-rm008z.c create mode 100644 drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c create mode 100644 drivers/media/IR/keymaps/rc-gotview7135.c create mode 100644 drivers/media/IR/keymaps/rc-hauppauge-new.c create mode 100644 drivers/media/IR/keymaps/rc-iodata-bctv7e.c create mode 100644 drivers/media/IR/keymaps/rc-kaiomy.c create mode 100644 drivers/media/IR/keymaps/rc-kworld-315u.c create mode 100644 drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c create mode 100644 drivers/media/IR/keymaps/rc-manli.c create mode 100644 drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c create mode 100644 drivers/media/IR/keymaps/rc-msi-tvanywhere.c create mode 100644 drivers/media/IR/keymaps/rc-nebula.c create mode 100644 drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c create mode 100644 drivers/media/IR/keymaps/rc-norwood.c create mode 100644 drivers/media/IR/keymaps/rc-npgtech.c create mode 100644 drivers/media/IR/keymaps/rc-pctv-sedna.c create mode 100644 drivers/media/IR/keymaps/rc-pinnacle-color.c create mode 100644 drivers/media/IR/keymaps/rc-pinnacle-grey.c create mode 100644 drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c create mode 100644 drivers/media/IR/keymaps/rc-pixelview-new.c create mode 100644 drivers/media/IR/keymaps/rc-pixelview.c create mode 100644 drivers/media/IR/keymaps/rc-powercolor-real-angel.c create mode 100644 drivers/media/IR/keymaps/rc-proteus-2309.c create mode 100644 drivers/media/IR/keymaps/rc-purpletv.c create mode 100644 drivers/media/IR/keymaps/rc-pv951.c create mode 100644 drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c create mode 100644 drivers/media/IR/keymaps/rc-rc5-tv.c create mode 100644 drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c create mode 100644 drivers/media/IR/keymaps/rc-tbs-nec.c create mode 100644 drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c create mode 100644 drivers/media/IR/keymaps/rc-tevii-nec.c create mode 100644 drivers/media/IR/keymaps/rc-tt-1500.c create mode 100644 drivers/media/IR/keymaps/rc-videomate-s350.c create mode 100644 drivers/media/IR/keymaps/rc-videomate-tv-pvr.c create mode 100644 drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c create mode 100644 drivers/media/IR/keymaps/rc-winfast.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index de410d46ae26..0c557b8cc932 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -8,6 +8,8 @@ config VIDEO_IR depends on IR_CORE default IR_CORE +source "drivers/media/IR/keymaps/Kconfig" + config IR_NEC_DECODER tristate "Enable IR raw decoder for NEC protocol" depends on IR_CORE diff --git a/drivers/media/IR/keymaps/Kconfig b/drivers/media/IR/keymaps/Kconfig new file mode 100644 index 000000000000..14b22f58f823 --- /dev/null +++ b/drivers/media/IR/keymaps/Kconfig @@ -0,0 +1,15 @@ +config RC_MAP + tristate "Compile Remote Controller keymap modules" + depends on IR_CORE + default y + + ---help--- + This option enables the compilation of lots of Remote + Controller tables. They are short tables, but if you + don't use a remote controller, or prefer to load the + tables on userspace, you should disable it. + + The ir-keytable program, available at v4l-utils package + provide the tool and the same RC maps for load from + userspace. Its available at + http://git.linuxtv.org/v4l-utils diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile new file mode 100644 index 000000000000..937b7db9c9d2 --- /dev/null +++ b/drivers/media/IR/keymaps/Makefile @@ -0,0 +1,64 @@ +obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ + rc-apac-viewcomp.o \ + rc-asus-pc39.o \ + rc-ati-tv-wonder-hd-600.o \ + rc-avermedia-a16d.o \ + rc-avermedia.o \ + rc-avermedia-cardbus.o \ + rc-avermedia-dvbt.o \ + rc-avermedia-m135a-rm-jx.o \ + rc-avertv-303.o \ + rc-behold.o \ + rc-behold-columbus.o \ + rc-budget-ci-old.o \ + rc-cinergy-1400.o \ + rc-cinergy.o \ + rc-dm1105-nec.o \ + rc-dntv-live-dvb-t.o \ + rc-dntv-live-dvbt-pro.o \ + rc-empty.o \ + rc-em-terratec.o \ + rc-encore-enltv2.o \ + rc-encore-enltv.o \ + rc-encore-enltv-fm53.o \ + rc-evga-indtube.o \ + rc-eztv.o \ + rc-flydvb.o \ + rc-flyvideo.o \ + rc-fusionhdtv-mce.o \ + rc-gadmei-rm008z.o \ + rc-genius-tvgo-a11mce.o \ + rc-gotview7135.o \ + rc-hauppauge-new.o \ + rc-iodata-bctv7e.o \ + rc-kaiomy.o \ + rc-kworld-315u.o \ + rc-kworld-plus-tv-analog.o \ + rc-manli.o \ + rc-msi-tvanywhere.o \ + rc-msi-tvanywhere-plus.o \ + rc-nebula.o \ + rc-nec-terratec-cinergy-xs.o \ + rc-norwood.o \ + rc-npgtech.o \ + rc-pctv-sedna.o \ + rc-pinnacle-color.o \ + rc-pinnacle-grey.o \ + rc-pinnacle-pctv-hd.o \ + rc-pixelview.o \ + rc-pixelview-new.o \ + rc-powercolor-real-angel.o \ + rc-proteus-2309.o \ + rc-purpletv.o \ + rc-pv951.o \ + rc-rc5-hauppauge-new.o \ + rc-rc5-tv.o \ + rc-real-audio-220-32-keys.o \ + rc-tbs-nec.o \ + rc-terratec-cinergy-xs.o \ + rc-tevii-nec.o \ + rc-tt-1500.o \ + rc-videomate-s350.o \ + rc-videomate-tv-pvr.o \ + rc-winfast.o \ + rc-winfast-usbii-deluxe.o diff --git a/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c new file mode 100644 index 000000000000..b17283176ecd --- /dev/null +++ b/drivers/media/IR/keymaps/rc-adstech-dvb-t-pci.c @@ -0,0 +1,89 @@ +/* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* ADS Tech Instant TV DVB-T PCI Remote */ + +static struct ir_scancode adstech_dvb_t_pci[] = { + /* Keys 0 to 9 */ + { 0x4d, KEY_0 }, + { 0x57, KEY_1 }, + { 0x4f, KEY_2 }, + { 0x53, KEY_3 }, + { 0x56, KEY_4 }, + { 0x4e, KEY_5 }, + { 0x5e, KEY_6 }, + { 0x54, KEY_7 }, + { 0x4c, KEY_8 }, + { 0x5c, KEY_9 }, + + { 0x5b, KEY_POWER }, + { 0x5f, KEY_MUTE }, + { 0x55, KEY_GOTO }, + { 0x5d, KEY_SEARCH }, + { 0x17, KEY_EPG }, /* Guide */ + { 0x1f, KEY_MENU }, + { 0x0f, KEY_UP }, + { 0x46, KEY_DOWN }, + { 0x16, KEY_LEFT }, + { 0x1e, KEY_RIGHT }, + { 0x0e, KEY_SELECT }, /* Enter */ + { 0x5a, KEY_INFO }, + { 0x52, KEY_EXIT }, + { 0x59, KEY_PREVIOUS }, + { 0x51, KEY_NEXT }, + { 0x58, KEY_REWIND }, + { 0x50, KEY_FORWARD }, + { 0x44, KEY_PLAYPAUSE }, + { 0x07, KEY_STOP }, + { 0x1b, KEY_RECORD }, + { 0x13, KEY_TUNER }, /* Live */ + { 0x0a, KEY_A }, + { 0x12, KEY_B }, + { 0x03, KEY_PROG1 }, /* 1 */ + { 0x01, KEY_PROG2 }, /* 2 */ + { 0x00, KEY_PROG3 }, /* 3 */ + { 0x06, KEY_DVD }, + { 0x48, KEY_AUX }, /* Photo */ + { 0x40, KEY_VIDEO }, + { 0x19, KEY_AUDIO }, /* Music */ + { 0x0b, KEY_CHANNELUP }, + { 0x08, KEY_CHANNELDOWN }, + { 0x15, KEY_VOLUMEUP }, + { 0x1c, KEY_VOLUMEDOWN }, +}; + +static struct rc_keymap adstech_dvb_t_pci_map = { + .map = { + .scan = adstech_dvb_t_pci, + .size = ARRAY_SIZE(adstech_dvb_t_pci), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ADSTECH_DVB_T_PCI, + } +}; + +static int __init init_rc_map_adstech_dvb_t_pci(void) +{ + return ir_register_map(&adstech_dvb_t_pci_map); +} + +static void __exit exit_rc_map_adstech_dvb_t_pci(void) +{ + ir_unregister_map(&adstech_dvb_t_pci_map); +} + +module_init(init_rc_map_adstech_dvb_t_pci) +module_exit(exit_rc_map_adstech_dvb_t_pci) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-apac-viewcomp.c b/drivers/media/IR/keymaps/rc-apac-viewcomp.c new file mode 100644 index 000000000000..0ef2b562baf0 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-apac-viewcomp.c @@ -0,0 +1,80 @@ +/* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Attila Kondoros */ + +static struct ir_scancode apac_viewcomp[] = { + + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x00, KEY_0 }, + { 0x17, KEY_LAST }, /* +100 */ + { 0x0a, KEY_LIST }, /* recall */ + + + { 0x1c, KEY_TUNER }, /* TV/FM */ + { 0x15, KEY_SEARCH }, /* scan */ + { 0x12, KEY_POWER }, /* power */ + { 0x1f, KEY_VOLUMEDOWN }, /* vol up */ + { 0x1b, KEY_VOLUMEUP }, /* vol down */ + { 0x1e, KEY_CHANNELDOWN }, /* chn up */ + { 0x1a, KEY_CHANNELUP }, /* chn down */ + + { 0x11, KEY_VIDEO }, /* video */ + { 0x0f, KEY_ZOOM }, /* full screen */ + { 0x13, KEY_MUTE }, /* mute/unmute */ + { 0x10, KEY_TEXT }, /* min */ + + { 0x0d, KEY_STOP }, /* freeze */ + { 0x0e, KEY_RECORD }, /* record */ + { 0x1d, KEY_PLAYPAUSE }, /* stop */ + { 0x19, KEY_PLAY }, /* play */ + + { 0x16, KEY_GOTO }, /* osd */ + { 0x14, KEY_REFRESH }, /* default */ + { 0x0c, KEY_KPPLUS }, /* fine tune >>>> */ + { 0x18, KEY_KPMINUS }, /* fine tune <<<< */ +}; + +static struct rc_keymap apac_viewcomp_map = { + .map = { + .scan = apac_viewcomp, + .size = ARRAY_SIZE(apac_viewcomp), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_APAC_VIEWCOMP, + } +}; + +static int __init init_rc_map_apac_viewcomp(void) +{ + return ir_register_map(&apac_viewcomp_map); +} + +static void __exit exit_rc_map_apac_viewcomp(void) +{ + ir_unregister_map(&apac_viewcomp_map); +} + +module_init(init_rc_map_apac_viewcomp) +module_exit(exit_rc_map_apac_viewcomp) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-asus-pc39.c b/drivers/media/IR/keymaps/rc-asus-pc39.c new file mode 100644 index 000000000000..2aa068cd6c75 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-asus-pc39.c @@ -0,0 +1,91 @@ +/* asus-pc39.h - Keytable for asus_pc39 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Marc Fargas + * this is the remote control that comes with the asus p7131 + * which has a label saying is "Model PC-39" + */ + +static struct ir_scancode asus_pc39[] = { + /* Keys 0 to 9 */ + { 0x15, KEY_0 }, + { 0x29, KEY_1 }, + { 0x2d, KEY_2 }, + { 0x2b, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0d, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x31, KEY_7 }, + { 0x35, KEY_8 }, + { 0x33, KEY_9 }, + + { 0x3e, KEY_RADIO }, /* radio */ + { 0x03, KEY_MENU }, /* dvd/menu */ + { 0x2a, KEY_VOLUMEUP }, + { 0x19, KEY_VOLUMEDOWN }, + { 0x37, KEY_UP }, + { 0x3b, KEY_DOWN }, + { 0x27, KEY_LEFT }, + { 0x2f, KEY_RIGHT }, + { 0x25, KEY_VIDEO }, /* video */ + { 0x39, KEY_AUDIO }, /* music */ + + { 0x21, KEY_TV }, /* tv */ + { 0x1d, KEY_EXIT }, /* back */ + { 0x0a, KEY_CHANNELUP }, /* channel / program + */ + { 0x1b, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x1a, KEY_ENTER }, /* enter */ + + { 0x06, KEY_PAUSE }, /* play/pause */ + { 0x1e, KEY_PREVIOUS }, /* rew */ + { 0x26, KEY_NEXT }, /* forward */ + { 0x0e, KEY_REWIND }, /* backward << */ + { 0x3a, KEY_FASTFORWARD }, /* forward >> */ + { 0x36, KEY_STOP }, + { 0x2e, KEY_RECORD }, /* recording */ + { 0x16, KEY_POWER }, /* the button that reads "close" */ + + { 0x11, KEY_ZOOM }, /* full screen */ + { 0x13, KEY_MACRO }, /* recall */ + { 0x23, KEY_HOME }, /* home */ + { 0x05, KEY_PVR }, /* picture */ + { 0x3d, KEY_MUTE }, /* mute */ + { 0x01, KEY_DVD }, /* dvd */ +}; + +static struct rc_keymap asus_pc39_map = { + .map = { + .scan = asus_pc39, + .size = ARRAY_SIZE(asus_pc39), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ASUS_PC39, + } +}; + +static int __init init_rc_map_asus_pc39(void) +{ + return ir_register_map(&asus_pc39_map); +} + +static void __exit exit_rc_map_asus_pc39(void) +{ + ir_unregister_map(&asus_pc39_map); +} + +module_init(init_rc_map_asus_pc39) +module_exit(exit_rc_map_asus_pc39) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c b/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c new file mode 100644 index 000000000000..8edfd293d010 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-ati-tv-wonder-hd-600.c @@ -0,0 +1,69 @@ +/* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* ATI TV Wonder HD 600 USB + Devin Heitmueller + */ + +static struct ir_scancode ati_tv_wonder_hd_600[] = { + { 0x00, KEY_RECORD}, /* Row 1 */ + { 0x01, KEY_PLAYPAUSE}, + { 0x02, KEY_STOP}, + { 0x03, KEY_POWER}, + { 0x04, KEY_PREVIOUS}, /* Row 2 */ + { 0x05, KEY_REWIND}, + { 0x06, KEY_FORWARD}, + { 0x07, KEY_NEXT}, + { 0x08, KEY_EPG}, /* Row 3 */ + { 0x09, KEY_HOME}, + { 0x0a, KEY_MENU}, + { 0x0b, KEY_CHANNELUP}, + { 0x0c, KEY_BACK}, /* Row 4 */ + { 0x0d, KEY_UP}, + { 0x0e, KEY_INFO}, + { 0x0f, KEY_CHANNELDOWN}, + { 0x10, KEY_LEFT}, /* Row 5 */ + { 0x11, KEY_SELECT}, + { 0x12, KEY_RIGHT}, + { 0x13, KEY_VOLUMEUP}, + { 0x14, KEY_LAST}, /* Row 6 */ + { 0x15, KEY_DOWN}, + { 0x16, KEY_MUTE}, + { 0x17, KEY_VOLUMEDOWN}, +}; + +static struct rc_keymap ati_tv_wonder_hd_600_map = { + .map = { + .scan = ati_tv_wonder_hd_600, + .size = ARRAY_SIZE(ati_tv_wonder_hd_600), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ATI_TV_WONDER_HD_600, + } +}; + +static int __init init_rc_map_ati_tv_wonder_hd_600(void) +{ + return ir_register_map(&ati_tv_wonder_hd_600_map); +} + +static void __exit exit_rc_map_ati_tv_wonder_hd_600(void) +{ + ir_unregister_map(&ati_tv_wonder_hd_600_map); +} + +module_init(init_rc_map_ati_tv_wonder_hd_600) +module_exit(exit_rc_map_ati_tv_wonder_hd_600) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-a16d.c b/drivers/media/IR/keymaps/rc-avermedia-a16d.c new file mode 100644 index 000000000000..12f043587f2e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-a16d.c @@ -0,0 +1,75 @@ +/* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode avermedia_a16d[] = { + { 0x20, KEY_LIST}, + { 0x00, KEY_POWER}, + { 0x28, KEY_1}, + { 0x18, KEY_2}, + { 0x38, KEY_3}, + { 0x24, KEY_4}, + { 0x14, KEY_5}, + { 0x34, KEY_6}, + { 0x2c, KEY_7}, + { 0x1c, KEY_8}, + { 0x3c, KEY_9}, + { 0x12, KEY_SUBTITLE}, + { 0x22, KEY_0}, + { 0x32, KEY_REWIND}, + { 0x3a, KEY_SHUFFLE}, + { 0x02, KEY_PRINT}, + { 0x11, KEY_CHANNELDOWN}, + { 0x31, KEY_CHANNELUP}, + { 0x0c, KEY_ZOOM}, + { 0x1e, KEY_VOLUMEDOWN}, + { 0x3e, KEY_VOLUMEUP}, + { 0x0a, KEY_MUTE}, + { 0x04, KEY_AUDIO}, + { 0x26, KEY_RECORD}, + { 0x06, KEY_PLAY}, + { 0x36, KEY_STOP}, + { 0x16, KEY_PAUSE}, + { 0x2e, KEY_REWIND}, + { 0x0e, KEY_FASTFORWARD}, + { 0x30, KEY_TEXT}, + { 0x21, KEY_GREEN}, + { 0x01, KEY_BLUE}, + { 0x08, KEY_EPG}, + { 0x2a, KEY_MENU}, +}; + +static struct rc_keymap avermedia_a16d_map = { + .map = { + .scan = avermedia_a16d, + .size = ARRAY_SIZE(avermedia_a16d), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA_A16D, + } +}; + +static int __init init_rc_map_avermedia_a16d(void) +{ + return ir_register_map(&avermedia_a16d_map); +} + +static void __exit exit_rc_map_avermedia_a16d(void) +{ + ir_unregister_map(&avermedia_a16d_map); +} + +module_init(init_rc_map_avermedia_a16d) +module_exit(exit_rc_map_avermedia_a16d) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-cardbus.c b/drivers/media/IR/keymaps/rc-avermedia-cardbus.c new file mode 100644 index 000000000000..2a945b02e8ca --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-cardbus.c @@ -0,0 +1,97 @@ +/* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Oldrich Jedlicka */ + +static struct ir_scancode avermedia_cardbus[] = { + { 0x00, KEY_POWER }, + { 0x01, KEY_TUNER }, /* TV/FM */ + { 0x03, KEY_TEXT }, /* Teletext */ + { 0x04, KEY_EPG }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x08, KEY_AUDIO }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0c, KEY_ZOOM }, /* Full screen */ + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + { 0x10, KEY_PAGEUP }, /* 16-CH PREV */ + { 0x11, KEY_0 }, + { 0x12, KEY_INFO }, + { 0x13, KEY_AGAIN }, /* CH RTN - channel return */ + { 0x14, KEY_MUTE }, + { 0x15, KEY_EDIT }, /* Autoscan */ + { 0x17, KEY_SAVE }, /* Screenshot */ + { 0x18, KEY_PLAYPAUSE }, + { 0x19, KEY_RECORD }, + { 0x1a, KEY_PLAY }, + { 0x1b, KEY_STOP }, + { 0x1c, KEY_FASTFORWARD }, + { 0x1d, KEY_REWIND }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_VOLUMEUP }, + { 0x22, KEY_SLEEP }, /* Sleep */ + { 0x23, KEY_ZOOM }, /* Aspect */ + { 0x26, KEY_SCREEN }, /* Pos */ + { 0x27, KEY_ANGLE }, /* Size */ + { 0x28, KEY_SELECT }, /* Select */ + { 0x29, KEY_BLUE }, /* Blue/Picture */ + { 0x2a, KEY_BACKSPACE }, /* Back */ + { 0x2b, KEY_MEDIA }, /* PIP (Picture-in-picture) */ + { 0x2c, KEY_DOWN }, + { 0x2e, KEY_DOT }, + { 0x2f, KEY_TV }, /* Live TV */ + { 0x32, KEY_LEFT }, + { 0x33, KEY_CLEAR }, /* Clear */ + { 0x35, KEY_RED }, /* Red/TV */ + { 0x36, KEY_UP }, + { 0x37, KEY_HOME }, /* Home */ + { 0x39, KEY_GREEN }, /* Green/Video */ + { 0x3d, KEY_YELLOW }, /* Yellow/Music */ + { 0x3e, KEY_OK }, /* Ok */ + { 0x3f, KEY_RIGHT }, + { 0x40, KEY_NEXT }, /* Next */ + { 0x41, KEY_PREVIOUS }, /* Previous */ + { 0x42, KEY_CHANNELDOWN }, /* Channel down */ + { 0x43, KEY_CHANNELUP }, /* Channel up */ +}; + +static struct rc_keymap avermedia_cardbus_map = { + .map = { + .scan = avermedia_cardbus, + .size = ARRAY_SIZE(avermedia_cardbus), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA_CARDBUS, + } +}; + +static int __init init_rc_map_avermedia_cardbus(void) +{ + return ir_register_map(&avermedia_cardbus_map); +} + +static void __exit exit_rc_map_avermedia_cardbus(void) +{ + ir_unregister_map(&avermedia_cardbus_map); +} + +module_init(init_rc_map_avermedia_cardbus) +module_exit(exit_rc_map_avermedia_cardbus) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-dvbt.c b/drivers/media/IR/keymaps/rc-avermedia-dvbt.c new file mode 100644 index 000000000000..39dde6222875 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-dvbt.c @@ -0,0 +1,78 @@ +/* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Matt Jesson >' */ + { 0x3a, KEY_RECORD }, /* 'capture' */ + { 0x0a, KEY_MUTE }, /* 'mute' */ + { 0x2c, KEY_RECORD }, /* 'record' */ + { 0x1c, KEY_PAUSE }, /* 'pause' */ + { 0x3c, KEY_STOP }, /* 'stop' */ + { 0x0c, KEY_PLAY }, /* 'play' */ + { 0x2e, KEY_RED }, /* 'red' */ + { 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */ + { 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */ + { 0x21, KEY_GREEN }, /* 'green' */ + { 0x11, KEY_CHANNELDOWN }, /* 'channel -' */ + { 0x31, KEY_CHANNELUP }, /* 'channel +' */ + { 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */ + { 0x3e, KEY_VOLUMEUP }, /* 'volume +' */ +}; + +static struct rc_keymap avermedia_dvbt_map = { + .map = { + .scan = avermedia_dvbt, + .size = ARRAY_SIZE(avermedia_dvbt), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA_DVBT, + } +}; + +static int __init init_rc_map_avermedia_dvbt(void) +{ + return ir_register_map(&avermedia_dvbt_map); +} + +static void __exit exit_rc_map_avermedia_dvbt(void) +{ + ir_unregister_map(&avermedia_dvbt_map); +} + +module_init(init_rc_map_avermedia_dvbt) +module_exit(exit_rc_map_avermedia_dvbt) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c b/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c new file mode 100644 index 000000000000..101e7ea85941 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia-m135a-rm-jx.c @@ -0,0 +1,90 @@ +/* avermedia-m135a-rm-jx.h - Keytable for avermedia_m135a_rm_jx Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Avermedia M135A with IR model RM-JX + * The same codes exist on both Positivo (BR) and original IR + * Mauro Carvalho Chehab + */ + +static struct ir_scancode avermedia_m135a_rm_jx[] = { + { 0x0200, KEY_POWER2 }, + { 0x022e, KEY_DOT }, /* '.' */ + { 0x0201, KEY_MODE }, /* TV/FM or SOURCE */ + + { 0x0205, KEY_1 }, + { 0x0206, KEY_2 }, + { 0x0207, KEY_3 }, + { 0x0209, KEY_4 }, + { 0x020a, KEY_5 }, + { 0x020b, KEY_6 }, + { 0x020d, KEY_7 }, + { 0x020e, KEY_8 }, + { 0x020f, KEY_9 }, + { 0x0211, KEY_0 }, + + { 0x0213, KEY_RIGHT }, /* -> or L */ + { 0x0212, KEY_LEFT }, /* <- or R */ + + { 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */ + { 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */ + + { 0x0303, KEY_CHANNELUP }, + { 0x0302, KEY_CHANNELDOWN }, + { 0x021f, KEY_VOLUMEUP }, + { 0x021e, KEY_VOLUMEDOWN }, + { 0x020c, KEY_ENTER }, /* Full Screen */ + + { 0x0214, KEY_MUTE }, + { 0x0208, KEY_AUDIO }, + + { 0x0203, KEY_TEXT }, /* Teletext */ + { 0x0204, KEY_EPG }, + { 0x022b, KEY_TV2 }, /* TV2 or PIP */ + + { 0x021d, KEY_RED }, + { 0x021c, KEY_YELLOW }, + { 0x0301, KEY_GREEN }, + { 0x0300, KEY_BLUE }, + + { 0x021a, KEY_PLAYPAUSE }, + { 0x0219, KEY_RECORD }, + { 0x0218, KEY_PLAY }, + { 0x021b, KEY_STOP }, +}; + +static struct rc_keymap avermedia_m135a_rm_jx_map = { + .map = { + .scan = avermedia_m135a_rm_jx, + .size = ARRAY_SIZE(avermedia_m135a_rm_jx), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_AVERMEDIA_M135A_RM_JX, + } +}; + +static int __init init_rc_map_avermedia_m135a_rm_jx(void) +{ + return ir_register_map(&avermedia_m135a_rm_jx_map); +} + +static void __exit exit_rc_map_avermedia_m135a_rm_jx(void) +{ + ir_unregister_map(&avermedia_m135a_rm_jx_map); +} + +module_init(init_rc_map_avermedia_m135a_rm_jx) +module_exit(exit_rc_map_avermedia_m135a_rm_jx) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avermedia.c b/drivers/media/IR/keymaps/rc-avermedia.c new file mode 100644 index 000000000000..21effd5bfb0d --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avermedia.c @@ -0,0 +1,86 @@ +/* avermedia.h - Keytable for avermedia Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Alex Hermann */ + +static struct ir_scancode avermedia[] = { + { 0x28, KEY_1 }, + { 0x18, KEY_2 }, + { 0x38, KEY_3 }, + { 0x24, KEY_4 }, + { 0x14, KEY_5 }, + { 0x34, KEY_6 }, + { 0x2c, KEY_7 }, + { 0x1c, KEY_8 }, + { 0x3c, KEY_9 }, + { 0x22, KEY_0 }, + + { 0x20, KEY_TV }, /* TV/FM */ + { 0x10, KEY_CD }, /* CD */ + { 0x30, KEY_TEXT }, /* TELETEXT */ + { 0x00, KEY_POWER }, /* POWER */ + + { 0x08, KEY_VIDEO }, /* VIDEO */ + { 0x04, KEY_AUDIO }, /* AUDIO */ + { 0x0c, KEY_ZOOM }, /* FULL SCREEN */ + + { 0x12, KEY_SUBTITLE }, /* DISPLAY */ + { 0x32, KEY_REWIND }, /* LOOP */ + { 0x02, KEY_PRINT }, /* PREVIEW */ + + { 0x2a, KEY_SEARCH }, /* AUTOSCAN */ + { 0x1a, KEY_SLEEP }, /* FREEZE */ + { 0x3a, KEY_CAMERA }, /* SNAPSHOT */ + { 0x0a, KEY_MUTE }, /* MUTE */ + + { 0x26, KEY_RECORD }, /* RECORD */ + { 0x16, KEY_PAUSE }, /* PAUSE */ + { 0x36, KEY_STOP }, /* STOP */ + { 0x06, KEY_PLAY }, /* PLAY */ + + { 0x2e, KEY_RED }, /* RED */ + { 0x21, KEY_GREEN }, /* GREEN */ + { 0x0e, KEY_YELLOW }, /* YELLOW */ + { 0x01, KEY_BLUE }, /* BLUE */ + + { 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */ + { 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */ + { 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */ + { 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */ +}; + +static struct rc_keymap avermedia_map = { + .map = { + .scan = avermedia, + .size = ARRAY_SIZE(avermedia), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERMEDIA, + } +}; + +static int __init init_rc_map_avermedia(void) +{ + return ir_register_map(&avermedia_map); +} + +static void __exit exit_rc_map_avermedia(void) +{ + ir_unregister_map(&avermedia_map); +} + +module_init(init_rc_map_avermedia) +module_exit(exit_rc_map_avermedia) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-avertv-303.c b/drivers/media/IR/keymaps/rc-avertv-303.c new file mode 100644 index 000000000000..971c59d6f9d6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-avertv-303.c @@ -0,0 +1,85 @@ +/* avertv-303.h - Keytable for avertv_303 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* AVERTV STUDIO 303 Remote */ + +static struct ir_scancode avertv_303[] = { + { 0x2a, KEY_1 }, + { 0x32, KEY_2 }, + { 0x3a, KEY_3 }, + { 0x4a, KEY_4 }, + { 0x52, KEY_5 }, + { 0x5a, KEY_6 }, + { 0x6a, KEY_7 }, + { 0x72, KEY_8 }, + { 0x7a, KEY_9 }, + { 0x0e, KEY_0 }, + + { 0x02, KEY_POWER }, + { 0x22, KEY_VIDEO }, + { 0x42, KEY_AUDIO }, + { 0x62, KEY_ZOOM }, + { 0x0a, KEY_TV }, + { 0x12, KEY_CD }, + { 0x1a, KEY_TEXT }, + + { 0x16, KEY_SUBTITLE }, + { 0x1e, KEY_REWIND }, + { 0x06, KEY_PRINT }, + + { 0x2e, KEY_SEARCH }, + { 0x36, KEY_SLEEP }, + { 0x3e, KEY_SHUFFLE }, + { 0x26, KEY_MUTE }, + + { 0x4e, KEY_RECORD }, + { 0x56, KEY_PAUSE }, + { 0x5e, KEY_STOP }, + { 0x46, KEY_PLAY }, + + { 0x6e, KEY_RED }, + { 0x0b, KEY_GREEN }, + { 0x66, KEY_YELLOW }, + { 0x03, KEY_BLUE }, + + { 0x76, KEY_LEFT }, + { 0x7e, KEY_RIGHT }, + { 0x13, KEY_DOWN }, + { 0x1b, KEY_UP }, +}; + +static struct rc_keymap avertv_303_map = { + .map = { + .scan = avertv_303, + .size = ARRAY_SIZE(avertv_303), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_AVERTV_303, + } +}; + +static int __init init_rc_map_avertv_303(void) +{ + return ir_register_map(&avertv_303_map); +} + +static void __exit exit_rc_map_avertv_303(void) +{ + ir_unregister_map(&avertv_303_map); +} + +module_init(init_rc_map_avertv_303) +module_exit(exit_rc_map_avertv_303) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-behold-columbus.c b/drivers/media/IR/keymaps/rc-behold-columbus.c new file mode 100644 index 000000000000..9f56c98fef5b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-behold-columbus.c @@ -0,0 +1,108 @@ +/* behold-columbus.h - Keytable for behold_columbus Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Beholder Intl. Ltd. 2008 + * Dmitry Belimov d.belimov@google.com + * Keytable is used by BeholdTV Columbus + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ + +static struct ir_scancode behold_columbus[] = { + + /* 0x13 0x11 0x1C 0x12 * + * Mute Source TV/FM Power * + * */ + + { 0x13, KEY_MUTE }, + { 0x11, KEY_PROPS }, + { 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */ + { 0x12, KEY_POWER }, + + /* 0x01 0x02 0x03 0x0D * + * 1 2 3 Stereo * + * * + * 0x04 0x05 0x06 0x19 * + * 4 5 6 Snapshot * + * * + * 0x07 0x08 0x09 0x10 * + * 7 8 9 Zoom * + * */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x0D, KEY_SETUP }, /* Setup key */ + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x19, KEY_CAMERA }, /* Snapshot key */ + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x10, KEY_ZOOM }, + + /* 0x0A 0x00 0x0B 0x0C * + * RECALL 0 ChannelUp VolumeUp * + * */ + { 0x0A, KEY_AGAIN }, + { 0x00, KEY_0 }, + { 0x0B, KEY_CHANNELUP }, + { 0x0C, KEY_VOLUMEUP }, + + /* 0x1B 0x1D 0x15 0x18 * + * Timeshift Record ChannelDown VolumeDown * + * */ + + { 0x1B, KEY_TIME }, + { 0x1D, KEY_RECORD }, + { 0x15, KEY_CHANNELDOWN }, + { 0x18, KEY_VOLUMEDOWN }, + + /* 0x0E 0x1E 0x0F 0x1A * + * Stop Pause Previouse Next * + * */ + + { 0x0E, KEY_STOP }, + { 0x1E, KEY_PAUSE }, + { 0x0F, KEY_PREVIOUS }, + { 0x1A, KEY_NEXT }, + +}; + +static struct rc_keymap behold_columbus_map = { + .map = { + .scan = behold_columbus, + .size = ARRAY_SIZE(behold_columbus), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_BEHOLD_COLUMBUS, + } +}; + +static int __init init_rc_map_behold_columbus(void) +{ + return ir_register_map(&behold_columbus_map); +} + +static void __exit exit_rc_map_behold_columbus(void) +{ + ir_unregister_map(&behold_columbus_map); +} + +module_init(init_rc_map_behold_columbus) +module_exit(exit_rc_map_behold_columbus) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-behold.c b/drivers/media/IR/keymaps/rc-behold.c new file mode 100644 index 000000000000..abc140b2098b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-behold.c @@ -0,0 +1,141 @@ +/* behold.h - Keytable for behold Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Igor Kuznetsov + * Andrey J. Melnikov + * + * Keytable is used by BeholdTV 60x series, M6 series at + * least, and probably other cards too. + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ + +static struct ir_scancode behold[] = { + + /* 0x1c 0x12 * + * TV/FM POWER * + * */ + { 0x1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */ + { 0x12, KEY_POWER }, + + /* 0x01 0x02 0x03 * + * 1 2 3 * + * * + * 0x04 0x05 0x06 * + * 4 5 6 * + * * + * 0x07 0x08 0x09 * + * 7 8 9 * + * */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + /* 0x0a 0x00 0x17 * + * RECALL 0 MODE * + * */ + { 0x0a, KEY_AGAIN }, + { 0x00, KEY_0 }, + { 0x17, KEY_MODE }, + + /* 0x14 0x10 * + * ASPECT FULLSCREEN * + * */ + { 0x14, KEY_SCREEN }, + { 0x10, KEY_ZOOM }, + + /* 0x0b * + * Up * + * * + * 0x18 0x16 0x0c * + * Left Ok Right * + * * + * 0x015 * + * Down * + * */ + { 0x0b, KEY_CHANNELUP }, + { 0x18, KEY_VOLUMEDOWN }, + { 0x16, KEY_OK }, /* XXX KEY_ENTER */ + { 0x0c, KEY_VOLUMEUP }, + { 0x15, KEY_CHANNELDOWN }, + + /* 0x11 0x0d * + * MUTE INFO * + * */ + { 0x11, KEY_MUTE }, + { 0x0d, KEY_INFO }, + + /* 0x0f 0x1b 0x1a * + * RECORD PLAY/PAUSE STOP * + * * + * 0x0e 0x1f 0x1e * + *TELETEXT AUDIO SOURCE * + * RED YELLOW * + * */ + { 0x0f, KEY_RECORD }, + { 0x1b, KEY_PLAYPAUSE }, + { 0x1a, KEY_STOP }, + { 0x0e, KEY_TEXT }, + { 0x1f, KEY_RED }, /*XXX KEY_AUDIO */ + { 0x1e, KEY_YELLOW }, /*XXX KEY_SOURCE */ + + /* 0x1d 0x13 0x19 * + * SLEEP PREVIEW DVB * + * GREEN BLUE * + * */ + { 0x1d, KEY_SLEEP }, + { 0x13, KEY_GREEN }, + { 0x19, KEY_BLUE }, /* XXX KEY_SAT */ + + /* 0x58 0x5c * + * FREEZE SNAPSHOT * + * */ + { 0x58, KEY_SLOW }, + { 0x5c, KEY_CAMERA }, + +}; + +static struct rc_keymap behold_map = { + .map = { + .scan = behold, + .size = ARRAY_SIZE(behold), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_BEHOLD, + } +}; + +static int __init init_rc_map_behold(void) +{ + return ir_register_map(&behold_map); +} + +static void __exit exit_rc_map_behold(void) +{ + ir_unregister_map(&behold_map); +} + +module_init(init_rc_map_behold) +module_exit(exit_rc_map_behold) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-budget-ci-old.c b/drivers/media/IR/keymaps/rc-budget-ci-old.c new file mode 100644 index 000000000000..64c2ac913338 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-budget-ci-old.c @@ -0,0 +1,92 @@ +/* budget-ci-old.h - Keytable for budget_ci_old Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* From reading the following remotes: + * Zenith Universal 7 / TV Mode 807 / VCR Mode 837 + * Hauppauge (from NOVA-CI-s box product) + * This is a "middle of the road" approach, differences are noted + */ + +static struct ir_scancode budget_ci_old[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_ENTER }, + { 0x0b, KEY_RED }, + { 0x0c, KEY_POWER }, /* RADIO on Hauppauge */ + { 0x0d, KEY_MUTE }, + { 0x0f, KEY_A }, /* TV on Hauppauge */ + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x14, KEY_B }, + { 0x1c, KEY_UP }, + { 0x1d, KEY_DOWN }, + { 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */ + { 0x1f, KEY_BREAK }, + { 0x20, KEY_CHANNELUP }, + { 0x21, KEY_CHANNELDOWN }, + { 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */ + { 0x24, KEY_RESTART }, + { 0x25, KEY_OK }, + { 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */ + { 0x28, KEY_ENTER }, /* VCR mode on Zenith */ + { 0x29, KEY_PAUSE }, + { 0x2b, KEY_RIGHT }, + { 0x2c, KEY_LEFT }, + { 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */ + { 0x30, KEY_SLOW }, + { 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */ + { 0x32, KEY_REWIND }, + { 0x34, KEY_FASTFORWARD }, + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, + { 0x38, KEY_TUNER }, /* TV/VCR on Zenith */ + { 0x3a, KEY_C }, + { 0x3c, KEY_EXIT }, + { 0x3d, KEY_POWER2 }, + { 0x3e, KEY_TUNER }, +}; + +static struct rc_keymap budget_ci_old_map = { + .map = { + .scan = budget_ci_old, + .size = ARRAY_SIZE(budget_ci_old), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_BUDGET_CI_OLD, + } +}; + +static int __init init_rc_map_budget_ci_old(void) +{ + return ir_register_map(&budget_ci_old_map); +} + +static void __exit exit_rc_map_budget_ci_old(void) +{ + ir_unregister_map(&budget_ci_old_map); +} + +module_init(init_rc_map_budget_ci_old) +module_exit(exit_rc_map_budget_ci_old) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-cinergy-1400.c b/drivers/media/IR/keymaps/rc-cinergy-1400.c new file mode 100644 index 000000000000..074f2c2c2c61 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-cinergy-1400.c @@ -0,0 +1,84 @@ +/* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Cinergy 1400 DVB-T */ + +static struct ir_scancode cinergy_1400[] = { + { 0x01, KEY_POWER }, + { 0x02, KEY_1 }, + { 0x03, KEY_2 }, + { 0x04, KEY_3 }, + { 0x05, KEY_4 }, + { 0x06, KEY_5 }, + { 0x07, KEY_6 }, + { 0x08, KEY_7 }, + { 0x09, KEY_8 }, + { 0x0a, KEY_9 }, + { 0x0c, KEY_0 }, + + { 0x0b, KEY_VIDEO }, + { 0x0d, KEY_REFRESH }, + { 0x0e, KEY_SELECT }, + { 0x0f, KEY_EPG }, + { 0x10, KEY_UP }, + { 0x11, KEY_LEFT }, + { 0x12, KEY_OK }, + { 0x13, KEY_RIGHT }, + { 0x14, KEY_DOWN }, + { 0x15, KEY_TEXT }, + { 0x16, KEY_INFO }, + + { 0x17, KEY_RED }, + { 0x18, KEY_GREEN }, + { 0x19, KEY_YELLOW }, + { 0x1a, KEY_BLUE }, + + { 0x1b, KEY_CHANNELUP }, + { 0x1c, KEY_VOLUMEUP }, + { 0x1d, KEY_MUTE }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_CHANNELDOWN }, + + { 0x40, KEY_PAUSE }, + { 0x4c, KEY_PLAY }, + { 0x58, KEY_RECORD }, + { 0x54, KEY_PREVIOUS }, + { 0x48, KEY_STOP }, + { 0x5c, KEY_NEXT }, +}; + +static struct rc_keymap cinergy_1400_map = { + .map = { + .scan = cinergy_1400, + .size = ARRAY_SIZE(cinergy_1400), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_CINERGY_1400, + } +}; + +static int __init init_rc_map_cinergy_1400(void) +{ + return ir_register_map(&cinergy_1400_map); +} + +static void __exit exit_rc_map_cinergy_1400(void) +{ + ir_unregister_map(&cinergy_1400_map); +} + +module_init(init_rc_map_cinergy_1400) +module_exit(exit_rc_map_cinergy_1400) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-cinergy.c b/drivers/media/IR/keymaps/rc-cinergy.c new file mode 100644 index 000000000000..cf84c3dba742 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-cinergy.c @@ -0,0 +1,78 @@ +/* cinergy.h - Keytable for cinergy Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode cinergy[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_POWER }, + { 0x0b, KEY_PROG1 }, /* app */ + { 0x0c, KEY_ZOOM }, /* zoom/fullscreen */ + { 0x0d, KEY_CHANNELUP }, /* channel */ + { 0x0e, KEY_CHANNELDOWN }, /* channel- */ + { 0x0f, KEY_VOLUMEUP }, + { 0x10, KEY_VOLUMEDOWN }, + { 0x11, KEY_TUNER }, /* AV */ + { 0x12, KEY_NUMLOCK }, /* -/-- */ + { 0x13, KEY_AUDIO }, /* audio */ + { 0x14, KEY_MUTE }, + { 0x15, KEY_UP }, + { 0x16, KEY_DOWN }, + { 0x17, KEY_LEFT }, + { 0x18, KEY_RIGHT }, + { 0x19, BTN_LEFT, }, + { 0x1a, BTN_RIGHT, }, + { 0x1b, KEY_WWW }, /* text */ + { 0x1c, KEY_REWIND }, + { 0x1d, KEY_FORWARD }, + { 0x1e, KEY_RECORD }, + { 0x1f, KEY_PLAY }, + { 0x20, KEY_PREVIOUSSONG }, + { 0x21, KEY_NEXTSONG }, + { 0x22, KEY_PAUSE }, + { 0x23, KEY_STOP }, +}; + +static struct rc_keymap cinergy_map = { + .map = { + .scan = cinergy, + .size = ARRAY_SIZE(cinergy), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_CINERGY, + } +}; + +static int __init init_rc_map_cinergy(void) +{ + return ir_register_map(&cinergy_map); +} + +static void __exit exit_rc_map_cinergy(void) +{ + ir_unregister_map(&cinergy_map); +} + +module_init(init_rc_map_cinergy) +module_exit(exit_rc_map_cinergy) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-dm1105-nec.c b/drivers/media/IR/keymaps/rc-dm1105-nec.c new file mode 100644 index 000000000000..90684d0efea3 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-dm1105-nec.c @@ -0,0 +1,76 @@ +/* dm1105-nec.h - Keytable for dm1105_nec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DVBWorld remotes + Igor M. Liplianin + */ + +static struct ir_scancode dm1105_nec[] = { + { 0x0a, KEY_POWER2}, /* power */ + { 0x0c, KEY_MUTE}, /* mute */ + { 0x11, KEY_1}, + { 0x12, KEY_2}, + { 0x13, KEY_3}, + { 0x14, KEY_4}, + { 0x15, KEY_5}, + { 0x16, KEY_6}, + { 0x17, KEY_7}, + { 0x18, KEY_8}, + { 0x19, KEY_9}, + { 0x10, KEY_0}, + { 0x1c, KEY_CHANNELUP}, /* ch+ */ + { 0x0f, KEY_CHANNELDOWN}, /* ch- */ + { 0x1a, KEY_VOLUMEUP}, /* vol+ */ + { 0x0e, KEY_VOLUMEDOWN}, /* vol- */ + { 0x04, KEY_RECORD}, /* rec */ + { 0x09, KEY_CHANNEL}, /* fav */ + { 0x08, KEY_BACKSPACE}, /* rewind */ + { 0x07, KEY_FASTFORWARD}, /* fast */ + { 0x0b, KEY_PAUSE}, /* pause */ + { 0x02, KEY_ESC}, /* cancel */ + { 0x03, KEY_TAB}, /* tab */ + { 0x00, KEY_UP}, /* up */ + { 0x1f, KEY_ENTER}, /* ok */ + { 0x01, KEY_DOWN}, /* down */ + { 0x05, KEY_RECORD}, /* cap */ + { 0x06, KEY_STOP}, /* stop */ + { 0x40, KEY_ZOOM}, /* full */ + { 0x1e, KEY_TV}, /* tvmode */ + { 0x1b, KEY_B}, /* recall */ +}; + +static struct rc_keymap dm1105_nec_map = { + .map = { + .scan = dm1105_nec, + .size = ARRAY_SIZE(dm1105_nec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_DM1105_NEC, + } +}; + +static int __init init_rc_map_dm1105_nec(void) +{ + return ir_register_map(&dm1105_nec_map); +} + +static void __exit exit_rc_map_dm1105_nec(void) +{ + ir_unregister_map(&dm1105_nec_map); +} + +module_init(init_rc_map_dm1105_nec) +module_exit(exit_rc_map_dm1105_nec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c new file mode 100644 index 000000000000..8a4027af964a --- /dev/null +++ b/drivers/media/IR/keymaps/rc-dntv-live-dvb-t.c @@ -0,0 +1,78 @@ +/* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DigitalNow DNTV Live DVB-T Remote */ + +static struct ir_scancode dntv_live_dvb_t[] = { + { 0x00, KEY_ESC }, /* 'go up a level?' */ + /* Keys 0 to 9 */ + { 0x0a, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0b, KEY_TUNER }, /* tv/fm */ + { 0x0c, KEY_SEARCH }, /* scan */ + { 0x0d, KEY_STOP }, + { 0x0e, KEY_PAUSE }, + { 0x0f, KEY_LIST }, /* source */ + + { 0x10, KEY_MUTE }, + { 0x11, KEY_REWIND }, /* backward << */ + { 0x12, KEY_POWER }, + { 0x13, KEY_CAMERA }, /* snap */ + { 0x14, KEY_AUDIO }, /* stereo */ + { 0x15, KEY_CLEAR }, /* reset */ + { 0x16, KEY_PLAY }, + { 0x17, KEY_ENTER }, + { 0x18, KEY_ZOOM }, /* full screen */ + { 0x19, KEY_FASTFORWARD }, /* forward >> */ + { 0x1a, KEY_CHANNELUP }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1c, KEY_INFO }, /* preview */ + { 0x1d, KEY_RECORD }, /* record */ + { 0x1e, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEDOWN }, +}; + +static struct rc_keymap dntv_live_dvb_t_map = { + .map = { + .scan = dntv_live_dvb_t, + .size = ARRAY_SIZE(dntv_live_dvb_t), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_DNTV_LIVE_DVB_T, + } +}; + +static int __init init_rc_map_dntv_live_dvb_t(void) +{ + return ir_register_map(&dntv_live_dvb_t_map); +} + +static void __exit exit_rc_map_dntv_live_dvb_t(void) +{ + ir_unregister_map(&dntv_live_dvb_t_map); +} + +module_init(init_rc_map_dntv_live_dvb_t) +module_exit(exit_rc_map_dntv_live_dvb_t) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c b/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c new file mode 100644 index 000000000000..6f4d60764d59 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-dntv-live-dvbt-pro.c @@ -0,0 +1,97 @@ +/* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DigitalNow DNTV Live! DVB-T Pro Remote */ + +static struct ir_scancode dntv_live_dvbt_pro[] = { + { 0x16, KEY_POWER }, + { 0x5b, KEY_HOME }, + + { 0x55, KEY_TV }, /* live tv */ + { 0x58, KEY_TUNER }, /* digital Radio */ + { 0x5a, KEY_RADIO }, /* FM radio */ + { 0x59, KEY_DVD }, /* dvd menu */ + { 0x03, KEY_1 }, + { 0x01, KEY_2 }, + { 0x06, KEY_3 }, + { 0x09, KEY_4 }, + { 0x1d, KEY_5 }, + { 0x1f, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x19, KEY_8 }, + { 0x1b, KEY_9 }, + { 0x0c, KEY_CANCEL }, + { 0x15, KEY_0 }, + { 0x4a, KEY_CLEAR }, + { 0x13, KEY_BACK }, + { 0x00, KEY_TAB }, + { 0x4b, KEY_UP }, + { 0x4e, KEY_LEFT }, + { 0x4f, KEY_OK }, + { 0x52, KEY_RIGHT }, + { 0x51, KEY_DOWN }, + { 0x1e, KEY_VOLUMEUP }, + { 0x0a, KEY_VOLUMEDOWN }, + { 0x02, KEY_CHANNELDOWN }, + { 0x05, KEY_CHANNELUP }, + { 0x11, KEY_RECORD }, + { 0x14, KEY_PLAY }, + { 0x4c, KEY_PAUSE }, + { 0x1a, KEY_STOP }, + { 0x40, KEY_REWIND }, + { 0x12, KEY_FASTFORWARD }, + { 0x41, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x42, KEY_NEXTSONG }, /* skip >| */ + { 0x54, KEY_CAMERA }, /* capture */ + { 0x50, KEY_LANGUAGE }, /* sap */ + { 0x47, KEY_TV2 }, /* pip */ + { 0x4d, KEY_SCREEN }, + { 0x43, KEY_SUBTITLE }, + { 0x10, KEY_MUTE }, + { 0x49, KEY_AUDIO }, /* l/r */ + { 0x07, KEY_SLEEP }, + { 0x08, KEY_VIDEO }, /* a/v */ + { 0x0e, KEY_PREVIOUS }, /* recall */ + { 0x45, KEY_ZOOM }, /* zoom + */ + { 0x46, KEY_ANGLE }, /* zoom - */ + { 0x56, KEY_RED }, + { 0x57, KEY_GREEN }, + { 0x5c, KEY_YELLOW }, + { 0x5d, KEY_BLUE }, +}; + +static struct rc_keymap dntv_live_dvbt_pro_map = { + .map = { + .scan = dntv_live_dvbt_pro, + .size = ARRAY_SIZE(dntv_live_dvbt_pro), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_DNTV_LIVE_DVBT_PRO, + } +}; + +static int __init init_rc_map_dntv_live_dvbt_pro(void) +{ + return ir_register_map(&dntv_live_dvbt_pro_map); +} + +static void __exit exit_rc_map_dntv_live_dvbt_pro(void) +{ + ir_unregister_map(&dntv_live_dvbt_pro_map); +} + +module_init(init_rc_map_dntv_live_dvbt_pro) +module_exit(exit_rc_map_dntv_live_dvbt_pro) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-em-terratec.c b/drivers/media/IR/keymaps/rc-em-terratec.c new file mode 100644 index 000000000000..3130c9c29e6b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-em-terratec.c @@ -0,0 +1,69 @@ +/* em-terratec.h - Keytable for em_terratec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode em_terratec[] = { + { 0x01, KEY_CHANNEL }, + { 0x02, KEY_SELECT }, + { 0x03, KEY_MUTE }, + { 0x04, KEY_POWER }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x08, KEY_CHANNELUP }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0c, KEY_CHANNELDOWN }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_0 }, + { 0x12, KEY_MENU }, + { 0x13, KEY_PRINT }, + { 0x14, KEY_VOLUMEDOWN }, + { 0x16, KEY_PAUSE }, + { 0x18, KEY_RECORD }, + { 0x19, KEY_REWIND }, + { 0x1a, KEY_PLAY }, + { 0x1b, KEY_FORWARD }, + { 0x1c, KEY_BACKSPACE }, + { 0x1e, KEY_STOP }, + { 0x40, KEY_ZOOM }, +}; + +static struct rc_keymap em_terratec_map = { + .map = { + .scan = em_terratec, + .size = ARRAY_SIZE(em_terratec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EM_TERRATEC, + } +}; + +static int __init init_rc_map_em_terratec(void) +{ + return ir_register_map(&em_terratec_map); +} + +static void __exit exit_rc_map_em_terratec(void) +{ + ir_unregister_map(&em_terratec_map); +} + +module_init(init_rc_map_em_terratec) +module_exit(exit_rc_map_em_terratec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-empty.c b/drivers/media/IR/keymaps/rc-empty.c new file mode 100644 index 000000000000..3b338d84b476 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-empty.c @@ -0,0 +1,44 @@ +/* empty.h - Keytable for empty Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* empty keytable, can be used as placeholder for not-yet created keytables */ + +static struct ir_scancode empty[] = { + { 0x2a, KEY_COFFEE }, +}; + +static struct rc_keymap empty_map = { + .map = { + .scan = empty, + .size = ARRAY_SIZE(empty), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EMPTY, + } +}; + +static int __init init_rc_map_empty(void) +{ + return ir_register_map(&empty_map); +} + +static void __exit exit_rc_map_empty(void) +{ + ir_unregister_map(&empty_map); +} + +module_init(init_rc_map_empty) +module_exit(exit_rc_map_empty) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c b/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c new file mode 100644 index 000000000000..4b816967877e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-encore-enltv-fm53.c @@ -0,0 +1,81 @@ +/* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Encore ENLTV-FM v5.3 + Mauro Carvalho Chehab + */ + +static struct ir_scancode encore_enltv_fm53[] = { + { 0x10, KEY_POWER2}, + { 0x06, KEY_MUTE}, + + { 0x09, KEY_1}, + { 0x1d, KEY_2}, + { 0x1f, KEY_3}, + { 0x19, KEY_4}, + { 0x1b, KEY_5}, + { 0x11, KEY_6}, + { 0x17, KEY_7}, + { 0x12, KEY_8}, + { 0x16, KEY_9}, + { 0x48, KEY_0}, + + { 0x04, KEY_LIST}, /* -/-- */ + { 0x40, KEY_LAST}, /* recall */ + + { 0x02, KEY_MODE}, /* TV/AV */ + { 0x05, KEY_CAMERA}, /* SNAPSHOT */ + + { 0x4c, KEY_CHANNELUP}, /* UP */ + { 0x00, KEY_CHANNELDOWN}, /* DOWN */ + { 0x0d, KEY_VOLUMEUP}, /* RIGHT */ + { 0x15, KEY_VOLUMEDOWN}, /* LEFT */ + { 0x49, KEY_ENTER}, /* OK */ + + { 0x54, KEY_RECORD}, + { 0x4d, KEY_PLAY}, /* pause */ + + { 0x1e, KEY_MENU}, /* video setting */ + { 0x0e, KEY_RIGHT}, /* <- */ + { 0x1a, KEY_LEFT}, /* -> */ + + { 0x0a, KEY_CLEAR}, /* video default */ + { 0x0c, KEY_ZOOM}, /* hide pannel */ + { 0x47, KEY_SLEEP}, /* shutdown */ +}; + +static struct rc_keymap encore_enltv_fm53_map = { + .map = { + .scan = encore_enltv_fm53, + .size = ARRAY_SIZE(encore_enltv_fm53), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ENCORE_ENLTV_FM53, + } +}; + +static int __init init_rc_map_encore_enltv_fm53(void) +{ + return ir_register_map(&encore_enltv_fm53_map); +} + +static void __exit exit_rc_map_encore_enltv_fm53(void) +{ + ir_unregister_map(&encore_enltv_fm53_map); +} + +module_init(init_rc_map_encore_enltv_fm53) +module_exit(exit_rc_map_encore_enltv_fm53) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-encore-enltv.c b/drivers/media/IR/keymaps/rc-encore-enltv.c new file mode 100644 index 000000000000..9fabffd28cc9 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-encore-enltv.c @@ -0,0 +1,112 @@ +/* encore-enltv.h - Keytable for encore_enltv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons + Juan Pablo Sormani */ + +static struct ir_scancode encore_enltv[] = { + + /* Power button does nothing, neither in Windows app, + although it sends data (used for BIOS wakeup?) */ + { 0x0d, KEY_MUTE }, + + { 0x1e, KEY_TV }, + { 0x00, KEY_VIDEO }, + { 0x01, KEY_AUDIO }, /* music */ + { 0x02, KEY_MHP }, /* picture */ + + { 0x1f, KEY_1 }, + { 0x03, KEY_2 }, + { 0x04, KEY_3 }, + { 0x05, KEY_4 }, + { 0x1c, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x1d, KEY_9 }, + { 0x0a, KEY_0 }, + + { 0x09, KEY_LIST }, /* -/-- */ + { 0x0b, KEY_LAST }, /* recall */ + + { 0x14, KEY_HOME }, /* win start menu */ + { 0x15, KEY_EXIT }, /* exit */ + { 0x16, KEY_CHANNELUP }, /* UP */ + { 0x12, KEY_CHANNELDOWN }, /* DOWN */ + { 0x0c, KEY_VOLUMEUP }, /* RIGHT */ + { 0x17, KEY_VOLUMEDOWN }, /* LEFT */ + + { 0x18, KEY_ENTER }, /* OK */ + + { 0x0e, KEY_ESC }, + { 0x13, KEY_CYCLEWINDOWS }, /* desktop */ + { 0x11, KEY_TAB }, + { 0x19, KEY_SWITCHVIDEOMODE }, /* switch */ + + { 0x1a, KEY_MENU }, + { 0x1b, KEY_ZOOM }, /* fullscreen */ + { 0x44, KEY_TIME }, /* time shift */ + { 0x40, KEY_MODE }, /* source */ + + { 0x5a, KEY_RECORD }, + { 0x42, KEY_PLAY }, /* play/pause */ + { 0x45, KEY_STOP }, + { 0x43, KEY_CAMERA }, /* camera icon */ + + { 0x48, KEY_REWIND }, + { 0x4a, KEY_FASTFORWARD }, + { 0x49, KEY_PREVIOUS }, + { 0x4b, KEY_NEXT }, + + { 0x4c, KEY_FAVORITES }, /* tv wall */ + { 0x4d, KEY_SOUND }, /* DVD sound */ + { 0x4e, KEY_LANGUAGE }, /* DVD lang */ + { 0x4f, KEY_TEXT }, /* DVD text */ + + { 0x50, KEY_SLEEP }, /* shutdown */ + { 0x51, KEY_MODE }, /* stereo > main */ + { 0x52, KEY_SELECT }, /* stereo > sap */ + { 0x53, KEY_PROG1 }, /* teletext */ + + + { 0x59, KEY_RED }, /* AP1 */ + { 0x41, KEY_GREEN }, /* AP2 */ + { 0x47, KEY_YELLOW }, /* AP3 */ + { 0x57, KEY_BLUE }, /* AP4 */ +}; + +static struct rc_keymap encore_enltv_map = { + .map = { + .scan = encore_enltv, + .size = ARRAY_SIZE(encore_enltv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ENCORE_ENLTV, + } +}; + +static int __init init_rc_map_encore_enltv(void) +{ + return ir_register_map(&encore_enltv_map); +} + +static void __exit exit_rc_map_encore_enltv(void) +{ + ir_unregister_map(&encore_enltv_map); +} + +module_init(init_rc_map_encore_enltv) +module_exit(exit_rc_map_encore_enltv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-encore-enltv2.c b/drivers/media/IR/keymaps/rc-encore-enltv2.c new file mode 100644 index 000000000000..efefd5166618 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-encore-enltv2.c @@ -0,0 +1,90 @@ +/* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton + Mauro Carvalho Chehab */ + +static struct ir_scancode encore_enltv2[] = { + { 0x4c, KEY_POWER2 }, + { 0x4a, KEY_TUNER }, + { 0x40, KEY_1 }, + { 0x60, KEY_2 }, + { 0x50, KEY_3 }, + { 0x70, KEY_4 }, + { 0x48, KEY_5 }, + { 0x68, KEY_6 }, + { 0x58, KEY_7 }, + { 0x78, KEY_8 }, + { 0x44, KEY_9 }, + { 0x54, KEY_0 }, + + { 0x64, KEY_LAST }, /* +100 */ + { 0x4e, KEY_AGAIN }, /* Recall */ + + { 0x6c, KEY_SWITCHVIDEOMODE }, /* Video Source */ + { 0x5e, KEY_MENU }, + { 0x56, KEY_SCREEN }, + { 0x7a, KEY_SETUP }, + + { 0x46, KEY_MUTE }, + { 0x5c, KEY_MODE }, /* Stereo */ + { 0x74, KEY_INFO }, + { 0x7c, KEY_CLEAR }, + + { 0x55, KEY_UP }, + { 0x49, KEY_DOWN }, + { 0x7e, KEY_LEFT }, + { 0x59, KEY_RIGHT }, + { 0x6a, KEY_ENTER }, + + { 0x42, KEY_VOLUMEUP }, + { 0x62, KEY_VOLUMEDOWN }, + { 0x52, KEY_CHANNELUP }, + { 0x72, KEY_CHANNELDOWN }, + + { 0x41, KEY_RECORD }, + { 0x51, KEY_CAMERA }, /* Snapshot */ + { 0x75, KEY_TIME }, /* Timeshift */ + { 0x71, KEY_TV2 }, /* PIP */ + + { 0x45, KEY_REWIND }, + { 0x6f, KEY_PAUSE }, + { 0x7d, KEY_FORWARD }, + { 0x79, KEY_STOP }, +}; + +static struct rc_keymap encore_enltv2_map = { + .map = { + .scan = encore_enltv2, + .size = ARRAY_SIZE(encore_enltv2), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_ENCORE_ENLTV2, + } +}; + +static int __init init_rc_map_encore_enltv2(void) +{ + return ir_register_map(&encore_enltv2_map); +} + +static void __exit exit_rc_map_encore_enltv2(void) +{ + ir_unregister_map(&encore_enltv2_map); +} + +module_init(init_rc_map_encore_enltv2) +module_exit(exit_rc_map_encore_enltv2) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-evga-indtube.c b/drivers/media/IR/keymaps/rc-evga-indtube.c new file mode 100644 index 000000000000..3f3fb13813b3 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-evga-indtube.c @@ -0,0 +1,61 @@ +/* evga-indtube.h - Keytable for evga_indtube Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* EVGA inDtube + Devin Heitmueller + */ + +static struct ir_scancode evga_indtube[] = { + { 0x12, KEY_POWER}, + { 0x02, KEY_MODE}, /* TV */ + { 0x14, KEY_MUTE}, + { 0x1a, KEY_CHANNELUP}, + { 0x16, KEY_TV2}, /* PIP */ + { 0x1d, KEY_VOLUMEUP}, + { 0x05, KEY_CHANNELDOWN}, + { 0x0f, KEY_PLAYPAUSE}, + { 0x19, KEY_VOLUMEDOWN}, + { 0x1c, KEY_REWIND}, + { 0x0d, KEY_RECORD}, + { 0x18, KEY_FORWARD}, + { 0x1e, KEY_PREVIOUS}, + { 0x1b, KEY_STOP}, + { 0x1f, KEY_NEXT}, + { 0x13, KEY_CAMERA}, +}; + +static struct rc_keymap evga_indtube_map = { + .map = { + .scan = evga_indtube, + .size = ARRAY_SIZE(evga_indtube), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EVGA_INDTUBE, + } +}; + +static int __init init_rc_map_evga_indtube(void) +{ + return ir_register_map(&evga_indtube_map); +} + +static void __exit exit_rc_map_evga_indtube(void) +{ + ir_unregister_map(&evga_indtube_map); +} + +module_init(init_rc_map_evga_indtube) +module_exit(exit_rc_map_evga_indtube) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-eztv.c b/drivers/media/IR/keymaps/rc-eztv.c new file mode 100644 index 000000000000..660907a78db9 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-eztv.c @@ -0,0 +1,96 @@ +/* eztv.h - Keytable for eztv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Alfons Geser + * updates from Job D. R. Borges */ + +static struct ir_scancode eztv[] = { + { 0x12, KEY_POWER }, + { 0x01, KEY_TV }, /* DVR */ + { 0x15, KEY_DVD }, /* DVD */ + { 0x17, KEY_AUDIO }, /* music */ + /* DVR mode / DVD mode / music mode */ + + { 0x1b, KEY_MUTE }, /* mute */ + { 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */ + { 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */ + { 0x16, KEY_ZOOM }, /* full screen */ + { 0x1c, KEY_VIDEO }, /* video source / eject / delall */ + { 0x1d, KEY_RESTART }, /* playback / angle / del */ + { 0x2f, KEY_SEARCH }, /* scan / menu / playlist */ + { 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */ + + { 0x31, KEY_HELP }, /* help */ + { 0x32, KEY_MODE }, /* num/memo */ + { 0x33, KEY_ESC }, /* cancel */ + + { 0x0c, KEY_UP }, /* up */ + { 0x10, KEY_DOWN }, /* down */ + { 0x08, KEY_LEFT }, /* left */ + { 0x04, KEY_RIGHT }, /* right */ + { 0x03, KEY_SELECT }, /* select */ + + { 0x1f, KEY_REWIND }, /* rewind */ + { 0x20, KEY_PLAYPAUSE },/* play/pause */ + { 0x29, KEY_FORWARD }, /* forward */ + { 0x14, KEY_AGAIN }, /* repeat */ + { 0x2b, KEY_RECORD }, /* recording */ + { 0x2c, KEY_STOP }, /* stop */ + { 0x2d, KEY_PLAY }, /* play */ + { 0x2e, KEY_CAMERA }, /* snapshot / shuffle */ + + { 0x00, KEY_0 }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + + { 0x2a, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x18, KEY_CHANNELUP },/* CH.tracking up */ + { 0x19, KEY_CHANNELDOWN },/* CH.tracking down */ + + { 0x13, KEY_ENTER }, /* enter */ + { 0x21, KEY_DOT }, /* . (decimal dot) */ +}; + +static struct rc_keymap eztv_map = { + .map = { + .scan = eztv, + .size = ARRAY_SIZE(eztv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_EZTV, + } +}; + +static int __init init_rc_map_eztv(void) +{ + return ir_register_map(&eztv_map); +} + +static void __exit exit_rc_map_eztv(void) +{ + ir_unregister_map(&eztv_map); +} + +module_init(init_rc_map_eztv) +module_exit(exit_rc_map_eztv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-flydvb.c b/drivers/media/IR/keymaps/rc-flydvb.c new file mode 100644 index 000000000000..a173c81035f4 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-flydvb.c @@ -0,0 +1,77 @@ +/* flydvb.h - Keytable for flydvb Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode flydvb[] = { + { 0x01, KEY_ZOOM }, /* Full Screen */ + { 0x00, KEY_POWER }, /* Power */ + + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x07, KEY_4 }, + { 0x08, KEY_5 }, + { 0x09, KEY_6 }, + { 0x0b, KEY_7 }, + { 0x0c, KEY_8 }, + { 0x0d, KEY_9 }, + { 0x06, KEY_AGAIN }, /* Recall */ + { 0x0f, KEY_0 }, + { 0x10, KEY_MUTE }, /* Mute */ + { 0x02, KEY_RADIO }, /* TV/Radio */ + { 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */ + + { 0x14, KEY_VOLUMEUP }, /* VOL+ */ + { 0x17, KEY_VOLUMEDOWN }, /* VOL- */ + { 0x12, KEY_CHANNELUP }, /* CH+ */ + { 0x13, KEY_CHANNELDOWN }, /* CH- */ + { 0x1d, KEY_ENTER }, /* Enter */ + + { 0x1a, KEY_MODE }, /* PIP */ + { 0x18, KEY_TUNER }, /* Source */ + + { 0x1e, KEY_RECORD }, /* Record/Pause */ + { 0x15, KEY_ANGLE }, /* Swap (no label on key) */ + { 0x1c, KEY_PAUSE }, /* Timeshift/Pause */ + { 0x19, KEY_BACK }, /* Rewind << */ + { 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */ + { 0x1f, KEY_FORWARD }, /* Forward >> */ + { 0x16, KEY_PREVIOUS }, /* Back |<< */ + { 0x11, KEY_STOP }, /* Stop */ + { 0x0e, KEY_NEXT }, /* End >>| */ +}; + +static struct rc_keymap flydvb_map = { + .map = { + .scan = flydvb, + .size = ARRAY_SIZE(flydvb), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_FLYDVB, + } +}; + +static int __init init_rc_map_flydvb(void) +{ + return ir_register_map(&flydvb_map); +} + +static void __exit exit_rc_map_flydvb(void) +{ + ir_unregister_map(&flydvb_map); +} + +module_init(init_rc_map_flydvb) +module_exit(exit_rc_map_flydvb) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-flyvideo.c b/drivers/media/IR/keymaps/rc-flyvideo.c new file mode 100644 index 000000000000..9c73043cbdba --- /dev/null +++ b/drivers/media/IR/keymaps/rc-flyvideo.c @@ -0,0 +1,70 @@ +/* flyvideo.h - Keytable for flyvideo Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode flyvideo[] = { + { 0x0f, KEY_0 }, + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x07, KEY_4 }, + { 0x08, KEY_5 }, + { 0x09, KEY_6 }, + { 0x0b, KEY_7 }, + { 0x0c, KEY_8 }, + { 0x0d, KEY_9 }, + + { 0x0e, KEY_MODE }, /* Air/Cable */ + { 0x11, KEY_VIDEO }, /* Video */ + { 0x15, KEY_AUDIO }, /* Audio */ + { 0x00, KEY_POWER }, /* Power */ + { 0x18, KEY_TUNER }, /* AV Source */ + { 0x02, KEY_ZOOM }, /* Fullscreen */ + { 0x1a, KEY_LANGUAGE }, /* Stereo */ + { 0x1b, KEY_MUTE }, /* Mute */ + { 0x14, KEY_VOLUMEUP }, /* Volume + */ + { 0x17, KEY_VOLUMEDOWN },/* Volume - */ + { 0x12, KEY_CHANNELUP },/* Channel + */ + { 0x13, KEY_CHANNELDOWN },/* Channel - */ + { 0x06, KEY_AGAIN }, /* Recall */ + { 0x10, KEY_ENTER }, /* Enter */ + + { 0x19, KEY_BACK }, /* Rewind ( <<< ) */ + { 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */ + { 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */ +}; + +static struct rc_keymap flyvideo_map = { + .map = { + .scan = flyvideo, + .size = ARRAY_SIZE(flyvideo), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_FLYVIDEO, + } +}; + +static int __init init_rc_map_flyvideo(void) +{ + return ir_register_map(&flyvideo_map); +} + +static void __exit exit_rc_map_flyvideo(void) +{ + ir_unregister_map(&flyvideo_map); +} + +module_init(init_rc_map_flyvideo) +module_exit(exit_rc_map_flyvideo) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c b/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c new file mode 100644 index 000000000000..cdb10389b10e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-fusionhdtv-mce.c @@ -0,0 +1,98 @@ +/* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* DViCO FUSION HDTV MCE remote */ + +static struct ir_scancode fusionhdtv_mce[] = { + + { 0x0b, KEY_1 }, + { 0x17, KEY_2 }, + { 0x1b, KEY_3 }, + { 0x07, KEY_4 }, + { 0x50, KEY_5 }, + { 0x54, KEY_6 }, + { 0x48, KEY_7 }, + { 0x4c, KEY_8 }, + { 0x58, KEY_9 }, + { 0x03, KEY_0 }, + + { 0x5e, KEY_OK }, + { 0x51, KEY_UP }, + { 0x53, KEY_DOWN }, + { 0x5b, KEY_LEFT }, + { 0x5f, KEY_RIGHT }, + + { 0x02, KEY_TV }, /* Labeled DTV on remote */ + { 0x0e, KEY_MP3 }, + { 0x1a, KEY_DVD }, + { 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */ + { 0x16, KEY_SETUP }, + { 0x46, KEY_POWER2 }, /* TV On/Off button on remote */ + { 0x0a, KEY_EPG }, /* Labeled Guide on remote */ + + { 0x49, KEY_BACK }, + { 0x59, KEY_INFO }, /* Labeled MORE on remote */ + { 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */ + { 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */ + + { 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */ + { 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */ + { 0x42, KEY_ENTER }, /* Labeled START with a green + MS windows logo on remote */ + + { 0x15, KEY_VOLUMEUP }, + { 0x05, KEY_VOLUMEDOWN }, + { 0x11, KEY_CHANNELUP }, + { 0x09, KEY_CHANNELDOWN }, + + { 0x52, KEY_CAMERA }, + { 0x5a, KEY_TUNER }, + { 0x19, KEY_OPEN }, + + { 0x13, KEY_MODE }, /* 4:3 16:9 select */ + { 0x1f, KEY_ZOOM }, + + { 0x43, KEY_REWIND }, + { 0x47, KEY_PLAYPAUSE }, + { 0x4f, KEY_FASTFORWARD }, + { 0x57, KEY_MUTE }, + { 0x0d, KEY_STOP }, + { 0x01, KEY_RECORD }, + { 0x4e, KEY_POWER }, +}; + +static struct rc_keymap fusionhdtv_mce_map = { + .map = { + .scan = fusionhdtv_mce, + .size = ARRAY_SIZE(fusionhdtv_mce), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_FUSIONHDTV_MCE, + } +}; + +static int __init init_rc_map_fusionhdtv_mce(void) +{ + return ir_register_map(&fusionhdtv_mce_map); +} + +static void __exit exit_rc_map_fusionhdtv_mce(void) +{ + ir_unregister_map(&fusionhdtv_mce_map); +} + +module_init(init_rc_map_fusionhdtv_mce) +module_exit(exit_rc_map_fusionhdtv_mce) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-gadmei-rm008z.c b/drivers/media/IR/keymaps/rc-gadmei-rm008z.c new file mode 100644 index 000000000000..c16c0d1263ac --- /dev/null +++ b/drivers/media/IR/keymaps/rc-gadmei-rm008z.c @@ -0,0 +1,81 @@ +/* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* GADMEI UTV330+ RM008Z remote + Shine Liu + */ + +static struct ir_scancode gadmei_rm008z[] = { + { 0x14, KEY_POWER2}, /* POWER OFF */ + { 0x0c, KEY_MUTE}, /* MUTE */ + + { 0x18, KEY_TV}, /* TV */ + { 0x0e, KEY_VIDEO}, /* AV */ + { 0x0b, KEY_AUDIO}, /* SV */ + { 0x0f, KEY_RADIO}, /* FM */ + + { 0x00, KEY_1}, + { 0x01, KEY_2}, + { 0x02, KEY_3}, + { 0x03, KEY_4}, + { 0x04, KEY_5}, + { 0x05, KEY_6}, + { 0x06, KEY_7}, + { 0x07, KEY_8}, + { 0x08, KEY_9}, + { 0x09, KEY_0}, + { 0x0a, KEY_INFO}, /* OSD */ + { 0x1c, KEY_BACKSPACE}, /* LAST */ + + { 0x0d, KEY_PLAY}, /* PLAY */ + { 0x1e, KEY_CAMERA}, /* SNAPSHOT */ + { 0x1a, KEY_RECORD}, /* RECORD */ + { 0x17, KEY_STOP}, /* STOP */ + + { 0x1f, KEY_UP}, /* UP */ + { 0x44, KEY_DOWN}, /* DOWN */ + { 0x46, KEY_TAB}, /* BACK */ + { 0x4a, KEY_ZOOM}, /* FULLSECREEN */ + + { 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */ + { 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ + { 0x12, KEY_CHANNELUP}, /* CHANNELUP */ + { 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */ + { 0x15, KEY_ENTER}, /* OK */ +}; + +static struct rc_keymap gadmei_rm008z_map = { + .map = { + .scan = gadmei_rm008z, + .size = ARRAY_SIZE(gadmei_rm008z), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_GADMEI_RM008Z, + } +}; + +static int __init init_rc_map_gadmei_rm008z(void) +{ + return ir_register_map(&gadmei_rm008z_map); +} + +static void __exit exit_rc_map_gadmei_rm008z(void) +{ + ir_unregister_map(&gadmei_rm008z_map); +} + +module_init(init_rc_map_gadmei_rm008z) +module_exit(exit_rc_map_gadmei_rm008z) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c b/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c new file mode 100644 index 000000000000..89f8e384e52a --- /dev/null +++ b/drivers/media/IR/keymaps/rc-genius-tvgo-a11mce.c @@ -0,0 +1,84 @@ +/* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Remote control for the Genius TVGO A11MCE + * Adrian Pardini + */ + +static struct ir_scancode genius_tvgo_a11mce[] = { + /* Keys 0 to 9 */ + { 0x48, KEY_0 }, + { 0x09, KEY_1 }, + { 0x1d, KEY_2 }, + { 0x1f, KEY_3 }, + { 0x19, KEY_4 }, + { 0x1b, KEY_5 }, + { 0x11, KEY_6 }, + { 0x17, KEY_7 }, + { 0x12, KEY_8 }, + { 0x16, KEY_9 }, + + { 0x54, KEY_RECORD }, /* recording */ + { 0x06, KEY_MUTE }, /* mute */ + { 0x10, KEY_POWER }, + { 0x40, KEY_LAST }, /* recall */ + { 0x4c, KEY_CHANNELUP }, /* channel / program + */ + { 0x00, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x0d, KEY_VOLUMEUP }, + { 0x15, KEY_VOLUMEDOWN }, + { 0x4d, KEY_OK }, /* also labeled as Pause */ + { 0x1c, KEY_ZOOM }, /* full screen and Stop*/ + { 0x02, KEY_MODE }, /* AV Source or Rewind*/ + { 0x04, KEY_LIST }, /* -/-- */ + /* small arrows above numbers */ + { 0x1a, KEY_NEXT }, /* also Fast Forward */ + { 0x0e, KEY_PREVIOUS }, /* also Rewind */ + /* these are in a rather non standard layout and have + an alternate name written */ + { 0x1e, KEY_UP }, /* Video Setting */ + { 0x0a, KEY_DOWN }, /* Video Default */ + { 0x05, KEY_CAMERA }, /* Snapshot */ + { 0x0c, KEY_RIGHT }, /* Hide Panel */ + /* Four buttons without label */ + { 0x49, KEY_RED }, + { 0x0b, KEY_GREEN }, + { 0x13, KEY_YELLOW }, + { 0x50, KEY_BLUE }, +}; + +static struct rc_keymap genius_tvgo_a11mce_map = { + .map = { + .scan = genius_tvgo_a11mce, + .size = ARRAY_SIZE(genius_tvgo_a11mce), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_GENIUS_TVGO_A11MCE, + } +}; + +static int __init init_rc_map_genius_tvgo_a11mce(void) +{ + return ir_register_map(&genius_tvgo_a11mce_map); +} + +static void __exit exit_rc_map_genius_tvgo_a11mce(void) +{ + ir_unregister_map(&genius_tvgo_a11mce_map); +} + +module_init(init_rc_map_genius_tvgo_a11mce) +module_exit(exit_rc_map_genius_tvgo_a11mce) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-gotview7135.c b/drivers/media/IR/keymaps/rc-gotview7135.c new file mode 100644 index 000000000000..52f025bb35f6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-gotview7135.c @@ -0,0 +1,79 @@ +/* gotview7135.h - Keytable for gotview7135 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Mike Baikov */ + +static struct ir_scancode gotview7135[] = { + + { 0x11, KEY_POWER }, + { 0x35, KEY_TV }, + { 0x1b, KEY_0 }, + { 0x29, KEY_1 }, + { 0x19, KEY_2 }, + { 0x39, KEY_3 }, + { 0x1f, KEY_4 }, + { 0x2c, KEY_5 }, + { 0x21, KEY_6 }, + { 0x24, KEY_7 }, + { 0x18, KEY_8 }, + { 0x2b, KEY_9 }, + { 0x3b, KEY_AGAIN }, /* LOOP */ + { 0x06, KEY_AUDIO }, + { 0x31, KEY_PRINT }, /* PREVIEW */ + { 0x3e, KEY_VIDEO }, + { 0x10, KEY_CHANNELUP }, + { 0x20, KEY_CHANNELDOWN }, + { 0x0c, KEY_VOLUMEDOWN }, + { 0x28, KEY_VOLUMEUP }, + { 0x08, KEY_MUTE }, + { 0x26, KEY_SEARCH }, /* SCAN */ + { 0x3f, KEY_CAMERA }, /* SNAPSHOT */ + { 0x12, KEY_RECORD }, + { 0x32, KEY_STOP }, + { 0x3c, KEY_PLAY }, + { 0x1d, KEY_REWIND }, + { 0x2d, KEY_PAUSE }, + { 0x0d, KEY_FORWARD }, + { 0x05, KEY_ZOOM }, /*FULL*/ + + { 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */ + { 0x0e, KEY_F22 }, /* MIN TIMESHIFT */ + { 0x1e, KEY_TIME }, /* TIMESHIFT */ + { 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */ +}; + +static struct rc_keymap gotview7135_map = { + .map = { + .scan = gotview7135, + .size = ARRAY_SIZE(gotview7135), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_GOTVIEW7135, + } +}; + +static int __init init_rc_map_gotview7135(void) +{ + return ir_register_map(&gotview7135_map); +} + +static void __exit exit_rc_map_gotview7135(void) +{ + ir_unregister_map(&gotview7135_map); +} + +module_init(init_rc_map_gotview7135) +module_exit(exit_rc_map_gotview7135) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-hauppauge-new.c b/drivers/media/IR/keymaps/rc-hauppauge-new.c new file mode 100644 index 000000000000..c6f8cd7c5186 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-hauppauge-new.c @@ -0,0 +1,100 @@ +/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Hauppauge: the newer, gray remotes (seems there are multiple + * slightly different versions), shipped with cx88+ivtv cards. + * almost rc5 coding, but some non-standard keys */ + +static struct ir_scancode hauppauge_new[] = { + /* Keys 0 to 9 */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_TEXT }, /* keypad asterisk as well */ + { 0x0b, KEY_RED }, /* red button */ + { 0x0c, KEY_RADIO }, + { 0x0d, KEY_MENU }, + { 0x0e, KEY_SUBTITLE }, /* also the # key */ + { 0x0f, KEY_MUTE }, + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x12, KEY_PREVIOUS }, /* previous channel */ + { 0x14, KEY_UP }, + { 0x15, KEY_DOWN }, + { 0x16, KEY_LEFT }, + { 0x17, KEY_RIGHT }, + { 0x18, KEY_VIDEO }, /* Videos */ + { 0x19, KEY_AUDIO }, /* Music */ + /* 0x1a: Pictures - presume this means + "Multimedia Home Platform" - + no "PICTURES" key in input.h + */ + { 0x1a, KEY_MHP }, + + { 0x1b, KEY_EPG }, /* Guide */ + { 0x1c, KEY_TV }, + { 0x1e, KEY_NEXTSONG }, /* skip >| */ + { 0x1f, KEY_EXIT }, /* back/exit */ + { 0x20, KEY_CHANNELUP }, /* channel / program + */ + { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x22, KEY_CHANNEL }, /* source (old black remote) */ + { 0x24, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x25, KEY_ENTER }, /* OK */ + { 0x26, KEY_SLEEP }, /* minimize (old black remote) */ + { 0x29, KEY_BLUE }, /* blue key */ + { 0x2e, KEY_GREEN }, /* green button */ + { 0x30, KEY_PAUSE }, /* pause */ + { 0x32, KEY_REWIND }, /* backward << */ + { 0x34, KEY_FASTFORWARD }, /* forward >> */ + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, /* recording */ + { 0x38, KEY_YELLOW }, /* yellow key */ + { 0x3b, KEY_SELECT }, /* top right button */ + { 0x3c, KEY_ZOOM }, /* full */ + { 0x3d, KEY_POWER }, /* system power (green button) */ +}; + +static struct rc_keymap hauppauge_new_map = { + .map = { + .scan = hauppauge_new, + .size = ARRAY_SIZE(hauppauge_new), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_HAUPPAUGE_NEW, + } +}; + +static int __init init_rc_map_hauppauge_new(void) +{ + return ir_register_map(&hauppauge_new_map); +} + +static void __exit exit_rc_map_hauppauge_new(void) +{ + ir_unregister_map(&hauppauge_new_map); +} + +module_init(init_rc_map_hauppauge_new) +module_exit(exit_rc_map_hauppauge_new) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-iodata-bctv7e.c b/drivers/media/IR/keymaps/rc-iodata-bctv7e.c new file mode 100644 index 000000000000..ef6600259fc0 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-iodata-bctv7e.c @@ -0,0 +1,88 @@ +/* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* IO-DATA BCTV7E Remote */ + +static struct ir_scancode iodata_bctv7e[] = { + { 0x40, KEY_TV }, + { 0x20, KEY_RADIO }, /* FM */ + { 0x60, KEY_EPG }, + { 0x00, KEY_POWER }, + + /* Keys 0 to 9 */ + { 0x44, KEY_0 }, /* 10 */ + { 0x50, KEY_1 }, + { 0x30, KEY_2 }, + { 0x70, KEY_3 }, + { 0x48, KEY_4 }, + { 0x28, KEY_5 }, + { 0x68, KEY_6 }, + { 0x58, KEY_7 }, + { 0x38, KEY_8 }, + { 0x78, KEY_9 }, + + { 0x10, KEY_L }, /* Live */ + { 0x08, KEY_TIME }, /* Time Shift */ + + { 0x18, KEY_PLAYPAUSE }, /* Play */ + + { 0x24, KEY_ENTER }, /* 11 */ + { 0x64, KEY_ESC }, /* 12 */ + { 0x04, KEY_M }, /* Multi */ + + { 0x54, KEY_VIDEO }, + { 0x34, KEY_CHANNELUP }, + { 0x74, KEY_VOLUMEUP }, + { 0x14, KEY_MUTE }, + + { 0x4c, KEY_VCR }, /* SVIDEO */ + { 0x2c, KEY_CHANNELDOWN }, + { 0x6c, KEY_VOLUMEDOWN }, + { 0x0c, KEY_ZOOM }, + + { 0x5c, KEY_PAUSE }, + { 0x3c, KEY_RED }, /* || (red) */ + { 0x7c, KEY_RECORD }, /* recording */ + { 0x1c, KEY_STOP }, + + { 0x41, KEY_REWIND }, /* backward << */ + { 0x21, KEY_PLAY }, + { 0x61, KEY_FASTFORWARD }, /* forward >> */ + { 0x01, KEY_NEXT }, /* skip >| */ +}; + +static struct rc_keymap iodata_bctv7e_map = { + .map = { + .scan = iodata_bctv7e, + .size = ARRAY_SIZE(iodata_bctv7e), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_IODATA_BCTV7E, + } +}; + +static int __init init_rc_map_iodata_bctv7e(void) +{ + return ir_register_map(&iodata_bctv7e_map); +} + +static void __exit exit_rc_map_iodata_bctv7e(void) +{ + ir_unregister_map(&iodata_bctv7e_map); +} + +module_init(init_rc_map_iodata_bctv7e) +module_exit(exit_rc_map_iodata_bctv7e) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-kaiomy.c b/drivers/media/IR/keymaps/rc-kaiomy.c new file mode 100644 index 000000000000..4c7883ba0f15 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-kaiomy.c @@ -0,0 +1,87 @@ +/* kaiomy.h - Keytable for kaiomy Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Kaiomy TVnPC U2 + Mauro Carvalho Chehab + */ + +static struct ir_scancode kaiomy[] = { + { 0x43, KEY_POWER2}, + { 0x01, KEY_LIST}, + { 0x0b, KEY_ZOOM}, + { 0x03, KEY_POWER}, + + { 0x04, KEY_1}, + { 0x08, KEY_2}, + { 0x02, KEY_3}, + + { 0x0f, KEY_4}, + { 0x05, KEY_5}, + { 0x06, KEY_6}, + + { 0x0c, KEY_7}, + { 0x0d, KEY_8}, + { 0x0a, KEY_9}, + + { 0x11, KEY_0}, + + { 0x09, KEY_CHANNELUP}, + { 0x07, KEY_CHANNELDOWN}, + + { 0x0e, KEY_VOLUMEUP}, + { 0x13, KEY_VOLUMEDOWN}, + + { 0x10, KEY_HOME}, + { 0x12, KEY_ENTER}, + + { 0x14, KEY_RECORD}, + { 0x15, KEY_STOP}, + { 0x16, KEY_PLAY}, + { 0x17, KEY_MUTE}, + + { 0x18, KEY_UP}, + { 0x19, KEY_DOWN}, + { 0x1a, KEY_LEFT}, + { 0x1b, KEY_RIGHT}, + + { 0x1c, KEY_RED}, + { 0x1d, KEY_GREEN}, + { 0x1e, KEY_YELLOW}, + { 0x1f, KEY_BLUE}, +}; + +static struct rc_keymap kaiomy_map = { + .map = { + .scan = kaiomy, + .size = ARRAY_SIZE(kaiomy), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_KAIOMY, + } +}; + +static int __init init_rc_map_kaiomy(void) +{ + return ir_register_map(&kaiomy_map); +} + +static void __exit exit_rc_map_kaiomy(void) +{ + ir_unregister_map(&kaiomy_map); +} + +module_init(init_rc_map_kaiomy) +module_exit(exit_rc_map_kaiomy) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-kworld-315u.c b/drivers/media/IR/keymaps/rc-kworld-315u.c new file mode 100644 index 000000000000..618c817374e6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-kworld-315u.c @@ -0,0 +1,83 @@ +/* kworld-315u.h - Keytable for kworld_315u Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Kworld 315U + */ + +static struct ir_scancode kworld_315u[] = { + { 0x6143, KEY_POWER }, + { 0x6101, KEY_TUNER }, /* source */ + { 0x610b, KEY_ZOOM }, + { 0x6103, KEY_POWER2 }, /* shutdown */ + + { 0x6104, KEY_1 }, + { 0x6108, KEY_2 }, + { 0x6102, KEY_3 }, + { 0x6109, KEY_CHANNELUP }, + + { 0x610f, KEY_4 }, + { 0x6105, KEY_5 }, + { 0x6106, KEY_6 }, + { 0x6107, KEY_CHANNELDOWN }, + + { 0x610c, KEY_7 }, + { 0x610d, KEY_8 }, + { 0x610a, KEY_9 }, + { 0x610e, KEY_VOLUMEUP }, + + { 0x6110, KEY_LAST }, + { 0x6111, KEY_0 }, + { 0x6112, KEY_ENTER }, + { 0x6113, KEY_VOLUMEDOWN }, + + { 0x6114, KEY_RECORD }, + { 0x6115, KEY_STOP }, + { 0x6116, KEY_PLAY }, + { 0x6117, KEY_MUTE }, + + { 0x6118, KEY_UP }, + { 0x6119, KEY_DOWN }, + { 0x611a, KEY_LEFT }, + { 0x611b, KEY_RIGHT }, + + { 0x611c, KEY_RED }, + { 0x611d, KEY_GREEN }, + { 0x611e, KEY_YELLOW }, + { 0x611f, KEY_BLUE }, +}; + +static struct rc_keymap kworld_315u_map = { + .map = { + .scan = kworld_315u, + .size = ARRAY_SIZE(kworld_315u), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_KWORLD_315U, + } +}; + +static int __init init_rc_map_kworld_315u(void) +{ + return ir_register_map(&kworld_315u_map); +} + +static void __exit exit_rc_map_kworld_315u(void) +{ + ir_unregister_map(&kworld_315u_map); +} + +module_init(init_rc_map_kworld_315u) +module_exit(exit_rc_map_kworld_315u) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c new file mode 100644 index 000000000000..366732f1f7b7 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-kworld-plus-tv-analog.c @@ -0,0 +1,99 @@ +/* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Kworld Plus TV Analog Lite PCI IR + Mauro Carvalho Chehab + */ + +static struct ir_scancode kworld_plus_tv_analog[] = { + { 0x0c, KEY_PROG1 }, /* Kworld key */ + { 0x16, KEY_CLOSECD }, /* -> ) */ + { 0x1d, KEY_POWER2 }, + + { 0x00, KEY_1 }, + { 0x01, KEY_2 }, + { 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */ + { 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */ + { 0x04, KEY_5 }, + { 0x05, KEY_6 }, + { 0x06, KEY_7 }, + { 0x07, KEY_8 }, + { 0x08, KEY_9 }, + { 0x0a, KEY_0 }, + + { 0x09, KEY_AGAIN }, + { 0x14, KEY_MUTE }, + + { 0x20, KEY_UP }, + { 0x21, KEY_DOWN }, + { 0x0b, KEY_ENTER }, + + { 0x10, KEY_CHANNELUP }, + { 0x11, KEY_CHANNELDOWN }, + + /* Couldn't map key left/key right since those + conflict with '3' and '4' scancodes + I dunno what the original driver does + */ + + { 0x13, KEY_VOLUMEUP }, + { 0x12, KEY_VOLUMEDOWN }, + + /* The lower part of the IR + There are several duplicated keycodes there. + Most of them conflict with digits. + Add mappings just to the unused scancodes. + Somehow, the original driver has a way to know, + but this doesn't seem to be on some GPIO. + Also, it is not related to the time between keyup + and keydown. + */ + { 0x19, KEY_TIME}, /* Timeshift */ + { 0x1a, KEY_STOP}, + { 0x1b, KEY_RECORD}, + + { 0x22, KEY_TEXT}, + + { 0x15, KEY_AUDIO}, /* ((*)) */ + { 0x0f, KEY_ZOOM}, + { 0x1c, KEY_CAMERA}, /* snapshot */ + + { 0x18, KEY_RED}, /* B */ + { 0x23, KEY_GREEN}, /* C */ +}; + +static struct rc_keymap kworld_plus_tv_analog_map = { + .map = { + .scan = kworld_plus_tv_analog, + .size = ARRAY_SIZE(kworld_plus_tv_analog), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_KWORLD_PLUS_TV_ANALOG, + } +}; + +static int __init init_rc_map_kworld_plus_tv_analog(void) +{ + return ir_register_map(&kworld_plus_tv_analog_map); +} + +static void __exit exit_rc_map_kworld_plus_tv_analog(void) +{ + ir_unregister_map(&kworld_plus_tv_analog_map); +} + +module_init(init_rc_map_kworld_plus_tv_analog) +module_exit(exit_rc_map_kworld_plus_tv_analog) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-manli.c b/drivers/media/IR/keymaps/rc-manli.c new file mode 100644 index 000000000000..1e9fbfa90a1e --- /dev/null +++ b/drivers/media/IR/keymaps/rc-manli.c @@ -0,0 +1,135 @@ +/* manli.h - Keytable for manli Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Michael Tokarev + http://www.corpit.ru/mjt/beholdTV/remote_control.jpg + keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at + least, and probably other cards too. + The "ascii-art picture" below (in comments, first row + is the keycode in hex, and subsequent row(s) shows + the button labels (several variants when appropriate) + helps to descide which keycodes to assign to the buttons. + */ + +static struct ir_scancode manli[] = { + + /* 0x1c 0x12 * + * FUNCTION POWER * + * FM (|) * + * */ + { 0x1c, KEY_RADIO }, /*XXX*/ + { 0x12, KEY_POWER }, + + /* 0x01 0x02 0x03 * + * 1 2 3 * + * * + * 0x04 0x05 0x06 * + * 4 5 6 * + * * + * 0x07 0x08 0x09 * + * 7 8 9 * + * */ + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + /* 0x0a 0x00 0x17 * + * RECALL 0 +100 * + * PLUS * + * */ + { 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */ + { 0x00, KEY_0 }, + { 0x17, KEY_DIGITS }, /*XXX*/ + + /* 0x14 0x10 * + * MENU INFO * + * OSD */ + { 0x14, KEY_MENU }, + { 0x10, KEY_INFO }, + + /* 0x0b * + * Up * + * * + * 0x18 0x16 0x0c * + * Left Ok Right * + * * + * 0x015 * + * Down * + * */ + { 0x0b, KEY_UP }, + { 0x18, KEY_LEFT }, + { 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */ + { 0x0c, KEY_RIGHT }, + { 0x15, KEY_DOWN }, + + /* 0x11 0x0d * + * TV/AV MODE * + * SOURCE STEREO * + * */ + { 0x11, KEY_TV }, /*XXX*/ + { 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */ + + /* 0x0f 0x1b 0x1a * + * AUDIO Vol+ Chan+ * + * TIMESHIFT??? * + * * + * 0x0e 0x1f 0x1e * + * SLEEP Vol- Chan- * + * */ + { 0x0f, KEY_AUDIO }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1a, KEY_CHANNELUP }, + { 0x0e, KEY_TIME }, + { 0x1f, KEY_VOLUMEDOWN }, + { 0x1e, KEY_CHANNELDOWN }, + + /* 0x13 0x19 * + * MUTE SNAPSHOT* + * */ + { 0x13, KEY_MUTE }, + { 0x19, KEY_CAMERA }, + + /* 0x1d unused ? */ +}; + +static struct rc_keymap manli_map = { + .map = { + .scan = manli, + .size = ARRAY_SIZE(manli), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_MANLI, + } +}; + +static int __init init_rc_map_manli(void) +{ + return ir_register_map(&manli_map); +} + +static void __exit exit_rc_map_manli(void) +{ + ir_unregister_map(&manli_map); +} + +module_init(init_rc_map_manli) +module_exit(exit_rc_map_manli) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c new file mode 100644 index 000000000000..eb8e42c18ff9 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-msi-tvanywhere-plus.c @@ -0,0 +1,123 @@ +/* msi-tvanywhere-plus.h - Keytable for msi_tvanywhere_plus Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card + is marked "KS003". The controller is I2C at address 0x30, but does not seem + to respond to probes until a read is performed from a valid device. + I don't know why... + + Note: This remote may be of similar or identical design to the + Pixelview remote (?). The raw codes and duplicate button codes + appear to be the same. + + Henry Wong + Some changes to formatting and keycodes by Mark Schultz +*/ + +static struct ir_scancode msi_tvanywhere_plus[] = { + +/* ---- Remote Button Layout ---- + + POWER SOURCE SCAN MUTE + TV/FM 1 2 3 + |> 4 5 6 + <| 7 8 9 + ^^UP 0 + RECALL + vvDN RECORD STOP PLAY + + MINIMIZE ZOOM + + CH+ + VOL- VOL+ + CH- + + SNAPSHOT MTS + + << FUNC >> RESET +*/ + + { 0x01, KEY_1 }, /* 1 */ + { 0x0b, KEY_2 }, /* 2 */ + { 0x1b, KEY_3 }, /* 3 */ + { 0x05, KEY_4 }, /* 4 */ + { 0x09, KEY_5 }, /* 5 */ + { 0x15, KEY_6 }, /* 6 */ + { 0x06, KEY_7 }, /* 7 */ + { 0x0a, KEY_8 }, /* 8 */ + { 0x12, KEY_9 }, /* 9 */ + { 0x02, KEY_0 }, /* 0 */ + { 0x10, KEY_KPPLUS }, /* + */ + { 0x13, KEY_AGAIN }, /* Recall */ + + { 0x1e, KEY_POWER }, /* Power */ + { 0x07, KEY_TUNER }, /* Source */ + { 0x1c, KEY_SEARCH }, /* Scan */ + { 0x18, KEY_MUTE }, /* Mute */ + + { 0x03, KEY_RADIO }, /* TV/FM */ + /* The next four keys are duplicates that appear to send the + same IR code as Ch+, Ch-, >>, and << . The raw code assigned + to them is the actual code + 0x20 - they will never be + detected as such unless some way is discovered to distinguish + these buttons from those that have the same code. */ + { 0x3f, KEY_RIGHT }, /* |> and Ch+ */ + { 0x37, KEY_LEFT }, /* <| and Ch- */ + { 0x2c, KEY_UP }, /* ^^Up and >> */ + { 0x24, KEY_DOWN }, /* vvDn and << */ + + { 0x00, KEY_RECORD }, /* Record */ + { 0x08, KEY_STOP }, /* Stop */ + { 0x11, KEY_PLAY }, /* Play */ + + { 0x0f, KEY_CLOSE }, /* Minimize */ + { 0x19, KEY_ZOOM }, /* Zoom */ + { 0x1a, KEY_CAMERA }, /* Snapshot */ + { 0x0d, KEY_LANGUAGE }, /* MTS */ + + { 0x14, KEY_VOLUMEDOWN }, /* Vol- */ + { 0x16, KEY_VOLUMEUP }, /* Vol+ */ + { 0x17, KEY_CHANNELDOWN }, /* Ch- */ + { 0x1f, KEY_CHANNELUP }, /* Ch+ */ + + { 0x04, KEY_REWIND }, /* << */ + { 0x0e, KEY_MENU }, /* Function */ + { 0x0c, KEY_FASTFORWARD }, /* >> */ + { 0x1d, KEY_RESTART }, /* Reset */ +}; + +static struct rc_keymap msi_tvanywhere_plus_map = { + .map = { + .scan = msi_tvanywhere_plus, + .size = ARRAY_SIZE(msi_tvanywhere_plus), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_MSI_TVANYWHERE_PLUS, + } +}; + +static int __init init_rc_map_msi_tvanywhere_plus(void) +{ + return ir_register_map(&msi_tvanywhere_plus_map); +} + +static void __exit exit_rc_map_msi_tvanywhere_plus(void) +{ + ir_unregister_map(&msi_tvanywhere_plus_map); +} + +module_init(init_rc_map_msi_tvanywhere_plus) +module_exit(exit_rc_map_msi_tvanywhere_plus) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-msi-tvanywhere.c b/drivers/media/IR/keymaps/rc-msi-tvanywhere.c new file mode 100644 index 000000000000..ef411854f067 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-msi-tvanywhere.c @@ -0,0 +1,69 @@ +/* msi-tvanywhere.h - Keytable for msi_tvanywhere Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* MSI TV@nywhere MASTER remote */ + +static struct ir_scancode msi_tvanywhere[] = { + /* Keys 0 to 9 */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0c, KEY_MUTE }, + { 0x0f, KEY_SCREEN }, /* Full Screen */ + { 0x10, KEY_FN }, /* Funtion */ + { 0x11, KEY_TIME }, /* Time shift */ + { 0x12, KEY_POWER }, + { 0x13, KEY_MEDIA }, /* MTS */ + { 0x14, KEY_SLOW }, + { 0x16, KEY_REWIND }, /* backward << */ + { 0x17, KEY_ENTER }, /* Return */ + { 0x18, KEY_FASTFORWARD }, /* forward >> */ + { 0x1a, KEY_CHANNELUP }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1e, KEY_CHANNELDOWN }, + { 0x1f, KEY_VOLUMEDOWN }, +}; + +static struct rc_keymap msi_tvanywhere_map = { + .map = { + .scan = msi_tvanywhere, + .size = ARRAY_SIZE(msi_tvanywhere), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_MSI_TVANYWHERE, + } +}; + +static int __init init_rc_map_msi_tvanywhere(void) +{ + return ir_register_map(&msi_tvanywhere_map); +} + +static void __exit exit_rc_map_msi_tvanywhere(void) +{ + ir_unregister_map(&msi_tvanywhere_map); +} + +module_init(init_rc_map_msi_tvanywhere) +module_exit(exit_rc_map_msi_tvanywhere) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-nebula.c b/drivers/media/IR/keymaps/rc-nebula.c new file mode 100644 index 000000000000..ccc50eb402ec --- /dev/null +++ b/drivers/media/IR/keymaps/rc-nebula.c @@ -0,0 +1,96 @@ +/* nebula.h - Keytable for nebula Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode nebula[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_TV }, + { 0x0b, KEY_AUX }, + { 0x0c, KEY_DVD }, + { 0x0d, KEY_POWER }, + { 0x0e, KEY_MHP }, /* labelled 'Picture' */ + { 0x0f, KEY_AUDIO }, + { 0x10, KEY_INFO }, + { 0x11, KEY_F13 }, /* 16:9 */ + { 0x12, KEY_F14 }, /* 14:9 */ + { 0x13, KEY_EPG }, + { 0x14, KEY_EXIT }, + { 0x15, KEY_MENU }, + { 0x16, KEY_UP }, + { 0x17, KEY_DOWN }, + { 0x18, KEY_LEFT }, + { 0x19, KEY_RIGHT }, + { 0x1a, KEY_ENTER }, + { 0x1b, KEY_CHANNELUP }, + { 0x1c, KEY_CHANNELDOWN }, + { 0x1d, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + { 0x1f, KEY_RED }, + { 0x20, KEY_GREEN }, + { 0x21, KEY_YELLOW }, + { 0x22, KEY_BLUE }, + { 0x23, KEY_SUBTITLE }, + { 0x24, KEY_F15 }, /* AD */ + { 0x25, KEY_TEXT }, + { 0x26, KEY_MUTE }, + { 0x27, KEY_REWIND }, + { 0x28, KEY_STOP }, + { 0x29, KEY_PLAY }, + { 0x2a, KEY_FASTFORWARD }, + { 0x2b, KEY_F16 }, /* chapter */ + { 0x2c, KEY_PAUSE }, + { 0x2d, KEY_PLAY }, + { 0x2e, KEY_RECORD }, + { 0x2f, KEY_F17 }, /* picture in picture */ + { 0x30, KEY_KPPLUS }, /* zoom in */ + { 0x31, KEY_KPMINUS }, /* zoom out */ + { 0x32, KEY_F18 }, /* capture */ + { 0x33, KEY_F19 }, /* web */ + { 0x34, KEY_EMAIL }, + { 0x35, KEY_PHONE }, + { 0x36, KEY_PC }, +}; + +static struct rc_keymap nebula_map = { + .map = { + .scan = nebula, + .size = ARRAY_SIZE(nebula), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_NEBULA, + } +}; + +static int __init init_rc_map_nebula(void) +{ + return ir_register_map(&nebula_map); +} + +static void __exit exit_rc_map_nebula(void) +{ + ir_unregister_map(&nebula_map); +} + +module_init(init_rc_map_nebula) +module_exit(exit_rc_map_nebula) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c new file mode 100644 index 000000000000..e1b54d20db60 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-nec-terratec-cinergy-xs.c @@ -0,0 +1,105 @@ +/* nec-terratec-cinergy-xs.h - Keytable for nec_terratec_cinergy_xs Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Terratec Cinergy Hybrid T USB XS FM + Mauro Carvalho Chehab + */ + +static struct ir_scancode nec_terratec_cinergy_xs[] = { + { 0x1441, KEY_HOME}, + { 0x1401, KEY_POWER2}, + + { 0x1442, KEY_MENU}, /* DVD menu */ + { 0x1443, KEY_SUBTITLE}, + { 0x1444, KEY_TEXT}, /* Teletext */ + { 0x1445, KEY_DELETE}, + + { 0x1402, KEY_1}, + { 0x1403, KEY_2}, + { 0x1404, KEY_3}, + { 0x1405, KEY_4}, + { 0x1406, KEY_5}, + { 0x1407, KEY_6}, + { 0x1408, KEY_7}, + { 0x1409, KEY_8}, + { 0x140a, KEY_9}, + { 0x140c, KEY_0}, + + { 0x140b, KEY_TUNER}, /* AV */ + { 0x140d, KEY_MODE}, /* A.B */ + + { 0x1446, KEY_TV}, + { 0x1447, KEY_DVD}, + { 0x1449, KEY_VIDEO}, + { 0x144a, KEY_RADIO}, /* Music */ + { 0x144b, KEY_CAMERA}, /* PIC */ + + { 0x1410, KEY_UP}, + { 0x1411, KEY_LEFT}, + { 0x1412, KEY_OK}, + { 0x1413, KEY_RIGHT}, + { 0x1414, KEY_DOWN}, + + { 0x140f, KEY_EPG}, + { 0x1416, KEY_INFO}, + { 0x144d, KEY_BACKSPACE}, + + { 0x141c, KEY_VOLUMEUP}, + { 0x141e, KEY_VOLUMEDOWN}, + + { 0x144c, KEY_PLAY}, + { 0x141d, KEY_MUTE}, + + { 0x141b, KEY_CHANNELUP}, + { 0x141f, KEY_CHANNELDOWN}, + + { 0x1417, KEY_RED}, + { 0x1418, KEY_GREEN}, + { 0x1419, KEY_YELLOW}, + { 0x141a, KEY_BLUE}, + + { 0x1458, KEY_RECORD}, + { 0x1448, KEY_STOP}, + { 0x1440, KEY_PAUSE}, + + { 0x1454, KEY_LAST}, + { 0x144e, KEY_REWIND}, + { 0x144f, KEY_FASTFORWARD}, + { 0x145c, KEY_NEXT}, +}; + +static struct rc_keymap nec_terratec_cinergy_xs_map = { + .map = { + .scan = nec_terratec_cinergy_xs, + .size = ARRAY_SIZE(nec_terratec_cinergy_xs), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_NEC_TERRATEC_CINERGY_XS, + } +}; + +static int __init init_rc_map_nec_terratec_cinergy_xs(void) +{ + return ir_register_map(&nec_terratec_cinergy_xs_map); +} + +static void __exit exit_rc_map_nec_terratec_cinergy_xs(void) +{ + ir_unregister_map(&nec_terratec_cinergy_xs_map); +} + +module_init(init_rc_map_nec_terratec_cinergy_xs) +module_exit(exit_rc_map_nec_terratec_cinergy_xs) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-norwood.c b/drivers/media/IR/keymaps/rc-norwood.c new file mode 100644 index 000000000000..e5849a6b3f05 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-norwood.c @@ -0,0 +1,85 @@ +/* norwood.h - Keytable for norwood Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Norwood Micro (non-Pro) TV Tuner + By Peter Naulls + Key comments are the functions given in the manual */ + +static struct ir_scancode norwood[] = { + /* Keys 0 to 9 */ + { 0x20, KEY_0 }, + { 0x21, KEY_1 }, + { 0x22, KEY_2 }, + { 0x23, KEY_3 }, + { 0x24, KEY_4 }, + { 0x25, KEY_5 }, + { 0x26, KEY_6 }, + { 0x27, KEY_7 }, + { 0x28, KEY_8 }, + { 0x29, KEY_9 }, + + { 0x78, KEY_TUNER }, /* Video Source */ + { 0x2c, KEY_EXIT }, /* Open/Close software */ + { 0x2a, KEY_SELECT }, /* 2 Digit Select */ + { 0x69, KEY_AGAIN }, /* Recall */ + + { 0x32, KEY_BRIGHTNESSUP }, /* Brightness increase */ + { 0x33, KEY_BRIGHTNESSDOWN }, /* Brightness decrease */ + { 0x6b, KEY_KPPLUS }, /* (not named >>>>>) */ + { 0x6c, KEY_KPMINUS }, /* (not named <<<<<) */ + + { 0x2d, KEY_MUTE }, /* Mute */ + { 0x30, KEY_VOLUMEUP }, /* Volume up */ + { 0x31, KEY_VOLUMEDOWN }, /* Volume down */ + { 0x60, KEY_CHANNELUP }, /* Channel up */ + { 0x61, KEY_CHANNELDOWN }, /* Channel down */ + + { 0x3f, KEY_RECORD }, /* Record */ + { 0x37, KEY_PLAY }, /* Play */ + { 0x36, KEY_PAUSE }, /* Pause */ + { 0x2b, KEY_STOP }, /* Stop */ + { 0x67, KEY_FASTFORWARD }, /* Foward */ + { 0x66, KEY_REWIND }, /* Rewind */ + { 0x3e, KEY_SEARCH }, /* Auto Scan */ + { 0x2e, KEY_CAMERA }, /* Capture Video */ + { 0x6d, KEY_MENU }, /* Show/Hide Control */ + { 0x2f, KEY_ZOOM }, /* Full Screen */ + { 0x34, KEY_RADIO }, /* FM */ + { 0x65, KEY_POWER }, /* Computer power */ +}; + +static struct rc_keymap norwood_map = { + .map = { + .scan = norwood, + .size = ARRAY_SIZE(norwood), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_NORWOOD, + } +}; + +static int __init init_rc_map_norwood(void) +{ + return ir_register_map(&norwood_map); +} + +static void __exit exit_rc_map_norwood(void) +{ + ir_unregister_map(&norwood_map); +} + +module_init(init_rc_map_norwood) +module_exit(exit_rc_map_norwood) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-npgtech.c b/drivers/media/IR/keymaps/rc-npgtech.c new file mode 100644 index 000000000000..b9ece1e90296 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-npgtech.c @@ -0,0 +1,80 @@ +/* npgtech.h - Keytable for npgtech Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode npgtech[] = { + { 0x1d, KEY_SWITCHVIDEOMODE }, /* switch inputs */ + { 0x2a, KEY_FRONT }, + + { 0x3e, KEY_1 }, + { 0x02, KEY_2 }, + { 0x06, KEY_3 }, + { 0x0a, KEY_4 }, + { 0x0e, KEY_5 }, + { 0x12, KEY_6 }, + { 0x16, KEY_7 }, + { 0x1a, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x3a, KEY_0 }, + { 0x22, KEY_NUMLOCK }, /* -/-- */ + { 0x20, KEY_REFRESH }, + + { 0x03, KEY_BRIGHTNESSDOWN }, + { 0x28, KEY_AUDIO }, + { 0x3c, KEY_CHANNELUP }, + { 0x3f, KEY_VOLUMEDOWN }, + { 0x2e, KEY_MUTE }, + { 0x3b, KEY_VOLUMEUP }, + { 0x00, KEY_CHANNELDOWN }, + { 0x07, KEY_BRIGHTNESSUP }, + { 0x2c, KEY_TEXT }, + + { 0x37, KEY_RECORD }, + { 0x17, KEY_PLAY }, + { 0x13, KEY_PAUSE }, + { 0x26, KEY_STOP }, + { 0x18, KEY_FASTFORWARD }, + { 0x14, KEY_REWIND }, + { 0x33, KEY_ZOOM }, + { 0x32, KEY_KEYBOARD }, + { 0x30, KEY_GOTO }, /* Pointing arrow */ + { 0x36, KEY_MACRO }, /* Maximize/Minimize (yellow) */ + { 0x0b, KEY_RADIO }, + { 0x10, KEY_POWER }, + +}; + +static struct rc_keymap npgtech_map = { + .map = { + .scan = npgtech, + .size = ARRAY_SIZE(npgtech), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_NPGTECH, + } +}; + +static int __init init_rc_map_npgtech(void) +{ + return ir_register_map(&npgtech_map); +} + +static void __exit exit_rc_map_npgtech(void) +{ + ir_unregister_map(&npgtech_map); +} + +module_init(init_rc_map_npgtech) +module_exit(exit_rc_map_npgtech) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pctv-sedna.c b/drivers/media/IR/keymaps/rc-pctv-sedna.c new file mode 100644 index 000000000000..4129bb44a25b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pctv-sedna.c @@ -0,0 +1,80 @@ +/* pctv-sedna.h - Keytable for pctv_sedna Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Mapping for the 28 key remote control as seen at + http://www.sednacomputer.com/photo/cardbus-tv.jpg + Pavel Mihaylov + Also for the remote bundled with Kozumi KTV-01C card */ + +static struct ir_scancode pctv_sedna[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0a, KEY_AGAIN }, /* Recall */ + { 0x0b, KEY_CHANNELUP }, + { 0x0c, KEY_VOLUMEUP }, + { 0x0d, KEY_MODE }, /* Stereo */ + { 0x0e, KEY_STOP }, + { 0x0f, KEY_PREVIOUSSONG }, + { 0x10, KEY_ZOOM }, + { 0x11, KEY_TUNER }, /* Source */ + { 0x12, KEY_POWER }, + { 0x13, KEY_MUTE }, + { 0x15, KEY_CHANNELDOWN }, + { 0x18, KEY_VOLUMEDOWN }, + { 0x19, KEY_CAMERA }, /* Snapshot */ + { 0x1a, KEY_NEXTSONG }, + { 0x1b, KEY_TIME }, /* Time Shift */ + { 0x1c, KEY_RADIO }, /* FM Radio */ + { 0x1d, KEY_RECORD }, + { 0x1e, KEY_PAUSE }, + /* additional codes for Kozumi's remote */ + { 0x14, KEY_INFO }, /* OSD */ + { 0x16, KEY_OK }, /* OK */ + { 0x17, KEY_DIGITS }, /* Plus */ + { 0x1f, KEY_PLAY }, /* Play */ +}; + +static struct rc_keymap pctv_sedna_map = { + .map = { + .scan = pctv_sedna, + .size = ARRAY_SIZE(pctv_sedna), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PCTV_SEDNA, + } +}; + +static int __init init_rc_map_pctv_sedna(void) +{ + return ir_register_map(&pctv_sedna_map); +} + +static void __exit exit_rc_map_pctv_sedna(void) +{ + ir_unregister_map(&pctv_sedna_map); +} + +module_init(init_rc_map_pctv_sedna) +module_exit(exit_rc_map_pctv_sedna) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pinnacle-color.c b/drivers/media/IR/keymaps/rc-pinnacle-color.c new file mode 100644 index 000000000000..326e023ce126 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pinnacle-color.c @@ -0,0 +1,94 @@ +/* pinnacle-color.h - Keytable for pinnacle_color Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode pinnacle_color[] = { + { 0x59, KEY_MUTE }, + { 0x4a, KEY_POWER }, + + { 0x18, KEY_TEXT }, + { 0x26, KEY_TV }, + { 0x3d, KEY_PRINT }, + + { 0x48, KEY_RED }, + { 0x04, KEY_GREEN }, + { 0x11, KEY_YELLOW }, + { 0x00, KEY_BLUE }, + + { 0x2d, KEY_VOLUMEUP }, + { 0x1e, KEY_VOLUMEDOWN }, + + { 0x49, KEY_MENU }, + + { 0x16, KEY_CHANNELUP }, + { 0x17, KEY_CHANNELDOWN }, + + { 0x20, KEY_UP }, + { 0x21, KEY_DOWN }, + { 0x22, KEY_LEFT }, + { 0x23, KEY_RIGHT }, + { 0x0d, KEY_SELECT }, + + { 0x08, KEY_BACK }, + { 0x07, KEY_REFRESH }, + + { 0x2f, KEY_ZOOM }, + { 0x29, KEY_RECORD }, + + { 0x4b, KEY_PAUSE }, + { 0x4d, KEY_REWIND }, + { 0x2e, KEY_PLAY }, + { 0x4e, KEY_FORWARD }, + { 0x53, KEY_PREVIOUS }, + { 0x4c, KEY_STOP }, + { 0x54, KEY_NEXT }, + + { 0x69, KEY_0 }, + { 0x6a, KEY_1 }, + { 0x6b, KEY_2 }, + { 0x6c, KEY_3 }, + { 0x6d, KEY_4 }, + { 0x6e, KEY_5 }, + { 0x6f, KEY_6 }, + { 0x70, KEY_7 }, + { 0x71, KEY_8 }, + { 0x72, KEY_9 }, + + { 0x74, KEY_CHANNEL }, + { 0x0a, KEY_BACKSPACE }, +}; + +static struct rc_keymap pinnacle_color_map = { + .map = { + .scan = pinnacle_color, + .size = ARRAY_SIZE(pinnacle_color), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PINNACLE_COLOR, + } +}; + +static int __init init_rc_map_pinnacle_color(void) +{ + return ir_register_map(&pinnacle_color_map); +} + +static void __exit exit_rc_map_pinnacle_color(void) +{ + ir_unregister_map(&pinnacle_color_map); +} + +module_init(init_rc_map_pinnacle_color) +module_exit(exit_rc_map_pinnacle_color) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pinnacle-grey.c b/drivers/media/IR/keymaps/rc-pinnacle-grey.c new file mode 100644 index 000000000000..14cb772515c6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pinnacle-grey.c @@ -0,0 +1,89 @@ +/* pinnacle-grey.h - Keytable for pinnacle_grey Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode pinnacle_grey[] = { + { 0x3a, KEY_0 }, + { 0x31, KEY_1 }, + { 0x32, KEY_2 }, + { 0x33, KEY_3 }, + { 0x34, KEY_4 }, + { 0x35, KEY_5 }, + { 0x36, KEY_6 }, + { 0x37, KEY_7 }, + { 0x38, KEY_8 }, + { 0x39, KEY_9 }, + + { 0x2f, KEY_POWER }, + + { 0x2e, KEY_P }, + { 0x1f, KEY_L }, + { 0x2b, KEY_I }, + + { 0x2d, KEY_SCREEN }, + { 0x1e, KEY_ZOOM }, + { 0x1b, KEY_VOLUMEUP }, + { 0x0f, KEY_VOLUMEDOWN }, + { 0x17, KEY_CHANNELUP }, + { 0x1c, KEY_CHANNELDOWN }, + { 0x25, KEY_INFO }, + + { 0x3c, KEY_MUTE }, + + { 0x3d, KEY_LEFT }, + { 0x3b, KEY_RIGHT }, + + { 0x3f, KEY_UP }, + { 0x3e, KEY_DOWN }, + { 0x1a, KEY_ENTER }, + + { 0x1d, KEY_MENU }, + { 0x19, KEY_AGAIN }, + { 0x16, KEY_PREVIOUSSONG }, + { 0x13, KEY_NEXTSONG }, + { 0x15, KEY_PAUSE }, + { 0x0e, KEY_REWIND }, + { 0x0d, KEY_PLAY }, + { 0x0b, KEY_STOP }, + { 0x07, KEY_FORWARD }, + { 0x27, KEY_RECORD }, + { 0x26, KEY_TUNER }, + { 0x29, KEY_TEXT }, + { 0x2a, KEY_MEDIA }, + { 0x18, KEY_EPG }, +}; + +static struct rc_keymap pinnacle_grey_map = { + .map = { + .scan = pinnacle_grey, + .size = ARRAY_SIZE(pinnacle_grey), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PINNACLE_GREY, + } +}; + +static int __init init_rc_map_pinnacle_grey(void) +{ + return ir_register_map(&pinnacle_grey_map); +} + +static void __exit exit_rc_map_pinnacle_grey(void) +{ + ir_unregister_map(&pinnacle_grey_map); +} + +module_init(init_rc_map_pinnacle_grey) +module_exit(exit_rc_map_pinnacle_grey) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c new file mode 100644 index 000000000000..835bf4ef8de7 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pinnacle-pctv-hd.c @@ -0,0 +1,73 @@ +/* pinnacle-pctv-hd.h - Keytable for pinnacle_pctv_hd Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Pinnacle PCTV HD 800i mini remote */ + +static struct ir_scancode pinnacle_pctv_hd[] = { + + { 0x0f, KEY_1 }, + { 0x15, KEY_2 }, + { 0x10, KEY_3 }, + { 0x18, KEY_4 }, + { 0x1b, KEY_5 }, + { 0x1e, KEY_6 }, + { 0x11, KEY_7 }, + { 0x21, KEY_8 }, + { 0x12, KEY_9 }, + { 0x27, KEY_0 }, + + { 0x24, KEY_ZOOM }, + { 0x2a, KEY_SUBTITLE }, + + { 0x00, KEY_MUTE }, + { 0x01, KEY_ENTER }, /* Pinnacle Logo */ + { 0x39, KEY_POWER }, + + { 0x03, KEY_VOLUMEUP }, + { 0x09, KEY_VOLUMEDOWN }, + { 0x06, KEY_CHANNELUP }, + { 0x0c, KEY_CHANNELDOWN }, + + { 0x2d, KEY_REWIND }, + { 0x30, KEY_PLAYPAUSE }, + { 0x33, KEY_FASTFORWARD }, + { 0x3c, KEY_STOP }, + { 0x36, KEY_RECORD }, + { 0x3f, KEY_EPG }, /* Labeled "?" */ +}; + +static struct rc_keymap pinnacle_pctv_hd_map = { + .map = { + .scan = pinnacle_pctv_hd, + .size = ARRAY_SIZE(pinnacle_pctv_hd), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PINNACLE_PCTV_HD, + } +}; + +static int __init init_rc_map_pinnacle_pctv_hd(void) +{ + return ir_register_map(&pinnacle_pctv_hd_map); +} + +static void __exit exit_rc_map_pinnacle_pctv_hd(void) +{ + ir_unregister_map(&pinnacle_pctv_hd_map); +} + +module_init(init_rc_map_pinnacle_pctv_hd) +module_exit(exit_rc_map_pinnacle_pctv_hd) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pixelview-new.c b/drivers/media/IR/keymaps/rc-pixelview-new.c new file mode 100644 index 000000000000..7bbbbf5735e6 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pixelview-new.c @@ -0,0 +1,83 @@ +/* pixelview-new.h - Keytable for pixelview_new Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + Mauro Carvalho Chehab + present on PV MPEG 8000GT + */ + +static struct ir_scancode pixelview_new[] = { + { 0x3c, KEY_TIME }, /* Timeshift */ + { 0x12, KEY_POWER }, + + { 0x3d, KEY_1 }, + { 0x38, KEY_2 }, + { 0x18, KEY_3 }, + { 0x35, KEY_4 }, + { 0x39, KEY_5 }, + { 0x15, KEY_6 }, + { 0x36, KEY_7 }, + { 0x3a, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x3e, KEY_0 }, + + { 0x1c, KEY_AGAIN }, /* LOOP */ + { 0x3f, KEY_MEDIA }, /* Source */ + { 0x1f, KEY_LAST }, /* +100 */ + { 0x1b, KEY_MUTE }, + + { 0x17, KEY_CHANNELDOWN }, + { 0x16, KEY_CHANNELUP }, + { 0x10, KEY_VOLUMEUP }, + { 0x14, KEY_VOLUMEDOWN }, + { 0x13, KEY_ZOOM }, + + { 0x19, KEY_CAMERA }, /* SNAPSHOT */ + { 0x1a, KEY_SEARCH }, /* scan */ + + { 0x37, KEY_REWIND }, /* << */ + { 0x32, KEY_RECORD }, /* o (red) */ + { 0x33, KEY_FORWARD }, /* >> */ + { 0x11, KEY_STOP }, /* square */ + { 0x3b, KEY_PLAY }, /* > */ + { 0x30, KEY_PLAYPAUSE }, /* || */ + + { 0x31, KEY_TV }, + { 0x34, KEY_RADIO }, +}; + +static struct rc_keymap pixelview_new_map = { + .map = { + .scan = pixelview_new, + .size = ARRAY_SIZE(pixelview_new), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PIXELVIEW_NEW, + } +}; + +static int __init init_rc_map_pixelview_new(void) +{ + return ir_register_map(&pixelview_new_map); +} + +static void __exit exit_rc_map_pixelview_new(void) +{ + ir_unregister_map(&pixelview_new_map); +} + +module_init(init_rc_map_pixelview_new) +module_exit(exit_rc_map_pixelview_new) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pixelview.c b/drivers/media/IR/keymaps/rc-pixelview.c new file mode 100644 index 000000000000..82ff12e182a0 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pixelview.c @@ -0,0 +1,82 @@ +/* pixelview.h - Keytable for pixelview Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode pixelview[] = { + + { 0x1e, KEY_POWER }, /* power */ + { 0x07, KEY_MEDIA }, /* source */ + { 0x1c, KEY_SEARCH }, /* scan */ + + + { 0x03, KEY_TUNER }, /* TV/FM */ + + { 0x00, KEY_RECORD }, + { 0x08, KEY_STOP }, + { 0x11, KEY_PLAY }, + + { 0x1a, KEY_PLAYPAUSE }, /* freeze */ + { 0x19, KEY_ZOOM }, /* zoom */ + { 0x0f, KEY_TEXT }, /* min */ + + { 0x01, KEY_1 }, + { 0x0b, KEY_2 }, + { 0x1b, KEY_3 }, + { 0x05, KEY_4 }, + { 0x09, KEY_5 }, + { 0x15, KEY_6 }, + { 0x06, KEY_7 }, + { 0x0a, KEY_8 }, + { 0x12, KEY_9 }, + { 0x02, KEY_0 }, + { 0x10, KEY_LAST }, /* +100 */ + { 0x13, KEY_LIST }, /* recall */ + + { 0x1f, KEY_CHANNELUP }, /* chn down */ + { 0x17, KEY_CHANNELDOWN }, /* chn up */ + { 0x16, KEY_VOLUMEUP }, /* vol down */ + { 0x14, KEY_VOLUMEDOWN }, /* vol up */ + + { 0x04, KEY_KPMINUS }, /* <<< */ + { 0x0e, KEY_SETUP }, /* function */ + { 0x0c, KEY_KPPLUS }, /* >>> */ + + { 0x0d, KEY_GOTO }, /* mts */ + { 0x1d, KEY_REFRESH }, /* reset */ + { 0x18, KEY_MUTE }, /* mute/unmute */ +}; + +static struct rc_keymap pixelview_map = { + .map = { + .scan = pixelview, + .size = ARRAY_SIZE(pixelview), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PIXELVIEW, + } +}; + +static int __init init_rc_map_pixelview(void) +{ + return ir_register_map(&pixelview_map); +} + +static void __exit exit_rc_map_pixelview(void) +{ + ir_unregister_map(&pixelview_map); +} + +module_init(init_rc_map_pixelview) +module_exit(exit_rc_map_pixelview) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-powercolor-real-angel.c b/drivers/media/IR/keymaps/rc-powercolor-real-angel.c new file mode 100644 index 000000000000..7cef8190a224 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-powercolor-real-angel.c @@ -0,0 +1,81 @@ +/* powercolor-real-angel.h - Keytable for powercolor_real_angel Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Remote control for Powercolor Real Angel 330 + * Daniel Fraga + */ + +static struct ir_scancode powercolor_real_angel[] = { + { 0x38, KEY_SWITCHVIDEOMODE }, /* switch inputs */ + { 0x0c, KEY_MEDIA }, /* Turn ON/OFF App */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + { 0x0a, KEY_DIGITS }, /* single, double, tripple digit */ + { 0x29, KEY_PREVIOUS }, /* previous channel */ + { 0x12, KEY_BRIGHTNESSUP }, + { 0x13, KEY_BRIGHTNESSDOWN }, + { 0x2b, KEY_MODE }, /* stereo/mono */ + { 0x2c, KEY_TEXT }, /* teletext */ + { 0x20, KEY_CHANNELUP }, /* channel up */ + { 0x21, KEY_CHANNELDOWN }, /* channel down */ + { 0x10, KEY_VOLUMEUP }, /* volume up */ + { 0x11, KEY_VOLUMEDOWN }, /* volume down */ + { 0x0d, KEY_MUTE }, + { 0x1f, KEY_RECORD }, + { 0x17, KEY_PLAY }, + { 0x16, KEY_PAUSE }, + { 0x0b, KEY_STOP }, + { 0x27, KEY_FASTFORWARD }, + { 0x26, KEY_REWIND }, + { 0x1e, KEY_SEARCH }, /* autoscan */ + { 0x0e, KEY_CAMERA }, /* snapshot */ + { 0x2d, KEY_SETUP }, + { 0x0f, KEY_SCREEN }, /* full screen */ + { 0x14, KEY_RADIO }, /* FM radio */ + { 0x25, KEY_POWER }, /* power */ +}; + +static struct rc_keymap powercolor_real_angel_map = { + .map = { + .scan = powercolor_real_angel, + .size = ARRAY_SIZE(powercolor_real_angel), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_POWERCOLOR_REAL_ANGEL, + } +}; + +static int __init init_rc_map_powercolor_real_angel(void) +{ + return ir_register_map(&powercolor_real_angel_map); +} + +static void __exit exit_rc_map_powercolor_real_angel(void) +{ + ir_unregister_map(&powercolor_real_angel_map); +} + +module_init(init_rc_map_powercolor_real_angel) +module_exit(exit_rc_map_powercolor_real_angel) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-proteus-2309.c b/drivers/media/IR/keymaps/rc-proteus-2309.c new file mode 100644 index 000000000000..22e92d39dee5 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-proteus-2309.c @@ -0,0 +1,69 @@ +/* proteus-2309.h - Keytable for proteus_2309 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Michal Majchrowicz */ + +static struct ir_scancode proteus_2309[] = { + /* numeric */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x5c, KEY_POWER }, /* power */ + { 0x20, KEY_ZOOM }, /* full screen */ + { 0x0f, KEY_BACKSPACE }, /* recall */ + { 0x1b, KEY_ENTER }, /* mute */ + { 0x41, KEY_RECORD }, /* record */ + { 0x43, KEY_STOP }, /* stop */ + { 0x16, KEY_S }, + { 0x1a, KEY_POWER2 }, /* off */ + { 0x2e, KEY_RED }, + { 0x1f, KEY_CHANNELDOWN }, /* channel - */ + { 0x1c, KEY_CHANNELUP }, /* channel + */ + { 0x10, KEY_VOLUMEDOWN }, /* volume - */ + { 0x1e, KEY_VOLUMEUP }, /* volume + */ + { 0x14, KEY_F1 }, +}; + +static struct rc_keymap proteus_2309_map = { + .map = { + .scan = proteus_2309, + .size = ARRAY_SIZE(proteus_2309), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PROTEUS_2309, + } +}; + +static int __init init_rc_map_proteus_2309(void) +{ + return ir_register_map(&proteus_2309_map); +} + +static void __exit exit_rc_map_proteus_2309(void) +{ + ir_unregister_map(&proteus_2309_map); +} + +module_init(init_rc_map_proteus_2309) +module_exit(exit_rc_map_proteus_2309) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-purpletv.c b/drivers/media/IR/keymaps/rc-purpletv.c new file mode 100644 index 000000000000..4e20fc2269f7 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-purpletv.c @@ -0,0 +1,81 @@ +/* purpletv.h - Keytable for purpletv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode purpletv[] = { + { 0x03, KEY_POWER }, + { 0x6f, KEY_MUTE }, + { 0x10, KEY_BACKSPACE }, /* Recall */ + + { 0x11, KEY_0 }, + { 0x04, KEY_1 }, + { 0x05, KEY_2 }, + { 0x06, KEY_3 }, + { 0x08, KEY_4 }, + { 0x09, KEY_5 }, + { 0x0a, KEY_6 }, + { 0x0c, KEY_7 }, + { 0x0d, KEY_8 }, + { 0x0e, KEY_9 }, + { 0x12, KEY_DOT }, /* 100+ */ + + { 0x07, KEY_VOLUMEUP }, + { 0x0b, KEY_VOLUMEDOWN }, + { 0x1a, KEY_KPPLUS }, + { 0x18, KEY_KPMINUS }, + { 0x15, KEY_UP }, + { 0x1d, KEY_DOWN }, + { 0x0f, KEY_CHANNELUP }, + { 0x13, KEY_CHANNELDOWN }, + { 0x48, KEY_ZOOM }, + + { 0x1b, KEY_VIDEO }, /* Video source */ + { 0x1f, KEY_CAMERA }, /* Snapshot */ + { 0x49, KEY_LANGUAGE }, /* MTS Select */ + { 0x19, KEY_SEARCH }, /* Auto Scan */ + + { 0x4b, KEY_RECORD }, + { 0x46, KEY_PLAY }, + { 0x45, KEY_PAUSE }, /* Pause */ + { 0x44, KEY_STOP }, + { 0x43, KEY_TIME }, /* Time Shift */ + { 0x17, KEY_CHANNEL }, /* SURF CH */ + { 0x40, KEY_FORWARD }, /* Forward ? */ + { 0x42, KEY_REWIND }, /* Backward ? */ + +}; + +static struct rc_keymap purpletv_map = { + .map = { + .scan = purpletv, + .size = ARRAY_SIZE(purpletv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PURPLETV, + } +}; + +static int __init init_rc_map_purpletv(void) +{ + return ir_register_map(&purpletv_map); +} + +static void __exit exit_rc_map_purpletv(void) +{ + ir_unregister_map(&purpletv_map); +} + +module_init(init_rc_map_purpletv) +module_exit(exit_rc_map_purpletv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-pv951.c b/drivers/media/IR/keymaps/rc-pv951.c new file mode 100644 index 000000000000..36679e706cf3 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pv951.c @@ -0,0 +1,78 @@ +/* pv951.h - Keytable for pv951 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Mark Phalan */ + +static struct ir_scancode pv951[] = { + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x12, KEY_POWER }, + { 0x10, KEY_MUTE }, + { 0x1f, KEY_VOLUMEDOWN }, + { 0x1b, KEY_VOLUMEUP }, + { 0x1a, KEY_CHANNELUP }, + { 0x1e, KEY_CHANNELDOWN }, + { 0x0e, KEY_PAGEUP }, + { 0x1d, KEY_PAGEDOWN }, + { 0x13, KEY_SOUND }, + + { 0x18, KEY_KPPLUSMINUS }, /* CH +/- */ + { 0x16, KEY_SUBTITLE }, /* CC */ + { 0x0d, KEY_TEXT }, /* TTX */ + { 0x0b, KEY_TV }, /* AIR/CBL */ + { 0x11, KEY_PC }, /* PC/TV */ + { 0x17, KEY_OK }, /* CH RTN */ + { 0x19, KEY_MODE }, /* FUNC */ + { 0x0c, KEY_SEARCH }, /* AUTOSCAN */ + + /* Not sure what to do with these ones! */ + { 0x0f, KEY_SELECT }, /* SOURCE */ + { 0x0a, KEY_KPPLUS }, /* +100 */ + { 0x14, KEY_EQUAL }, /* SYNC */ + { 0x1c, KEY_MEDIA }, /* PC/TV */ +}; + +static struct rc_keymap pv951_map = { + .map = { + .scan = pv951, + .size = ARRAY_SIZE(pv951), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_PV951, + } +}; + +static int __init init_rc_map_pv951(void) +{ + return ir_register_map(&pv951_map); +} + +static void __exit exit_rc_map_pv951(void) +{ + ir_unregister_map(&pv951_map); +} + +module_init(init_rc_map_pv951) +module_exit(exit_rc_map_pv951) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c new file mode 100644 index 000000000000..cc6b8f548747 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-rc5-hauppauge-new.c @@ -0,0 +1,103 @@ +/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Hauppauge:the newer, gray remotes (seems there are multiple + * slightly different versions), shipped with cx88+ivtv cards. + * + * This table contains the complete RC5 code, instead of just the data part + */ + +static struct ir_scancode rc5_hauppauge_new[] = { + /* Keys 0 to 9 */ + { 0x1e00, KEY_0 }, + { 0x1e01, KEY_1 }, + { 0x1e02, KEY_2 }, + { 0x1e03, KEY_3 }, + { 0x1e04, KEY_4 }, + { 0x1e05, KEY_5 }, + { 0x1e06, KEY_6 }, + { 0x1e07, KEY_7 }, + { 0x1e08, KEY_8 }, + { 0x1e09, KEY_9 }, + + { 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */ + { 0x1e0b, KEY_RED }, /* red button */ + { 0x1e0c, KEY_RADIO }, + { 0x1e0d, KEY_MENU }, + { 0x1e0e, KEY_SUBTITLE }, /* also the # key */ + { 0x1e0f, KEY_MUTE }, + { 0x1e10, KEY_VOLUMEUP }, + { 0x1e11, KEY_VOLUMEDOWN }, + { 0x1e12, KEY_PREVIOUS }, /* previous channel */ + { 0x1e14, KEY_UP }, + { 0x1e15, KEY_DOWN }, + { 0x1e16, KEY_LEFT }, + { 0x1e17, KEY_RIGHT }, + { 0x1e18, KEY_VIDEO }, /* Videos */ + { 0x1e19, KEY_AUDIO }, /* Music */ + /* 0x1e1a: Pictures - presume this means + "Multimedia Home Platform" - + no "PICTURES" key in input.h + */ + { 0x1e1a, KEY_MHP }, + + { 0x1e1b, KEY_EPG }, /* Guide */ + { 0x1e1c, KEY_TV }, + { 0x1e1e, KEY_NEXTSONG }, /* skip >| */ + { 0x1e1f, KEY_EXIT }, /* back/exit */ + { 0x1e20, KEY_CHANNELUP }, /* channel / program + */ + { 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x1e22, KEY_CHANNEL }, /* source (old black remote) */ + { 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */ + { 0x1e25, KEY_ENTER }, /* OK */ + { 0x1e26, KEY_SLEEP }, /* minimize (old black remote) */ + { 0x1e29, KEY_BLUE }, /* blue key */ + { 0x1e2e, KEY_GREEN }, /* green button */ + { 0x1e30, KEY_PAUSE }, /* pause */ + { 0x1e32, KEY_REWIND }, /* backward << */ + { 0x1e34, KEY_FASTFORWARD }, /* forward >> */ + { 0x1e35, KEY_PLAY }, + { 0x1e36, KEY_STOP }, + { 0x1e37, KEY_RECORD }, /* recording */ + { 0x1e38, KEY_YELLOW }, /* yellow key */ + { 0x1e3b, KEY_SELECT }, /* top right button */ + { 0x1e3c, KEY_ZOOM }, /* full */ + { 0x1e3d, KEY_POWER }, /* system power (green button) */ +}; + +static struct rc_keymap rc5_hauppauge_new_map = { + .map = { + .scan = rc5_hauppauge_new, + .size = ARRAY_SIZE(rc5_hauppauge_new), + .ir_type = IR_TYPE_RC5, + .name = RC_MAP_RC5_HAUPPAUGE_NEW, + } +}; + +static int __init init_rc_map_rc5_hauppauge_new(void) +{ + return ir_register_map(&rc5_hauppauge_new_map); +} + +static void __exit exit_rc_map_rc5_hauppauge_new(void) +{ + ir_unregister_map(&rc5_hauppauge_new_map); +} + +module_init(init_rc_map_rc5_hauppauge_new) +module_exit(exit_rc_map_rc5_hauppauge_new) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-rc5-tv.c b/drivers/media/IR/keymaps/rc-rc5-tv.c new file mode 100644 index 000000000000..73cce2f8ddfb --- /dev/null +++ b/drivers/media/IR/keymaps/rc-rc5-tv.c @@ -0,0 +1,81 @@ +/* rc5-tv.h - Keytable for rc5_tv Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* generic RC5 keytable */ +/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ +/* used by old (black) Hauppauge remotes */ + +static struct ir_scancode rc5_tv[] = { + /* Keys 0 to 9 */ + { 0x00, KEY_0 }, + { 0x01, KEY_1 }, + { 0x02, KEY_2 }, + { 0x03, KEY_3 }, + { 0x04, KEY_4 }, + { 0x05, KEY_5 }, + { 0x06, KEY_6 }, + { 0x07, KEY_7 }, + { 0x08, KEY_8 }, + { 0x09, KEY_9 }, + + { 0x0b, KEY_CHANNEL }, /* channel / program (japan: 11) */ + { 0x0c, KEY_POWER }, /* standby */ + { 0x0d, KEY_MUTE }, /* mute / demute */ + { 0x0f, KEY_TV }, /* display */ + { 0x10, KEY_VOLUMEUP }, + { 0x11, KEY_VOLUMEDOWN }, + { 0x12, KEY_BRIGHTNESSUP }, + { 0x13, KEY_BRIGHTNESSDOWN }, + { 0x1e, KEY_SEARCH }, /* search + */ + { 0x20, KEY_CHANNELUP }, /* channel / program + */ + { 0x21, KEY_CHANNELDOWN }, /* channel / program - */ + { 0x22, KEY_CHANNEL }, /* alt / channel */ + { 0x23, KEY_LANGUAGE }, /* 1st / 2nd language */ + { 0x26, KEY_SLEEP }, /* sleeptimer */ + { 0x2e, KEY_MENU }, /* 2nd controls (USA: menu) */ + { 0x30, KEY_PAUSE }, + { 0x32, KEY_REWIND }, + { 0x33, KEY_GOTO }, + { 0x35, KEY_PLAY }, + { 0x36, KEY_STOP }, + { 0x37, KEY_RECORD }, /* recording */ + { 0x3c, KEY_TEXT }, /* teletext submode (Japan: 12) */ + { 0x3d, KEY_SUSPEND }, /* system standby */ + +}; + +static struct rc_keymap rc5_tv_map = { + .map = { + .scan = rc5_tv, + .size = ARRAY_SIZE(rc5_tv), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_RC5_TV, + } +}; + +static int __init init_rc_map_rc5_tv(void) +{ + return ir_register_map(&rc5_tv_map); +} + +static void __exit exit_rc_map_rc5_tv(void) +{ + ir_unregister_map(&rc5_tv_map); +} + +module_init(init_rc_map_rc5_tv) +module_exit(exit_rc_map_rc5_tv) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c new file mode 100644 index 000000000000..ab1a6d2baf72 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-real-audio-220-32-keys.c @@ -0,0 +1,78 @@ +/* real-audio-220-32-keys.h - Keytable for real_audio_220_32_keys Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Zogis Real Audio 220 - 32 keys IR */ + +static struct ir_scancode real_audio_220_32_keys[] = { + { 0x1c, KEY_RADIO}, + { 0x12, KEY_POWER2}, + + { 0x01, KEY_1}, + { 0x02, KEY_2}, + { 0x03, KEY_3}, + { 0x04, KEY_4}, + { 0x05, KEY_5}, + { 0x06, KEY_6}, + { 0x07, KEY_7}, + { 0x08, KEY_8}, + { 0x09, KEY_9}, + { 0x00, KEY_0}, + + { 0x0c, KEY_VOLUMEUP}, + { 0x18, KEY_VOLUMEDOWN}, + { 0x0b, KEY_CHANNELUP}, + { 0x15, KEY_CHANNELDOWN}, + { 0x16, KEY_ENTER}, + + { 0x11, KEY_LIST}, /* Source */ + { 0x0d, KEY_AUDIO}, /* stereo */ + + { 0x0f, KEY_PREVIOUS}, /* Prev */ + { 0x1b, KEY_TIME}, /* Timeshift */ + { 0x1a, KEY_NEXT}, /* Next */ + + { 0x0e, KEY_STOP}, + { 0x1f, KEY_PLAY}, + { 0x1e, KEY_PLAYPAUSE}, /* Pause */ + + { 0x1d, KEY_RECORD}, + { 0x13, KEY_MUTE}, + { 0x19, KEY_CAMERA}, /* Snapshot */ + +}; + +static struct rc_keymap real_audio_220_32_keys_map = { + .map = { + .scan = real_audio_220_32_keys, + .size = ARRAY_SIZE(real_audio_220_32_keys), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_REAL_AUDIO_220_32_KEYS, + } +}; + +static int __init init_rc_map_real_audio_220_32_keys(void) +{ + return ir_register_map(&real_audio_220_32_keys_map); +} + +static void __exit exit_rc_map_real_audio_220_32_keys(void) +{ + ir_unregister_map(&real_audio_220_32_keys_map); +} + +module_init(init_rc_map_real_audio_220_32_keys) +module_exit(exit_rc_map_real_audio_220_32_keys) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-tbs-nec.c b/drivers/media/IR/keymaps/rc-tbs-nec.c new file mode 100644 index 000000000000..3309631e6f80 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-tbs-nec.c @@ -0,0 +1,73 @@ +/* tbs-nec.h - Keytable for tbs_nec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode tbs_nec[] = { + { 0x04, KEY_POWER2}, /*power*/ + { 0x14, KEY_MUTE}, /*mute*/ + { 0x07, KEY_1}, + { 0x06, KEY_2}, + { 0x05, KEY_3}, + { 0x0b, KEY_4}, + { 0x0a, KEY_5}, + { 0x09, KEY_6}, + { 0x0f, KEY_7}, + { 0x0e, KEY_8}, + { 0x0d, KEY_9}, + { 0x12, KEY_0}, + { 0x16, KEY_CHANNELUP}, /*ch+*/ + { 0x11, KEY_CHANNELDOWN},/*ch-*/ + { 0x13, KEY_VOLUMEUP}, /*vol+*/ + { 0x0c, KEY_VOLUMEDOWN},/*vol-*/ + { 0x03, KEY_RECORD}, /*rec*/ + { 0x18, KEY_PAUSE}, /*pause*/ + { 0x19, KEY_OK}, /*ok*/ + { 0x1a, KEY_CAMERA}, /* snapshot */ + { 0x01, KEY_UP}, + { 0x10, KEY_LEFT}, + { 0x02, KEY_RIGHT}, + { 0x08, KEY_DOWN}, + { 0x15, KEY_FAVORITES}, + { 0x17, KEY_SUBTITLE}, + { 0x1d, KEY_ZOOM}, + { 0x1f, KEY_EXIT}, + { 0x1e, KEY_MENU}, + { 0x1c, KEY_EPG}, + { 0x00, KEY_PREVIOUS}, + { 0x1b, KEY_MODE}, +}; + +static struct rc_keymap tbs_nec_map = { + .map = { + .scan = tbs_nec, + .size = ARRAY_SIZE(tbs_nec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TBS_NEC, + } +}; + +static int __init init_rc_map_tbs_nec(void) +{ + return ir_register_map(&tbs_nec_map); +} + +static void __exit exit_rc_map_tbs_nec(void) +{ + ir_unregister_map(&tbs_nec_map); +} + +module_init(init_rc_map_tbs_nec) +module_exit(exit_rc_map_tbs_nec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c b/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c new file mode 100644 index 000000000000..5326a0b444c1 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-terratec-cinergy-xs.c @@ -0,0 +1,92 @@ +/* terratec-cinergy-xs.h - Keytable for terratec_cinergy_xs Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Terratec Cinergy Hybrid T USB XS + Devin Heitmueller + */ + +static struct ir_scancode terratec_cinergy_xs[] = { + { 0x41, KEY_HOME}, + { 0x01, KEY_POWER}, + { 0x42, KEY_MENU}, + { 0x02, KEY_1}, + { 0x03, KEY_2}, + { 0x04, KEY_3}, + { 0x43, KEY_SUBTITLE}, + { 0x05, KEY_4}, + { 0x06, KEY_5}, + { 0x07, KEY_6}, + { 0x44, KEY_TEXT}, + { 0x08, KEY_7}, + { 0x09, KEY_8}, + { 0x0a, KEY_9}, + { 0x45, KEY_DELETE}, + { 0x0b, KEY_TUNER}, + { 0x0c, KEY_0}, + { 0x0d, KEY_MODE}, + { 0x46, KEY_TV}, + { 0x47, KEY_DVD}, + { 0x49, KEY_VIDEO}, + { 0x4b, KEY_AUX}, + { 0x10, KEY_UP}, + { 0x11, KEY_LEFT}, + { 0x12, KEY_OK}, + { 0x13, KEY_RIGHT}, + { 0x14, KEY_DOWN}, + { 0x0f, KEY_EPG}, + { 0x16, KEY_INFO}, + { 0x4d, KEY_BACKSPACE}, + { 0x1c, KEY_VOLUMEUP}, + { 0x4c, KEY_PLAY}, + { 0x1b, KEY_CHANNELUP}, + { 0x1e, KEY_VOLUMEDOWN}, + { 0x1d, KEY_MUTE}, + { 0x1f, KEY_CHANNELDOWN}, + { 0x17, KEY_RED}, + { 0x18, KEY_GREEN}, + { 0x19, KEY_YELLOW}, + { 0x1a, KEY_BLUE}, + { 0x58, KEY_RECORD}, + { 0x48, KEY_STOP}, + { 0x40, KEY_PAUSE}, + { 0x54, KEY_LAST}, + { 0x4e, KEY_REWIND}, + { 0x4f, KEY_FASTFORWARD}, + { 0x5c, KEY_NEXT}, +}; + +static struct rc_keymap terratec_cinergy_xs_map = { + .map = { + .scan = terratec_cinergy_xs, + .size = ARRAY_SIZE(terratec_cinergy_xs), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TERRATEC_CINERGY_XS, + } +}; + +static int __init init_rc_map_terratec_cinergy_xs(void) +{ + return ir_register_map(&terratec_cinergy_xs_map); +} + +static void __exit exit_rc_map_terratec_cinergy_xs(void) +{ + ir_unregister_map(&terratec_cinergy_xs_map); +} + +module_init(init_rc_map_terratec_cinergy_xs) +module_exit(exit_rc_map_terratec_cinergy_xs) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-tevii-nec.c b/drivers/media/IR/keymaps/rc-tevii-nec.c new file mode 100644 index 000000000000..e30d411c07bb --- /dev/null +++ b/drivers/media/IR/keymaps/rc-tevii-nec.c @@ -0,0 +1,88 @@ +/* tevii-nec.h - Keytable for tevii_nec Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode tevii_nec[] = { + { 0x0a, KEY_POWER2}, + { 0x0c, KEY_MUTE}, + { 0x11, KEY_1}, + { 0x12, KEY_2}, + { 0x13, KEY_3}, + { 0x14, KEY_4}, + { 0x15, KEY_5}, + { 0x16, KEY_6}, + { 0x17, KEY_7}, + { 0x18, KEY_8}, + { 0x19, KEY_9}, + { 0x10, KEY_0}, + { 0x1c, KEY_MENU}, + { 0x0f, KEY_VOLUMEDOWN}, + { 0x1a, KEY_LAST}, + { 0x0e, KEY_OPEN}, + { 0x04, KEY_RECORD}, + { 0x09, KEY_VOLUMEUP}, + { 0x08, KEY_CHANNELUP}, + { 0x07, KEY_PVR}, + { 0x0b, KEY_TIME}, + { 0x02, KEY_RIGHT}, + { 0x03, KEY_LEFT}, + { 0x00, KEY_UP}, + { 0x1f, KEY_OK}, + { 0x01, KEY_DOWN}, + { 0x05, KEY_TUNER}, + { 0x06, KEY_CHANNELDOWN}, + { 0x40, KEY_PLAYPAUSE}, + { 0x1e, KEY_REWIND}, + { 0x1b, KEY_FAVORITES}, + { 0x1d, KEY_BACK}, + { 0x4d, KEY_FASTFORWARD}, + { 0x44, KEY_EPG}, + { 0x4c, KEY_INFO}, + { 0x41, KEY_AB}, + { 0x43, KEY_AUDIO}, + { 0x45, KEY_SUBTITLE}, + { 0x4a, KEY_LIST}, + { 0x46, KEY_F1}, + { 0x47, KEY_F2}, + { 0x5e, KEY_F3}, + { 0x5c, KEY_F4}, + { 0x52, KEY_F5}, + { 0x5a, KEY_F6}, + { 0x56, KEY_MODE}, + { 0x58, KEY_SWITCHVIDEOMODE}, +}; + +static struct rc_keymap tevii_nec_map = { + .map = { + .scan = tevii_nec, + .size = ARRAY_SIZE(tevii_nec), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TEVII_NEC, + } +}; + +static int __init init_rc_map_tevii_nec(void) +{ + return ir_register_map(&tevii_nec_map); +} + +static void __exit exit_rc_map_tevii_nec(void) +{ + ir_unregister_map(&tevii_nec_map); +} + +module_init(init_rc_map_tevii_nec) +module_exit(exit_rc_map_tevii_nec) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-tt-1500.c b/drivers/media/IR/keymaps/rc-tt-1500.c new file mode 100644 index 000000000000..bc88de011d5d --- /dev/null +++ b/drivers/media/IR/keymaps/rc-tt-1500.c @@ -0,0 +1,82 @@ +/* tt-1500.h - Keytable for tt_1500 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* for the Technotrend 1500 bundled remotes (grey and black): */ + +static struct ir_scancode tt_1500[] = { + { 0x01, KEY_POWER }, + { 0x02, KEY_SHUFFLE }, /* ? double-arrow key */ + { 0x03, KEY_1 }, + { 0x04, KEY_2 }, + { 0x05, KEY_3 }, + { 0x06, KEY_4 }, + { 0x07, KEY_5 }, + { 0x08, KEY_6 }, + { 0x09, KEY_7 }, + { 0x0a, KEY_8 }, + { 0x0b, KEY_9 }, + { 0x0c, KEY_0 }, + { 0x0d, KEY_UP }, + { 0x0e, KEY_LEFT }, + { 0x0f, KEY_OK }, + { 0x10, KEY_RIGHT }, + { 0x11, KEY_DOWN }, + { 0x12, KEY_INFO }, + { 0x13, KEY_EXIT }, + { 0x14, KEY_RED }, + { 0x15, KEY_GREEN }, + { 0x16, KEY_YELLOW }, + { 0x17, KEY_BLUE }, + { 0x18, KEY_MUTE }, + { 0x19, KEY_TEXT }, + { 0x1a, KEY_MODE }, /* ? TV/Radio */ + { 0x21, KEY_OPTION }, + { 0x22, KEY_EPG }, + { 0x23, KEY_CHANNELUP }, + { 0x24, KEY_CHANNELDOWN }, + { 0x25, KEY_VOLUMEUP }, + { 0x26, KEY_VOLUMEDOWN }, + { 0x27, KEY_SETUP }, + { 0x3a, KEY_RECORD }, /* these keys are only in the black remote */ + { 0x3b, KEY_PLAY }, + { 0x3c, KEY_STOP }, + { 0x3d, KEY_REWIND }, + { 0x3e, KEY_PAUSE }, + { 0x3f, KEY_FORWARD }, +}; + +static struct rc_keymap tt_1500_map = { + .map = { + .scan = tt_1500, + .size = ARRAY_SIZE(tt_1500), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_TT_1500, + } +}; + +static int __init init_rc_map_tt_1500(void) +{ + return ir_register_map(&tt_1500_map); +} + +static void __exit exit_rc_map_tt_1500(void) +{ + ir_unregister_map(&tt_1500_map); +} + +module_init(init_rc_map_tt_1500) +module_exit(exit_rc_map_tt_1500) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-videomate-s350.c b/drivers/media/IR/keymaps/rc-videomate-s350.c new file mode 100644 index 000000000000..4df7fcd1d2fc --- /dev/null +++ b/drivers/media/IR/keymaps/rc-videomate-s350.c @@ -0,0 +1,85 @@ +/* videomate-s350.h - Keytable for videomate_s350 Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode videomate_s350[] = { + { 0x00, KEY_TV}, + { 0x01, KEY_DVD}, + { 0x04, KEY_RECORD}, + { 0x05, KEY_VIDEO}, /* TV/Video */ + { 0x07, KEY_STOP}, + { 0x08, KEY_PLAYPAUSE}, + { 0x0a, KEY_REWIND}, + { 0x0f, KEY_FASTFORWARD}, + { 0x10, KEY_CHANNELUP}, + { 0x12, KEY_VOLUMEUP}, + { 0x13, KEY_CHANNELDOWN}, + { 0x14, KEY_MUTE}, + { 0x15, KEY_VOLUMEDOWN}, + { 0x16, KEY_1}, + { 0x17, KEY_2}, + { 0x18, KEY_3}, + { 0x19, KEY_4}, + { 0x1a, KEY_5}, + { 0x1b, KEY_6}, + { 0x1c, KEY_7}, + { 0x1d, KEY_8}, + { 0x1e, KEY_9}, + { 0x1f, KEY_0}, + { 0x21, KEY_SLEEP}, + { 0x24, KEY_ZOOM}, + { 0x25, KEY_LAST}, /* Recall */ + { 0x26, KEY_SUBTITLE}, /* CC */ + { 0x27, KEY_LANGUAGE}, /* MTS */ + { 0x29, KEY_CHANNEL}, /* SURF */ + { 0x2b, KEY_A}, + { 0x2c, KEY_B}, + { 0x2f, KEY_CAMERA}, /* Snapshot */ + { 0x23, KEY_RADIO}, + { 0x02, KEY_PREVIOUSSONG}, + { 0x06, KEY_NEXTSONG}, + { 0x03, KEY_EPG}, + { 0x09, KEY_SETUP}, + { 0x22, KEY_BACKSPACE}, + { 0x0c, KEY_UP}, + { 0x0e, KEY_DOWN}, + { 0x0b, KEY_LEFT}, + { 0x0d, KEY_RIGHT}, + { 0x11, KEY_ENTER}, + { 0x20, KEY_TEXT}, +}; + +static struct rc_keymap videomate_s350_map = { + .map = { + .scan = videomate_s350, + .size = ARRAY_SIZE(videomate_s350), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_VIDEOMATE_S350, + } +}; + +static int __init init_rc_map_videomate_s350(void) +{ + return ir_register_map(&videomate_s350_map); +} + +static void __exit exit_rc_map_videomate_s350(void) +{ + ir_unregister_map(&videomate_s350_map); +} + +module_init(init_rc_map_videomate_s350) +module_exit(exit_rc_map_videomate_s350) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c b/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c new file mode 100644 index 000000000000..776b0a638d87 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-videomate-tv-pvr.c @@ -0,0 +1,87 @@ +/* videomate-tv-pvr.h - Keytable for videomate_tv_pvr Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +static struct ir_scancode videomate_tv_pvr[] = { + { 0x14, KEY_MUTE }, + { 0x24, KEY_ZOOM }, + + { 0x01, KEY_DVD }, + { 0x23, KEY_RADIO }, + { 0x00, KEY_TV }, + + { 0x0a, KEY_REWIND }, + { 0x08, KEY_PLAYPAUSE }, + { 0x0f, KEY_FORWARD }, + + { 0x02, KEY_PREVIOUS }, + { 0x07, KEY_STOP }, + { 0x06, KEY_NEXT }, + + { 0x0c, KEY_UP }, + { 0x0e, KEY_DOWN }, + { 0x0b, KEY_LEFT }, + { 0x0d, KEY_RIGHT }, + { 0x11, KEY_OK }, + + { 0x03, KEY_MENU }, + { 0x09, KEY_SETUP }, + { 0x05, KEY_VIDEO }, + { 0x22, KEY_CHANNEL }, + + { 0x12, KEY_VOLUMEUP }, + { 0x15, KEY_VOLUMEDOWN }, + { 0x10, KEY_CHANNELUP }, + { 0x13, KEY_CHANNELDOWN }, + + { 0x04, KEY_RECORD }, + + { 0x16, KEY_1 }, + { 0x17, KEY_2 }, + { 0x18, KEY_3 }, + { 0x19, KEY_4 }, + { 0x1a, KEY_5 }, + { 0x1b, KEY_6 }, + { 0x1c, KEY_7 }, + { 0x1d, KEY_8 }, + { 0x1e, KEY_9 }, + { 0x1f, KEY_0 }, + + { 0x20, KEY_LANGUAGE }, + { 0x21, KEY_SLEEP }, +}; + +static struct rc_keymap videomate_tv_pvr_map = { + .map = { + .scan = videomate_tv_pvr, + .size = ARRAY_SIZE(videomate_tv_pvr), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_VIDEOMATE_TV_PVR, + } +}; + +static int __init init_rc_map_videomate_tv_pvr(void) +{ + return ir_register_map(&videomate_tv_pvr_map); +} + +static void __exit exit_rc_map_videomate_tv_pvr(void) +{ + ir_unregister_map(&videomate_tv_pvr_map); +} + +module_init(init_rc_map_videomate_tv_pvr) +module_exit(exit_rc_map_videomate_tv_pvr) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c b/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c new file mode 100644 index 000000000000..9d2d550aaa90 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-winfast-usbii-deluxe.c @@ -0,0 +1,82 @@ +/* winfast-usbii-deluxe.h - Keytable for winfast_usbii_deluxe Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Leadtek Winfast TV USB II Deluxe remote + Magnus Alm + */ + +static struct ir_scancode winfast_usbii_deluxe[] = { + { 0x62, KEY_0}, + { 0x75, KEY_1}, + { 0x76, KEY_2}, + { 0x77, KEY_3}, + { 0x79, KEY_4}, + { 0x7a, KEY_5}, + { 0x7b, KEY_6}, + { 0x7d, KEY_7}, + { 0x7e, KEY_8}, + { 0x7f, KEY_9}, + + { 0x38, KEY_CAMERA}, /* SNAPSHOT */ + { 0x37, KEY_RECORD}, /* RECORD */ + { 0x35, KEY_TIME}, /* TIMESHIFT */ + + { 0x74, KEY_VOLUMEUP}, /* VOLUMEUP */ + { 0x78, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */ + { 0x64, KEY_MUTE}, /* MUTE */ + + { 0x21, KEY_CHANNEL}, /* SURF */ + { 0x7c, KEY_CHANNELUP}, /* CHANNELUP */ + { 0x60, KEY_CHANNELDOWN}, /* CHANNELDOWN */ + { 0x61, KEY_LAST}, /* LAST CHANNEL (RECALL) */ + + { 0x72, KEY_VIDEO}, /* INPUT MODES (TV/FM) */ + + { 0x70, KEY_POWER2}, /* TV ON/OFF */ + + { 0x39, KEY_CYCLEWINDOWS}, /* MINIMIZE (BOSS) */ + { 0x3a, KEY_NEW}, /* PIP */ + { 0x73, KEY_ZOOM}, /* FULLSECREEN */ + + { 0x66, KEY_INFO}, /* OSD (DISPLAY) */ + + { 0x31, KEY_DOT}, /* '.' */ + { 0x63, KEY_ENTER}, /* ENTER */ + +}; + +static struct rc_keymap winfast_usbii_deluxe_map = { + .map = { + .scan = winfast_usbii_deluxe, + .size = ARRAY_SIZE(winfast_usbii_deluxe), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_WINFAST_USBII_DELUXE, + } +}; + +static int __init init_rc_map_winfast_usbii_deluxe(void) +{ + return ir_register_map(&winfast_usbii_deluxe_map); +} + +static void __exit exit_rc_map_winfast_usbii_deluxe(void) +{ + ir_unregister_map(&winfast_usbii_deluxe_map); +} + +module_init(init_rc_map_winfast_usbii_deluxe) +module_exit(exit_rc_map_winfast_usbii_deluxe) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/keymaps/rc-winfast.c b/drivers/media/IR/keymaps/rc-winfast.c new file mode 100644 index 000000000000..0e90a3bd9499 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-winfast.c @@ -0,0 +1,102 @@ +/* winfast.h - Keytable for winfast Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ + +static struct ir_scancode winfast[] = { + /* Keys 0 to 9 */ + { 0x12, KEY_0 }, + { 0x05, KEY_1 }, + { 0x06, KEY_2 }, + { 0x07, KEY_3 }, + { 0x09, KEY_4 }, + { 0x0a, KEY_5 }, + { 0x0b, KEY_6 }, + { 0x0d, KEY_7 }, + { 0x0e, KEY_8 }, + { 0x0f, KEY_9 }, + + { 0x00, KEY_POWER }, + { 0x1b, KEY_AUDIO }, /* Audio Source */ + { 0x02, KEY_TUNER }, /* TV/FM, not on Y0400052 */ + { 0x1e, KEY_VIDEO }, /* Video Source */ + { 0x16, KEY_INFO }, /* Display information */ + { 0x04, KEY_VOLUMEUP }, + { 0x08, KEY_VOLUMEDOWN }, + { 0x0c, KEY_CHANNELUP }, + { 0x10, KEY_CHANNELDOWN }, + { 0x03, KEY_ZOOM }, /* fullscreen */ + { 0x1f, KEY_TEXT }, /* closed caption/teletext */ + { 0x20, KEY_SLEEP }, + { 0x29, KEY_CLEAR }, /* boss key */ + { 0x14, KEY_MUTE }, + { 0x2b, KEY_RED }, + { 0x2c, KEY_GREEN }, + { 0x2d, KEY_YELLOW }, + { 0x2e, KEY_BLUE }, + { 0x18, KEY_KPPLUS }, /* fine tune + , not on Y040052 */ + { 0x19, KEY_KPMINUS }, /* fine tune - , not on Y040052 */ + { 0x2a, KEY_MEDIA }, /* PIP (Picture in picture */ + { 0x21, KEY_DOT }, + { 0x13, KEY_ENTER }, + { 0x11, KEY_LAST }, /* Recall (last channel */ + { 0x22, KEY_PREVIOUS }, + { 0x23, KEY_PLAYPAUSE }, + { 0x24, KEY_NEXT }, + { 0x25, KEY_TIME }, /* Time Shifting */ + { 0x26, KEY_STOP }, + { 0x27, KEY_RECORD }, + { 0x28, KEY_SAVE }, /* Screenshot */ + { 0x2f, KEY_MENU }, + { 0x30, KEY_CANCEL }, + { 0x31, KEY_CHANNEL }, /* Channel Surf */ + { 0x32, KEY_SUBTITLE }, + { 0x33, KEY_LANGUAGE }, + { 0x34, KEY_REWIND }, + { 0x35, KEY_FASTFORWARD }, + { 0x36, KEY_TV }, + { 0x37, KEY_RADIO }, /* FM */ + { 0x38, KEY_DVD }, + + { 0x1a, KEY_MODE}, /* change to MCE mode on Y04G0051 */ + { 0x3e, KEY_F21 }, /* MCE +VOL, on Y04G0033 */ + { 0x3a, KEY_F22 }, /* MCE -VOL, on Y04G0033 */ + { 0x3b, KEY_F23 }, /* MCE +CH, on Y04G0033 */ + { 0x3f, KEY_F24 } /* MCE -CH, on Y04G0033 */ +}; + +static struct rc_keymap winfast_map = { + .map = { + .scan = winfast, + .size = ARRAY_SIZE(winfast), + .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */ + .name = RC_MAP_WINFAST, + } +}; + +static int __init init_rc_map_winfast(void) +{ + return ir_register_map(&winfast_map); +} + +static void __exit exit_rc_map_winfast(void) +{ + ir_unregister_map(&winfast_map); +} + +module_init(init_rc_map_winfast) +module_exit(exit_rc_map_winfast) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index aa269f5ef3fe..02c72f086fe0 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c @@ -64,7 +64,7 @@ int ir_register_map(struct rc_keymap *map) spin_unlock(&rc_map_lock); return 0; } -EXPORT_SYMBOL_GPL(ir_raw_handler_register); +EXPORT_SYMBOL_GPL(ir_register_map); void ir_unregister_map(struct rc_keymap *map) { @@ -72,4 +72,4 @@ void ir_unregister_map(struct rc_keymap *map) list_del(&map->list); spin_unlock(&rc_map_lock); } -EXPORT_SYMBOL_GPL(ir_raw_handler_unregister); +EXPORT_SYMBOL_GPL(ir_unregister_map); -- cgit v1.2.3 From b2245ba1644eb1eba400fd04c6e7bb3ab2d4a8fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 2 Apr 2010 13:18:42 -0300 Subject: V4L/DVB: ir: prepare IR code for a parameter change at register function A latter patch will reuse the ir_input_register with a different meaning. Before it, change all occurrences to a temporary name. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 99cad829a18a..5d4ddc9f4cab 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -461,7 +461,7 @@ static void ir_close(struct input_dev *input_dev) } /** - * ir_input_register() - sets the IR keycode table and add the handlers + * __ir_input_register() - sets the IR keycode table and add the handlers * for keymap table get/set * @input_dev: the struct input_dev descriptor of the device * @rc_tab: the struct ir_scancode_table table of scancode/keymap @@ -471,7 +471,7 @@ static void ir_close(struct input_dev *input_dev) * It will register the input/evdev interface for the device and * register the syfs code for IR class */ -int ir_input_register(struct input_dev *input_dev, +int __ir_input_register(struct input_dev *input_dev, const struct ir_scancode_table *rc_tab, const struct ir_dev_props *props, const char *driver_name) @@ -539,7 +539,7 @@ err: kfree(ir_dev); return rc; } -EXPORT_SYMBOL_GPL(ir_input_register); +EXPORT_SYMBOL_GPL(__ir_input_register); /** * ir_input_unregister() - unregisters IR and frees resources -- cgit v1.2.3 From 02858eedcb78a664215b918d98cdb753ce432ce6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 2 Apr 2010 20:01:00 -0300 Subject: V4L/DVB: ir-core: Make use of the new IR keymap modules Instead of using the ugly keymap sequences, use the new rc-*.ko keymap files. For now, it is still needed to have one keymap loaded, for the RC code to work. Later patches will remove this depenency. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Makefile | 2 ++ drivers/media/IR/ir-sysfs.c | 4 +++- drivers/media/IR/rc-map.c | 27 +++++++++++++++++++++------ 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 3a4f590d0bbb..3d8dd306df46 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,6 +1,8 @@ ir-common-objs := ir-functions.o ir-keymaps.o ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o +obj-y += keymaps/ + obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 36dfe51aad92..58ecca2003a4 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -251,8 +251,10 @@ static int __init ir_core_init(void) return rc; } - /* Initialize/load the decoders that will be used */ + /* Initialize/load the decoders/keymap code that will be used */ ir_raw_init(); + rc_map_init(); + return 0; } diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index 02c72f086fe0..2f6201ce1898 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c @@ -26,12 +26,14 @@ static struct rc_keymap *seek_rc_map(const char *name) spin_lock(&rc_map_lock); list_for_each_entry(map, &rc_map_list, list) { - if (!strcmp(name, map->map.name)) - break; + if (!strcmp(name, map->map.name)) { + spin_unlock(&rc_map_lock); + return map; + } } spin_unlock(&rc_map_lock); - return map; + return NULL; } struct ir_scancode_table *get_rc_map(const char *name) @@ -43,15 +45,22 @@ struct ir_scancode_table *get_rc_map(const char *name) map = seek_rc_map(name); #ifdef MODULE if (!map) { - rc = request_module("name"); - if (rc < 0) + rc = request_module(name); + if (rc < 0) { + printk(KERN_ERR "Couldn't load IR keymap %s\n", name); return NULL; + } + msleep(20); /* Give some time for IR to register */ map = seek_rc_map(name); } #endif - if (!map) + if (!map) { + printk(KERN_ERR "IR keymap %s not found\n", name); return NULL; + } + + printk(KERN_INFO "Registered IR keymap %s\n", map->map.name); return &map->map; } @@ -73,3 +82,9 @@ void ir_unregister_map(struct rc_keymap *map) spin_unlock(&rc_map_lock); } EXPORT_SYMBOL_GPL(ir_unregister_map); + +void rc_map_init(void) +{ + spin_lock_init(&rc_map_lock); + +} -- cgit v1.2.3 From bd7261d3d7dfe61e8bf8945051c1905ba4dba3b5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 2 Apr 2010 20:11:45 -0300 Subject: V4L/DVB: ir-common: remove keymap tables from the module Now that the remote keymaps were broken into separate modules, get rid of the keycode tables that were hardcoded into ir-common. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Makefile | 2 +- drivers/media/IR/ir-keymaps.c | 45 ------------------------------------------- 2 files changed, 1 insertion(+), 46 deletions(-) delete mode 100644 drivers/media/IR/ir-keymaps.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 3d8dd306df46..0e3f912054ca 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -1,4 +1,4 @@ -ir-common-objs := ir-functions.o ir-keymaps.o +ir-common-objs := ir-functions.o ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o rc-map.o obj-y += keymaps/ diff --git a/drivers/media/IR/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c deleted file mode 100644 index eb2553192789..000000000000 --- a/drivers/media/IR/ir-keymaps.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - Keytables for supported remote controls, used on drivers/media - devices. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#define IR_KEYMAPS - -/* - * NOTICE FOR DEVELOPERS: - * The IR mappings should be as close as possible to what's - * specified at: - * http://linuxtv.org/wiki/index.php/Remote_Controllers - * - * The usage of tables with just the command part is deprecated. - * All new IR keytables should contain address+command and need - * to define the proper IR_TYPE (IR_TYPE_RC5/IR_TYPE_NEC). - * The deprecated tables should use IR_TYPE_UNKNOWN - */ -#include - -#include -#include - -/* - * All keytables got moved to include/media/keytables directory. - * This file is still needed - at least for now, as their data is - * dynamically inserted here by the media/ir-common.h, due to the - * #define IR_KEYMAPS line, at the beginning of this file. The - * plans are to get rid of this file completely in a near future. - */ - -- cgit v1.2.3 From b3074c0a3f020766c05c1249a31212bff4a77bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Fri, 2 Apr 2010 15:58:28 -0300 Subject: V4L/DVB: drivers/media/IR - improve keytable code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The attached patch rewrites much of the keytable code in drivers/media/IR/ir-keytable.c. The scancodes are now inserted into the array in sorted order which allows for a binary search on lookup. The code has also been shrunk by about 150 lines. In addition it fixes the following bugs: Any use of ir_seek_table() was racy. ir_dev->driver_name is leaked between ir_input_register() and ir_input_unregister(). ir_setkeycode() unconditionally does clear_bit() on dev->keybit when removing a mapping, but there might be another mapping with a different scancode and the same keycode. This version has been updated to incorporate patch feedback from Mauro Carvalho Chehab. [mchehab@redhat.com: Fix a conflict with RC keytable breakup patches and input changes] Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 518 +++++++++++++++-------------------------- 1 file changed, 188 insertions(+), 330 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 5d4ddc9f4cab..10e4be22dbfd 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -17,344 +17,214 @@ #include #include -#define IR_TAB_MIN_SIZE 32 -#define IR_TAB_MAX_SIZE 1024 +/* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ +#define IR_TAB_MIN_SIZE 256 +#define IR_TAB_MAX_SIZE 8192 /** - * ir_seek_table() - returns the element order on the table - * @rc_tab: the ir_scancode_table with the keymap to be used - * @scancode: the scancode that we're seeking + * ir_resize_table() - resizes a scancode table if necessary + * @rc_tab: the ir_scancode_table to resize + * @return: zero on success or a negative error code * - * This routine is used by the input routines when a key is pressed at the - * IR. The scancode is received and needs to be converted into a keycode. - * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the - * corresponding keycode from the table. + * This routine will shrink the ir_scancode_table if it has lots of + * unused entries and grow it if it is full. */ -static int ir_seek_table(struct ir_scancode_table *rc_tab, u32 scancode) +static int ir_resize_table(struct ir_scancode_table *rc_tab) { - int rc; - unsigned long flags; - struct ir_scancode *keymap = rc_tab->scan; + unsigned int oldalloc = rc_tab->alloc; + unsigned int newalloc = oldalloc; + struct ir_scancode *oldscan = rc_tab->scan; + struct ir_scancode *newscan; + + if (rc_tab->size == rc_tab->len) { + /* All entries in use -> grow keytable */ + if (rc_tab->alloc >= IR_TAB_MAX_SIZE) + return -ENOMEM; - spin_lock_irqsave(&rc_tab->lock, flags); + newalloc *= 2; + IR_dprintk(1, "Growing table to %u bytes\n", newalloc); + } - /* FIXME: replace it by a binary search */ + if ((rc_tab->len * 3 < rc_tab->size) && (oldalloc > IR_TAB_MIN_SIZE)) { + /* Less than 1/3 of entries in use -> shrink keytable */ + newalloc /= 2; + IR_dprintk(1, "Shrinking table to %u bytes\n", newalloc); + } - for (rc = 0; rc < rc_tab->size; rc++) - if (keymap[rc].scancode == scancode) - goto exit; + if (newalloc == oldalloc) + return 0; - /* Not found */ - rc = -EINVAL; + newscan = kmalloc(newalloc, GFP_ATOMIC); + if (!newscan) { + IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc); + return -ENOMEM; + } -exit: - spin_unlock_irqrestore(&rc_tab->lock, flags); - return rc; + memcpy(newscan, rc_tab->scan, rc_tab->len * sizeof(struct ir_scancode)); + rc_tab->scan = newscan; + rc_tab->alloc = newalloc; + rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode); + kfree(oldscan); + return 0; } /** - * ir_roundup_tablesize() - gets an optimum value for the table size - * @n_elems: minimum number of entries to store keycodes - * - * This routine is used to choose the keycode table size. + * ir_do_setkeycode() - internal function to set a keycode in the + * scancode->keycode table + * @dev: the struct input_dev device descriptor + * @rc_tab: the struct ir_scancode_table to set the keycode in + * @scancode: the scancode for the ir command + * @keycode: the keycode for the ir command + * @return: -EINVAL if the keycode could not be inserted, otherwise zero. * - * In order to have some empty space for new keycodes, - * and knowing in advance that kmalloc allocates only power of two - * segments, it optimizes the allocated space to have some spare space - * for those new keycodes by using the maximum number of entries that - * will be effectively be allocated by kmalloc. - * In order to reduce the quantity of table resizes, it has a minimum - * table size of IR_TAB_MIN_SIZE. + * This routine is used internally to manipulate the scancode->keycode table. + * The caller has to hold @rc_tab->lock. */ -static int ir_roundup_tablesize(int n_elems) +static int ir_do_setkeycode(struct input_dev *dev, + struct ir_scancode_table *rc_tab, + unsigned scancode, unsigned keycode) { - size_t size; + unsigned int i; + int old_keycode = KEY_RESERVED; + + /* First check if we already have a mapping for this ir command */ + for (i = 0; i < rc_tab->len; i++) { + /* Keytable is sorted from lowest to highest scancode */ + if (rc_tab->scan[i].scancode > scancode) + break; + else if (rc_tab->scan[i].scancode < scancode) + continue; - if (n_elems < IR_TAB_MIN_SIZE) - n_elems = IR_TAB_MIN_SIZE; + old_keycode = rc_tab->scan[i].keycode; + rc_tab->scan[i].keycode = keycode; - /* - * As kmalloc only allocates sizes of power of two, get as - * much entries as possible for the allocated memory segment - */ - size = roundup_pow_of_two(n_elems * sizeof(struct ir_scancode)); - n_elems = size / sizeof(struct ir_scancode); + /* Did the user wish to remove the mapping? */ + if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) { + rc_tab->len--; + memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1], + (rc_tab->len - i) * sizeof(struct ir_scancode)); + } - return n_elems; -} - -/** - * ir_copy_table() - copies a keytable, discarding the unused entries - * @destin: destin table - * @origin: origin table - * - * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED - * Also copies table size and table protocol. - * NOTE: It shouldn't copy the lock field - */ - -static int ir_copy_table(struct ir_scancode_table *destin, - const struct ir_scancode_table *origin) -{ - int i, j = 0; + /* Possibly shrink the keytable, failure is not a problem */ + ir_resize_table(rc_tab); + break; + } - for (i = 0; i < origin->size; i++) { - if (origin->scan[i].keycode == KEY_UNKNOWN || - origin->scan[i].keycode == KEY_RESERVED) - continue; + if (old_keycode == KEY_RESERVED) { + /* No previous mapping found, we might need to grow the table */ + if (ir_resize_table(rc_tab)) + return -ENOMEM; - memcpy(&destin->scan[j], &origin->scan[i], sizeof(struct ir_scancode)); - j++; + /* i is the proper index to insert our new keycode */ + memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], + (rc_tab->len - i) * sizeof(struct ir_scancode)); + rc_tab->scan[i].scancode = scancode; + rc_tab->scan[i].keycode = keycode; + rc_tab->len++; + set_bit(keycode, dev->keybit); + } else { + /* A previous mapping was updated... */ + clear_bit(old_keycode, dev->keybit); + /* ...but another scancode might use the same keycode */ + for (i = 0; i < rc_tab->len; i++) { + if (rc_tab->scan[i].keycode == old_keycode) { + set_bit(old_keycode, dev->keybit); + break; + } + } } - destin->size = j; - destin->ir_type = origin->ir_type; - - IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size); return 0; } /** - * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table + * ir_setkeycode() - set a keycode in the scancode->keycode table * @dev: the struct input_dev device descriptor * @scancode: the desired scancode - * @keycode: the keycode to be retorned. + * @keycode: result + * @return: -EINVAL if the keycode could not be inserted, otherwise zero. * - * This routine is used to handle evdev EVIOCGKEY ioctl. - * If the key is not found, returns -EINVAL, otherwise, returns 0. + * This routine is used to handle evdev EVIOCSKEY ioctl. */ -static int ir_getkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode) +static int ir_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { - int elem; + int rc; + unsigned long flags; struct ir_input_dev *ir_dev = input_get_drvdata(dev); struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - elem = ir_seek_table(rc_tab, scancode); - if (elem >= 0) { - *keycode = rc_tab->scan[elem].keycode; - return 0; - } - - /* - * Scancode not found and table can't be expanded - */ - if (elem < 0 && rc_tab->size == IR_TAB_MAX_SIZE) - return -EINVAL; - - /* - * If is there extra space, returns KEY_RESERVED, - * otherwise, input core won't let ir_setkeycode to work - */ - *keycode = KEY_RESERVED; - return 0; -} - -/** - * ir_is_resize_needed() - Check if the table needs rezise - * @table: keycode table that may need to resize - * @n_elems: minimum number of entries to store keycodes - * - * Considering that kmalloc uses power of two storage areas, this - * routine detects if the real alloced size will change. If not, it - * just returns without doing nothing. Otherwise, it will extend or - * reduce the table size to meet the new needs. - * - * It returns 0 if no resize is needed, 1 otherwise. - */ -static int ir_is_resize_needed(struct ir_scancode_table *table, int n_elems) -{ - int cur_size = ir_roundup_tablesize(table->size); - int new_size = ir_roundup_tablesize(n_elems); - - if (cur_size == new_size) - return 0; - - /* Resize is needed */ - return 1; -} - -/** - * ir_delete_key() - remove a keycode from the table - * @rc_tab: keycode table - * @elem: element to be removed - * - */ -static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem) -{ - unsigned long flags = 0; - int newsize = rc_tab->size - 1; - int resize = ir_is_resize_needed(rc_tab, newsize); - struct ir_scancode *oldkeymap = rc_tab->scan; - struct ir_scancode *newkeymap = NULL; - - if (resize) - newkeymap = kzalloc(ir_roundup_tablesize(newsize) * - sizeof(*newkeymap), GFP_ATOMIC); - - /* There's no memory for resize. Keep the old table */ - if (!resize || !newkeymap) { - newkeymap = oldkeymap; - - /* We'll modify the live table. Lock it */ - spin_lock_irqsave(&rc_tab->lock, flags); - } - - /* - * Copy the elements before the one that will be deleted - * if (!resize), both oldkeymap and newkeymap points - * to the same place, so, there's no need to copy - */ - if (resize && elem > 0) - memcpy(newkeymap, oldkeymap, - elem * sizeof(*newkeymap)); - - /* - * Copy the other elements overwriting the element to be removed - * This operation applies to both resize and non-resize case - */ - if (elem < newsize) - memcpy(&newkeymap[elem], &oldkeymap[elem + 1], - (newsize - elem) * sizeof(*newkeymap)); - - if (resize) { - /* - * As the copy happened to a temporary table, only here - * it needs to lock while replacing the table pointers - * to use the new table - */ - spin_lock_irqsave(&rc_tab->lock, flags); - rc_tab->size = newsize; - rc_tab->scan = newkeymap; - spin_unlock_irqrestore(&rc_tab->lock, flags); - - /* Frees the old keytable */ - kfree(oldkeymap); - } else { - rc_tab->size = newsize; - spin_unlock_irqrestore(&rc_tab->lock, flags); - } + spin_lock_irqsave(&rc_tab->lock, flags); + rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode); + spin_unlock_irqrestore(&rc_tab->lock, flags); + return rc; } /** - * ir_insert_key() - insert a keycode at the table - * @rc_tab: keycode table - * @scancode: the desired scancode - * @keycode: the keycode to be retorned. + * ir_setkeytable() - sets several entries in the scancode->keycode table + * @dev: the struct input_dev device descriptor + * @to: the struct ir_scancode_table to copy entries to + * @from: the struct ir_scancode_table to copy entries from + * @return: -EINVAL if all keycodes could not be inserted, otherwise zero. * + * This routine is used to handle table initialization. */ -static int ir_insert_key(struct ir_scancode_table *rc_tab, - int scancode, int keycode) +static int ir_setkeytable(struct input_dev *dev, + struct ir_scancode_table *to, + const struct ir_scancode_table *from) { + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; unsigned long flags; - int elem = rc_tab->size; - int newsize = rc_tab->size + 1; - int resize = ir_is_resize_needed(rc_tab, newsize); - struct ir_scancode *oldkeymap = rc_tab->scan; - struct ir_scancode *newkeymap; - - if (resize) { - newkeymap = kzalloc(ir_roundup_tablesize(newsize) * - sizeof(*newkeymap), GFP_ATOMIC); - if (!newkeymap) - return -ENOMEM; - - memcpy(newkeymap, oldkeymap, - rc_tab->size * sizeof(*newkeymap)); - } else - newkeymap = oldkeymap; - - /* Stores the new code at the table */ - IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", - rc_tab->size, scancode, keycode); + unsigned int i; + int rc = 0; spin_lock_irqsave(&rc_tab->lock, flags); - rc_tab->size = newsize; - if (resize) { - rc_tab->scan = newkeymap; - kfree(oldkeymap); + for (i = 0; i < from->size; i++) { + rc = ir_do_setkeycode(dev, to, from->scan[i].scancode, + from->scan[i].keycode); + if (rc) + break; } - newkeymap[elem].scancode = scancode; - newkeymap[elem].keycode = keycode; spin_unlock_irqrestore(&rc_tab->lock, flags); - - return 0; + return rc; } /** - * ir_setkeycode() - set a keycode at the evdev scancode ->keycode table + * ir_getkeycode() - get a keycode from the scancode->keycode table * @dev: the struct input_dev device descriptor * @scancode: the desired scancode - * @keycode: the keycode to be retorned. + * @keycode: used to return the keycode, if found, or KEY_RESERVED + * @return: always returns zero. * - * This routine is used to handle evdev EVIOCSKEY ioctl. - * There's one caveat here: how can we increase the size of the table? - * If the key is not found, returns -EINVAL, otherwise, returns 0. + * This routine is used to handle evdev EVIOCGKEY ioctl. */ -static int ir_setkeycode(struct input_dev *dev, - unsigned int scancode, unsigned int keycode) +static int ir_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { - int rc = 0; + int start, end, mid; + unsigned long flags; + int key = KEY_RESERVED; struct ir_input_dev *ir_dev = input_get_drvdata(dev); struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - struct ir_scancode *keymap = rc_tab->scan; - unsigned long flags; - - /* - * Handle keycode table deletions - * - * If userspace is adding a KEY_UNKNOWN or KEY_RESERVED, - * deal as a trial to remove an existing scancode attribution - * if table become too big, reduce it to save space - */ - if (keycode == KEY_UNKNOWN || keycode == KEY_RESERVED) { - rc = ir_seek_table(rc_tab, scancode); - if (rc < 0) - return 0; - - IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", rc, scancode); - clear_bit(keymap[rc].keycode, dev->keybit); - ir_delete_key(rc_tab, rc); - - return 0; - } - - /* - * Handle keycode replacements - * - * If the scancode exists, just replace by the new value - */ - rc = ir_seek_table(rc_tab, scancode); - if (rc >= 0) { - IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", - rc, scancode, keycode); - clear_bit(keymap[rc].keycode, dev->keybit); - - spin_lock_irqsave(&rc_tab->lock, flags); - keymap[rc].keycode = keycode; - spin_unlock_irqrestore(&rc_tab->lock, flags); - - set_bit(keycode, dev->keybit); - - return 0; + spin_lock_irqsave(&rc_tab->lock, flags); + start = 0; + end = rc_tab->len - 1; + while (start <= end) { + mid = (start + end) / 2; + if (rc_tab->scan[mid].scancode < scancode) + start = mid + 1; + else if (rc_tab->scan[mid].scancode > scancode) + end = mid - 1; + else { + key = rc_tab->scan[mid].keycode; + break; + } } + spin_unlock_irqrestore(&rc_tab->lock, flags); - /* - * Handle new scancode inserts - * - * reallocate table if needed and insert a new keycode - */ - - /* Avoid growing the table indefinitely */ - if (rc_tab->size + 1 > IR_TAB_MAX_SIZE) - return -EINVAL; - - rc = ir_insert_key(rc_tab, scancode, keycode); - if (rc < 0) - return rc; - set_bit(keycode, dev->keybit); - + *keycode = key; return 0; } @@ -370,24 +240,12 @@ static int ir_setkeycode(struct input_dev *dev, */ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) { - struct ir_input_dev *ir_dev = input_get_drvdata(dev); - struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; - struct ir_scancode *keymap = rc_tab->scan; - int elem; - - elem = ir_seek_table(rc_tab, scancode); - if (elem >= 0) { - IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", - dev->name, scancode, keymap[elem].keycode); - - return rc_tab->scan[elem].keycode; - } + int keycode; - printk(KERN_INFO "%s: unknown key for scancode 0x%04x\n", - dev->name, scancode); - - /* Reports userspace that an unknown keycode were got */ - return KEY_RESERVED; + ir_getkeycode(dev, scancode, &keycode); + IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", + dev->name, scancode, keycode); + return keycode; } EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); @@ -477,8 +335,7 @@ int __ir_input_register(struct input_dev *input_dev, const char *driver_name) { struct ir_input_dev *ir_dev; - struct ir_scancode *keymap = rc_tab->scan; - int i, rc; + int rc; if (rc_tab->scan == NULL || !rc_tab->size) return -EINVAL; @@ -487,55 +344,55 @@ int __ir_input_register(struct input_dev *input_dev, if (!ir_dev) return -ENOMEM; - spin_lock_init(&ir_dev->rc_tab.lock); + ir_dev->driver_name = kasprintf(GFP_KERNEL, "%s", driver_name); + if (!ir_dev->driver_name) { + rc = -ENOMEM; + goto out_dev; + } - ir_dev->driver_name = kmalloc(strlen(driver_name) + 1, GFP_KERNEL); - if (!ir_dev->driver_name) - return -ENOMEM; - strcpy(ir_dev->driver_name, driver_name); + input_dev->getkeycode = ir_getkeycode; + input_dev->setkeycode = ir_setkeycode; + input_set_drvdata(input_dev, ir_dev); + + spin_lock_init(&ir_dev->rc_tab.lock); ir_dev->rc_tab.name = rc_tab->name; - ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size); - ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size * - sizeof(struct ir_scancode), GFP_KERNEL); + ir_dev->rc_tab.ir_type = rc_tab->ir_type; + ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size * + sizeof(struct ir_scancode)); + ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL); + ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode); + if (!ir_dev->rc_tab.scan) { - kfree(ir_dev); - return -ENOMEM; + rc = -ENOMEM; + goto out_name; } - IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n", - ir_dev->rc_tab.size, - ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan)); + IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n", + ir_dev->rc_tab.size, ir_dev->rc_tab.alloc); + + set_bit(EV_KEY, input_dev->evbit); + if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { + rc = -ENOMEM; + goto out_table; + } - ir_copy_table(&ir_dev->rc_tab, rc_tab); ir_dev->props = props; if (props && props->open) input_dev->open = ir_open; if (props && props->close) input_dev->close = ir_close; - /* set the bits for the keys */ - IR_dprintk(1, "key map size: %d\n", rc_tab->size); - for (i = 0; i < rc_tab->size; i++) { - IR_dprintk(1, "#%d: setting bit for keycode 0x%04x\n", - i, keymap[i].keycode); - set_bit(keymap[i].keycode, input_dev->keybit); - } - clear_bit(0, input_dev->keybit); - - set_bit(EV_KEY, input_dev->evbit); - - input_dev->getkeycode = ir_getkeycode; - input_dev->setkeycode = ir_setkeycode; - input_set_drvdata(input_dev, ir_dev); - rc = ir_register_class(input_dev); if (rc < 0) - goto err; + goto out_table; return 0; -err: - kfree(rc_tab->scan); +out_table: + kfree(ir_dev->rc_tab.scan); +out_name: + kfree(ir_dev->driver_name); +out_dev: kfree(ir_dev); return rc; } @@ -564,6 +421,7 @@ void ir_input_unregister(struct input_dev *dev) ir_unregister_class(dev); + kfree(ir_dev->driver_name); kfree(ir_dev); } EXPORT_SYMBOL_GPL(ir_input_unregister); -- cgit v1.2.3 From 354389467b6b2a3b36666b6e933d78bbd9e23577 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 3 Apr 2010 16:53:16 -0300 Subject: V4L/DVB: ir-core: re-add some debug functions for keytable changes Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 10e4be22dbfd..a0aa5c1b6b41 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -100,6 +100,8 @@ static int ir_do_setkeycode(struct input_dev *dev, /* Did the user wish to remove the mapping? */ if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) { + IR_dprintk(1, "#%d: Deleting scan 0x%04x\n", + i, scancode); rc_tab->len--; memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1], (rc_tab->len - i) * sizeof(struct ir_scancode)); @@ -115,6 +117,9 @@ static int ir_do_setkeycode(struct input_dev *dev, if (ir_resize_table(rc_tab)) return -ENOMEM; + IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", + i, scancode, keycode); + /* i is the proper index to insert our new keycode */ memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i], (rc_tab->len - i) * sizeof(struct ir_scancode)); @@ -123,6 +128,8 @@ static int ir_do_setkeycode(struct input_dev *dev, rc_tab->len++; set_bit(keycode, dev->keybit); } else { + IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n", + i, scancode, keycode); /* A previous mapping was updated... */ clear_bit(old_keycode, dev->keybit); /* ...but another scancode might use the same keycode */ @@ -224,6 +231,10 @@ static int ir_getkeycode(struct input_dev *dev, } spin_unlock_irqrestore(&rc_tab->lock, flags); + if (key == KEY_RESERVED) + IR_dprintk(1, "unknown key for scancode 0x%04x\n", + scancode); + *keycode = key; return 0; } @@ -243,8 +254,9 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode) int keycode; ir_getkeycode(dev, scancode, &keycode); - IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", - dev->name, scancode, keycode); + if (keycode != KEY_RESERVED) + IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n", + dev->name, scancode, keycode); return keycode; } EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); @@ -386,6 +398,9 @@ int __ir_input_register(struct input_dev *input_dev, if (rc < 0) goto out_table; + IR_dprintk(1, "Registered input device on %s for %s remote.\n", + driver_name, rc_tab->name); + return 0; out_table: -- cgit v1.2.3 From a374fef4437abd0a1ee27afe0cca7a55425c1c3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Fri, 2 Apr 2010 15:58:29 -0300 Subject: V4L/DVB: ir-core: improve keyup/keydown logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrites the keyup/keydown logic in drivers/media/IR/ir-keytable.c. All knowledge of keystates etc is now internal to ir-keytable.c and not scattered around ir-raw-event.c and ir-nec-decoder.c (where it doesn't belong). In addition, I've changed the API slightly so that ir_input_dev is passed as the first argument rather than input_dev. If we're ever going to support multiple keytables we need to move towards making ir_input_dev the main interface from a driver POV and obscure away the input_dev as an implementational detail in ir-core. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 125 ++++++++++++++++++++++++++++++-------- drivers/media/IR/ir-nec-decoder.c | 7 +-- drivers/media/IR/ir-raw-event.c | 14 ----- 3 files changed, 103 insertions(+), 43 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index a0aa5c1b6b41..a89456932f7c 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -21,6 +21,9 @@ #define IR_TAB_MIN_SIZE 256 #define IR_TAB_MAX_SIZE 8192 +/* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */ +#define IR_KEYPRESS_TIMEOUT 250 + /** * ir_resize_table() - resizes a scancode table if necessary * @rc_tab: the ir_scancode_table to resize @@ -263,56 +266,124 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table); /** * ir_keyup() - generates input event to cleanup a key press - * @input_dev: the struct input_dev descriptor of the device + * @ir: the struct ir_input_dev descriptor of the device * - * This routine is used by the input routines when a key is pressed at the - * IR. It reports a keyup input event via input_report_key(). + * This routine is used to signal that a key has been released on the + * remote control. It reports a keyup input event via input_report_key(). + */ +static void ir_keyup(struct ir_input_dev *ir) +{ + if (!ir->keypressed) + return; + + IR_dprintk(1, "keyup key 0x%04x\n", ir->last_keycode); + input_report_key(ir->input_dev, ir->last_keycode, 0); + input_sync(ir->input_dev); + ir->keypressed = false; +} + +/** + * ir_timer_keyup() - generates a keyup event after a timeout + * @cookie: a pointer to struct ir_input_dev passed to setup_timer() + * + * This routine will generate a keyup event some time after a keydown event + * is generated when no further activity has been detected. */ -void ir_keyup(struct input_dev *dev) +static void ir_timer_keyup(unsigned long cookie) { + struct ir_input_dev *ir = (struct ir_input_dev *)cookie; + unsigned long flags; + + /* + * ir->keyup_jiffies is used to prevent a race condition if a + * hardware interrupt occurs at this point and the keyup timer + * event is moved further into the future as a result. + * + * The timer will then be reactivated and this function called + * again in the future. We need to exit gracefully in that case + * to allow the input subsystem to do its auto-repeat magic or + * a keyup event might follow immediately after the keydown. + */ + spin_lock_irqsave(&ir->keylock, flags); + if (time_is_after_eq_jiffies(ir->keyup_jiffies)) + ir_keyup(ir); + spin_unlock_irqrestore(&ir->keylock, flags); +} + +/** + * ir_repeat() - notifies the IR core that a key is still pressed + * @dev: the struct input_dev descriptor of the device + * + * This routine is used by IR decoders when a repeat message which does + * not include the necessary bits to reproduce the scancode has been + * received. + */ +void ir_repeat(struct input_dev *dev) +{ + unsigned long flags; struct ir_input_dev *ir = input_get_drvdata(dev); + spin_lock_irqsave(&ir->keylock, flags); + if (!ir->keypressed) - return; + goto out; - IR_dprintk(1, "keyup key 0x%04x\n", ir->keycode); - input_report_key(dev, ir->keycode, 0); - input_sync(dev); - ir->keypressed = 0; + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); + +out: + spin_unlock_irqrestore(&ir->keylock, flags); } -EXPORT_SYMBOL_GPL(ir_keyup); +EXPORT_SYMBOL_GPL(ir_repeat); /** * ir_keydown() - generates input event for a key press - * @input_dev: the struct input_dev descriptor of the device - * @scancode: the scancode that we're seeking + * @dev: the struct input_dev descriptor of the device + * @scancode: the scancode that we're seeking + * @toggle: the toggle value (protocol dependent, if the protocol doesn't + * support toggle values, this should be set to zero) * * This routine is used by the input routines when a key is pressed at the * IR. It gets the keycode for a scancode and reports an input event via * input_report_key(). */ -void ir_keydown(struct input_dev *dev, int scancode) +void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) { + unsigned long flags; struct ir_input_dev *ir = input_get_drvdata(dev); u32 keycode = ir_g_keycode_from_table(dev, scancode); - /* If already sent a keydown, do a keyup */ - if (ir->keypressed) - ir_keyup(dev); + spin_lock_irqsave(&ir->keylock, flags); - if (KEY_RESERVED == keycode) - return; + /* Repeat event? */ + if (ir->keypressed && + ir->last_scancode == scancode && + ir->last_toggle == toggle) + goto set_timer; - ir->keycode = keycode; - ir->keypressed = 1; + /* Release old keypress */ + ir_keyup(ir); - IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", - dev->name, keycode, scancode); + ir->last_scancode = scancode; + ir->last_toggle = toggle; + ir->last_keycode = keycode; + + if (keycode == KEY_RESERVED) + goto out; - input_report_key(dev, ir->keycode, 1); + /* Register a keypress */ + ir->keypressed = true; + IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", + dev->name, keycode, scancode); + input_report_key(dev, ir->last_keycode, 1); input_sync(dev); +set_timer: + ir->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); + mod_timer(&ir->timer_keyup, ir->keyup_jiffies); +out: + spin_unlock_irqrestore(&ir->keylock, flags); } EXPORT_SYMBOL_GPL(ir_keydown); @@ -365,8 +436,12 @@ int __ir_input_register(struct input_dev *input_dev, input_dev->getkeycode = ir_getkeycode; input_dev->setkeycode = ir_setkeycode; input_set_drvdata(input_dev, ir_dev); + ir_dev->input_dev = input_dev; spin_lock_init(&ir_dev->rc_tab.lock); + spin_lock_init(&ir_dev->keylock); + setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev); + ir_dev->rc_tab.name = rc_tab->name; ir_dev->rc_tab.ir_type = rc_tab->ir_type; ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size * @@ -383,6 +458,8 @@ int __ir_input_register(struct input_dev *input_dev, ir_dev->rc_tab.size, ir_dev->rc_tab.alloc); set_bit(EV_KEY, input_dev->evbit); + set_bit(EV_REP, input_dev->evbit); + if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { rc = -ENOMEM; goto out_table; @@ -428,7 +505,7 @@ void ir_input_unregister(struct input_dev *dev) return; IR_dprintk(1, "Freed keycode table\n"); - + del_timer_sync(&ir_dev->timer_keyup); rc_tab = &ir_dev->rc_tab; rc_tab->size = 0; kfree(rc_tab->scan); diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 83a9912722f4..0b50060ffbaf 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -180,8 +180,7 @@ static int __ir_nec_decode(struct input_dev *input_dev, if (is_repeat(evs, len, *pos)) { *pos += 2; if (ir->keypressed) { - mod_timer(&ir->raw->timer_keyup, - jiffies + msecs_to_jiffies(REPEAT_TIME)); + ir_repeat(input_dev); IR_dprintk(1, "NEC repeat event\n"); return 1; } else { @@ -238,9 +237,7 @@ static int __ir_nec_decode(struct input_dev *input_dev, } IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); - ir_keydown(input_dev, ircode); - mod_timer(&ir->raw->timer_keyup, - jiffies + msecs_to_jiffies(REPEAT_TIME)); + ir_keydown(input_dev, ircode, 0); return 1; err: diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 371d88e5a586..59f20541b03e 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -53,13 +53,6 @@ static spinlock_t ir_raw_handler_lock; /* Used to load the decoders */ static struct work_struct wq_load; -static void ir_keyup_timer(unsigned long data) -{ - struct input_dev *input_dev = (struct input_dev *)data; - - ir_keyup(input_dev); -} - int ir_raw_event_register(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); @@ -72,11 +65,6 @@ int ir_raw_event_register(struct input_dev *input_dev) size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; size = roundup_pow_of_two(size); - init_timer(&ir->raw->timer_keyup); - ir->raw->timer_keyup.function = ir_keyup_timer; - ir->raw->timer_keyup.data = (unsigned long)input_dev; - set_bit(EV_REP, input_dev->evbit); - rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); if (rc < 0) { kfree(ir->raw); @@ -103,8 +91,6 @@ void ir_raw_event_unregister(struct input_dev *input_dev) if (!ir->raw) return; - del_timer_sync(&ir->raw->timer_keyup); - RUN_DECODER(raw_unregister, input_dev); kfifo_free(&ir->raw->kfifo); -- cgit v1.2.3 From 2f16f6315f583964732bc23c873d4024281d763c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 3 Apr 2010 18:51:50 -0300 Subject: V4L/DVB: ir-nec-decoder: Reimplement the entire decoder Thanks to Andy Walls for pointing me his code, that gave me some ideas to better implement it. After some work with saa7134 bits, I found a way to catch both IRQ edge pulses. By enabling it, the NEC decoder can now take both pulse and spaces into account, making it more precise. Instead of the old strategy of handling the events all at once, this code implements a state machine. Due to that, it handles individual pulse or space events, validating them against the protocol, producing a much more reliable decoding. With the new implementation, the protocol trailer bits are properly handled, making possible for the repeat key to work. Also, the code is now capable of handling both NEC and NEC extended IR devices. With NEC, it produces a 16 bits code, while with NEC extended, a 24 bits code is returned. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 271 +++++++++++++++++++++++--------------- 1 file changed, 167 insertions(+), 104 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 0b50060ffbaf..33b260f517f5 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -14,6 +14,14 @@ #include +#define NEC_UNIT 559979 /* ns */ +#define NEC_HEADER_MARK (16 * NEC_UNIT) +#define NEC_HEADER_SPACE (8 * NEC_UNIT) +#define NEC_REPEAT_SPACE (4 * NEC_UNIT) +#define NEC_MARK (NEC_UNIT) +#define NEC_0_SYMBOL (NEC_UNIT) +#define NEC_1_SYMBOL (3 * NEC_UNIT) + /* Start time: 4.5 ms + 560 us of the next pulse */ #define MIN_START_TIME (3900000 + 560000) #define MAX_START_TIME (5100000 + 560000) @@ -43,10 +51,32 @@ static LIST_HEAD(decoder_list); static spinlock_t decoder_lock; +enum nec_state { + STATE_INACTIVE, + STATE_HEADER_MARK, + STATE_HEADER_SPACE, + STATE_MARK, + STATE_SPACE, + STATE_TRAILER_MARK, + STATE_TRAILER_SPACE, +}; + +struct nec_code { + u8 address; + u8 not_address; + u8 command; + u8 not_command; +}; + struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; int enabled:1; + + /* State machine control */ + enum nec_state state; + struct nec_code nec_code; + unsigned count; }; @@ -118,139 +148,173 @@ static struct attribute_group decoder_attribute_group = { }; -/** is_repeat - Check if it is a NEC repeat event +/** + * handle_event() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device - * @pos: the position of the first event - * @len: the length of the buffer + * @ev: event array with type/duration of pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine */ -static int is_repeat(struct ir_raw_event *evs, int len, int pos) +static int handle_event(struct input_dev *input_dev, + struct ir_raw_event *ev) { - if ((evs[pos].delta.tv_nsec < MIN_REPEAT_START_TIME) || - (evs[pos].delta.tv_nsec > MAX_REPEAT_START_TIME)) - return 0; + struct decoder_data *data; + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int bit, last_bit; - if (++pos >= len) - return 0; + data = get_decoder_data(ir_dev); + if (!data) + return -EINVAL; - if ((evs[pos].delta.tv_nsec < MIN_REPEAT_TIME) || - (evs[pos].delta.tv_nsec > MAX_REPEAT_TIME)) - return 0; + /* Except for the initial event, what matters is the previous bit */ + bit = (ev->type & IR_PULSE) ? 1 : 0; - return 1; -} + last_bit = !bit; -/** - * __ir_nec_decode() - Decode one NEC pulsecode - * @input_dev: the struct input_dev descriptor of the device - * @evs: event array with type/duration of pulse/space - * @len: length of the array - * @pos: position to start seeking for a code - * This function returns -EINVAL if no pulse got decoded, - * 0 if buffer is empty and 1 if one keycode were handled. - */ -static int __ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *evs, - int len, int *pos) -{ - struct ir_input_dev *ir = input_get_drvdata(input_dev); - int count = -1; - int ircode = 0, not_code = 0; - - /* Be sure that the first event is an start one and is a pulse */ - for (; *pos < len; (*pos)++) { - /* Very long delays are considered as start events */ - if (evs[*pos].delta.tv_nsec > MAX_NEC_TIME) - break; - if (evs[*pos].type & IR_START_EVENT) - break; - IR_dprintk(1, "%luus: Spurious NEC %s\n", - (evs[*pos].delta.tv_nsec + 500) / 1000, - (evs[*pos].type & IR_SPACE) ? "space" : "pulse"); + /* Discards spurious space last_bits when inactive */ - } - if (*pos >= len) - return 0; + /* Very long delays are considered as start events */ + if (ev->delta.tv_nsec > NEC_HEADER_MARK + NEC_HEADER_SPACE - NEC_UNIT / 2) + data->state = STATE_INACTIVE; - (*pos)++; /* First event doesn't contain data */ + if (ev->type & IR_START_EVENT) + data->state = STATE_INACTIVE; - if (evs[*pos].type != IR_PULSE) - goto err; + switch (data->state) { + case STATE_INACTIVE: + if (!bit) /* PULSE marks the start event */ + return 0; - /* Check if it is a NEC repeat event */ - if (is_repeat(evs, len, *pos)) { - *pos += 2; - if (ir->keypressed) { - ir_repeat(input_dev); - IR_dprintk(1, "NEC repeat event\n"); - return 1; - } else { - IR_dprintk(1, "missing NEC repeat event\n"); + data->count = 0; + data->state = STATE_HEADER_MARK; + memset (&data->nec_code, 0, sizeof(data->nec_code)); + return 0; + case STATE_HEADER_MARK: + if (!last_bit) + goto err; + if (ev->delta.tv_nsec < NEC_HEADER_MARK - 6 * NEC_UNIT) + goto err; + data->state = STATE_HEADER_SPACE; + return 0; + case STATE_HEADER_SPACE: + if (last_bit) + goto err; + if (ev->delta.tv_nsec >= NEC_HEADER_SPACE - NEC_UNIT / 2) { + data->state = STATE_MARK; return 0; } - } - /* First space should have 4.5 ms otherwise is not NEC protocol */ - if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) || - (evs[*pos].delta.tv_nsec > MAX_START_TIME)) + if (ev->delta.tv_nsec >= NEC_REPEAT_SPACE - NEC_UNIT / 2) { + ir_repeat(input_dev); + IR_dprintk(1, "Repeat last key\n"); + data->state = STATE_TRAILER_MARK; + return 0; + } goto err; + case STATE_MARK: + if (!last_bit) + goto err; + if ((ev->delta.tv_nsec > NEC_MARK + NEC_UNIT / 2) || + (ev->delta.tv_nsec < NEC_MARK - NEC_UNIT / 2)) + goto err; + data->state = STATE_SPACE; + return 0; + case STATE_SPACE: + if (last_bit) + goto err; - count = 0; - for ((*pos)++; *pos < len; (*pos)++) { - int bit; - if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) && - (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME)) - bit = 1; - else if ((evs[*pos].delta.tv_nsec > MIN_BIT0_TIME) && - (evs[*pos].delta.tv_nsec < MAX_BIT0_TIME)) + if ((ev->delta.tv_nsec >= NEC_0_SYMBOL - NEC_UNIT / 2) && + (ev->delta.tv_nsec < NEC_0_SYMBOL + NEC_UNIT / 2)) bit = 0; - else - goto err; + else if ((ev->delta.tv_nsec >= NEC_1_SYMBOL - NEC_UNIT / 2) && + (ev->delta.tv_nsec < NEC_1_SYMBOL + NEC_UNIT / 2)) + bit = 1; + else { + IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", + data->count, + last_bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); + + goto err2; + } + /* Ok, we've got a valid bit. proccess it */ if (bit) { - int shift = count; - /* Address first, then command */ + int shift = data->count; + + /* + * NEC transmit bytes on this temporal order: + * address | not address | command | not command + */ if (shift < 8) { - shift += 8; - ircode |= 1 << shift; + data->nec_code.address |= 1 << shift; } else if (shift < 16) { - not_code |= 1 << shift; + data->nec_code.not_address |= 1 << (shift - 8); } else if (shift < 24) { - shift -= 16; - ircode |= 1 << shift; + data->nec_code.command |= 1 << (shift - 16); } else { - shift -= 24; - not_code |= 1 << shift; + data->nec_code.not_command |= 1 << (shift - 24); } } - if (++count == 32) - break; - } - (*pos)++; - - /* - * Fixme: may need to accept Extended NEC protocol? - */ - if ((ircode & ~not_code) != ircode) { - IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n", - ircode, not_code); - return -EINVAL; - } + if (++data->count == 32) { + u32 scancode; + /* + * Fixme: may need to accept Extended NEC protocol? + */ + if ((data->nec_code.command ^ data->nec_code.not_command) != 0xff) + goto checksum_err; + + if ((data->nec_code.address ^ data->nec_code.not_address) != 0xff) { + /* Extended NEC */ + scancode = data->nec_code.address << 16 | + data->nec_code.not_address << 8 | + data->nec_code.command; + IR_dprintk(1, "NEC scancode 0x%06x\n", scancode); + } else { + /* normal NEC */ + scancode = data->nec_code.address << 8 | + data->nec_code.command; + IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); + } + ir_keydown(input_dev, scancode, 0); - IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); - ir_keydown(input_dev, ircode, 0); + data->state = STATE_TRAILER_MARK; + } else + data->state = STATE_MARK; + return 0; + case STATE_TRAILER_MARK: + if (!last_bit) + goto err; + data->state = STATE_TRAILER_SPACE; + return 0; + case STATE_TRAILER_SPACE: + if (last_bit) + goto err; + data->state = STATE_INACTIVE; + return 0; + } - return 1; err: - IR_dprintk(1, "NEC decoded failed at bit %d (%s) while decoding %luus time\n", - count, - (evs[*pos].type & IR_SPACE) ? "space" : "pulse", - (evs[*pos].delta.tv_nsec + 500) / 1000); + IR_dprintk(1, "NEC decoded failed at state %d (%s) @ %luus\n", + data->state, + bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); +err2: + data->state = STATE_INACTIVE; + return -EINVAL; +checksum_err: + data->state = STATE_INACTIVE; + IR_dprintk(1, "NEC checksum error: received 0x%02x%02x%02x%02x\n", + data->nec_code.address, + data->nec_code.not_address, + data->nec_code.command, + data->nec_code.not_command); return -EINVAL; } /** - * __ir_nec_decode() - Decodes all NEC pulsecodes on a given array + * ir_nec_decode() - Decodes all NEC pulsecodes on a given array * @input_dev: the struct input_dev descriptor of the device * @evs: event array with type/duration of pulse/space * @len: length of the array @@ -269,10 +333,9 @@ static int ir_nec_decode(struct input_dev *input_dev, if (!data || !data->enabled) return 0; - while (pos < len) { - if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) - rc++; - } + for (pos = 0; pos < len; pos++) + handle_event(input_dev, &evs[pos]); + return rc; } -- cgit v1.2.3 From 67780d6a2347d03b640f22295f8df7f00fbc829f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 3 Apr 2010 20:33:00 -0300 Subject: V4L/DVB: ir-nec-decoder: Cleanups Remove dead code and properly name a few constants Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 40 ++++++++------------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 33b260f517f5..087211c5496a 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -14,38 +14,14 @@ #include +#define NEC_NBITS 32 #define NEC_UNIT 559979 /* ns */ #define NEC_HEADER_MARK (16 * NEC_UNIT) #define NEC_HEADER_SPACE (8 * NEC_UNIT) #define NEC_REPEAT_SPACE (4 * NEC_UNIT) #define NEC_MARK (NEC_UNIT) -#define NEC_0_SYMBOL (NEC_UNIT) -#define NEC_1_SYMBOL (3 * NEC_UNIT) - -/* Start time: 4.5 ms + 560 us of the next pulse */ -#define MIN_START_TIME (3900000 + 560000) -#define MAX_START_TIME (5100000 + 560000) - -/* Bit 1 time: 2.25ms us */ -#define MIN_BIT1_TIME 2050000 -#define MAX_BIT1_TIME 2450000 - -/* Bit 0 time: 1.12ms us */ -#define MIN_BIT0_TIME 920000 -#define MAX_BIT0_TIME 1320000 - -/* Total IR code is 110 ms, including the 9 ms for the start pulse */ -#define MAX_NEC_TIME 4000000 - -/* Total IR code is 110 ms, including the 9 ms for the start pulse */ -#define MIN_REPEAT_TIME 99000000 -#define MAX_REPEAT_TIME 112000000 - -/* Repeat time: 2.25ms us */ -#define MIN_REPEAT_START_TIME 2050000 -#define MAX_REPEAT_START_TIME 3000000 - -#define REPEAT_TIME 240 /* ms */ +#define NEC_0_SPACE (NEC_UNIT) +#define NEC_1_SPACE (3 * NEC_UNIT) /* Used to register nec_decoder clients */ static LIST_HEAD(decoder_list); @@ -223,11 +199,11 @@ static int handle_event(struct input_dev *input_dev, if (last_bit) goto err; - if ((ev->delta.tv_nsec >= NEC_0_SYMBOL - NEC_UNIT / 2) && - (ev->delta.tv_nsec < NEC_0_SYMBOL + NEC_UNIT / 2)) + if ((ev->delta.tv_nsec >= NEC_0_SPACE - NEC_UNIT / 2) && + (ev->delta.tv_nsec < NEC_0_SPACE + NEC_UNIT / 2)) bit = 0; - else if ((ev->delta.tv_nsec >= NEC_1_SYMBOL - NEC_UNIT / 2) && - (ev->delta.tv_nsec < NEC_1_SYMBOL + NEC_UNIT / 2)) + else if ((ev->delta.tv_nsec >= NEC_1_SPACE - NEC_UNIT / 2) && + (ev->delta.tv_nsec < NEC_1_SPACE + NEC_UNIT / 2)) bit = 1; else { IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", @@ -256,7 +232,7 @@ static int handle_event(struct input_dev *input_dev, data->nec_code.not_command |= 1 << (shift - 24); } } - if (++data->count == 32) { + if (++data->count == NEC_NBITS) { u32 scancode; /* * Fixme: may need to accept Extended NEC protocol? -- cgit v1.2.3 From db1423a6c79f66db2b1846614c13bde9c2db7ad2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 4 Apr 2010 10:27:20 -0300 Subject: V4L-DVB: ir-rc5-decoder: Add a decoder for RC-5 IR protocol This decoder is also based on a state machine, just like the NEC protocol decoder. It is pedantic in the sense that accepts only 14 bits. As there are some variants that outputs less bits, it needs to be improved to also handle those. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 9 + drivers/media/IR/Makefile | 1 + drivers/media/IR/ir-raw-event.c | 1 + drivers/media/IR/ir-rc5-decoder.c | 371 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 382 insertions(+) create mode 100644 drivers/media/IR/ir-rc5-decoder.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 0c557b8cc932..ba81bda3513d 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -18,3 +18,12 @@ config IR_NEC_DECODER ---help--- Enable this option if you have IR with NEC protocol, and if the IR is decoded in software + +config IR_RC5_DECODER + tristate "Enable IR raw decoder for RC-5 protocol" + depends on IR_CORE + default y + + ---help--- + Enable this option if you have IR with RC-5 protocol, and + if the IR is decoded in software diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 0e3f912054ca..62e12d5c443a 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -6,3 +6,4 @@ obj-y += keymaps/ obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o +obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 59f20541b03e..617e437e2beb 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -200,6 +200,7 @@ static void init_decoders(struct work_struct *work) /* Load the decoder modules */ load_nec_decode(); + load_rc5_decode(); /* If needed, we may later add some init code. In this case, it is needed to change the CONFIG_MODULE test at ir-core.h diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c new file mode 100644 index 000000000000..4b7eafecd842 --- /dev/null +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -0,0 +1,371 @@ +/* ir-rc5-decoder.c - handle RC-5 IR Pulse/Space protocol + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * This code only handles 14 bits RC-5 protocols. There are other variants + * that use a different number of bits. This is currently unsupported + */ + +#include + +#define RC5_NBITS 14 +#define RC5_HALFBIT 888888 /* ns */ +#define RC5_BIT (RC5_HALFBIT * 2) +#define RC5_DURATION (RC5_BIT * RC5_NBITS) + +#define is_rc5_halfbit(nsec) ((ev->delta.tv_nsec >= RC5_HALFBIT / 2) && \ + (ev->delta.tv_nsec < RC5_HALFBIT + RC5_HALFBIT / 2)) + +#define n_half(nsec) ((ev->delta.tv_nsec + RC5_HALFBIT / 2) / RC5_HALFBIT) + +/* Used to register rc5_decoder clients */ +static LIST_HEAD(decoder_list); +static spinlock_t decoder_lock; + +enum rc5_state { + STATE_INACTIVE, + STATE_START2_SPACE, + STATE_START2_MARK, + STATE_MARKSPACE, + STATE_TRAILER_MARK, +}; + +static char *st_name[] = { + "Inactive", + "start2 sapce", + "start2 mark", + "mark", + "space", + "trailer" +}; + +struct rc5_code { + u8 address; + u8 command; +}; + +struct decoder_data { + struct list_head list; + struct ir_input_dev *ir_dev; + int enabled:1; + + /* State machine control */ + enum rc5_state state; + struct rc5_code rc5_code; + unsigned n_half; + unsigned count; +}; + + +/** + * get_decoder_data() - gets decoder data + * @input_dev: input device + * + * Returns the struct decoder_data that corresponds to a device + */ + +static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) +{ + struct decoder_data *data = NULL; + + spin_lock(&decoder_lock); + list_for_each_entry(data, &decoder_list, list) { + if (data->ir_dev == ir_dev) + break; + } + spin_unlock(&decoder_lock); + return data; +} + +static ssize_t store_enabled(struct device *d, + struct device_attribute *mattr, + const char *buf, + size_t len) +{ + unsigned long value; + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (strict_strtoul(buf, 10, &value) || value > 1) + return -EINVAL; + + data->enabled = value; + + return len; +} + +static ssize_t show_enabled(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (data->enabled) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); + +static struct attribute *decoder_attributes[] = { + &dev_attr_enabled.attr, + NULL +}; + +static struct attribute_group decoder_attribute_group = { + .name = "rc5_decoder", + .attrs = decoder_attributes, +}; + +/** + * handle_event() - Decode one RC-5 pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @ev: event array with type/duration of pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int handle_event(struct input_dev *input_dev, + struct ir_raw_event *ev) +{ + struct decoder_data *data; + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + int bit, last_bit, n_half; + + data = get_decoder_data(ir_dev); + if (!data) + return -EINVAL; + + /* Except for the initial event, what matters is the previous bit */ + bit = (ev->type & IR_PULSE) ? 1 : 0; + + last_bit = !bit; + + /* Discards spurious space last_bits when inactive */ + + /* Very long delays are considered as start events */ + if (ev->delta.tv_nsec > RC5_DURATION + RC5_HALFBIT / 2) + data->state = STATE_INACTIVE; + + if (ev->type & IR_START_EVENT) + data->state = STATE_INACTIVE; + + switch (data->state) { + case STATE_INACTIVE: +IR_dprintk(1, "currently inative. Received bit (%s) @%luus\n", + last_bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); + + /* Discards the initial start space */ + if (bit) + return 0; + data->count = 0; + data->n_half = 0; + memset (&data->rc5_code, 0, sizeof(data->rc5_code)); + + data->state = STATE_START2_SPACE; + return 0; + case STATE_START2_SPACE: + if (last_bit) + goto err; + if (!is_rc5_halfbit(ev->delta.tv_nsec)) + goto err; + data->state = STATE_START2_MARK; + return 0; + case STATE_START2_MARK: + if (!last_bit) + goto err; + + if (!is_rc5_halfbit(ev->delta.tv_nsec)) + goto err; + + data->state = STATE_MARKSPACE; + return 0; + case STATE_MARKSPACE: + n_half = n_half(ev->delta.tv_nsec); + if (n_half < 1 || n_half > 3) { + IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", + data->count, + last_bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); +printk("%d halves\n", n_half); + goto err2; + } + data->n_half += n_half; + + if (!last_bit) + return 0; + + /* Got one complete mark/space cycle */ + + bit = ((data->count + 1) * 2)/ data->n_half; + +printk("%d halves, %d bits\n", n_half, bit); + +#if 1 /* SANITY check - while testing the decoder */ + if (bit > 1) { + IR_dprintk(1, "Decoder HAS failed at %d-th bit (%s) @%luus\n", + data->count, + last_bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); + + goto err2; + } +#endif + /* Ok, we've got a valid bit. proccess it */ + if (bit) { + int shift = data->count; + + /* + * RC-5 transmit bytes on this temporal order: + * address | not address | command | not command + */ + if (shift < 8) { + data->rc5_code.address |= 1 << shift; + } else { + data->rc5_code.command |= 1 << (shift - 8); + } + } + IR_dprintk(1, "RC-5: bit #%d: %d (%d)\n", + data->count, bit, data->n_half); + if (++data->count >= RC5_NBITS) { + u32 scancode; + scancode = data->rc5_code.address << 8 | + data->rc5_code.command; + IR_dprintk(1, "RC-5 scancode 0x%04x\n", scancode); + + ir_keydown(input_dev, scancode, 0); + + data->state = STATE_TRAILER_MARK; + } + return 0; + case STATE_TRAILER_MARK: + if (!last_bit) + goto err; + data->state = STATE_INACTIVE; + return 0; + } + +err: + IR_dprintk(1, "RC-5 decoded failed at state %s (%s) @ %luus\n", + st_name[data->state], + bit ? "pulse" : "space", + (ev->delta.tv_nsec + 500) / 1000); +err2: + data->state = STATE_INACTIVE; + return -EINVAL; +} + +/** + * ir_rc5_decode() - Decodes all RC-5 pulsecodes on a given array + * @input_dev: the struct input_dev descriptor of the device + * @evs: event array with type/duration of pulse/space + * @len: length of the array + * This function returns the number of decoded pulses + */ +static int ir_rc5_decode(struct input_dev *input_dev, + struct ir_raw_event *evs, + int len) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct decoder_data *data; + int pos = 0; + int rc = 0; + + data = get_decoder_data(ir_dev); + if (!data || !data->enabled) + return 0; + + for (pos = 0; pos < len; pos++) + handle_event(input_dev, &evs[pos]); + + return rc; +} + +static int ir_rc5_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct decoder_data *data; + int rc; + + rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); + if (rc < 0) + return rc; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + return -ENOMEM; + } + + data->ir_dev = ir_dev; + data->enabled = 1; + + spin_lock(&decoder_lock); + list_add_tail(&data->list, &decoder_list); + spin_unlock(&decoder_lock); + + return 0; +} + +static int ir_rc5_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + static struct decoder_data *data; + + data = get_decoder_data(ir_dev); + if (!data) + return 0; + + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + + spin_lock(&decoder_lock); + list_del(&data->list); + spin_unlock(&decoder_lock); + + return 0; +} + +static struct ir_raw_handler rc5_handler = { + .decode = ir_rc5_decode, + .raw_register = ir_rc5_register, + .raw_unregister = ir_rc5_unregister, +}; + +static int __init ir_rc5_decode_init(void) +{ + ir_raw_handler_register(&rc5_handler); + + printk(KERN_INFO "IR RC-5 protocol handler initialized\n"); + return 0; +} + +static void __exit ir_rc5_decode_exit(void) +{ + ir_raw_handler_unregister(&rc5_handler); +} + +module_init(ir_rc5_decode_init); +module_exit(ir_rc5_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); +MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); +MODULE_DESCRIPTION("RC-5 IR protocol decoder"); -- cgit v1.2.3 From 587835a4b0ada7d78c4f3300e3ab26b7b2495705 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 4 Apr 2010 10:44:51 -0300 Subject: V4L-DVB: ir-core: remove the ancillary buffer Now that the decoders are state machine, there's no need to create an ancillary buffer while decoding the protocol. Just call the decoders code directly, event by event. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 32 +++----------------------------- drivers/media/IR/ir-raw-event.c | 20 ++++++++------------ drivers/media/IR/ir-rc5-decoder.c | 28 +--------------------------- 3 files changed, 12 insertions(+), 68 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 087211c5496a..28d773563556 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -125,14 +125,14 @@ static struct attribute_group decoder_attribute_group = { /** - * handle_event() - Decode one NEC pulse or space + * ir_nec_decode() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device * @ev: event array with type/duration of pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int handle_event(struct input_dev *input_dev, - struct ir_raw_event *ev) +static int ir_nec_decode(struct input_dev *input_dev, + struct ir_raw_event *ev) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); @@ -289,32 +289,6 @@ checksum_err: return -EINVAL; } -/** - * ir_nec_decode() - Decodes all NEC pulsecodes on a given array - * @input_dev: the struct input_dev descriptor of the device - * @evs: event array with type/duration of pulse/space - * @len: length of the array - * This function returns the number of decoded pulses - */ -static int ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *evs, - int len) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct decoder_data *data; - int pos = 0; - int rc = 0; - - data = get_decoder_data(ir_dev); - if (!data || !data->enabled) - return 0; - - for (pos = 0; pos < len; pos++) - handle_event(input_dev, &evs[pos]); - - return rc; -} - static int ir_nec_register(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 617e437e2beb..57990a337922 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -138,37 +138,33 @@ int ir_raw_event_handle(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); int rc; - struct ir_raw_event *evs; + struct ir_raw_event ev; int len, i; /* * Store the events into a temporary buffer. This allows calling more than * one decoder to deal with the received data */ - len = kfifo_len(&ir->raw->kfifo) / sizeof(*evs); + len = kfifo_len(&ir->raw->kfifo) / sizeof(ev); if (!len) return 0; - evs = kmalloc(len * sizeof(*evs), GFP_ATOMIC); for (i = 0; i < len; i++) { - rc = kfifo_out(&ir->raw->kfifo, &evs[i], sizeof(*evs)); - if (rc != sizeof(*evs)) { + rc = kfifo_out(&ir->raw->kfifo, &ev, sizeof(ev)); + if (rc != sizeof(ev)) { IR_dprintk(1, "overflow error: received %d instead of %zd\n", - rc, sizeof(*evs)); + rc, sizeof(ev)); return -EINVAL; } IR_dprintk(2, "event type %d, time before event: %07luus\n", - evs[i].type, (evs[i].delta.tv_nsec + 500) / 1000); + ev.type, (ev.delta.tv_nsec + 500) / 1000); + rc = RUN_DECODER(decode, input_dev, &ev); } /* * Call all ir decoders. This allows decoding the same event with - * more than one protocol handler. It returns the number of keystrokes - * sent to the event interface + * more than one protocol handler. */ - rc = RUN_DECODER(decode, input_dev, evs, len); - - kfree(evs); return rc; } diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 4b7eafecd842..61b58397a3c2 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -142,7 +142,7 @@ static struct attribute_group decoder_attribute_group = { * * This function returns -EINVAL if the pulse violates the state machine */ -static int handle_event(struct input_dev *input_dev, +static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event *ev) { struct decoder_data *data; @@ -273,32 +273,6 @@ err2: return -EINVAL; } -/** - * ir_rc5_decode() - Decodes all RC-5 pulsecodes on a given array - * @input_dev: the struct input_dev descriptor of the device - * @evs: event array with type/duration of pulse/space - * @len: length of the array - * This function returns the number of decoded pulses - */ -static int ir_rc5_decode(struct input_dev *input_dev, - struct ir_raw_event *evs, - int len) -{ - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - struct decoder_data *data; - int pos = 0; - int rc = 0; - - data = get_decoder_data(ir_dev); - if (!data || !data->enabled) - return 0; - - for (pos = 0; pos < len; pos++) - handle_event(input_dev, &evs[pos]); - - return rc; -} - static int ir_rc5_register(struct input_dev *input_dev) { struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); -- cgit v1.2.3 From 9dfe4e8339499bfe8e9a362fefc290b4cb9c3803 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 4 Apr 2010 14:06:55 -0300 Subject: V4L/DVB: ir-core: Add support for badly-implemented hardware decoders A few hardware Remote Controller decoders, even using a standard protocol, aren't able to provide the entire scancode. Due to that, the capability of using other IR's are limited on those hardware. Adds a way to indicate to ir-core what are the bits that the hardware provides, from a scancode, allowing the addition of a complete IR table to the kernel and allowing a limited support for changing the Remote Controller on those devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 25 +++++++-- drivers/media/IR/keymaps/Makefile | 1 + drivers/media/IR/keymaps/rc-pixelview-mk12.c | 83 ++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 drivers/media/IR/keymaps/rc-pixelview-mk12.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index a89456932f7c..af7400bc906f 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -89,6 +89,18 @@ static int ir_do_setkeycode(struct input_dev *dev, { unsigned int i; int old_keycode = KEY_RESERVED; + struct ir_input_dev *ir_dev = input_get_drvdata(dev); + + /* + * Unfortunately, some hardware-based IR decoders don't provide + * all bits for the complete IR code. In general, they provide only + * the command part of the IR code. Yet, as it is possible to replace + * the provided IR with another one, it is needed to allow loading + * IR tables from other remotes. So, + */ + if (ir_dev->props && ir_dev->props->scanmask) { + scancode &= ir_dev->props->scanmask; + } /* First check if we already have a mapping for this ir command */ for (i = 0; i < rc_tab->len; i++) { @@ -448,6 +460,13 @@ int __ir_input_register(struct input_dev *input_dev, sizeof(struct ir_scancode)); ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL); ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode); + if (props) { + ir_dev->props = props; + if (props->open) + input_dev->open = ir_open; + if (props->close) + input_dev->close = ir_close; + } if (!ir_dev->rc_tab.scan) { rc = -ENOMEM; @@ -465,12 +484,6 @@ int __ir_input_register(struct input_dev *input_dev, goto out_table; } - ir_dev->props = props; - if (props && props->open) - input_dev->open = ir_open; - if (props && props->close) - input_dev->close = ir_close; - rc = ir_register_class(input_dev); if (rc < 0) goto out_table; diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile index 937b7db9c9d2..c4d891d79491 100644 --- a/drivers/media/IR/keymaps/Makefile +++ b/drivers/media/IR/keymaps/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-pinnacle-grey.o \ rc-pinnacle-pctv-hd.o \ rc-pixelview.o \ + rc-pixelview-mk12.o \ rc-pixelview-new.o \ rc-powercolor-real-angel.o \ rc-proteus-2309.o \ diff --git a/drivers/media/IR/keymaps/rc-pixelview-mk12.c b/drivers/media/IR/keymaps/rc-pixelview-mk12.c new file mode 100644 index 000000000000..5a735d569a8b --- /dev/null +++ b/drivers/media/IR/keymaps/rc-pixelview-mk12.c @@ -0,0 +1,83 @@ +/* rc-pixelview-mk12.h - Keytable for pixelview Remote Controller + * + * keymap imported from ir-keymaps.c + * + * Copyright (c) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * Keytable for MK-F12 IR remote provided together with Pixelview + * Ultra Pro Remote Controller. Uses NEC extended format. + */ +static struct ir_scancode pixelview_mk12[] = { + { 0x866b03, KEY_TUNER }, /* Timeshift */ + { 0x866b1e, KEY_POWER2 }, /* power */ + + { 0x866b01, KEY_1 }, + { 0x866b0b, KEY_2 }, + { 0x866b1b, KEY_3 }, + { 0x866b05, KEY_4 }, + { 0x866b09, KEY_5 }, + { 0x866b15, KEY_6 }, + { 0x866b06, KEY_7 }, + { 0x866b0a, KEY_8 }, + { 0x866b12, KEY_9 }, + { 0x866b02, KEY_0 }, + + { 0x866b13, KEY_AGAIN }, /* loop */ + { 0x866b10, KEY_DIGITS }, /* +100 */ + + { 0x866b00, KEY_MEDIA }, /* source */ + { 0x866b18, KEY_MUTE }, /* mute */ + { 0x866b19, KEY_CAMERA }, /* snapshot */ + { 0x866b1a, KEY_SEARCH }, /* scan */ + + { 0x866b16, KEY_CHANNELUP }, /* chn + */ + { 0x866b14, KEY_CHANNELDOWN }, /* chn - */ + { 0x866b1f, KEY_VOLUMEUP }, /* vol + */ + { 0x866b17, KEY_VOLUMEDOWN }, /* vol - */ + { 0x866b1c, KEY_ZOOM }, /* zoom */ + + { 0x866b04, KEY_REWIND }, + { 0x866b0e, KEY_RECORD }, + { 0x866b0c, KEY_FORWARD }, + + { 0x866b1d, KEY_STOP }, + { 0x866b08, KEY_PLAY }, + { 0x866b0f, KEY_PAUSE }, + + { 0x866b0d, KEY_TV }, + { 0x866b07, KEY_RADIO }, /* FM */ +}; + +static struct rc_keymap pixelview_map = { + .map = { + .scan = pixelview_mk12, + .size = ARRAY_SIZE(pixelview_mk12), + .ir_type = IR_TYPE_NEC, + .name = RC_MAP_PIXELVIEW_MK12, + } +}; + +static int __init init_rc_map_pixelview(void) +{ + return ir_register_map(&pixelview_map); +} + +static void __exit exit_rc_map_pixelview(void) +{ + ir_unregister_map(&pixelview_map); +} + +module_init(init_rc_map_pixelview) +module_exit(exit_rc_map_pixelview) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab "); -- cgit v1.2.3 From 7f20d32d446097789ade5ada6b645742ddac4ece Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 4 Apr 2010 14:45:04 -0300 Subject: V4L/DVB: re-add enable/disable check to the IR decoders A previous cleanup patch removed more than needed. Re-add the logic that disable the decoders. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 3 +++ drivers/media/IR/ir-rc5-decoder.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 28d773563556..9d1ada95aa72 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -142,6 +142,9 @@ static int ir_nec_decode(struct input_dev *input_dev, if (!data) return -EINVAL; + if (!data->enabled) + return 0; + /* Except for the initial event, what matters is the previous bit */ bit = (ev->type & IR_PULSE) ? 1 : 0; diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 61b58397a3c2..4fb3ce410e24 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -153,6 +153,9 @@ static int ir_rc5_decode(struct input_dev *input_dev, if (!data) return -EINVAL; + if (!data->enabled) + return 0; + /* Except for the initial event, what matters is the previous bit */ bit = (ev->type & IR_PULSE) ? 1 : 0; -- cgit v1.2.3 From 9b09df51b8c2b4615376e5ada3e2eb7eeed3cf5d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 Apr 2010 02:29:42 -0300 Subject: V4L/DVB: ir-rc5-decoder: fix state machine Reimplement the RC-5 decoder state machine. Code is now clear, and works properly. It is also simpler than the previous implementations. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-rc5-decoder.c | 161 ++++++++++++-------------------------- 1 file changed, 52 insertions(+), 109 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 4fb3ce410e24..a62277b625a8 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -15,19 +15,17 @@ /* * This code only handles 14 bits RC-5 protocols. There are other variants * that use a different number of bits. This is currently unsupported + * It considers a carrier of 36 kHz, with a total of 14 bits, where + * the first two bits are start bits, and a third one is a filing bit */ #include -#define RC5_NBITS 14 -#define RC5_HALFBIT 888888 /* ns */ -#define RC5_BIT (RC5_HALFBIT * 2) -#define RC5_DURATION (RC5_BIT * RC5_NBITS) - -#define is_rc5_halfbit(nsec) ((ev->delta.tv_nsec >= RC5_HALFBIT / 2) && \ - (ev->delta.tv_nsec < RC5_HALFBIT + RC5_HALFBIT / 2)) +static unsigned int ir_rc5_remote_gap = 888888; -#define n_half(nsec) ((ev->delta.tv_nsec + RC5_HALFBIT / 2) / RC5_HALFBIT) +#define RC5_NBITS 14 +#define RC5_BIT (ir_rc5_remote_gap * 2) +#define RC5_DURATION (ir_rc5_remote_gap * RC5_NBITS) /* Used to register rc5_decoder clients */ static LIST_HEAD(decoder_list); @@ -35,19 +33,8 @@ static spinlock_t decoder_lock; enum rc5_state { STATE_INACTIVE, - STATE_START2_SPACE, - STATE_START2_MARK, STATE_MARKSPACE, - STATE_TRAILER_MARK, -}; - -static char *st_name[] = { - "Inactive", - "start2 sapce", - "start2 mark", - "mark", - "space", - "trailer" + STATE_TRAILER, }; struct rc5_code { @@ -63,8 +50,7 @@ struct decoder_data { /* State machine control */ enum rc5_state state; struct rc5_code rc5_code; - unsigned n_half; - unsigned count; + unsigned code, elapsed, last_bit, last_code; }; @@ -147,7 +133,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int bit, last_bit, n_half; + int is_pulse, scancode, delta, toggle; data = get_decoder_data(ir_dev); if (!data) @@ -156,122 +142,79 @@ static int ir_rc5_decode(struct input_dev *input_dev, if (!data->enabled) return 0; - /* Except for the initial event, what matters is the previous bit */ - bit = (ev->type & IR_PULSE) ? 1 : 0; - - last_bit = !bit; + delta = DIV_ROUND_CLOSEST(ev->delta.tv_nsec, ir_rc5_remote_gap); - /* Discards spurious space last_bits when inactive */ + /* The duration time refers to the last bit time */ + is_pulse = (ev->type & IR_PULSE) ? 1 : 0; /* Very long delays are considered as start events */ - if (ev->delta.tv_nsec > RC5_DURATION + RC5_HALFBIT / 2) - data->state = STATE_INACTIVE; - - if (ev->type & IR_START_EVENT) + if (delta > RC5_DURATION || (ev->type & IR_START_EVENT)) data->state = STATE_INACTIVE; switch (data->state) { case STATE_INACTIVE: -IR_dprintk(1, "currently inative. Received bit (%s) @%luus\n", - last_bit ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); + IR_dprintk(2, "currently inative. Start bit (%s) @%uus\n", + is_pulse ? "pulse" : "space", + (unsigned)(ev->delta.tv_nsec + 500) / 1000); /* Discards the initial start space */ - if (bit) - return 0; - data->count = 0; - data->n_half = 0; - memset (&data->rc5_code, 0, sizeof(data->rc5_code)); - - data->state = STATE_START2_SPACE; - return 0; - case STATE_START2_SPACE: - if (last_bit) - goto err; - if (!is_rc5_halfbit(ev->delta.tv_nsec)) - goto err; - data->state = STATE_START2_MARK; - return 0; - case STATE_START2_MARK: - if (!last_bit) + if (!is_pulse) goto err; - - if (!is_rc5_halfbit(ev->delta.tv_nsec)) - goto err; - + data->code = 1; + data->last_bit = 1; + data->elapsed = 0; + memset(&data->rc5_code, 0, sizeof(data->rc5_code)); data->state = STATE_MARKSPACE; return 0; case STATE_MARKSPACE: - n_half = n_half(ev->delta.tv_nsec); - if (n_half < 1 || n_half > 3) { - IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", - data->count, - last_bit ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); -printk("%d halves\n", n_half); - goto err2; - } - data->n_half += n_half; + if (delta != 1) + data->last_bit = data->last_bit ? 0 : 1; - if (!last_bit) - return 0; + data->elapsed += delta; - /* Got one complete mark/space cycle */ + if ((data->elapsed % 2) == 1) + return 0; - bit = ((data->count + 1) * 2)/ data->n_half; + data->code <<= 1; + data->code |= data->last_bit; -printk("%d halves, %d bits\n", n_half, bit); + /* Fill the 2 unused bits at the command with 0 */ + if (data->elapsed / 2 == 6) + data->code <<= 2; -#if 1 /* SANITY check - while testing the decoder */ - if (bit > 1) { - IR_dprintk(1, "Decoder HAS failed at %d-th bit (%s) @%luus\n", - data->count, - last_bit ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); + if (data->elapsed >= (RC5_NBITS - 1) * 2) { + scancode = data->code; - goto err2; - } -#endif - /* Ok, we've got a valid bit. proccess it */ - if (bit) { - int shift = data->count; - - /* - * RC-5 transmit bytes on this temporal order: - * address | not address | command | not command - */ - if (shift < 8) { - data->rc5_code.address |= 1 << shift; - } else { - data->rc5_code.command |= 1 << (shift - 8); + /* Check for the start bits */ + if ((scancode & 0xc000) != 0xc000) { + IR_dprintk(1, "Code 0x%04x doesn't have two start bits. It is not RC-5\n", scancode); + goto err; } - } - IR_dprintk(1, "RC-5: bit #%d: %d (%d)\n", - data->count, bit, data->n_half); - if (++data->count >= RC5_NBITS) { - u32 scancode; - scancode = data->rc5_code.address << 8 | - data->rc5_code.command; - IR_dprintk(1, "RC-5 scancode 0x%04x\n", scancode); - ir_keydown(input_dev, scancode, 0); + toggle = (scancode & 0x2000) ? 1 : 0; + + if (scancode == data->last_code) { + IR_dprintk(1, "RC-5 repeat\n"); + ir_repeat(input_dev); + } else { + data->last_code = scancode; + scancode &= 0x1fff; + IR_dprintk(1, "RC-5 scancode 0x%04x\n", scancode); - data->state = STATE_TRAILER_MARK; + ir_keydown(input_dev, scancode, 0); + } + data->state = STATE_TRAILER; } return 0; - case STATE_TRAILER_MARK: - if (!last_bit) - goto err; + case STATE_TRAILER: data->state = STATE_INACTIVE; return 0; } err: - IR_dprintk(1, "RC-5 decoded failed at state %s (%s) @ %luus\n", - st_name[data->state], - bit ? "pulse" : "space", + IR_dprintk(1, "RC-5 decoded failed at %s @ %luus\n", + is_pulse ? "pulse" : "space", (ev->delta.tv_nsec + 500) / 1000); -err2: data->state = STATE_INACTIVE; return -EINVAL; } -- cgit v1.2.3 From 6eb9435b874ae5ff56d56952167a8e9be5c5deeb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 7 Apr 2010 16:19:36 -0300 Subject: V4L/DVB: ir: Make sure that the spinlocks are properly initialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some spinlocks are not properly initialized on ir core: [ 471.714132] BUG: spinlock bad magic on CPU#0, modprobe/1899 [ 471.719838] lock: f92a08ac, .magic: 00000000, .owner: /-1, .owner_cpu: 0 [ 471.727301] Pid: 1899, comm: modprobe Not tainted 2.6.33 #36 [ 471.733062] Call Trace: [ 471.735537] [] ? printk+0x1d/0x22 [ 471.739866] [] spin_bug+0xa3/0xf0 [ 471.744224] [] do_raw_spin_lock+0x7d/0x160 [ 471.749364] [] ? ir_rc5_register+0x6f/0xf0 [ir_rc5_decoder] So, use static initialization for the static spinlocks, instead of the dynamic ones (currently used), as proposed by David Härdeman on one of his RFC patches. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 2 +- drivers/media/IR/ir-raw-event.c | 4 +--- drivers/media/IR/ir-rc5-decoder.c | 2 +- drivers/media/IR/rc-map.c | 3 +-- 4 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 9d1ada95aa72..18918e52c0c0 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -25,7 +25,7 @@ /* Used to register nec_decoder clients */ static LIST_HEAD(decoder_list); -static spinlock_t decoder_lock; +static DEFINE_SPINLOCK(decoder_lock); enum nec_state { STATE_INACTIVE, diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 57990a337922..ddb3365adc82 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -21,7 +21,7 @@ /* Used to handle IR raw handler extensions */ static LIST_HEAD(ir_raw_handler_list); -static spinlock_t ir_raw_handler_lock; +static DEFINE_SPINLOCK(ir_raw_handler_lock); /** * RUN_DECODER() - runs an operation on all IR decoders @@ -205,8 +205,6 @@ static void init_decoders(struct work_struct *work) void ir_raw_init(void) { - spin_lock_init(&ir_raw_handler_lock); - #ifdef MODULE INIT_WORK(&wq_load, init_decoders); schedule_work(&wq_load); diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index a62277b625a8..6323066438b5 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -29,7 +29,7 @@ static unsigned int ir_rc5_remote_gap = 888888; /* Used to register rc5_decoder clients */ static LIST_HEAD(decoder_list); -static spinlock_t decoder_lock; +static DEFINE_SPINLOCK(decoder_lock); enum rc5_state { STATE_INACTIVE, diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index 2f6201ce1898..ff185c054267 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c @@ -17,8 +17,7 @@ /* Used to handle IR raw handler extensions */ static LIST_HEAD(rc_map_list); -static spinlock_t rc_map_lock; - +static DEFINE_SPINLOCK(rc_map_lock); static struct rc_keymap *seek_rc_map(const char *name) { -- cgit v1.2.3 From de88f31cef8fee7c890cf2128bec8dae06bb20f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sun, 28 Mar 2010 18:38:49 -0300 Subject: V4L/DVB: rename sysfs remote controller devices from rcrcv to rc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the remote controller class is anyway being renamed from ir to rc this would be a good time to also rename the devices from rcrcvX to rcX. I know we haven't reached any agreement on whether transmission will eventually be handled by the same device, but this change will at least make the device name non-receive-specific which will make it possible in the future (and if a different approach is finally agreed upon, the device name still works). Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 58ecca2003a4..c33333f1f60e 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -40,7 +40,7 @@ static struct class ir_input_class = { * @buf: a pointer to the output buffer * * This routine is a callback routine for input read the IR protocol type. - * it is trigged by reading /sys/class/rc/rcrcv?/current_protocol. + * it is trigged by reading /sys/class/rc/rc?/current_protocol. * It returns the protocol name, as understood by the driver. */ static ssize_t show_protocol(struct device *d, @@ -75,7 +75,7 @@ static ssize_t show_protocol(struct device *d, * @len: length of the input buffer * * This routine is a callback routine for changing the IR protocol type. - * it is trigged by reading /sys/class/rc/rcrcv?/current_protocol. + * it is trigged by reading /sys/class/rc/rc?/current_protocol. * It changes the IR the protocol name, if the IR type is recognized * by the driver. * If an unknown protocol name is used, returns -EINVAL. @@ -172,7 +172,7 @@ static struct device_type ir_dev_type = { }; /** - * ir_register_class() - creates the sysfs for /sys/class/rc/rcrcv? + * ir_register_class() - creates the sysfs for /sys/class/rc/rc? * @input_dev: the struct input_dev descriptor of the device * * This routine is used to register the syfs code for IR class @@ -192,7 +192,7 @@ int ir_register_class(struct input_dev *input_dev) ir_dev->dev.type = &ir_dev_type; ir_dev->dev.class = &ir_input_class; ir_dev->dev.parent = input_dev->dev.parent; - dev_set_name(&ir_dev->dev, "rcrcv%d", devno); + dev_set_name(&ir_dev->dev, "rc%d", devno); dev_set_drvdata(&ir_dev->dev, ir_dev); rc = device_register(&ir_dev->dev); if (rc) @@ -223,7 +223,7 @@ int ir_register_class(struct input_dev *input_dev) /** * ir_unregister_class() - removes the sysfs for sysfs for - * /sys/class/rc/rcrcv? + * /sys/class/rc/rc? * @input_dev: the struct input_dev descriptor of the device * * This routine is used to unregister the syfs code for IR class -- cgit v1.2.3 From 626cf6979e99bf2c642456308bed7bb25a37569b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 Apr 2010 23:21:46 -0300 Subject: V4L/DVB: ir-core: Distinguish sysfs attributes for in-hardware and raw decoders Some devices have in-hardware Remote Controller decoder, while others need a software decoder to get the IR code. As each software decoder can be enabled/disabled individually, allowing multiple protocol decoding capability. On the other hand, hardware decoders have a limited protocol support, often being able of decoding just one protocol each time. So, each type needs a different set of capabilities to control the supported protocol(s). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 17 ++++++++++++++--- drivers/media/IR/ir-raw-event.c | 2 -- drivers/media/IR/ir-sysfs.c | 25 ++++++++++++++++--------- 3 files changed, 30 insertions(+), 14 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index af7400bc906f..1fdb528737fe 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -488,11 +488,19 @@ int __ir_input_register(struct input_dev *input_dev, if (rc < 0) goto out_table; + if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) { + rc = ir_raw_event_register(input_dev); + if (rc < 0) + goto out_event; + } + IR_dprintk(1, "Registered input device on %s for %s remote.\n", driver_name, rc_tab->name); return 0; +out_event: + ir_unregister_class(input_dev); out_table: kfree(ir_dev->rc_tab.scan); out_name: @@ -509,22 +517,25 @@ EXPORT_SYMBOL_GPL(__ir_input_register); * This routine is used to free memory and de-register interfaces. */ -void ir_input_unregister(struct input_dev *dev) +void ir_input_unregister(struct input_dev *input_dev) { - struct ir_input_dev *ir_dev = input_get_drvdata(dev); + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct ir_scancode_table *rc_tab; if (!ir_dev) return; IR_dprintk(1, "Freed keycode table\n"); + del_timer_sync(&ir_dev->timer_keyup); + if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW) + ir_raw_event_unregister(input_dev); rc_tab = &ir_dev->rc_tab; rc_tab->size = 0; kfree(rc_tab->scan); rc_tab->scan = NULL; - ir_unregister_class(dev); + ir_unregister_class(input_dev); kfree(ir_dev->driver_name); kfree(ir_dev); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index ddb3365adc82..bc4ca08adf4a 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -82,7 +82,6 @@ int ir_raw_event_register(struct input_dev *input_dev) return rc; } -EXPORT_SYMBOL_GPL(ir_raw_event_register); void ir_raw_event_unregister(struct input_dev *input_dev) { @@ -97,7 +96,6 @@ void ir_raw_event_unregister(struct input_dev *input_dev) kfree(ir->raw); ir->raw = NULL; } -EXPORT_SYMBOL_GPL(ir_raw_event_unregister); int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) { diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index c33333f1f60e..81eebd8eae5a 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -152,22 +152,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, show_protocol, store_protocol); -static struct attribute *ir_dev_attrs[] = { +static struct attribute *ir_hw_dev_attrs[] = { &dev_attr_current_protocol.attr, NULL, }; -static struct attribute_group ir_dev_attr_grp = { - .attrs = ir_dev_attrs, +static struct attribute_group ir_hw_dev_attr_grp = { + .attrs = ir_hw_dev_attrs, }; -static const struct attribute_group *ir_dev_attr_groups[] = { - &ir_dev_attr_grp, +static const struct attribute_group *ir_hw_dev_attr_groups[] = { + &ir_hw_dev_attr_grp, NULL }; -static struct device_type ir_dev_type = { - .groups = ir_dev_attr_groups, +static struct device_type rc_dev_type = { + .groups = ir_hw_dev_attr_groups, + .uevent = ir_dev_uevent, +}; + +static struct device_type ir_raw_dev_type = { .uevent = ir_dev_uevent, }; @@ -181,7 +185,6 @@ int ir_register_class(struct input_dev *input_dev) { int rc; const char *path; - struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); int devno = find_first_zero_bit(&ir_core_dev_number, IRRCV_NUM_DEVICES); @@ -189,7 +192,11 @@ int ir_register_class(struct input_dev *input_dev) if (unlikely(devno < 0)) return devno; - ir_dev->dev.type = &ir_dev_type; + if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + ir_dev->dev.type = &rc_dev_type; + else + ir_dev->dev.type = &ir_raw_dev_type; + ir_dev->dev.class = &ir_input_class; ir_dev->dev.parent = input_dev->dev.parent; dev_set_name(&ir_dev->dev, "rc%d", devno); -- cgit v1.2.3 From b320f80a6a02bbf31f7ed6ab3332f7c4ebaaac2c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 8 Apr 2010 01:02:49 -0300 Subject: V4L/DVB: ir-core: properly present the supported and current protocols Hardware decoders have a more limited set of decoders than software ones. In general, they support just one protocol at a given time, but allow changing between a few options. Rename the previous badly named "current_protocol" as just "protocol", meaning the current protocol(s) accepted by the driver, and add a "support_protocols" to represent the entire universe of supported protocols by that specific hardware. As commented on http://lwn.net/Articles/378884/, the "one file, one value" rule doesn't fit nor does make much sense for bitmap or enum values. So, the supported_protocols will enum all supported protocols, and the protocol will present all active protocols. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 63 +++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 19 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 81eebd8eae5a..e47a4f102637 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -56,13 +56,13 @@ static ssize_t show_protocol(struct device *d, if (ir_type == IR_TYPE_UNKNOWN) s = "Unknown"; else if (ir_type == IR_TYPE_RC5) - s = "RC-5"; + s = "rc-5"; else if (ir_type == IR_TYPE_PD) - s = "Pulse/distance"; + s = "pulse-distance"; else if (ir_type == IR_TYPE_NEC) - s = "NEC"; + s = "nec"; else - s = "Other"; + s = "other"; return sprintf(buf, "%s\n", s); } @@ -86,23 +86,22 @@ static ssize_t store_protocol(struct device *d, size_t len) { struct ir_input_dev *ir_dev = dev_get_drvdata(d); - u64 ir_type = IR_TYPE_UNKNOWN; + u64 ir_type = 0; int rc = -EINVAL; unsigned long flags; char *buf; - buf = strsep((char **) &data, "\n"); - - if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) - ir_type = IR_TYPE_RC5; - else if (!strcasecmp(buf, "pd")) - ir_type = IR_TYPE_PD; - else if (!strcasecmp(buf, "nec")) - ir_type = IR_TYPE_NEC; + while (buf = strsep((char **) &data, " \n")) { + if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) + ir_type |= IR_TYPE_RC5; + if (!strcasecmp(buf, "pd") || !strcasecmp(buf, "pulse-distance")) + ir_type |= IR_TYPE_PD; + if (!strcasecmp(buf, "nec")) + ir_type |= IR_TYPE_NEC; + } - if (ir_type == IR_TYPE_UNKNOWN) { - IR_dprintk(1, "Error setting protocol to %lld\n", - (long long)ir_type); + if (!ir_type) { + IR_dprintk(1, "Unknown protocol\n"); return -EINVAL; } @@ -120,12 +119,34 @@ static ssize_t store_protocol(struct device *d, ir_dev->rc_tab.ir_type = ir_type; spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); - IR_dprintk(1, "Current protocol is %lld\n", + IR_dprintk(1, "Current protocol(s) is(are) %lld\n", (long long)ir_type); return len; } +static ssize_t show_supported_protocols(struct device *d, + struct device_attribute *mattr, char *buf) +{ + char *orgbuf = buf; + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + + /* FIXME: doesn't support multiple protocols at the same time */ + if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN) + buf += sprintf(buf, "unknown "); + if (ir_dev->props->allowed_protos & IR_TYPE_RC5) + buf += sprintf(buf, "rc-5 "); + if (ir_dev->props->allowed_protos & IR_TYPE_PD) + buf += sprintf(buf, "pulse-distance "); + if (ir_dev->props->allowed_protos & IR_TYPE_NEC) + buf += sprintf(buf, "nec "); + if (buf == orgbuf) + buf += sprintf(buf, "other "); + + buf += sprintf(buf - 1, "\n"); + + return buf - orgbuf; +} #define ADD_HOTPLUG_VAR(fmt, val...) \ do { \ @@ -149,11 +170,15 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) /* * Static device attribute struct with the sysfs attributes for IR's */ -static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, +static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR, show_protocol, store_protocol); +static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR, + show_supported_protocols, NULL); + static struct attribute *ir_hw_dev_attrs[] = { - &dev_attr_current_protocol.attr, + &dev_attr_protocol.attr, + &dev_attr_supported_protocols.attr, NULL, }; -- cgit v1.2.3 From d22e546ea18ee66c255af906f2714d3ee82d4b42 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 8 Apr 2010 09:33:45 -0300 Subject: V4L/DVB: ir-core: fix gcc warning noise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/IR/ir-sysfs.c: In function ‘store_protocol’: drivers/media/IR/ir-sysfs.c:93: warning: suggest parentheses around assignment used as truth value Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index e47a4f102637..af1edd073b16 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -91,7 +91,7 @@ static ssize_t store_protocol(struct device *d, unsigned long flags; char *buf; - while (buf = strsep((char **) &data, " \n")) { + while ((buf = strsep((char **) &data, " \n")) != NULL) { if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) ir_type |= IR_TYPE_RC5; if (!strcasecmp(buf, "pd") || !strcasecmp(buf, "pulse-distance")) -- cgit v1.2.3 From 724e2495502a98aaa3f93c404472a991da8ff857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 8 Apr 2010 13:10:00 -0300 Subject: V4L/DVB: Teach drivers/media/IR/ir-raw-event.c to use durations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/IR/ir-raw-event.c is currently written with the assumption that all "raw" hardware will generate events only on state change (i.e. when a pulse or space starts). However, some hardware (like mceusb, probably the most popular IR receiver out there) only generates duration data (and that data is buffered so using any kind of timing on the data is futile). Furthermore, using signed int's to represent pulse/space durations is a well-known approach when writing ir decoders. With this patch: - s64 int's are used to represent pulse/space durations in ns - a workqueue is used to decode the ir protocols outside of interrupt context - #defines are added to make decoders clearer - decoder reset is implemented by passing a zero duration to the kfifo queue and decoders are updated accordingly Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 247 +++++++++++++++----------------------- drivers/media/IR/ir-raw-event.c | 143 +++++++++++++--------- drivers/media/IR/ir-rc5-decoder.c | 150 +++++++++++------------ 3 files changed, 259 insertions(+), 281 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 18918e52c0c0..02682e617fae 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -13,15 +13,16 @@ */ #include +#include #define NEC_NBITS 32 -#define NEC_UNIT 559979 /* ns */ -#define NEC_HEADER_MARK (16 * NEC_UNIT) -#define NEC_HEADER_SPACE (8 * NEC_UNIT) -#define NEC_REPEAT_SPACE (4 * NEC_UNIT) -#define NEC_MARK (NEC_UNIT) -#define NEC_0_SPACE (NEC_UNIT) -#define NEC_1_SPACE (3 * NEC_UNIT) +#define NEC_UNIT 562500 /* ns */ +#define NEC_HEADER_PULSE PULSE(16) +#define NEC_HEADER_SPACE SPACE(8) +#define NEC_REPEAT_SPACE SPACE(4) +#define NEC_BIT_PULSE PULSE(1) +#define NEC_BIT_0_SPACE SPACE(1) +#define NEC_BIT_1_SPACE SPACE(3) /* Used to register nec_decoder clients */ static LIST_HEAD(decoder_list); @@ -29,21 +30,13 @@ static DEFINE_SPINLOCK(decoder_lock); enum nec_state { STATE_INACTIVE, - STATE_HEADER_MARK, STATE_HEADER_SPACE, - STATE_MARK, - STATE_SPACE, - STATE_TRAILER_MARK, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_TRAILER_PULSE, STATE_TRAILER_SPACE, }; -struct nec_code { - u8 address; - u8 not_address; - u8 command; - u8 not_command; -}; - struct decoder_data { struct list_head list; struct ir_input_dev *ir_dev; @@ -51,7 +44,7 @@ struct decoder_data { /* State machine control */ enum nec_state state; - struct nec_code nec_code; + u32 nec_bits; unsigned count; }; @@ -62,7 +55,6 @@ struct decoder_data { * * Returns the struct decoder_data that corresponds to a device */ - static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) { struct decoder_data *data = NULL; @@ -123,20 +115,20 @@ static struct attribute_group decoder_attribute_group = { .attrs = decoder_attributes, }; - /** * ir_nec_decode() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device - * @ev: event array with type/duration of pulse/space + * @duration: duration in ns of pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_nec_decode(struct input_dev *input_dev, - struct ir_raw_event *ev) +static int ir_nec_decode(struct input_dev *input_dev, s64 duration) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int bit, last_bit; + int u; + u32 scancode; + u8 address, not_address, command, not_command; data = get_decoder_data(ir_dev); if (!data) @@ -145,150 +137,107 @@ static int ir_nec_decode(struct input_dev *input_dev, if (!data->enabled) return 0; - /* Except for the initial event, what matters is the previous bit */ - bit = (ev->type & IR_PULSE) ? 1 : 0; - - last_bit = !bit; - - /* Discards spurious space last_bits when inactive */ - - /* Very long delays are considered as start events */ - if (ev->delta.tv_nsec > NEC_HEADER_MARK + NEC_HEADER_SPACE - NEC_UNIT / 2) + if (IS_RESET(duration)) { data->state = STATE_INACTIVE; + return 0; + } - if (ev->type & IR_START_EVENT) - data->state = STATE_INACTIVE; + u = TO_UNITS(duration, NEC_UNIT); + if (DURATION(u) == 0) + goto out; + + IR_dprintk(2, "NEC decode started at state %d (%i units, %ius)\n", + data->state, u, TO_US(duration)); switch (data->state) { - case STATE_INACTIVE: - if (!bit) /* PULSE marks the start event */ - return 0; - data->count = 0; - data->state = STATE_HEADER_MARK; - memset (&data->nec_code, 0, sizeof(data->nec_code)); - return 0; - case STATE_HEADER_MARK: - if (!last_bit) - goto err; - if (ev->delta.tv_nsec < NEC_HEADER_MARK - 6 * NEC_UNIT) - goto err; - data->state = STATE_HEADER_SPACE; + case STATE_INACTIVE: + if (u == NEC_HEADER_PULSE) { + data->count = 0; + data->state = STATE_HEADER_SPACE; + } return 0; + case STATE_HEADER_SPACE: - if (last_bit) - goto err; - if (ev->delta.tv_nsec >= NEC_HEADER_SPACE - NEC_UNIT / 2) { - data->state = STATE_MARK; + if (u == NEC_HEADER_SPACE) { + data->state = STATE_BIT_PULSE; return 0; - } - - if (ev->delta.tv_nsec >= NEC_REPEAT_SPACE - NEC_UNIT / 2) { + } else if (u == NEC_REPEAT_SPACE) { ir_repeat(input_dev); IR_dprintk(1, "Repeat last key\n"); - data->state = STATE_TRAILER_MARK; + data->state = STATE_TRAILER_PULSE; return 0; } - goto err; - case STATE_MARK: - if (!last_bit) - goto err; - if ((ev->delta.tv_nsec > NEC_MARK + NEC_UNIT / 2) || - (ev->delta.tv_nsec < NEC_MARK - NEC_UNIT / 2)) - goto err; - data->state = STATE_SPACE; - return 0; - case STATE_SPACE: - if (last_bit) - goto err; - - if ((ev->delta.tv_nsec >= NEC_0_SPACE - NEC_UNIT / 2) && - (ev->delta.tv_nsec < NEC_0_SPACE + NEC_UNIT / 2)) - bit = 0; - else if ((ev->delta.tv_nsec >= NEC_1_SPACE - NEC_UNIT / 2) && - (ev->delta.tv_nsec < NEC_1_SPACE + NEC_UNIT / 2)) - bit = 1; - else { - IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", - data->count, - last_bit ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); - - goto err2; + break; + + case STATE_BIT_PULSE: + if (u == NEC_BIT_PULSE) { + data->state = STATE_BIT_SPACE; + return 0; + } + break; + + case STATE_BIT_SPACE: + if (u != NEC_BIT_0_SPACE && u != NEC_BIT_1_SPACE) + break; + + data->nec_bits <<= 1; + if (u == NEC_BIT_1_SPACE) + data->nec_bits |= 1; + data->count++; + + if (data->count != NEC_NBITS) { + data->state = STATE_BIT_PULSE; + return 0; + } + + address = bitrev8((data->nec_bits >> 24) & 0xff); + not_address = bitrev8((data->nec_bits >> 16) & 0xff); + command = bitrev8((data->nec_bits >> 8) & 0xff); + not_command = bitrev8((data->nec_bits >> 0) & 0xff); + + if ((command ^ not_command) != 0xff) { + IR_dprintk(1, "NEC checksum error: received 0x%08x\n", + data->nec_bits); + break; } - /* Ok, we've got a valid bit. proccess it */ - if (bit) { - int shift = data->count; - - /* - * NEC transmit bytes on this temporal order: - * address | not address | command | not command - */ - if (shift < 8) { - data->nec_code.address |= 1 << shift; - } else if (shift < 16) { - data->nec_code.not_address |= 1 << (shift - 8); - } else if (shift < 24) { - data->nec_code.command |= 1 << (shift - 16); - } else { - data->nec_code.not_command |= 1 << (shift - 24); - } + if ((address ^ not_address) != 0xff) { + /* Extended NEC */ + scancode = address << 16 | + not_address << 8 | + command; + IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); + } else { + /* normal NEC */ + scancode = address << 8 | command; + IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); } - if (++data->count == NEC_NBITS) { - u32 scancode; - /* - * Fixme: may need to accept Extended NEC protocol? - */ - if ((data->nec_code.command ^ data->nec_code.not_command) != 0xff) - goto checksum_err; - - if ((data->nec_code.address ^ data->nec_code.not_address) != 0xff) { - /* Extended NEC */ - scancode = data->nec_code.address << 16 | - data->nec_code.not_address << 8 | - data->nec_code.command; - IR_dprintk(1, "NEC scancode 0x%06x\n", scancode); - } else { - /* normal NEC */ - scancode = data->nec_code.address << 8 | - data->nec_code.command; - IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); - } - ir_keydown(input_dev, scancode, 0); - - data->state = STATE_TRAILER_MARK; - } else - data->state = STATE_MARK; - return 0; - case STATE_TRAILER_MARK: - if (!last_bit) - goto err; - data->state = STATE_TRAILER_SPACE; + + ir_keydown(input_dev, scancode, 0); + data->state = STATE_TRAILER_PULSE; return 0; + + case STATE_TRAILER_PULSE: + if (u > 0) { + data->state = STATE_TRAILER_SPACE; + return 0; + } + break; + case STATE_TRAILER_SPACE: - if (last_bit) - goto err; - data->state = STATE_INACTIVE; - return 0; - } + if (u < 0) { + data->state = STATE_INACTIVE; + return 0; + } -err: - IR_dprintk(1, "NEC decoded failed at state %d (%s) @ %luus\n", - data->state, - bit ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); -err2: - data->state = STATE_INACTIVE; - return -EINVAL; + break; + } -checksum_err: +out: + IR_dprintk(1, "NEC decode failed at state %d (%i units, %ius)\n", + data->state, u, TO_US(duration)); data->state = STATE_INACTIVE; - IR_dprintk(1, "NEC checksum error: received 0x%02x%02x%02x%02x\n", - data->nec_code.address, - data->nec_code.not_address, - data->nec_code.command, - data->nec_code.not_command); return -EINVAL; } diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index bc4ca08adf4a..e144f1522962 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -15,9 +15,10 @@ #include #include #include +#include -/* Define the max number of bit transitions per IR keycode */ -#define MAX_IR_EVENT_SIZE 256 +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 /* Used to handle IR raw handler extensions */ static LIST_HEAD(ir_raw_handler_list); @@ -53,19 +54,30 @@ static DEFINE_SPINLOCK(ir_raw_handler_lock); /* Used to load the decoders */ static struct work_struct wq_load; +static void ir_raw_event_work(struct work_struct *work) +{ + s64 d; + struct ir_raw_event_ctrl *raw = + container_of(work, struct ir_raw_event_ctrl, rx_work); + + while (kfifo_out(&raw->kfifo, &d, sizeof(d)) == sizeof(d)) + RUN_DECODER(decode, raw->input_dev, d); +} + int ir_raw_event_register(struct input_dev *input_dev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); - int rc, size; + int rc; ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); if (!ir->raw) return -ENOMEM; - size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; - size = roundup_pow_of_two(size); + ir->raw->input_dev = input_dev; + INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); - rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); + rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, + GFP_KERNEL); if (rc < 0) { kfree(ir->raw); ir->raw = NULL; @@ -90,6 +102,7 @@ void ir_raw_event_unregister(struct input_dev *input_dev) if (!ir->raw) return; + cancel_work_sync(&ir->raw->rx_work); RUN_DECODER(raw_unregister, input_dev); kfifo_free(&ir->raw->kfifo); @@ -97,74 +110,90 @@ void ir_raw_event_unregister(struct input_dev *input_dev) ir->raw = NULL; } -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) +/** + * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders + * @input_dev: the struct input_dev device descriptor + * @duration: duration of the pulse or space in ns + * + * This routine (which may be called from an interrupt context) stores a + * pulse/space duration for the raw ir decoding state machines. Pulses are + * signalled as positive values and spaces as negative values. A zero value + * will reset the decoding state machines. + */ +int ir_raw_event_store(struct input_dev *input_dev, s64 duration) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); - struct timespec ts; - struct ir_raw_event event; - int rc; + struct ir_input_dev *ir = input_get_drvdata(input_dev); if (!ir->raw) return -EINVAL; - event.type = type; - event.delta.tv_sec = 0; - event.delta.tv_nsec = 0; + if (kfifo_in(&ir->raw->kfifo, &duration, sizeof(duration)) != sizeof(duration)) + return -ENOMEM; - ktime_get_ts(&ts); + return 0; +} +EXPORT_SYMBOL_GPL(ir_raw_event_store); - if (timespec_equal(&ir->raw->last_event, &event.delta)) - event.type |= IR_START_EVENT; - else - event.delta = timespec_sub(ts, ir->raw->last_event); +/** + * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space + * @input_dev: the struct input_dev device descriptor + * @type: the type of the event that has occurred + * + * This routine (which may be called from an interrupt context) is used to + * store the beginning of an ir pulse or space (or the start/end of ir + * reception) for the raw ir decoding state machines. This is used by + * hardware which does not provide durations directly but only interrupts + * (or similar events) on state change. + */ +int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) +{ + struct ir_input_dev *ir = input_get_drvdata(input_dev); + ktime_t now; + s64 delta; /* ns */ + int rc = 0; - memcpy(&ir->raw->last_event, &ts, sizeof(ts)); + if (!ir->raw) + return -EINVAL; - if (event.delta.tv_sec) { - event.type |= IR_START_EVENT; - event.delta.tv_sec = 0; - event.delta.tv_nsec = 0; - } + now = ktime_get(); + delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); - kfifo_in(&ir->raw->kfifo, &event, sizeof(event)); + /* Check for a long duration since last event or if we're + * being called for the first time, note that delta can't + * possibly be negative. + */ + if (delta > NSEC_PER_SEC || !ir->raw->last_type) + type |= IR_START_EVENT; + + if (type & IR_START_EVENT) + ir_raw_event_reset(input_dev); + else if (ir->raw->last_type & IR_SPACE) + rc = ir_raw_event_store(input_dev, -delta); + else if (ir->raw->last_type & IR_PULSE) + rc = ir_raw_event_store(input_dev, delta); + else + return 0; + ir->raw->last_event = now; + ir->raw->last_type = type; return rc; } -EXPORT_SYMBOL_GPL(ir_raw_event_store); +EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); -int ir_raw_event_handle(struct input_dev *input_dev) +/** + * ir_raw_event_handle() - schedules the decoding of stored ir data + * @input_dev: the struct input_dev device descriptor + * + * This routine will signal the workqueue to start decoding stored ir data. + */ +void ir_raw_event_handle(struct input_dev *input_dev) { - struct ir_input_dev *ir = input_get_drvdata(input_dev); - int rc; - struct ir_raw_event ev; - int len, i; - - /* - * Store the events into a temporary buffer. This allows calling more than - * one decoder to deal with the received data - */ - len = kfifo_len(&ir->raw->kfifo) / sizeof(ev); - if (!len) - return 0; - - for (i = 0; i < len; i++) { - rc = kfifo_out(&ir->raw->kfifo, &ev, sizeof(ev)); - if (rc != sizeof(ev)) { - IR_dprintk(1, "overflow error: received %d instead of %zd\n", - rc, sizeof(ev)); - return -EINVAL; - } - IR_dprintk(2, "event type %d, time before event: %07luus\n", - ev.type, (ev.delta.tv_nsec + 500) / 1000); - rc = RUN_DECODER(decode, input_dev, &ev); - } + struct ir_input_dev *ir = input_get_drvdata(input_dev); - /* - * Call all ir decoders. This allows decoding the same event with - * more than one protocol handler. - */ + if (!ir->raw) + return; - return rc; + schedule_work(&ir->raw->rx_work); } EXPORT_SYMBOL_GPL(ir_raw_event_handle); diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 6323066438b5..1d0857b69089 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -21,11 +21,8 @@ #include -static unsigned int ir_rc5_remote_gap = 888888; - #define RC5_NBITS 14 -#define RC5_BIT (ir_rc5_remote_gap * 2) -#define RC5_DURATION (ir_rc5_remote_gap * RC5_NBITS) +#define RC5_UNIT 888888 /* ns */ /* Used to register rc5_decoder clients */ static LIST_HEAD(decoder_list); @@ -33,13 +30,9 @@ static DEFINE_SPINLOCK(decoder_lock); enum rc5_state { STATE_INACTIVE, - STATE_MARKSPACE, - STATE_TRAILER, -}; - -struct rc5_code { - u8 address; - u8 command; + STATE_BIT_START, + STATE_BIT_END, + STATE_FINISHED, }; struct decoder_data { @@ -49,8 +42,9 @@ struct decoder_data { /* State machine control */ enum rc5_state state; - struct rc5_code rc5_code; - unsigned code, elapsed, last_bit, last_code; + u32 rc5_bits; + int last_unit; + unsigned count; }; @@ -122,18 +116,19 @@ static struct attribute_group decoder_attribute_group = { }; /** - * handle_event() - Decode one RC-5 pulse or space + * ir_rc5_decode() - Decode one RC-5 pulse or space * @input_dev: the struct input_dev descriptor of the device - * @ev: event array with type/duration of pulse/space + * @duration: duration of pulse/space in ns * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_rc5_decode(struct input_dev *input_dev, - struct ir_raw_event *ev) +static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int is_pulse, scancode, delta, toggle; + u8 command, system, toggle; + u32 scancode; + int u; data = get_decoder_data(ir_dev); if (!data) @@ -142,79 +137,84 @@ static int ir_rc5_decode(struct input_dev *input_dev, if (!data->enabled) return 0; - delta = DIV_ROUND_CLOSEST(ev->delta.tv_nsec, ir_rc5_remote_gap); - - /* The duration time refers to the last bit time */ - is_pulse = (ev->type & IR_PULSE) ? 1 : 0; - - /* Very long delays are considered as start events */ - if (delta > RC5_DURATION || (ev->type & IR_START_EVENT)) + if (IS_RESET(duration)) { data->state = STATE_INACTIVE; - - switch (data->state) { - case STATE_INACTIVE: - IR_dprintk(2, "currently inative. Start bit (%s) @%uus\n", - is_pulse ? "pulse" : "space", - (unsigned)(ev->delta.tv_nsec + 500) / 1000); - - /* Discards the initial start space */ - if (!is_pulse) - goto err; - data->code = 1; - data->last_bit = 1; - data->elapsed = 0; - memset(&data->rc5_code, 0, sizeof(data->rc5_code)); - data->state = STATE_MARKSPACE; return 0; - case STATE_MARKSPACE: - if (delta != 1) - data->last_bit = data->last_bit ? 0 : 1; + } - data->elapsed += delta; + u = TO_UNITS(duration, RC5_UNIT); + if (DURATION(u) == 0) + goto out; - if ((data->elapsed % 2) == 1) - return 0; +again: + IR_dprintk(2, "RC5 decode started at state %i (%i units, %ius)\n", + data->state, u, TO_US(duration)); - data->code <<= 1; - data->code |= data->last_bit; - - /* Fill the 2 unused bits at the command with 0 */ - if (data->elapsed / 2 == 6) - data->code <<= 2; + if (DURATION(u) == 0 && data->state != STATE_FINISHED) + return 0; - if (data->elapsed >= (RC5_NBITS - 1) * 2) { - scancode = data->code; + switch (data->state) { - /* Check for the start bits */ - if ((scancode & 0xc000) != 0xc000) { - IR_dprintk(1, "Code 0x%04x doesn't have two start bits. It is not RC-5\n", scancode); - goto err; + case STATE_INACTIVE: + if (IS_PULSE(u)) { + data->state = STATE_BIT_START; + data->count = 1; + DECREASE_DURATION(u, 1); + goto again; + } + break; + + case STATE_BIT_START: + if (DURATION(u) == 1) { + data->rc5_bits <<= 1; + if (IS_SPACE(u)) + data->rc5_bits |= 1; + data->count++; + data->last_unit = u; + + /* + * If the last bit is zero, a space will merge + * with the silence after the command. + */ + if (IS_PULSE(u) && data->count == RC5_NBITS) { + data->state = STATE_FINISHED; + goto again; } - toggle = (scancode & 0x2000) ? 1 : 0; + data->state = STATE_BIT_END; + return 0; + } + break; - if (scancode == data->last_code) { - IR_dprintk(1, "RC-5 repeat\n"); - ir_repeat(input_dev); - } else { - data->last_code = scancode; - scancode &= 0x1fff; - IR_dprintk(1, "RC-5 scancode 0x%04x\n", scancode); + case STATE_BIT_END: + if (IS_TRANSITION(u, data->last_unit)) { + if (data->count == RC5_NBITS) + data->state = STATE_FINISHED; + else + data->state = STATE_BIT_START; - ir_keydown(input_dev, scancode, 0); - } - data->state = STATE_TRAILER; + DECREASE_DURATION(u, 1); + goto again; } - return 0; - case STATE_TRAILER: + break; + + case STATE_FINISHED: + command = (data->rc5_bits & 0x0003F) >> 0; + system = (data->rc5_bits & 0x007C0) >> 6; + toggle = (data->rc5_bits & 0x00800) ? 1 : 0; + command += (data->rc5_bits & 0x01000) ? 0 : 0x40; + scancode = system << 8 | command; + + IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", + scancode, toggle); + ir_keydown(input_dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } -err: - IR_dprintk(1, "RC-5 decoded failed at %s @ %luus\n", - is_pulse ? "pulse" : "space", - (ev->delta.tv_nsec + 500) / 1000); +out: + IR_dprintk(1, "RC5 decode failed at state %i (%i units, %ius)\n", + data->state, u, TO_US(duration)); data->state = STATE_INACTIVE; return -EINVAL; } -- cgit v1.2.3 From 3f113e36106f133752de47208816b28aa8e60f88 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 8 Apr 2010 15:10:27 -0300 Subject: V4L/DVB: ir-core: move subsystem internal calls to ir-core-priv.h ir-core.h has the kABI to be used by the bridge drivers, when needing to register IR protocols and pass IR events. However, the same file also contains IR subsystem internal calls, meant to be used inside ir-core and between ir-core and the raw decoders. Better to move those functions to an internal header, for some reasons: 1) Header will be a little more cleaner; 2) It avoids the need of recompile everything (bridge/hardware drivers, etc), just because a new decoder were added, or some other internal change were needed; 3) Better organize the ir-core API, splitting the functions that are internal to IR core and the ancillary drivers (decoders, lirc_dev) from the features that should be exported to IR subsystem clients. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-core-priv.h | 111 ++++++++++++++++++++++++++++++++++++++ drivers/media/IR/ir-functions.c | 1 + drivers/media/IR/ir-keytable.c | 2 +- drivers/media/IR/ir-nec-decoder.c | 2 +- drivers/media/IR/ir-raw-event.c | 2 +- drivers/media/IR/ir-rc5-decoder.c | 2 +- drivers/media/IR/ir-sysfs.c | 2 +- 7 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 drivers/media/IR/ir-core-priv.h (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h new file mode 100644 index 000000000000..ea546659e4ce --- /dev/null +++ b/drivers/media/IR/ir-core-priv.h @@ -0,0 +1,111 @@ +/* + * Remote Controller core raw events header + * + * Copyright (C) 2010 by Mauro Carvalho Chehab + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _IR_RAW_EVENT +#define _IR_RAW_EVENT + +#include +#include + +struct ir_raw_handler { + struct list_head list; + + int (*decode)(struct input_dev *input_dev, s64 duration); + int (*raw_register)(struct input_dev *input_dev); + int (*raw_unregister)(struct input_dev *input_dev); +}; + +struct ir_raw_event_ctrl { + struct work_struct rx_work; /* for the rx decoding workqueue */ + struct kfifo kfifo; /* fifo for the pulse/space durations */ + ktime_t last_event; /* when last event occurred */ + enum raw_event_type last_type; /* last event type */ + struct input_dev *input_dev; /* pointer to the parent input_dev */ +}; + +/* macros for IR decoders */ +#define PULSE(units) ((units)) +#define SPACE(units) (-(units)) +#define IS_RESET(duration) ((duration) == 0) +#define IS_PULSE(duration) ((duration) > 0) +#define IS_SPACE(duration) ((duration) < 0) +#define DURATION(duration) (abs((duration))) +#define IS_TRANSITION(x, y) ((x) * (y) < 0) +#define DECREASE_DURATION(duration, amount) \ + do { \ + if (IS_SPACE(duration)) \ + duration += (amount); \ + else if (IS_PULSE(duration)) \ + duration -= (amount); \ + } while (0) + +#define TO_UNITS(duration, unit_len) \ + ((int)((duration) > 0 ? \ + DIV_ROUND_CLOSEST(abs((duration)), (unit_len)) :\ + -DIV_ROUND_CLOSEST(abs((duration)), (unit_len)))) +#define TO_US(duration) ((int)TO_UNITS(duration, 1000)) + +/* + * Routines from ir-keytable.c to be used internally on ir-core and decoders + */ + +u32 ir_g_keycode_from_table(struct input_dev *input_dev, + u32 scancode); + +/* + * Routines from ir-sysfs.c - Meant to be called only internally inside + * ir-core + */ + +int ir_register_class(struct input_dev *input_dev); +void ir_unregister_class(struct input_dev *input_dev); + +/* + * Routines from ir-raw-event.c to be used internally and by decoders + */ +int ir_raw_event_register(struct input_dev *input_dev); +void ir_raw_event_unregister(struct input_dev *input_dev); +static inline void ir_raw_event_reset(struct input_dev *input_dev) +{ + ir_raw_event_store(input_dev, 0); + ir_raw_event_handle(input_dev); +} +int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); +void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); +void ir_raw_init(void); + + +/* + * Decoder initialization code + * + * Those load logic are called during ir-core init, and automatically + * loads the compiled decoders for their usage with IR raw events + */ + +/* from ir-nec-decoder.c */ +#ifdef CONFIG_IR_NEC_DECODER_MODULE +#define load_nec_decode() request_module("ir-nec-decoder") +#else +#define load_nec_decode() 0 +#endif + +/* from ir-rc5-decoder.c */ +#ifdef CONFIG_IR_RC5_DECODER_MODULE +#define load_rc5_decode() request_module("ir-rc5-decoder") +#else +#define load_rc5_decode() 0 +#endif + +#endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/IR/ir-functions.c b/drivers/media/IR/ir-functions.c index ab06919ad5fc..db591e421887 100644 --- a/drivers/media/IR/ir-functions.c +++ b/drivers/media/IR/ir-functions.c @@ -24,6 +24,7 @@ #include #include #include +#include "ir-core-priv.h" /* -------------------------------------------------------------------------- */ diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 1fdb528737fe..599e39c34445 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -15,7 +15,7 @@ #include #include -#include +#include "ir-core-priv.h" /* Sizes are in bytes, 256 bytes allows for 32 entries on x64 */ #define IR_TAB_MIN_SIZE 256 diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 02682e617fae..4c223f611a5e 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -12,8 +12,8 @@ * GNU General Public License for more details. */ -#include #include +#include "ir-core-priv.h" #define NEC_NBITS 32 #define NEC_UNIT 562500 /* ns */ diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index e144f1522962..6a4445e5db1a 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -12,10 +12,10 @@ * GNU General Public License for more details. */ -#include #include #include #include +#include "ir-core-priv.h" /* Define the max number of pulse/space transitions to buffer */ #define MAX_IR_EVENT_SIZE 512 diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 1d0857b69089..d8f0760890fa 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -19,7 +19,7 @@ * the first two bits are start bits, and a third one is a filing bit */ -#include +#include "ir-core-priv.h" #define RC5_NBITS 14 #define RC5_UNIT 888888 /* ns */ diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index af1edd073b16..57f09c4ca9fb 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include "ir-core-priv.h" #define IRRCV_NUM_DEVICES 256 -- cgit v1.2.3 From 5fa2989f78a381ccc1cde219f0a3da942d6c1680 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 8 Apr 2010 19:04:06 -0300 Subject: V4L/DVB: ir-core: Remove warining noise if decoders compiled builtin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/IR/ir-raw-event.c:55: warning: ‘wq_load’ defined but not used drivers/media/IR/ir-raw-event.c:222: warning: ‘init_decoders’ defined but not used drivers/media/IR/rc-map.c: In function ‘get_rc_map’: drivers/media/IR/rc-map.c:40: warning: unused variable ‘rc’ Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-raw-event.c | 5 ++++- drivers/media/IR/rc-map.c | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 6a4445e5db1a..b49d01256be3 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -50,9 +50,10 @@ static DEFINE_SPINLOCK(ir_raw_handler_lock); _sumrc; \ }) - +#ifdef MODULE /* Used to load the decoders */ static struct work_struct wq_load; +#endif static void ir_raw_event_work(struct work_struct *work) { @@ -218,6 +219,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) } EXPORT_SYMBOL(ir_raw_handler_unregister); +#ifdef MODULE static void init_decoders(struct work_struct *work) { /* Load the decoder modules */ @@ -229,6 +231,7 @@ static void init_decoders(struct work_struct *work) it is needed to change the CONFIG_MODULE test at ir-core.h */ } +#endif void ir_raw_init(void) { diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index ff185c054267..1a3f4b123a37 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c @@ -37,14 +37,13 @@ static struct rc_keymap *seek_rc_map(const char *name) struct ir_scancode_table *get_rc_map(const char *name) { - int rc = 0; struct rc_keymap *map; map = seek_rc_map(name); #ifdef MODULE if (!map) { - rc = request_module(name); + int rc = request_module(name); if (rc < 0) { printk(KERN_ERR "Couldn't load IR keymap %s\n", name); return NULL; -- cgit v1.2.3 From 733419b5c4d29186006982a9a27227e214a39dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 8 Apr 2010 20:04:30 -0300 Subject: V4L/DVB: Add RC5x support to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds RC5x support to drivers/media/IR/ir-rc5-decoder.c Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-rc5-decoder.c | 78 +++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 19 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index d8f0760890fa..dd5a4d5f25fd 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -1,4 +1,4 @@ -/* ir-rc5-decoder.c - handle RC-5 IR Pulse/Space protocol +/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol * * Copyright (C) 2010 by Mauro Carvalho Chehab * @@ -13,15 +13,19 @@ */ /* - * This code only handles 14 bits RC-5 protocols. There are other variants - * that use a different number of bits. This is currently unsupported - * It considers a carrier of 36 kHz, with a total of 14 bits, where + * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols. + * There are other variants that use a different number of bits. + * This is currently unsupported. + * It considers a carrier of 36 kHz, with a total of 14/20 bits, where * the first two bits are start bits, and a third one is a filing bit */ #include "ir-core-priv.h" #define RC5_NBITS 14 +#define RC5X_NBITS 20 +#define CHECK_RC5X_NBITS 8 +#define RC5X_SPACE SPACE(4) #define RC5_UNIT 888888 /* ns */ /* Used to register rc5_decoder clients */ @@ -32,6 +36,7 @@ enum rc5_state { STATE_INACTIVE, STATE_BIT_START, STATE_BIT_END, + STATE_CHECK_RC5X, STATE_FINISHED, }; @@ -45,6 +50,7 @@ struct decoder_data { u32 rc5_bits; int last_unit; unsigned count; + unsigned wanted_bits; }; @@ -126,7 +132,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - u8 command, system, toggle; + u8 toggle; u32 scancode; int u; @@ -147,7 +153,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) goto out; again: - IR_dprintk(2, "RC5 decode started at state %i (%i units, %ius)\n", + IR_dprintk(2, "RC5(x) decode started at state %i (%i units, %ius)\n", data->state, u, TO_US(duration)); if (DURATION(u) == 0 && data->state != STATE_FINISHED) @@ -159,6 +165,8 @@ again: if (IS_PULSE(u)) { data->state = STATE_BIT_START; data->count = 1; + /* We just need enough bits to get to STATE_CHECK_RC5X */ + data->wanted_bits = RC5X_NBITS; DECREASE_DURATION(u, 1); goto again; } @@ -176,7 +184,7 @@ again: * If the last bit is zero, a space will merge * with the silence after the command. */ - if (IS_PULSE(u) && data->count == RC5_NBITS) { + if (IS_PULSE(u) && data->count == data->wanted_bits) { data->state = STATE_FINISHED; goto again; } @@ -188,8 +196,10 @@ again: case STATE_BIT_END: if (IS_TRANSITION(u, data->last_unit)) { - if (data->count == RC5_NBITS) + if (data->count == data->wanted_bits) data->state = STATE_FINISHED; + else if (data->count == CHECK_RC5X_NBITS) + data->state = STATE_CHECK_RC5X; else data->state = STATE_BIT_START; @@ -198,22 +208,52 @@ again: } break; + case STATE_CHECK_RC5X: + if (IS_SPACE(u) && DURATION(u) >= DURATION(RC5X_SPACE)) { + /* RC5X */ + data->wanted_bits = RC5X_NBITS; + DECREASE_DURATION(u, DURATION(RC5X_SPACE)); + } else { + /* RC5 */ + data->wanted_bits = RC5_NBITS; + } + data->state = STATE_BIT_START; + goto again; + case STATE_FINISHED: - command = (data->rc5_bits & 0x0003F) >> 0; - system = (data->rc5_bits & 0x007C0) >> 6; - toggle = (data->rc5_bits & 0x00800) ? 1 : 0; - command += (data->rc5_bits & 0x01000) ? 0 : 0x40; - scancode = system << 8 | command; - - IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", - scancode, toggle); + if (data->wanted_bits == RC5X_NBITS) { + /* RC5X */ + u8 xdata, command, system; + xdata = (data->rc5_bits & 0x0003F) >> 0; + command = (data->rc5_bits & 0x00FC0) >> 6; + system = (data->rc5_bits & 0x1F000) >> 12; + toggle = (data->rc5_bits & 0x20000) ? 1 : 0; + command += (data->rc5_bits & 0x01000) ? 0 : 0x40; + scancode = system << 16 | command << 8 | xdata; + + IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n", + scancode, toggle); + + } else { + /* RC5 */ + u8 command, system; + command = (data->rc5_bits & 0x0003F) >> 0; + system = (data->rc5_bits & 0x007C0) >> 6; + toggle = (data->rc5_bits & 0x00800) ? 1 : 0; + command += (data->rc5_bits & 0x01000) ? 0 : 0x40; + scancode = system << 8 | command; + + IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", + scancode, toggle); + } + ir_keydown(input_dev, scancode, toggle); data->state = STATE_INACTIVE; return 0; } out: - IR_dprintk(1, "RC5 decode failed at state %i (%i units, %ius)\n", + IR_dprintk(1, "RC5(x) decode failed at state %i (%i units, %ius)\n", data->state, u, TO_US(duration)); data->state = STATE_INACTIVE; return -EINVAL; @@ -273,7 +313,7 @@ static int __init ir_rc5_decode_init(void) { ir_raw_handler_register(&rc5_handler); - printk(KERN_INFO "IR RC-5 protocol handler initialized\n"); + printk(KERN_INFO "IR RC5(x) protocol handler initialized\n"); return 0; } @@ -288,4 +328,4 @@ module_exit(ir_rc5_decode_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mauro Carvalho Chehab "); MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); -MODULE_DESCRIPTION("RC-5 IR protocol decoder"); +MODULE_DESCRIPTION("RC5(x) IR protocol decoder"); -- cgit v1.2.3 From 25bb10c11e6cca461f09df8f59c2eb501a9e4d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 8 Apr 2010 20:04:35 -0300 Subject: V4L/DVB: Add NECx support to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds NECx support to drivers/media/IR/ir-nec-decoder.c Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-nec-decoder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 4c223f611a5e..14609d9580a8 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -18,6 +18,7 @@ #define NEC_NBITS 32 #define NEC_UNIT 562500 /* ns */ #define NEC_HEADER_PULSE PULSE(16) +#define NECX_HEADER_PULSE PULSE(8) /* Less common NEC variant */ #define NEC_HEADER_SPACE SPACE(8) #define NEC_REPEAT_SPACE SPACE(4) #define NEC_BIT_PULSE PULSE(1) @@ -152,7 +153,7 @@ static int ir_nec_decode(struct input_dev *input_dev, s64 duration) switch (data->state) { case STATE_INACTIVE: - if (u == NEC_HEADER_PULSE) { + if (u == NEC_HEADER_PULSE || u == NECX_HEADER_PULSE) { data->count = 0; data->state = STATE_HEADER_SPACE; } -- cgit v1.2.3 From 784a493168f71ce02b5f9eab0ec19df29b999631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 8 Apr 2010 20:04:40 -0300 Subject: V4L/DVB: Add RC6 support to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds an RC6 decoder (modes 0 and 6A) to ir-core. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 9 + drivers/media/IR/Makefile | 1 + drivers/media/IR/ir-core-priv.h | 7 + drivers/media/IR/ir-raw-event.c | 1 + drivers/media/IR/ir-rc6-decoder.c | 412 ++++++++++++++++++++++++++++++++++++++ drivers/media/IR/ir-sysfs.c | 2 + 6 files changed, 432 insertions(+) create mode 100644 drivers/media/IR/ir-rc6-decoder.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index ba81bda3513d..28d336d98187 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -27,3 +27,12 @@ config IR_RC5_DECODER ---help--- Enable this option if you have IR with RC-5 protocol, and if the IR is decoded in software + +config IR_RC6_DECODER + tristate "Enable IR raw decoder for the RC6 protocol" + depends on IR_CORE + default y + + ---help--- + Enable this option if you have an infrared remote control which + uses the RC6 protocol, and you need software decoding support. diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 62e12d5c443a..792d9cad7efc 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_IR_CORE) += ir-core.o obj-$(CONFIG_VIDEO_IR) += ir-common.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o +obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index ea546659e4ce..59d5ed7e103e 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -108,4 +108,11 @@ void ir_raw_init(void); #define load_rc5_decode() 0 #endif +/* from ir-rc6-decoder.c */ +#ifdef CONFIG_IR_RC5_DECODER_MODULE +#define load_rc6_decode() request_module("ir-rc6-decoder") +#else +#define load_rc6_decode() 0 +#endif + #endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index b49d01256be3..674442b2f0a8 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -226,6 +226,7 @@ static void init_decoders(struct work_struct *work) load_nec_decode(); load_rc5_decode(); + load_rc6_decode(); /* If needed, we may later add some init code. In this case, it is needed to change the CONFIG_MODULE test at ir-core.h diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c new file mode 100644 index 000000000000..ccc5be240f82 --- /dev/null +++ b/drivers/media/IR/ir-rc6-decoder.c @@ -0,0 +1,412 @@ +/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol + * + * Copyright (C) 2010 by David Härdeman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "ir-core-priv.h" + +/* + * This decoder currently supports: + * RC6-0-16 (standard toggle bit in header) + * RC6-6A-24 (no toggle bit) + * RC6-6A-32 (MCE version with toggle bit in body) + */ + +#define RC6_UNIT 444444 /* us */ +#define RC6_HEADER_NBITS 4 /* not including toggle bit */ +#define RC6_0_NBITS 16 +#define RC6_6A_SMALL_NBITS 24 +#define RC6_6A_LARGE_NBITS 32 +#define RC6_PREFIX_PULSE PULSE(6) +#define RC6_PREFIX_SPACE SPACE(2) +#define RC6_MODE_MASK 0x07 /* for the header bits */ +#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ +#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + +/* Used to register rc6_decoder clients */ +static LIST_HEAD(decoder_list); +static DEFINE_SPINLOCK(decoder_lock); + +enum rc6_mode { + RC6_MODE_0, + RC6_MODE_6A, + RC6_MODE_UNKNOWN, +}; + +enum rc6_state { + STATE_INACTIVE, + STATE_PREFIX_SPACE, + STATE_HEADER_BIT_START, + STATE_HEADER_BIT_END, + STATE_TOGGLE_START, + STATE_TOGGLE_END, + STATE_BODY_BIT_START, + STATE_BODY_BIT_END, + STATE_FINISHED, +}; + +struct decoder_data { + struct list_head list; + struct ir_input_dev *ir_dev; + int enabled:1; + + /* State machine control */ + enum rc6_state state; + u8 header; + u32 body; + int last_unit; + bool toggle; + unsigned count; + unsigned wanted_bits; +}; + + +/** + * get_decoder_data() - gets decoder data + * @input_dev: input device + * + * Returns the struct decoder_data that corresponds to a device + */ +static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) +{ + struct decoder_data *data = NULL; + + spin_lock(&decoder_lock); + list_for_each_entry(data, &decoder_list, list) { + if (data->ir_dev == ir_dev) + break; + } + spin_unlock(&decoder_lock); + return data; +} + +static ssize_t store_enabled(struct device *d, + struct device_attribute *mattr, + const char *buf, + size_t len) +{ + unsigned long value; + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (strict_strtoul(buf, 10, &value) || value > 1) + return -EINVAL; + + data->enabled = value; + + return len; +} + +static ssize_t show_enabled(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (data->enabled) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); + +static struct attribute *decoder_attributes[] = { + &dev_attr_enabled.attr, + NULL +}; + +static struct attribute_group decoder_attribute_group = { + .name = "rc6_decoder", + .attrs = decoder_attributes, +}; + +static enum rc6_mode rc6_mode(struct decoder_data *data) { + switch (data->header & RC6_MODE_MASK) { + case 0: + return RC6_MODE_0; + case 6: + if (!data->toggle) + return RC6_MODE_6A; + /* fall through */ + default: + return RC6_MODE_UNKNOWN; + } +} + +/** + * ir_rc6_decode() - Decode one RC6 pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @duration: duration of pulse/space in ns + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_rc6_decode(struct input_dev *input_dev, s64 duration) +{ + struct decoder_data *data; + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + u32 scancode; + u8 toggle; + int u; + + data = get_decoder_data(ir_dev); + if (!data) + return -EINVAL; + + if (!data->enabled) + return 0; + + if (IS_RESET(duration)) { + data->state = STATE_INACTIVE; + return 0; + } + + u = TO_UNITS(duration, RC6_UNIT); + if (DURATION(u) == 0) + goto out; + +again: + IR_dprintk(2, "RC6 decode started at state %i (%i units, %ius)\n", + data->state, u, TO_US(duration)); + + if (DURATION(u) == 0 && data->state != STATE_FINISHED) + return 0; + + switch (data->state) { + + case STATE_INACTIVE: + if (u >= RC6_PREFIX_PULSE - 1 && u <= RC6_PREFIX_PULSE + 1) { + data->state = STATE_PREFIX_SPACE; + data->count = 0; + return 0; + } + break; + + case STATE_PREFIX_SPACE: + if (u == RC6_PREFIX_SPACE) { + data->state = STATE_HEADER_BIT_START; + return 0; + } + break; + + case STATE_HEADER_BIT_START: + if (DURATION(u) == 1) { + data->header <<= 1; + if (IS_PULSE(u)) + data->header |= 1; + data->count++; + data->last_unit = u; + data->state = STATE_HEADER_BIT_END; + return 0; + } + break; + + case STATE_HEADER_BIT_END: + if (IS_TRANSITION(u, data->last_unit)) { + if (data->count == RC6_HEADER_NBITS) + data->state = STATE_TOGGLE_START; + else + data->state = STATE_HEADER_BIT_START; + + DECREASE_DURATION(u, 1); + goto again; + } + break; + + case STATE_TOGGLE_START: + if (DURATION(u) == 2) { + data->toggle = IS_PULSE(u); + data->last_unit = u; + data->state = STATE_TOGGLE_END; + return 0; + } + break; + + case STATE_TOGGLE_END: + if (IS_TRANSITION(u, data->last_unit) && DURATION(u) >= 2) { + data->state = STATE_BODY_BIT_START; + data->last_unit = u; + DECREASE_DURATION(u, 2); + data->count = 0; + + if (!(data->header & RC6_STARTBIT_MASK)) { + IR_dprintk(1, "RC6 invalid start bit\n"); + break; + } + + switch (rc6_mode(data)) { + case RC6_MODE_0: + data->wanted_bits = RC6_0_NBITS; + break; + case RC6_MODE_6A: + /* This might look weird, but we basically + check the value of the first body bit to + determine the number of bits in mode 6A */ + if ((DURATION(u) == 0 && IS_SPACE(data->last_unit)) || DURATION(u) > 0) + data->wanted_bits = RC6_6A_LARGE_NBITS; + else + data->wanted_bits = RC6_6A_SMALL_NBITS; + break; + default: + IR_dprintk(1, "RC6 unknown mode\n"); + goto out; + } + goto again; + } + break; + + case STATE_BODY_BIT_START: + if (DURATION(u) == 1) { + data->body <<= 1; + if (IS_PULSE(u)) + data->body |= 1; + data->count++; + data->last_unit = u; + + /* + * If the last bit is one, a space will merge + * with the silence after the command. + */ + if (IS_PULSE(u) && data->count == data->wanted_bits) { + data->state = STATE_FINISHED; + goto again; + } + + data->state = STATE_BODY_BIT_END; + return 0; + } + break; + + case STATE_BODY_BIT_END: + if (IS_TRANSITION(u, data->last_unit)) { + if (data->count == data->wanted_bits) + data->state = STATE_FINISHED; + else + data->state = STATE_BODY_BIT_START; + + DECREASE_DURATION(u, 1); + goto again; + } + break; + + case STATE_FINISHED: + switch (rc6_mode(data)) { + case RC6_MODE_0: + scancode = data->body & 0xffff; + toggle = data->toggle; + IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", + scancode, toggle); + break; + case RC6_MODE_6A: + if (data->wanted_bits == RC6_6A_LARGE_NBITS) { + toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; + scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; + } else { + toggle = 0; + scancode = data->body & 0xffffff; + } + + IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", + scancode, toggle); + break; + default: + IR_dprintk(1, "RC6 unknown mode\n"); + goto out; + } + + ir_keydown(input_dev, scancode, toggle); + data->state = STATE_INACTIVE; + return 0; + } + +out: + IR_dprintk(1, "RC6 decode failed at state %i (%i units, %ius)\n", + data->state, u, TO_US(duration)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static int ir_rc6_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct decoder_data *data; + int rc; + + rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); + if (rc < 0) + return rc; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + return -ENOMEM; + } + + data->ir_dev = ir_dev; + data->enabled = 1; + + spin_lock(&decoder_lock); + list_add_tail(&data->list, &decoder_list); + spin_unlock(&decoder_lock); + + return 0; +} + +static int ir_rc6_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + static struct decoder_data *data; + + data = get_decoder_data(ir_dev); + if (!data) + return 0; + + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + + spin_lock(&decoder_lock); + list_del(&data->list); + spin_unlock(&decoder_lock); + + return 0; +} + +static struct ir_raw_handler rc6_handler = { + .decode = ir_rc6_decode, + .raw_register = ir_rc6_register, + .raw_unregister = ir_rc6_unregister, +}; + +static int __init ir_rc6_decode_init(void) +{ + ir_raw_handler_register(&rc6_handler); + + printk(KERN_INFO "IR RC6 protocol handler initialized\n"); + return 0; +} + +static void __exit ir_rc6_decode_exit(void) +{ + ir_raw_handler_unregister(&rc6_handler); +} + +module_init(ir_rc6_decode_init); +module_exit(ir_rc6_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("RC6 IR protocol decoder"); diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 57f09c4ca9fb..073b5c0dc654 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -61,6 +61,8 @@ static ssize_t show_protocol(struct device *d, s = "pulse-distance"; else if (ir_type == IR_TYPE_NEC) s = "nec"; + else if (ir_type == IR_TYPE_RC6) + s = "rc6"; else s = "other"; -- cgit v1.2.3 From f35473e6f556b48ebf1a105ce27ed5ec1c81844b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 9 Apr 2010 09:17:02 -0300 Subject: V4L/DVB: ir-core-priv: fix a typo for RC6 config option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As Adreas pointed, RC6 should use CONFIG_IR_RC6_DECODER_MODULE, instead of the RC5 config option. Thanks-to: Andreas Oberitter Acked-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-core-priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index 59d5ed7e103e..fb2622a24ed8 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -109,7 +109,7 @@ void ir_raw_init(void); #endif /* from ir-rc6-decoder.c */ -#ifdef CONFIG_IR_RC5_DECODER_MODULE +#ifdef CONFIG_IR_RC6_DECODER_MODULE #define load_rc6_decode() request_module("ir-rc6-decoder") #else #define load_rc6_decode() 0 -- cgit v1.2.3 From 897c7b3b19cca7aad20bb1a3422553d7b646f2fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 9 Apr 2010 09:20:11 -0300 Subject: V4L/DVB: ir Kconfig: better describe the options Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index 28d336d98187..ee66d16d9ff2 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -11,7 +11,7 @@ config VIDEO_IR source "drivers/media/IR/keymaps/Kconfig" config IR_NEC_DECODER - tristate "Enable IR raw decoder for NEC protocol" + tristate "Enable IR raw decoder for the NEC protocol" depends on IR_CORE default y @@ -20,7 +20,7 @@ config IR_NEC_DECODER if the IR is decoded in software config IR_RC5_DECODER - tristate "Enable IR raw decoder for RC-5 protocol" + tristate "Enable IR raw decoder for the RC-5 protocol" depends on IR_CORE default y -- cgit v1.2.3 From 3efaa062a9bd1cd41c4901b8f41718410452499c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 10 Apr 2010 23:43:39 -0300 Subject: ir-core: Remove the quotation mark from the uevent names There's no need to use quotation marks at the uevent names for the driver and table. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 073b5c0dc654..ceec980552a4 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -162,9 +162,9 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) struct ir_input_dev *ir_dev = dev_get_drvdata(device); if (ir_dev->rc_tab.name) - ADD_HOTPLUG_VAR("NAME=\"%s\"", ir_dev->rc_tab.name); + ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name); if (ir_dev->driver_name) - ADD_HOTPLUG_VAR("DRV_NAME=\"%s\"", ir_dev->driver_name); + ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name); return 0; } -- cgit v1.2.3 From 09bd00e7e12bbc9ca0ba20e0511995cddd3c93b9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 11 Apr 2010 00:26:23 -0300 Subject: ir-core: Fix the delete logic Instead of removing an entry, the logic were doing both a deletion and a key addition, as shown by the log: [11517.323314] ir_getkeycode: unknown key for scancode 0x0050 [11517.326529] ir_do_setkeycode: #80: Deleting scan 0x0050 [11517.326529] ir_do_setkeycode: #80: New scan 0x0050 with key 0x0000 [11517.340598] ir_getkeycode: unknown key for scancode 0x0051 [11517.343811] ir_do_setkeycode: #81: Deleting scan 0x0051 [11517.343811] ir_do_setkeycode: #81: New scan 0x0051 with key 0x0000 [11517.357889] ir_getkeycode: unknown key for scancode 0x0052 [11517.361104] ir_do_setkeycode: #82: Deleting scan 0x0052 [11517.361104] ir_do_setkeycode: #82: New scan 0x0052 with key 0x0000 [11517.375453] ir_getkeycode: unknown key for scancode 0x0053 [11517.378474] ir_do_setkeycode: #83: Deleting scan 0x0053 [11517.378474] ir_do_setkeycode: #83: New scan 0x0053 with key 0x0000 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 599e39c34445..1bb4e32f3dc3 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -127,7 +127,7 @@ static int ir_do_setkeycode(struct input_dev *dev, break; } - if (old_keycode == KEY_RESERVED) { + if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) { /* No previous mapping found, we might need to grow the table */ if (ir_resize_table(rc_tab)) return -ENOMEM; -- cgit v1.2.3 From 1c0e0ee580c476234b5ea410f5263fcb27d96389 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 16 Apr 2010 18:27:58 -0300 Subject: V4L/DVB: ir-core: make ir_g_keycode_from_table a public function The imon driver I've previously submitted and have been porting to use ir-core needs to use ir_g_keycode_from_table, as ir_keydown is not sufficient, due to these things having really oddball hardware decoders in them. This just moves the function declaration from ir-core-priv.h over to ir-core.h. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-core-priv.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index fb2622a24ed8..8c1f84645eaf 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -57,13 +57,6 @@ struct ir_raw_event_ctrl { -DIV_ROUND_CLOSEST(abs((duration)), (unit_len)))) #define TO_US(duration) ((int)TO_UNITS(duration, 1000)) -/* - * Routines from ir-keytable.c to be used internally on ir-core and decoders - */ - -u32 ir_g_keycode_from_table(struct input_dev *input_dev, - u32 scancode); - /* * Routines from ir-sysfs.c - Meant to be called only internally inside * ir-core -- cgit v1.2.3 From 1159f838c0a334855c05c7c94f7a20799c57442d Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 16 Apr 2010 18:28:35 -0300 Subject: V4L/DVB: ir-core: add imon pad and mce keymaps This adds the keymaps for the hardware decode scancodes imon devices create for their native imon pad (and mini) remotes, and the hardware scancodes generated by the imon devices when used with an rc6 windows media center ed. remote. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/keymaps/Makefile | 2 + drivers/media/IR/keymaps/rc-imon-mce.c | 142 ++++++++++++++++++++++++++++++ drivers/media/IR/keymaps/rc-imon-pad.c | 155 +++++++++++++++++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 drivers/media/IR/keymaps/rc-imon-mce.c create mode 100644 drivers/media/IR/keymaps/rc-imon-pad.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile index c4d891d79491..ec25258a955f 100644 --- a/drivers/media/IR/keymaps/Makefile +++ b/drivers/media/IR/keymaps/Makefile @@ -30,6 +30,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-genius-tvgo-a11mce.o \ rc-gotview7135.o \ rc-hauppauge-new.o \ + rc-imon-mce.o \ + rc-imon-pad.o \ rc-iodata-bctv7e.o \ rc-kaiomy.o \ rc-kworld-315u.o \ diff --git a/drivers/media/IR/keymaps/rc-imon-mce.c b/drivers/media/IR/keymaps/rc-imon-mce.c new file mode 100644 index 000000000000..9c6dda30c649 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-imon-mce.c @@ -0,0 +1,142 @@ +/* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use + * with the SoundGraph iMON/Antec Veris hardware IR decoder + * + * Copyright (c) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* mce-mode imon mce remote key table */ +static struct ir_scancode imon_mce[] = { + /* keys sorted mostly by frequency of use to optimize lookups */ + { 0x800ff415, KEY_REWIND }, + { 0x800ff414, KEY_FASTFORWARD }, + { 0x800ff41b, KEY_PREVIOUS }, + { 0x800ff41a, KEY_NEXT }, + + { 0x800ff416, KEY_PLAY }, + { 0x800ff418, KEY_PAUSE }, + { 0x800ff419, KEY_STOP }, + { 0x800ff417, KEY_RECORD }, + + { 0x02000052, KEY_UP }, + { 0x02000051, KEY_DOWN }, + { 0x02000050, KEY_LEFT }, + { 0x0200004f, KEY_RIGHT }, + + { 0x800ff41e, KEY_UP }, + { 0x800ff41f, KEY_DOWN }, + { 0x800ff420, KEY_LEFT }, + { 0x800ff421, KEY_RIGHT }, + + /* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */ + { 0x800ff40b, KEY_ENTER }, + { 0x02000028, KEY_ENTER }, +/* the OK and Enter buttons decode to the same value on some remotes + { 0x02000028, KEY_OK }, */ + { 0x800ff422, KEY_OK }, + { 0x0200002a, KEY_EXIT }, + { 0x800ff423, KEY_EXIT }, + { 0x02000029, KEY_DELETE }, + /* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */ + { 0x800ff40a, KEY_DELETE }, + + { 0x800ff40e, KEY_MUTE }, + { 0x800ff410, KEY_VOLUMEUP }, + { 0x800ff411, KEY_VOLUMEDOWN }, + { 0x800ff412, KEY_CHANNELUP }, + { 0x800ff413, KEY_CHANNELDOWN }, + + { 0x0200001e, KEY_NUMERIC_1 }, + { 0x0200001f, KEY_NUMERIC_2 }, + { 0x02000020, KEY_NUMERIC_3 }, + { 0x02000021, KEY_NUMERIC_4 }, + { 0x02000022, KEY_NUMERIC_5 }, + { 0x02000023, KEY_NUMERIC_6 }, + { 0x02000024, KEY_NUMERIC_7 }, + { 0x02000025, KEY_NUMERIC_8 }, + { 0x02000026, KEY_NUMERIC_9 }, + { 0x02000027, KEY_NUMERIC_0 }, + + { 0x800ff401, KEY_NUMERIC_1 }, + { 0x800ff402, KEY_NUMERIC_2 }, + { 0x800ff403, KEY_NUMERIC_3 }, + { 0x800ff404, KEY_NUMERIC_4 }, + { 0x800ff405, KEY_NUMERIC_5 }, + { 0x800ff406, KEY_NUMERIC_6 }, + { 0x800ff407, KEY_NUMERIC_7 }, + { 0x800ff408, KEY_NUMERIC_8 }, + { 0x800ff409, KEY_NUMERIC_9 }, + { 0x800ff400, KEY_NUMERIC_0 }, + + { 0x02200025, KEY_NUMERIC_STAR }, + { 0x02200020, KEY_NUMERIC_POUND }, + /* 0x800ff41d also KEY_BLUE on some receivers */ + { 0x800ff41d, KEY_NUMERIC_STAR }, + /* 0x800ff41c also KEY_PREVIOUS on some receivers */ + { 0x800ff41c, KEY_NUMERIC_POUND }, + + { 0x800ff446, KEY_TV }, + { 0x800ff447, KEY_AUDIO }, /* My Music */ + { 0x800ff448, KEY_PVR }, /* RecordedTV */ + { 0x800ff449, KEY_CAMERA }, + { 0x800ff44a, KEY_VIDEO }, + /* 0x800ff424 also KEY_MENU on some receivers */ + { 0x800ff424, KEY_DVD }, + /* 0x800ff425 also KEY_GREEN on some receivers */ + { 0x800ff425, KEY_TUNER }, /* LiveTV */ + { 0x800ff450, KEY_RADIO }, + + { 0x800ff44c, KEY_LANGUAGE }, + { 0x800ff427, KEY_ZOOM }, /* Aspect */ + + { 0x800ff45b, KEY_RED }, + { 0x800ff45c, KEY_GREEN }, + { 0x800ff45d, KEY_YELLOW }, + { 0x800ff45e, KEY_BLUE }, + + { 0x800ff466, KEY_RED }, + /* { 0x800ff425, KEY_GREEN }, */ + { 0x800ff468, KEY_YELLOW }, + /* { 0x800ff41d, KEY_BLUE }, */ + + { 0x800ff40f, KEY_INFO }, + { 0x800ff426, KEY_EPG }, /* Guide */ + { 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */ + { 0x800ff44d, KEY_TITLE }, + + { 0x800ff40c, KEY_POWER }, + { 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */ + +}; + +static struct rc_keymap imon_mce_map = { + .map = { + .scan = imon_mce, + .size = ARRAY_SIZE(imon_mce), + /* its actually RC6, but w/a hardware decoder */ + .ir_type = IR_TYPE_UNKNOWN, + .name = RC_MAP_IMON_MCE, + } +}; + +static int __init init_rc_map_imon_mce(void) +{ + return ir_register_map(&imon_mce_map); +} + +static void __exit exit_rc_map_imon_mce(void) +{ + ir_unregister_map(&imon_mce_map); +} + +module_init(init_rc_map_imon_mce) +module_exit(exit_rc_map_imon_mce) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); diff --git a/drivers/media/IR/keymaps/rc-imon-pad.c b/drivers/media/IR/keymaps/rc-imon-pad.c new file mode 100644 index 000000000000..331ba9066b46 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-imon-pad.c @@ -0,0 +1,155 @@ +/* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris + * RM-200 Remote Control + * + * Copyright (c) 2010 by Jarod Wilson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include + +/* + * standard imon remote key table, which isn't really entirely + * "standard", as different receivers decode the same key on the + * same remote to different hex codes, and the silkscreened names + * vary a bit between the SoundGraph and Antec remotes... ugh. + */ +static struct ir_scancode imon_pad[] = { + /* keys sorted mostly by frequency of use to optimize lookups */ + { 0x2a8195b7, KEY_REWIND }, + { 0x298315b7, KEY_REWIND }, + { 0x2b8115b7, KEY_FASTFORWARD }, + { 0x2b8315b7, KEY_FASTFORWARD }, + { 0x2b9115b7, KEY_PREVIOUS }, + { 0x298195b7, KEY_NEXT }, + + { 0x2a8115b7, KEY_PLAY }, + { 0x2a8315b7, KEY_PLAY }, + { 0x2a9115b7, KEY_PAUSE }, + { 0x2b9715b7, KEY_STOP }, + { 0x298115b7, KEY_RECORD }, + + { 0x01008000, KEY_UP }, + { 0x01007f00, KEY_DOWN }, + { 0x01000080, KEY_LEFT }, + { 0x0100007f, KEY_RIGHT }, + + { 0x2aa515b7, KEY_UP }, + { 0x289515b7, KEY_DOWN }, + { 0x29a515b7, KEY_LEFT }, + { 0x2ba515b7, KEY_RIGHT }, + + { 0x0200002c, KEY_SPACE }, /* Select/Space */ + { 0x2a9315b7, KEY_SPACE }, /* Select/Space */ + { 0x02000028, KEY_ENTER }, + { 0x28a195b7, KEY_ENTER }, + { 0x288195b7, KEY_EXIT }, + { 0x02000029, KEY_ESC }, + { 0x2bb715b7, KEY_ESC }, + { 0x0200002a, KEY_BACKSPACE }, + { 0x28a115b7, KEY_BACKSPACE }, + + { 0x2b9595b7, KEY_MUTE }, + { 0x28a395b7, KEY_VOLUMEUP }, + { 0x28a595b7, KEY_VOLUMEDOWN }, + { 0x289395b7, KEY_CHANNELUP }, + { 0x288795b7, KEY_CHANNELDOWN }, + + { 0x0200001e, KEY_NUMERIC_1 }, + { 0x0200001f, KEY_NUMERIC_2 }, + { 0x02000020, KEY_NUMERIC_3 }, + { 0x02000021, KEY_NUMERIC_4 }, + { 0x02000022, KEY_NUMERIC_5 }, + { 0x02000023, KEY_NUMERIC_6 }, + { 0x02000024, KEY_NUMERIC_7 }, + { 0x02000025, KEY_NUMERIC_8 }, + { 0x02000026, KEY_NUMERIC_9 }, + { 0x02000027, KEY_NUMERIC_0 }, + + { 0x28b595b7, KEY_NUMERIC_1 }, + { 0x2bb195b7, KEY_NUMERIC_2 }, + { 0x28b195b7, KEY_NUMERIC_3 }, + { 0x2a8595b7, KEY_NUMERIC_4 }, + { 0x299595b7, KEY_NUMERIC_5 }, + { 0x2aa595b7, KEY_NUMERIC_6 }, + { 0x2b9395b7, KEY_NUMERIC_7 }, + { 0x2a8515b7, KEY_NUMERIC_8 }, + { 0x2aa115b7, KEY_NUMERIC_9 }, + { 0x2ba595b7, KEY_NUMERIC_0 }, + + { 0x02200025, KEY_NUMERIC_STAR }, + { 0x28b515b7, KEY_NUMERIC_STAR }, + { 0x02200020, KEY_NUMERIC_POUND }, + { 0x29a115b7, KEY_NUMERIC_POUND }, + + { 0x2b8515b7, KEY_VIDEO }, + { 0x299195b7, KEY_AUDIO }, + { 0x2ba115b7, KEY_CAMERA }, + { 0x28a515b7, KEY_TV }, + { 0x29a395b7, KEY_DVD }, + { 0x29a295b7, KEY_DVD }, + + /* the Menu key between DVD and Subtitle on the RM-200... */ + { 0x2ba385b7, KEY_MENU }, + { 0x2ba395b7, KEY_MENU }, + + { 0x288515b7, KEY_BOOKMARKS }, + { 0x2ab715b7, KEY_MEDIA }, /* Thumbnail */ + { 0x298595b7, KEY_SUBTITLE }, + { 0x2b8595b7, KEY_LANGUAGE }, + + { 0x29a595b7, KEY_ZOOM }, + { 0x2aa395b7, KEY_SCREEN }, /* FullScreen */ + + { 0x299115b7, KEY_KEYBOARD }, + { 0x299135b7, KEY_KEYBOARD }, + + { 0x01010000, BTN_LEFT }, + { 0x01020000, BTN_RIGHT }, + { 0x01010080, BTN_LEFT }, + { 0x01020080, BTN_RIGHT }, + { 0x688301b7, BTN_LEFT }, + { 0x688481b7, BTN_RIGHT }, + + { 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */ + { 0x2b8395b7, KEY_TIME }, /* Timer */ + + { 0x289115b7, KEY_POWER }, + { 0x29b195b7, KEY_EJECTCD }, /* the one next to play */ + { 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */ + + { 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */ + { 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/ + { 0x02000065, KEY_COMPOSE }, /* RightMenu */ + { 0x28b715b7, KEY_COMPOSE }, /* RightMenu */ + { 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */ + { 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */ +}; + +static struct rc_keymap imon_pad_map = { + .map = { + .scan = imon_pad, + .size = ARRAY_SIZE(imon_pad), + .ir_type = IR_TYPE_UNKNOWN, + .name = RC_MAP_IMON_PAD, + } +}; + +static int __init init_rc_map_imon_pad(void) +{ + return ir_register_map(&imon_pad_map); +} + +static void __exit exit_rc_map_imon_pad(void) +{ + ir_unregister_map(&imon_pad_map); +} + +module_init(init_rc_map_imon_pad) +module_exit(exit_rc_map_imon_pad) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson "); -- cgit v1.2.3 From 21677cfc562a27e099719d413287bc8d1d24deb7 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 16 Apr 2010 18:29:02 -0300 Subject: V4L/DVB: ir-core: add imon driver This is a new driver for the SoundGraph iMON and Antec Veris IR/display devices commonly found in many home theater pc cases and as after-market case additions. [mchehab@redhat.com: add KERN_CONT on line 2098 to shutup checkpatc.pl] Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 12 + drivers/media/IR/Makefile | 3 + drivers/media/IR/imon.c | 2417 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2432 insertions(+) create mode 100644 drivers/media/IR/imon.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index ee66d16d9ff2..dae5ea113867 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -36,3 +36,15 @@ config IR_RC6_DECODER ---help--- Enable this option if you have an infrared remote control which uses the RC6 protocol, and you need software decoding support. + +config IR_IMON + tristate "SoundGraph iMON Receiver and Display" + depends on USB_ARCH_HAS_HCD + depends on IR_CORE + select USB + ---help--- + Say Y here if you want to use a SoundGraph iMON (aka Antec Veris) + IR Receiver and/or LCD/VFD/VGA display. + + To compile this driver as a module, choose M here: the + module will be called imon. diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 792d9cad7efc..57b145515d4f 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -8,3 +8,6 @@ obj-$(CONFIG_VIDEO_IR) += ir-common.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o + +# stand-alone IR receivers/transmitters +obj-$(CONFIG_IR_IMON) += imon.o diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c new file mode 100644 index 000000000000..170fb9f2ca26 --- /dev/null +++ b/drivers/media/IR/imon.c @@ -0,0 +1,2417 @@ +/* + * imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD + * + * Copyright(C) 2009 Jarod Wilson + * Portions based on the original lirc_imon driver, + * Copyright(C) 2004 Venky Raju(dev@venky.ws) + * + * Huge thanks to R. Geoff Newbury for invaluable debugging on the + * 0xffdc iMON devices, and for sending me one to hack on, without + * which the support for them wouldn't be nearly as good. Thanks + * also to the numerous 0xffdc device owners that tested auto-config + * support for me and provided debug dumps from their devices. + * + * imon is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define MOD_AUTHOR "Jarod Wilson " +#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" +#define MOD_NAME "imon" +#define MOD_VERSION "0.9.1" + +#define DISPLAY_MINOR_BASE 144 +#define DEVICE_NAME "lcd%d" + +#define BUF_CHUNK_SIZE 8 +#define BUF_SIZE 128 + +#define BIT_DURATION 250 /* each bit received is 250us */ + +#define IMON_CLOCK_ENABLE_PACKETS 2 +#define IMON_KEY_RELEASE_OFFSET 1000 + +/*** P R O T O T Y P E S ***/ + +/* USB Callback prototypes */ +static int imon_probe(struct usb_interface *interface, + const struct usb_device_id *id); +static void imon_disconnect(struct usb_interface *interface); +static void usb_rx_callback_intf0(struct urb *urb); +static void usb_rx_callback_intf1(struct urb *urb); +static void usb_tx_callback(struct urb *urb); + +/* suspend/resume support */ +static int imon_resume(struct usb_interface *intf); +static int imon_suspend(struct usb_interface *intf, pm_message_t message); + +/* Display file_operations function prototypes */ +static int display_open(struct inode *inode, struct file *file); +static int display_close(struct inode *inode, struct file *file); + +/* VFD write operation */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/* LCD file_operations override function prototypes */ +static ssize_t lcd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos); + +/*** G L O B A L S ***/ + +struct imon_context { + struct device *dev; + struct ir_dev_props *props; + struct ir_input_dev *ir; + /* Newer devices have two interfaces */ + struct usb_device *usbdev_intf0; + struct usb_device *usbdev_intf1; + + bool display_supported; /* not all controllers do */ + bool display_isopen; /* display port has been opened */ + bool rf_isassociating; /* RF remote associating */ + bool dev_present_intf0; /* USB device presence, interface 0 */ + bool dev_present_intf1; /* USB device presence, interface 1 */ + + struct mutex lock; /* to lock this object */ + wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ + + struct usb_endpoint_descriptor *rx_endpoint_intf0; + struct usb_endpoint_descriptor *rx_endpoint_intf1; + struct usb_endpoint_descriptor *tx_endpoint; + struct urb *rx_urb_intf0; + struct urb *rx_urb_intf1; + struct urb *tx_urb; + bool tx_control; + unsigned char usb_rx_buf[8]; + unsigned char usb_tx_buf[8]; + + struct tx_t { + unsigned char data_buf[35]; /* user data buffer */ + struct completion finished; /* wait for write to finish */ + bool busy; /* write in progress */ + int status; /* status of tx completion */ + } tx; + + u16 vendor; /* usb vendor ID */ + u16 product; /* usb product ID */ + + struct input_dev *idev; /* input device for remote */ + struct input_dev *touch; /* input device for touchscreen */ + + u32 kc; /* current input keycode */ + u32 last_keycode; /* last reported input keycode */ + u8 ir_protocol; /* iMON or MCE (RC6) IR protocol? */ + u8 ir_proto_mask; /* supported IR protocol mask */ + u8 mce_toggle_bit; /* last mce toggle bit */ + bool release_code; /* some keys send a release code */ + + u8 display_type; /* store the display type */ + bool pad_mouse; /* toggle kbd(0)/mouse(1) mode */ + + char name_idev[128]; /* input device name */ + char phys_idev[64]; /* input device phys path */ + struct timer_list itimer; /* input device timer, need for rc6 */ + + char name_touch[128]; /* touch screen name */ + char phys_touch[64]; /* touch screen phys path */ + struct timer_list ttimer; /* touch screen timer */ + int touch_x; /* x coordinate on touchscreen */ + int touch_y; /* y coordinate on touchscreen */ +}; + +#define TOUCH_TIMEOUT (HZ/30) +#define MCE_TIMEOUT_MS 200 + +/* vfd character device file operations */ +static const struct file_operations vfd_fops = { + .owner = THIS_MODULE, + .open = &display_open, + .write = &vfd_write, + .release = &display_close +}; + +/* lcd character device file operations */ +static const struct file_operations lcd_fops = { + .owner = THIS_MODULE, + .open = &display_open, + .write = &lcd_write, + .release = &display_close +}; + +enum { + IMON_DISPLAY_TYPE_AUTO = 0, + IMON_DISPLAY_TYPE_VFD = 1, + IMON_DISPLAY_TYPE_LCD = 2, + IMON_DISPLAY_TYPE_VGA = 3, + IMON_DISPLAY_TYPE_NONE = 4, +}; + +enum { + IMON_IR_PROTOCOL_AUTO = 0x0, + IMON_IR_PROTOCOL_MCE = 0x1, + IMON_IR_PROTOCOL_IMON = 0x2, + IMON_IR_PROTOCOL_IMON_NOPAD = 0x4, +}; + +enum { + IMON_IR_PROTO_MASK_NONE = 0x0, + IMON_IR_PROTO_MASK_MCE = IMON_IR_PROTOCOL_MCE, + IMON_IR_PROTO_MASK_IMON = IMON_IR_PROTOCOL_IMON | + IMON_IR_PROTOCOL_IMON_NOPAD, +}; + +enum { + IMON_KEY_IMON = 0, + IMON_KEY_MCE = 1, + IMON_KEY_PANEL = 2, +}; + +/* + * USB Device ID for iMON USB Control Boards + * + * The Windows drivers contain 6 different inf files, more or less one for + * each new device until the 0x0034-0x0046 devices, which all use the same + * driver. Some of the devices in the 34-46 range haven't been definitively + * identified yet. Early devices have either a TriGem Computer, Inc. or a + * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later + * devices use the SoundGraph vendor ID (0x15c2). This driver only supports + * the ffdc and later devices, which do onboard decoding. + */ +static struct usb_device_id imon_usb_id_table[] = { + /* + * Several devices with this same device ID, all use iMON_PAD.inf + * SoundGraph iMON PAD (IR & VFD) + * SoundGraph iMON PAD (IR & LCD) + * SoundGraph iMON Knob (IR only) + */ + { USB_DEVICE(0x15c2, 0xffdc) }, + + /* + * Newer devices, all driven by the latest iMON Windows driver, full + * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2' + * Need user input to fill in details on unknown devices. + */ + /* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */ + { USB_DEVICE(0x15c2, 0x0034) }, + /* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */ + { USB_DEVICE(0x15c2, 0x0035) }, + /* SoundGraph iMON OEM VFD (IR & VFD) */ + { USB_DEVICE(0x15c2, 0x0036) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x0037) }, + /* SoundGraph iMON OEM LCD (IR & LCD) */ + { USB_DEVICE(0x15c2, 0x0038) }, + /* SoundGraph iMON UltraBay (IR & LCD) */ + { USB_DEVICE(0x15c2, 0x0039) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003a) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003b) }, + /* SoundGraph iMON OEM Inside (IR only) */ + { USB_DEVICE(0x15c2, 0x003c) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003d) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003e) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x003f) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x0040) }, + /* SoundGraph iMON MINI (IR only) */ + { USB_DEVICE(0x15c2, 0x0041) }, + /* Antec Veris Multimedia Station EZ External (IR only) */ + { USB_DEVICE(0x15c2, 0x0042) }, + /* Antec Veris Multimedia Station Basic Internal (IR only) */ + { USB_DEVICE(0x15c2, 0x0043) }, + /* Antec Veris Multimedia Station Elite (IR & VFD) */ + { USB_DEVICE(0x15c2, 0x0044) }, + /* Antec Veris Multimedia Station Premiere (IR & LCD) */ + { USB_DEVICE(0x15c2, 0x0045) }, + /* device specifics unknown */ + { USB_DEVICE(0x15c2, 0x0046) }, + {} +}; + +/* USB Device data */ +static struct usb_driver imon_driver = { + .name = MOD_NAME, + .probe = imon_probe, + .disconnect = imon_disconnect, + .suspend = imon_suspend, + .resume = imon_resume, + .id_table = imon_usb_id_table, +}; + +static struct usb_class_driver imon_vfd_class = { + .name = DEVICE_NAME, + .fops = &vfd_fops, + .minor_base = DISPLAY_MINOR_BASE, +}; + +static struct usb_class_driver imon_lcd_class = { + .name = DEVICE_NAME, + .fops = &lcd_fops, + .minor_base = DISPLAY_MINOR_BASE, +}; + +/* imon receiver front panel/knob key table */ +static const struct { + u64 hw_code; + u32 keycode; +} imon_panel_key_table[] = { + { 0x000000000f00ffee, KEY_PROG1 }, /* Go */ + { 0x000000001f00ffee, KEY_AUDIO }, + { 0x000000002000ffee, KEY_VIDEO }, + { 0x000000002100ffee, KEY_CAMERA }, + { 0x000000002700ffee, KEY_DVD }, + { 0x000000002300ffee, KEY_TV }, + { 0x000000000500ffee, KEY_PREVIOUS }, + { 0x000000000700ffee, KEY_REWIND }, + { 0x000000000400ffee, KEY_STOP }, + { 0x000000003c00ffee, KEY_PLAYPAUSE }, + { 0x000000000800ffee, KEY_FASTFORWARD }, + { 0x000000000600ffee, KEY_NEXT }, + { 0x000000010000ffee, KEY_RIGHT }, + { 0x000001000000ffee, KEY_LEFT }, + { 0x000000003d00ffee, KEY_SELECT }, + { 0x000100000000ffee, KEY_VOLUMEUP }, + { 0x010000000000ffee, KEY_VOLUMEDOWN }, + { 0x000000000100ffee, KEY_MUTE }, + /* iMON Knob values */ + { 0x000100ffffffffee, KEY_VOLUMEUP }, + { 0x010000ffffffffee, KEY_VOLUMEDOWN }, + { 0x000008ffffffffee, KEY_MUTE }, +}; + +/* to prevent races between open() and disconnect(), probing, etc */ +static DEFINE_MUTEX(driver_lock); + +/* Module bookkeeping bits */ +MODULE_AUTHOR(MOD_AUTHOR); +MODULE_DESCRIPTION(MOD_DESC); +MODULE_VERSION(MOD_VERSION); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, imon_usb_id_table); + +static bool debug; +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); + +/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */ +static int display_type; +module_param(display_type, int, S_IRUGO); +MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, " + "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)"); + +/* IR protocol: native iMON, Windows MCE (RC-6), or iMON w/o PAD stabilize */ +static int ir_protocol; +module_param(ir_protocol, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ir_protocol, "Which IR protocol to use. 0=auto-detect, " + "1=Windows Media Center Ed. (RC-6), 2=iMON native, " + "4=iMON w/o PAD stabilize (default: auto-detect)"); + +/* + * In certain use cases, mouse mode isn't really helpful, and could actually + * cause confusion, so allow disabling it when the IR device is open. + */ +static bool nomouse; +module_param(nomouse, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is " + "open. 0=don't disable, 1=disable. (default: don't disable)"); + +/* threshold at which a pad push registers as an arrow key in kbd mode */ +static int pad_thresh; +module_param(pad_thresh, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an " + "arrow key in kbd mode (default: 28)"); + + +static void free_imon_context(struct imon_context *ictx) +{ + struct device *dev = ictx->dev; + + usb_free_urb(ictx->tx_urb); + usb_free_urb(ictx->rx_urb_intf0); + usb_free_urb(ictx->rx_urb_intf1); + kfree(ictx); + + dev_dbg(dev, "%s: iMON context freed\n", __func__); +} + +/** + * Called when the Display device (e.g. /dev/lcd0) + * is opened by the application. + */ +static int display_open(struct inode *inode, struct file *file) +{ + struct usb_interface *interface; + struct imon_context *ictx = NULL; + int subminor; + int retval = 0; + + /* prevent races with disconnect */ + mutex_lock(&driver_lock); + + subminor = iminor(inode); + interface = usb_find_interface(&imon_driver, subminor); + if (!interface) { + err("%s: could not find interface for minor %d", + __func__, subminor); + retval = -ENODEV; + goto exit; + } + ictx = usb_get_intfdata(interface); + + if (!ictx) { + err("%s: no context found for minor %d", __func__, subminor); + retval = -ENODEV; + goto exit; + } + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + err("%s: display not supported by device", __func__); + retval = -ENODEV; + } else if (ictx->display_isopen) { + err("%s: display port is already open", __func__); + retval = -EBUSY; + } else { + ictx->display_isopen = 1; + file->private_data = ictx; + dev_dbg(ictx->dev, "display port opened\n"); + } + + mutex_unlock(&ictx->lock); + +exit: + mutex_unlock(&driver_lock); + return retval; +} + +/** + * Called when the display device (e.g. /dev/lcd0) + * is closed by the application. + */ +static int display_close(struct inode *inode, struct file *file) +{ + struct imon_context *ictx = NULL; + int retval = 0; + + ictx = (struct imon_context *)file->private_data; + + if (!ictx) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + err("%s: display not supported by device", __func__); + retval = -ENODEV; + } else if (!ictx->display_isopen) { + err("%s: display is not open", __func__); + retval = -EIO; + } else { + ictx->display_isopen = 0; + dev_dbg(ictx->dev, "display port closed\n"); + if (!ictx->dev_present_intf0) { + /* + * Device disconnected before close and IR port is not + * open. If IR port is open, context will be deleted by + * ir_close. + */ + mutex_unlock(&ictx->lock); + free_imon_context(ictx); + return retval; + } + } + + mutex_unlock(&ictx->lock); + return retval; +} + +/** + * Sends a packet to the device -- this function must be called + * with ictx->lock held. + */ +static int send_packet(struct imon_context *ictx) +{ + unsigned int pipe; + unsigned long timeout; + int interval = 0; + int retval = 0; + struct usb_ctrlrequest *control_req = NULL; + + /* Check if we need to use control or interrupt urb */ + if (!ictx->tx_control) { + pipe = usb_sndintpipe(ictx->usbdev_intf0, + ictx->tx_endpoint->bEndpointAddress); + interval = ictx->tx_endpoint->bInterval; + + usb_fill_int_urb(ictx->tx_urb, ictx->usbdev_intf0, pipe, + ictx->usb_tx_buf, + sizeof(ictx->usb_tx_buf), + usb_tx_callback, ictx, interval); + + ictx->tx_urb->actual_length = 0; + } else { + /* fill request into kmalloc'ed space: */ + control_req = kmalloc(sizeof(struct usb_ctrlrequest), + GFP_KERNEL); + if (control_req == NULL) + return -ENOMEM; + + /* setup packet is '21 09 0200 0001 0008' */ + control_req->bRequestType = 0x21; + control_req->bRequest = 0x09; + control_req->wValue = cpu_to_le16(0x0200); + control_req->wIndex = cpu_to_le16(0x0001); + control_req->wLength = cpu_to_le16(0x0008); + + /* control pipe is endpoint 0x00 */ + pipe = usb_sndctrlpipe(ictx->usbdev_intf0, 0); + + /* build the control urb */ + usb_fill_control_urb(ictx->tx_urb, ictx->usbdev_intf0, + pipe, (unsigned char *)control_req, + ictx->usb_tx_buf, + sizeof(ictx->usb_tx_buf), + usb_tx_callback, ictx); + ictx->tx_urb->actual_length = 0; + } + + init_completion(&ictx->tx.finished); + ictx->tx.busy = 1; + smp_rmb(); /* ensure later readers know we're busy */ + + retval = usb_submit_urb(ictx->tx_urb, GFP_KERNEL); + if (retval) { + ictx->tx.busy = 0; + smp_rmb(); /* ensure later readers know we're not busy */ + err("%s: error submitting urb(%d)", __func__, retval); + } else { + /* Wait for transmission to complete (or abort) */ + mutex_unlock(&ictx->lock); + retval = wait_for_completion_interruptible( + &ictx->tx.finished); + if (retval) + err("%s: task interrupted", __func__); + mutex_lock(&ictx->lock); + + retval = ictx->tx.status; + if (retval) + err("%s: packet tx failed (%d)", __func__, retval); + } + + kfree(control_req); + + /* + * Induce a mandatory 5ms delay before returning, as otherwise, + * send_packet can get called so rapidly as to overwhelm the device, + * particularly on faster systems and/or those with quirky usb. + */ + timeout = msecs_to_jiffies(5); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(timeout); + + return retval; +} + +/** + * Sends an associate packet to the iMON 2.4G. + * + * This might not be such a good idea, since it has an id collision with + * some versions of the "IR & VFD" combo. The only way to determine if it + * is an RF version is to look at the product description string. (Which + * we currently do not fetch). + */ +static int send_associate_24g(struct imon_context *ictx) +{ + int retval; + const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20 }; + + if (!ictx) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + if (!ictx->dev_present_intf0) { + err("%s: no iMON device present", __func__); + return -ENODEV; + } + + memcpy(ictx->usb_tx_buf, packet, sizeof(packet)); + retval = send_packet(ictx); + + return retval; +} + +/** + * Sends packets to setup and show clock on iMON display + * + * Arguments: year - last 2 digits of year, month - 1..12, + * day - 1..31, dow - day of the week (0-Sun...6-Sat), + * hour - 0..23, minute - 0..59, second - 0..59 + */ +static int send_set_imon_clock(struct imon_context *ictx, + unsigned int year, unsigned int month, + unsigned int day, unsigned int dow, + unsigned int hour, unsigned int minute, + unsigned int second) +{ + unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8]; + int retval = 0; + int i; + + if (!ictx) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + switch (ictx->display_type) { + case IMON_DISPLAY_TYPE_LCD: + clock_enable_pkt[0][0] = 0x80; + clock_enable_pkt[0][1] = year; + clock_enable_pkt[0][2] = month-1; + clock_enable_pkt[0][3] = day; + clock_enable_pkt[0][4] = hour; + clock_enable_pkt[0][5] = minute; + clock_enable_pkt[0][6] = second; + + clock_enable_pkt[1][0] = 0x80; + clock_enable_pkt[1][1] = 0; + clock_enable_pkt[1][2] = 0; + clock_enable_pkt[1][3] = 0; + clock_enable_pkt[1][4] = 0; + clock_enable_pkt[1][5] = 0; + clock_enable_pkt[1][6] = 0; + + if (ictx->product == 0xffdc) { + clock_enable_pkt[0][7] = 0x50; + clock_enable_pkt[1][7] = 0x51; + } else { + clock_enable_pkt[0][7] = 0x88; + clock_enable_pkt[1][7] = 0x8a; + } + + break; + + case IMON_DISPLAY_TYPE_VFD: + clock_enable_pkt[0][0] = year; + clock_enable_pkt[0][1] = month-1; + clock_enable_pkt[0][2] = day; + clock_enable_pkt[0][3] = dow; + clock_enable_pkt[0][4] = hour; + clock_enable_pkt[0][5] = minute; + clock_enable_pkt[0][6] = second; + clock_enable_pkt[0][7] = 0x40; + + clock_enable_pkt[1][0] = 0; + clock_enable_pkt[1][1] = 0; + clock_enable_pkt[1][2] = 1; + clock_enable_pkt[1][3] = 0; + clock_enable_pkt[1][4] = 0; + clock_enable_pkt[1][5] = 0; + clock_enable_pkt[1][6] = 0; + clock_enable_pkt[1][7] = 0x42; + + break; + + default: + return -ENODEV; + } + + for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) { + memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8); + retval = send_packet(ictx); + if (retval) { + err("%s: send_packet failed for packet %d", + __func__, i); + break; + } + } + + return retval; +} + +/** + * These are the sysfs functions to handle the association on the iMON 2.4G LT. + */ +static ssize_t show_associate_remote(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct imon_context *ictx = dev_get_drvdata(d); + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + if (ictx->rf_isassociating) + strcpy(buf, "associating\n"); + else + strcpy(buf, "closed\n"); + + dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for " + "instructions on how to associate your iMON 2.4G DT/LT " + "remote\n"); + mutex_unlock(&ictx->lock); + return strlen(buf); +} + +static ssize_t store_associate_remote(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct imon_context *ictx; + + ictx = dev_get_drvdata(d); + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + ictx->rf_isassociating = 1; + send_associate_24g(ictx); + mutex_unlock(&ictx->lock); + + return count; +} + +/** + * sysfs functions to control internal imon clock + */ +static ssize_t show_imon_clock(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct imon_context *ictx = dev_get_drvdata(d); + size_t len; + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + len = snprintf(buf, PAGE_SIZE, "Not supported."); + } else { + len = snprintf(buf, PAGE_SIZE, + "To set the clock on your iMON display:\n" + "# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n" + "%s", ictx->display_isopen ? + "\nNOTE: imon device must be closed\n" : ""); + } + + mutex_unlock(&ictx->lock); + + return len; +} + +static ssize_t store_imon_clock(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct imon_context *ictx = dev_get_drvdata(d); + ssize_t retval; + unsigned int year, month, day, dow, hour, minute, second; + + if (!ictx) + return -ENODEV; + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + retval = -ENODEV; + goto exit; + } else if (ictx->display_isopen) { + retval = -EBUSY; + goto exit; + } + + if (sscanf(buf, "%u %u %u %u %u %u %u", &year, &month, &day, &dow, + &hour, &minute, &second) != 7) { + retval = -EINVAL; + goto exit; + } + + if ((month < 1 || month > 12) || + (day < 1 || day > 31) || (dow > 6) || + (hour > 23) || (minute > 59) || (second > 59)) { + retval = -EINVAL; + goto exit; + } + + retval = send_set_imon_clock(ictx, year, month, day, dow, + hour, minute, second); + if (retval) + goto exit; + + retval = count; +exit: + mutex_unlock(&ictx->lock); + + return retval; +} + + +static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock, + store_imon_clock); + +static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote, + store_associate_remote); + +static struct attribute *imon_display_sysfs_entries[] = { + &dev_attr_imon_clock.attr, + NULL +}; + +static struct attribute_group imon_display_attribute_group = { + .attrs = imon_display_sysfs_entries +}; + +static struct attribute *imon_rf_sysfs_entries[] = { + &dev_attr_associate_remote.attr, + NULL +}; + +static struct attribute_group imon_rf_attribute_group = { + .attrs = imon_rf_sysfs_entries +}; + +/** + * Writes data to the VFD. The iMON VFD is 2x16 characters + * and requires data in 5 consecutive USB interrupt packets, + * each packet but the last carrying 7 bytes. + * + * I don't know if the VFD board supports features such as + * scrolling, clearing rows, blanking, etc. so at + * the caller must provide a full screen of data. If fewer + * than 32 bytes are provided spaces will be appended to + * generate a full screen. + */ +static ssize_t vfd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int i; + int offset; + int seq; + int retval = 0; + struct imon_context *ictx; + const unsigned char vfd_packet6[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; + + ictx = (struct imon_context *)file->private_data; + if (!ictx) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&ictx->lock); + + if (!ictx->dev_present_intf0) { + err("%s: no iMON device present", __func__); + retval = -ENODEV; + goto exit; + } + + if (n_bytes <= 0 || n_bytes > 32) { + err("%s: invalid payload size", __func__); + retval = -EINVAL; + goto exit; + } + + if (copy_from_user(ictx->tx.data_buf, buf, n_bytes)) { + retval = -EFAULT; + goto exit; + } + + /* Pad with spaces */ + for (i = n_bytes; i < 32; ++i) + ictx->tx.data_buf[i] = ' '; + + for (i = 32; i < 35; ++i) + ictx->tx.data_buf[i] = 0xFF; + + offset = 0; + seq = 0; + + do { + memcpy(ictx->usb_tx_buf, ictx->tx.data_buf + offset, 7); + ictx->usb_tx_buf[7] = (unsigned char) seq; + + retval = send_packet(ictx); + if (retval) { + err("%s: send packet failed for packet #%d", + __func__, seq/2); + goto exit; + } else { + seq += 2; + offset += 7; + } + + } while (offset < 35); + + /* Send packet #6 */ + memcpy(ictx->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); + ictx->usb_tx_buf[7] = (unsigned char) seq; + retval = send_packet(ictx); + if (retval) + err("%s: send packet failed for packet #%d", + __func__, seq / 2); + +exit: + mutex_unlock(&ictx->lock); + + return (!retval) ? n_bytes : retval; +} + +/** + * Writes data to the LCD. The iMON OEM LCD screen expects 8-byte + * packets. We accept data as 16 hexadecimal digits, followed by a + * newline (to make it easy to drive the device from a command-line + * -- even though the actual binary data is a bit complicated). + * + * The device itself is not a "traditional" text-mode display. It's + * actually a 16x96 pixel bitmap display. That means if you want to + * display text, you've got to have your own "font" and translate the + * text into bitmaps for display. This is really flexible (you can + * display whatever diacritics you need, and so on), but it's also + * a lot more complicated than most LCDs... + */ +static ssize_t lcd_write(struct file *file, const char *buf, + size_t n_bytes, loff_t *pos) +{ + int retval = 0; + struct imon_context *ictx; + + ictx = (struct imon_context *)file->private_data; + if (!ictx) { + err("%s: no context for device", __func__); + return -ENODEV; + } + + mutex_lock(&ictx->lock); + + if (!ictx->display_supported) { + err("%s: no iMON display present", __func__); + retval = -ENODEV; + goto exit; + } + + if (n_bytes != 8) { + err("%s: invalid payload size: %d (expecting 8)", + __func__, (int) n_bytes); + retval = -EINVAL; + goto exit; + } + + if (copy_from_user(ictx->usb_tx_buf, buf, 8)) { + retval = -EFAULT; + goto exit; + } + + retval = send_packet(ictx); + if (retval) { + err("%s: send packet failed!", __func__); + goto exit; + } else { + dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n", + __func__, (int) n_bytes); + } +exit: + mutex_unlock(&ictx->lock); + return (!retval) ? n_bytes : retval; +} + +/** + * Callback function for USB core API: transmit data + */ +static void usb_tx_callback(struct urb *urb) +{ + struct imon_context *ictx; + + if (!urb) + return; + ictx = (struct imon_context *)urb->context; + if (!ictx) + return; + + ictx->tx.status = urb->status; + + /* notify waiters that write has finished */ + ictx->tx.busy = 0; + smp_rmb(); /* ensure later readers know we're not busy */ + complete(&ictx->tx.finished); +} + +/** + * mce/rc6 keypresses have no distinct release code, use timer + */ +static void imon_mce_timeout(unsigned long data) +{ + struct imon_context *ictx = (struct imon_context *)data; + + input_report_key(ictx->idev, ictx->last_keycode, 0); + input_sync(ictx->idev); +} + +/** + * report touchscreen input + */ +static void imon_touch_display_timeout(unsigned long data) +{ + struct imon_context *ictx = (struct imon_context *)data; + + if (!ictx->display_type == IMON_DISPLAY_TYPE_VGA) + return; + + input_report_abs(ictx->touch, ABS_X, ictx->touch_x); + input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); + input_report_key(ictx->touch, BTN_TOUCH, 0x00); + input_sync(ictx->touch); +} + +/** + * iMON IR receivers support two different signal sets -- those used by + * the iMON remotes, and those used by the Windows MCE remotes (which is + * really just RC-6), but only one or the other at a time, as the signals + * are decoded onboard the receiver. + */ +static void imon_set_ir_protocol(struct imon_context *ictx) +{ + int retval; + struct device *dev = ictx->dev; + unsigned char ir_proto_packet[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; + + if (ir_protocol && !(ir_protocol & ictx->ir_proto_mask)) + dev_warn(dev, "Looks like you're trying to use an IR protocol " + "this device does not support\n"); + + switch (ir_protocol) { + case IMON_IR_PROTOCOL_AUTO: + if (ictx->product == 0xffdc) { + if (ictx->ir_proto_mask & IMON_IR_PROTO_MASK_MCE) { + ir_proto_packet[0] = 0x01; + ictx->ir_protocol = IMON_IR_PROTOCOL_MCE; + ictx->pad_mouse = 0; + init_timer(&ictx->itimer); + ictx->itimer.data = (unsigned long)ictx; + ictx->itimer.function = imon_mce_timeout; + } else { + ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; + ictx->pad_mouse = 1; + } + } + break; + case IMON_IR_PROTOCOL_MCE: + dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); + ir_proto_packet[0] = 0x01; + ictx->ir_protocol = IMON_IR_PROTOCOL_MCE; + ictx->pad_mouse = 0; + init_timer(&ictx->itimer); + ictx->itimer.data = (unsigned long)ictx; + ictx->itimer.function = imon_mce_timeout; + break; + case IMON_IR_PROTOCOL_IMON: + dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); + /* ir_proto_packet[0] = 0x00; // already the default */ + ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; + ictx->pad_mouse = 1; + break; + case IMON_IR_PROTOCOL_IMON_NOPAD: + dev_dbg(dev, "Configuring IR receiver for iMON protocol " + "without PAD stabilize function enabled\n"); + /* ir_proto_packet[0] = 0x00; // already the default */ + ictx->ir_protocol = IMON_IR_PROTOCOL_IMON_NOPAD; + ictx->pad_mouse = 0; + break; + default: + dev_info(dev, "%s: unknown IR protocol specified, will " + "just default to iMON protocol\n", __func__); + ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; + ictx->pad_mouse = 1; + break; + } + + memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); + + retval = send_packet(ictx); + if (retval) { + dev_info(dev, "%s: failed to set IR protocol, falling back " + "to standard iMON protocol mode\n", __func__); + ir_protocol = IMON_IR_PROTOCOL_IMON; + ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; + } +} + +static inline int tv2int(const struct timeval *a, const struct timeval *b) +{ + int usecs = 0; + int sec = 0; + + if (b->tv_usec > a->tv_usec) { + usecs = 1000000; + sec--; + } + + usecs += a->tv_usec - b->tv_usec; + + sec += a->tv_sec - b->tv_sec; + sec *= 1000; + usecs /= 1000; + sec += usecs; + + if (sec < 0) + sec = 1000; + + return sec; +} + +/** + * The directional pad behaves a bit differently, depending on whether this is + * one of the older ffdc devices or a newer device. Newer devices appear to + * have a higher resolution matrix for more precise mouse movement, but it + * makes things overly sensitive in keyboard mode, so we do some interesting + * contortions to make it less touchy. Older devices run through the same + * routine with shorter timeout and a smaller threshold. + */ +static int stabilize(int a, int b, u16 timeout, u16 threshold) +{ + struct timeval ct; + static struct timeval prev_time = {0, 0}; + static struct timeval hit_time = {0, 0}; + static int x, y, prev_result, hits; + int result = 0; + int msec, msec_hit; + + do_gettimeofday(&ct); + msec = tv2int(&ct, &prev_time); + msec_hit = tv2int(&ct, &hit_time); + + if (msec > 100) { + x = 0; + y = 0; + hits = 0; + } + + x += a; + y += b; + + prev_time = ct; + + if (abs(x) > threshold || abs(y) > threshold) { + if (abs(y) > abs(x)) + result = (y > 0) ? 0x7F : 0x80; + else + result = (x > 0) ? 0x7F00 : 0x8000; + + x = 0; + y = 0; + + if (result == prev_result) { + hits++; + + if (hits > 3) { + switch (result) { + case 0x7F: + y = 17 * threshold / 30; + break; + case 0x80: + y -= 17 * threshold / 30; + break; + case 0x7F00: + x = 17 * threshold / 30; + break; + case 0x8000: + x -= 17 * threshold / 30; + break; + } + } + + if (hits == 2 && msec_hit < timeout) { + result = 0; + hits = 1; + } + } else { + prev_result = result; + hits = 1; + hit_time = ct; + } + } + + return result; +} + +static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code) +{ + u32 scancode = be32_to_cpu(hw_code); + u32 keycode; + u32 release; + bool is_release_code = false; + + /* Look for the initial press of a button */ + keycode = ir_g_keycode_from_table(ictx->idev, scancode); + + /* Look for the release of a button */ + if (keycode == KEY_RESERVED) { + release = scancode & ~0x4000; + keycode = ir_g_keycode_from_table(ictx->idev, release); + if (keycode != KEY_RESERVED) + is_release_code = true; + } + + ictx->release_code = is_release_code; + + return keycode; +} + +static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code) +{ + u32 scancode = be32_to_cpu(hw_code); + u32 keycode; + +#define MCE_KEY_MASK 0x7000 +#define MCE_TOGGLE_BIT 0x8000 + + /* + * On some receivers, mce keys decode to 0x8000f04xx and 0x8000f84xx + * (the toggle bit flipping between alternating key presses), while + * on other receivers, we see 0x8000f74xx and 0x8000ff4xx. To keep + * the table trim, we always or in the bits to look up 0x8000ff4xx, + * but we can't or them into all codes, as some keys are decoded in + * a different way w/o the same use of the toggle bit... + */ + if ((scancode >> 24) & 0x80) + scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT; + + keycode = ir_g_keycode_from_table(ictx->idev, scancode); + + return keycode; +} + +static u32 imon_panel_key_lookup(u64 hw_code) +{ + int i; + u64 code = be64_to_cpu(hw_code); + u32 keycode; + + for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) + if (imon_panel_key_table[i].hw_code == (code | 0xffee)) + break; + + keycode = imon_panel_key_table[i % IMON_KEY_RELEASE_OFFSET].keycode; + + return keycode; +} + +static bool imon_mouse_event(struct imon_context *ictx, + unsigned char *buf, int len) +{ + char rel_x = 0x00, rel_y = 0x00; + u8 right_shift = 1; + bool mouse_input = 1; + int dir = 0; + + /* newer iMON device PAD or mouse button */ + if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) { + rel_x = buf[2]; + rel_y = buf[3]; + right_shift = 1; + /* 0xffdc iMON PAD or mouse button input */ + } else if (ictx->product == 0xffdc && (buf[0] & 0x40) && + !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) { + rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | + (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; + if (buf[0] & 0x02) + rel_x |= ~0x0f; + rel_x = rel_x + rel_x / 2; + rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | + (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; + if (buf[0] & 0x01) + rel_y |= ~0x0f; + rel_y = rel_y + rel_y / 2; + right_shift = 2; + /* some ffdc devices decode mouse buttons differently... */ + } else if (ictx->product == 0xffdc && (buf[0] == 0x68)) { + right_shift = 2; + /* ch+/- buttons, which we use for an emulated scroll wheel */ + } else if (ictx->kc == KEY_CHANNELUP && (buf[2] & 0x40) != 0x40) { + dir = 1; + } else if (ictx->kc == KEY_CHANNELDOWN && (buf[2] & 0x40) != 0x40) { + dir = -1; + } else + mouse_input = 0; + + if (mouse_input) { + dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); + + if (dir) { + input_report_rel(ictx->idev, REL_WHEEL, dir); + } else if (rel_x || rel_y) { + input_report_rel(ictx->idev, REL_X, rel_x); + input_report_rel(ictx->idev, REL_Y, rel_y); + } else { + input_report_key(ictx->idev, BTN_LEFT, buf[1] & 0x1); + input_report_key(ictx->idev, BTN_RIGHT, + buf[1] >> right_shift & 0x1); + } + input_sync(ictx->idev); + ictx->last_keycode = ictx->kc; + } + + return mouse_input; +} + +static void imon_touch_event(struct imon_context *ictx, unsigned char *buf) +{ + mod_timer(&ictx->ttimer, jiffies + TOUCH_TIMEOUT); + ictx->touch_x = (buf[0] << 4) | (buf[1] >> 4); + ictx->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf)); + input_report_abs(ictx->touch, ABS_X, ictx->touch_x); + input_report_abs(ictx->touch, ABS_Y, ictx->touch_y); + input_report_key(ictx->touch, BTN_TOUCH, 0x01); + input_sync(ictx->touch); +} + +static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) +{ + int dir = 0; + char rel_x = 0x00, rel_y = 0x00; + u16 timeout, threshold; + u64 temp_key; + u32 remote_key; + + /* + * The imon directional pad functions more like a touchpad. Bytes 3 & 4 + * contain a position coordinate (x,y), with each component ranging + * from -14 to 14. We want to down-sample this to only 4 discrete values + * for up/down/left/right arrow keys. Also, when you get too close to + * diagonals, it has a tendancy to jump back and forth, so lets try to + * ignore when they get too close. + */ + if (ictx->product != 0xffdc) { + /* first, pad to 8 bytes so it conforms with everything else */ + buf[5] = buf[6] = buf[7] = 0; + timeout = 500; /* in msecs */ + /* (2*threshold) x (2*threshold) square */ + threshold = pad_thresh ? pad_thresh : 28; + rel_x = buf[2]; + rel_y = buf[3]; + + if (ictx->ir_protocol == IMON_IR_PROTOCOL_IMON) { + if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { + dir = stabilize((int)rel_x, (int)rel_y, + timeout, threshold); + if (!dir) { + ictx->kc = KEY_UNKNOWN; + return; + } + buf[2] = dir & 0xFF; + buf[3] = (dir >> 8) & 0xFF; + memcpy(&temp_key, buf, sizeof(temp_key)); + remote_key = (u32) (le64_to_cpu(temp_key) + & 0xffffffff); + ictx->kc = imon_remote_key_lookup(ictx, + remote_key); + } + } else { + if (abs(rel_y) > abs(rel_x)) { + buf[2] = (rel_y > 0) ? 0x7F : 0x80; + buf[3] = 0; + ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; + } else { + buf[2] = 0; + buf[3] = (rel_x > 0) ? 0x7F : 0x80; + ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; + } + } + + /* + * Handle on-board decoded pad events for e.g. older VFD/iMON-Pad + * device (15c2:ffdc). The remote generates various codes from + * 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button generates + * 0x688301b7 and the right one 0x688481b7. All other keys generate + * 0x2nnnnnnn. Position coordinate is encoded in buf[1] and buf[2] with + * reversed endianess. Extract direction from buffer, rotate endianess, + * adjust sign and feed the values into stabilize(). The resulting codes + * will be 0x01008000, 0x01007F00, which match the newer devices. + */ + } else { + timeout = 10; /* in msecs */ + /* (2*threshold) x (2*threshold) square */ + threshold = pad_thresh ? pad_thresh : 15; + + /* buf[1] is x */ + rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | + (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; + if (buf[0] & 0x02) + rel_x |= ~0x10+1; + /* buf[2] is y */ + rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | + (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; + if (buf[0] & 0x01) + rel_y |= ~0x10+1; + + buf[0] = 0x01; + buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; + + if (ictx->ir_protocol == IMON_IR_PROTOCOL_IMON) { + dir = stabilize((int)rel_x, (int)rel_y, + timeout, threshold); + if (!dir) { + ictx->kc = KEY_UNKNOWN; + return; + } + buf[2] = dir & 0xFF; + buf[3] = (dir >> 8) & 0xFF; + memcpy(&temp_key, buf, sizeof(temp_key)); + remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); + ictx->kc = imon_remote_key_lookup(ictx, remote_key); + } else { + if (abs(rel_y) > abs(rel_x)) { + buf[2] = (rel_y > 0) ? 0x7F : 0x80; + buf[3] = 0; + ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP; + } else { + buf[2] = 0; + buf[3] = (rel_x > 0) ? 0x7F : 0x80; + ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT; + } + } + } +} + +static int imon_parse_press_type(struct imon_context *ictx, + unsigned char *buf, u8 ktype) +{ + int press_type = 0; + + /* key release of 0x02XXXXXX key */ + if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) + ictx->kc = ictx->last_keycode; + + /* mouse button release on (some) 0xffdc devices */ + else if (ictx->kc == KEY_RESERVED && buf[0] == 0x68 && buf[1] == 0x82 && + buf[2] == 0x81 && buf[3] == 0xb7) + ictx->kc = ictx->last_keycode; + + /* mouse button release on (some other) 0xffdc devices */ + else if (ictx->kc == KEY_RESERVED && buf[0] == 0x01 && buf[1] == 0x00 && + buf[2] == 0x81 && buf[3] == 0xb7) + ictx->kc = ictx->last_keycode; + + /* mce-specific button handling */ + else if (ktype == IMON_KEY_MCE) { + /* initial press */ + if (ictx->kc != ictx->last_keycode + || buf[2] != ictx->mce_toggle_bit) { + ictx->last_keycode = ictx->kc; + ictx->mce_toggle_bit = buf[2]; + press_type = 1; + mod_timer(&ictx->itimer, + jiffies + msecs_to_jiffies(MCE_TIMEOUT_MS)); + /* repeat */ + } else { + press_type = 2; + mod_timer(&ictx->itimer, + jiffies + msecs_to_jiffies(MCE_TIMEOUT_MS)); + } + + /* incoherent or irrelevant data */ + } else if (ictx->kc == KEY_RESERVED) + press_type = -EINVAL; + + /* key release of 0xXXXXXXb7 key */ + else if (ictx->release_code) + press_type = 0; + + /* this is a button press */ + else + press_type = 1; + + return press_type; +} + +/** + * Process the incoming packet + */ +static void imon_incoming_packet(struct imon_context *ictx, + struct urb *urb, int intf) +{ + int len = urb->actual_length; + unsigned char *buf = urb->transfer_buffer; + struct device *dev = ictx->dev; + u32 kc; + bool norelease = 0; + int i; + u64 temp_key; + u64 panel_key = 0; + u32 remote_key = 0; + struct input_dev *idev = NULL; + int press_type = 0; + int msec; + struct timeval t; + static struct timeval prev_time = { 0, 0 }; + u8 ktype = IMON_KEY_IMON; + + idev = ictx->idev; + + /* filter out junk data on the older 0xffdc imon devices */ + if ((buf[0] == 0xff) && (buf[7] == 0xff)) + return; + + /* Figure out what key was pressed */ + memcpy(&temp_key, buf, sizeof(temp_key)); + if (len == 8 && buf[7] == 0xee) { + ktype = IMON_KEY_PANEL; + panel_key = le64_to_cpu(temp_key); + kc = imon_panel_key_lookup(panel_key); + } else { + remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); + if (ictx->ir_protocol == IMON_IR_PROTOCOL_MCE) { + if (buf[0] == 0x80) + ktype = IMON_KEY_MCE; + kc = imon_mce_key_lookup(ictx, remote_key); + } else + kc = imon_remote_key_lookup(ictx, remote_key); + } + + /* keyboard/mouse mode toggle button */ + if (kc == KEY_KEYBOARD && !ictx->release_code) { + ictx->last_keycode = kc; + if (!nomouse) { + ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; + dev_dbg(dev, "toggling to %s mode\n", + ictx->pad_mouse ? "mouse" : "keyboard"); + return; + } else { + ictx->pad_mouse = 0; + dev_dbg(dev, "mouse mode disabled, passing key value\n"); + } + } + + ictx->kc = kc; + + /* send touchscreen events through input subsystem if touchpad data */ + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && + buf[7] == 0x86) { + imon_touch_event(ictx, buf); + + /* look for mouse events with pad in mouse mode */ + } else if (ictx->pad_mouse) { + if (imon_mouse_event(ictx, buf, len)) + return; + } + + /* Now for some special handling to convert pad input to arrow keys */ + if (((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) || + ((len == 8) && (buf[0] & 0x40) && + !(buf[1] & 0x1 || buf[1] >> 2 & 0x1))) { + len = 8; + imon_pad_to_keys(ictx, buf); + norelease = 1; + } + + if (debug) { + printk(KERN_INFO "intf%d decoded packet: ", intf); + for (i = 0; i < len; ++i) + printk("%02x ", buf[i]); + printk("\n"); + } + + press_type = imon_parse_press_type(ictx, buf, ktype); + if (press_type < 0) + goto not_input_data; + + if (ictx->kc == KEY_UNKNOWN) + goto unknown_key; + + /* KEY_MUTE repeats from MCE and knob need to be suppressed */ + if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) + && (buf[7] == 0xee || ktype == IMON_KEY_MCE)) { + do_gettimeofday(&t); + msec = tv2int(&t, &prev_time); + prev_time = t; + if (msec < 200) + return; + } + + input_report_key(idev, ictx->kc, press_type); + input_sync(idev); + + /* panel keys and some remote keys don't generate a release */ + if (panel_key || norelease) { + input_report_key(idev, ictx->kc, 0); + input_sync(idev); + } + + ictx->last_keycode = ictx->kc; + + return; + +unknown_key: + dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, + (panel_key ? be64_to_cpu(panel_key) : + be32_to_cpu(remote_key))); + return; + +not_input_data: + if (len != 8) { + dev_warn(dev, "imon %s: invalid incoming packet " + "size (len = %d, intf%d)\n", __func__, len, intf); + return; + } + + /* iMON 2.4G associate frame */ + if (buf[0] == 0x00 && + buf[2] == 0xFF && /* REFID */ + buf[3] == 0xFF && + buf[4] == 0xFF && + buf[5] == 0xFF && /* iMON 2.4G */ + ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */ + (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ + dev_warn(dev, "%s: remote associated refid=%02X\n", + __func__, buf[1]); + ictx->rf_isassociating = 0; + } +} + +/** + * Callback function for USB core API: receive data + */ +static void usb_rx_callback_intf0(struct urb *urb) +{ + struct imon_context *ictx; + int intfnum = 0; + + if (!urb) + return; + + ictx = (struct imon_context *)urb->context; + if (!ictx) + return; + + switch (urb->status) { + case -ENOENT: /* usbcore unlink successful! */ + return; + + case -ESHUTDOWN: /* transport endpoint was shut down */ + break; + + case 0: + imon_incoming_packet(ictx, urb, intfnum); + break; + + default: + dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", + __func__, urb->status); + break; + } + + usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); +} + +static void usb_rx_callback_intf1(struct urb *urb) +{ + struct imon_context *ictx; + int intfnum = 1; + + if (!urb) + return; + + ictx = (struct imon_context *)urb->context; + if (!ictx) + return; + + switch (urb->status) { + case -ENOENT: /* usbcore unlink successful! */ + return; + + case -ESHUTDOWN: /* transport endpoint was shut down */ + break; + + case 0: + imon_incoming_packet(ictx, urb, intfnum); + break; + + default: + dev_warn(ictx->dev, "imon %s: status(%d): ignored\n", + __func__, urb->status); + break; + } + + usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); +} + +static struct input_dev *imon_init_idev(struct imon_context *ictx) +{ + struct input_dev *idev; + struct ir_dev_props *props; + struct ir_input_dev *ir; + int ret, i; + char *ir_codes = NULL; + + if (ir_protocol == IMON_IR_PROTOCOL_MCE) + ir_codes = RC_MAP_IMON_MCE; + else + ir_codes = RC_MAP_IMON_PAD; + + idev = input_allocate_device(); + if (!idev) { + dev_err(ictx->dev, "remote input dev allocation failed\n"); + goto idev_alloc_failed; + } + + props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); + if (!props) { + dev_err(ictx->dev, "remote ir dev props allocation failed\n"); + goto props_alloc_failed; + } + + ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL); + if (!props) { + dev_err(ictx->dev, "remote ir input dev allocation failed\n"); + goto ir_dev_alloc_failed; + } + + snprintf(ictx->name_idev, sizeof(ictx->name_idev), + "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); + idev->name = ictx->name_idev; + + usb_make_path(ictx->usbdev_intf0, ictx->phys_idev, + sizeof(ictx->phys_idev)); + strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev)); + idev->phys = ictx->phys_idev; + + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); + + idev->keybit[BIT_WORD(BTN_MOUSE)] = + BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); + idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | + BIT_MASK(REL_WHEEL); + + /* panel and/or knob code support */ + for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { + u32 kc = imon_panel_key_table[i].keycode; + __set_bit(kc, idev->keybit); + } + + props->driver_type = RC_DRIVER_SCANCODE; + props->allowed_protos = IR_TYPE_UNKNOWN; + + ictx->ir = ir; + memcpy(&ir->dev, ictx->dev, sizeof(struct device)); + + usb_to_input_id(ictx->usbdev_intf0, &idev->id); + idev->dev.parent = ictx->dev; + + input_set_drvdata(idev, ir); + + ret = ir_input_register(idev, ir_codes, props, MOD_NAME); + if (ret < 0) { + dev_err(ictx->dev, "remote input dev register failed\n"); + goto idev_register_failed; + } + + return idev; + +idev_register_failed: + kfree(ir); +ir_dev_alloc_failed: + kfree(props); +props_alloc_failed: + input_free_device(idev); +idev_alloc_failed: + + return NULL; +} + +static struct input_dev *imon_init_touch(struct imon_context *ictx) +{ + struct input_dev *touch; + int ret; + + touch = input_allocate_device(); + if (!touch) { + dev_err(ictx->dev, "touchscreen input dev allocation failed\n"); + goto touch_alloc_failed; + } + + snprintf(ictx->name_touch, sizeof(ictx->name_touch), + "iMON USB Touchscreen (%04x:%04x)", + ictx->vendor, ictx->product); + touch->name = ictx->name_touch; + + usb_make_path(ictx->usbdev_intf1, ictx->phys_touch, + sizeof(ictx->phys_touch)); + strlcat(ictx->phys_touch, "/input1", sizeof(ictx->phys_touch)); + touch->phys = ictx->phys_touch; + + touch->evbit[0] = + BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + touch->keybit[BIT_WORD(BTN_TOUCH)] = + BIT_MASK(BTN_TOUCH); + input_set_abs_params(touch, ABS_X, + 0x00, 0xfff, 0, 0); + input_set_abs_params(touch, ABS_Y, + 0x00, 0xfff, 0, 0); + + input_set_drvdata(touch, ictx); + + usb_to_input_id(ictx->usbdev_intf1, &touch->id); + touch->dev.parent = ictx->dev; + ret = input_register_device(touch); + if (ret < 0) { + dev_info(ictx->dev, "touchscreen input dev register failed\n"); + goto touch_register_failed; + } + + return touch; + +touch_register_failed: + input_free_device(ictx->touch); + mutex_unlock(&ictx->lock); + +touch_alloc_failed: + return NULL; +} + +static bool imon_find_endpoints(struct imon_context *ictx, + struct usb_host_interface *iface_desc) +{ + struct usb_endpoint_descriptor *ep; + struct usb_endpoint_descriptor *rx_endpoint = NULL; + struct usb_endpoint_descriptor *tx_endpoint = NULL; + int ifnum = iface_desc->desc.bInterfaceNumber; + int num_endpts = iface_desc->desc.bNumEndpoints; + int i, ep_dir, ep_type; + bool ir_ep_found = 0; + bool display_ep_found = 0; + bool tx_control = 0; + + /* + * Scan the endpoint list and set: + * first input endpoint = IR endpoint + * first output endpoint = display endpoint + */ + for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { + ep = &iface_desc->endpoint[i].desc; + ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + if (!ir_ep_found && ep_dir == USB_DIR_IN && + ep_type == USB_ENDPOINT_XFER_INT) { + + rx_endpoint = ep; + ir_ep_found = 1; + dev_dbg(ictx->dev, "%s: found IR endpoint\n", __func__); + + } else if (!display_ep_found && ep_dir == USB_DIR_OUT && + ep_type == USB_ENDPOINT_XFER_INT) { + tx_endpoint = ep; + display_ep_found = 1; + dev_dbg(ictx->dev, "%s: found display endpoint\n", __func__); + } + } + + if (ifnum == 0) { + ictx->rx_endpoint_intf0 = rx_endpoint; + /* + * tx is used to send characters to lcd/vfd, associate RF + * remotes, set IR protocol, and maybe more... + */ + ictx->tx_endpoint = tx_endpoint; + } else { + ictx->rx_endpoint_intf1 = rx_endpoint; + } + + /* + * If we didn't find a display endpoint, this is probably one of the + * newer iMON devices that use control urb instead of interrupt + */ + if (!display_ep_found) { + tx_control = 1; + display_ep_found = 1; + dev_dbg(ictx->dev, "%s: device uses control endpoint, not " + "interface OUT endpoint\n", __func__); + } + + /* + * Some iMON receivers have no display. Unfortunately, it seems + * that SoundGraph recycles device IDs between devices both with + * and without... :\ + */ + if (ictx->display_type == IMON_DISPLAY_TYPE_NONE) { + display_ep_found = 0; + dev_dbg(ictx->dev, "%s: device has no display\n", __func__); + } + + /* + * iMON Touch devices have a VGA touchscreen, but no "display", as + * that refers to e.g. /dev/lcd0 (a character device LCD or VFD). + */ + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { + display_ep_found = 0; + dev_dbg(ictx->dev, "%s: iMON Touch device found\n", __func__); + } + + /* Input endpoint is mandatory */ + if (!ir_ep_found) + err("%s: no valid input (IR) endpoint found.", __func__); + + ictx->tx_control = tx_control; + + if (display_ep_found) + ictx->display_supported = true; + + return ir_ep_found; + +} + +static struct imon_context *imon_init_intf0(struct usb_interface *intf) +{ + struct imon_context *ictx; + struct urb *rx_urb; + struct urb *tx_urb; + struct device *dev = &intf->dev; + struct usb_host_interface *iface_desc; + int ret; + + ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); + if (!ictx) { + dev_err(dev, "%s: kzalloc failed for context", __func__); + goto exit; + } + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + dev_err(dev, "%s: usb_alloc_urb failed for IR urb", __func__); + goto rx_urb_alloc_failed; + } + tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!tx_urb) { + dev_err(dev, "%s: usb_alloc_urb failed for display urb", + __func__); + goto tx_urb_alloc_failed; + } + + mutex_init(&ictx->lock); + + mutex_lock(&ictx->lock); + + ictx->dev = dev; + ictx->usbdev_intf0 = usb_get_dev(interface_to_usbdev(intf)); + ictx->dev_present_intf0 = 1; + ictx->rx_urb_intf0 = rx_urb; + ictx->tx_urb = tx_urb; + + ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor); + ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct); + + iface_desc = intf->cur_altsetting; + if (!imon_find_endpoints(ictx, iface_desc)) + goto find_endpoint_failed; + + ictx->idev = imon_init_idev(ictx); + if (!ictx->idev) { + dev_err(dev, "%s: input device setup failed\n", __func__); + goto idev_setup_failed; + } + + usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, + usb_rcvintpipe(ictx->usbdev_intf0, + ictx->rx_endpoint_intf0->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf0, ictx, + ictx->rx_endpoint_intf0->bInterval); + + ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL); + if (ret) { + err("%s: usb_submit_urb failed for intf0 (%d)", + __func__, ret); + goto urb_submit_failed; + } + + return ictx; + +urb_submit_failed: + input_unregister_device(ictx->idev); + input_free_device(ictx->idev); +idev_setup_failed: +find_endpoint_failed: + mutex_unlock(&ictx->lock); + usb_free_urb(tx_urb); +tx_urb_alloc_failed: + usb_free_urb(rx_urb); +rx_urb_alloc_failed: + kfree(ictx); +exit: + dev_err(dev, "unable to initialize intf0, err %d\n", ret); + + return NULL; +} + +static struct imon_context *imon_init_intf1(struct usb_interface *intf, + struct imon_context *ictx) +{ + struct urb *rx_urb; + struct usb_host_interface *iface_desc; + int ret; + + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + err("%s: usb_alloc_urb failed for IR urb", __func__); + ret = -ENOMEM; + goto rx_urb_alloc_failed; + } + + mutex_lock(&ictx->lock); + + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { + init_timer(&ictx->ttimer); + ictx->ttimer.data = (unsigned long)ictx; + ictx->ttimer.function = imon_touch_display_timeout; + } + + ictx->usbdev_intf1 = usb_get_dev(interface_to_usbdev(intf)); + ictx->dev_present_intf1 = 1; + ictx->rx_urb_intf1 = rx_urb; + + iface_desc = intf->cur_altsetting; + if (!imon_find_endpoints(ictx, iface_desc)) + goto find_endpoint_failed; + + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) { + ictx->touch = imon_init_touch(ictx); + if (!ictx->touch) + goto touch_setup_failed; + } else + ictx->touch = NULL; + + usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, + usb_rcvintpipe(ictx->usbdev_intf1, + ictx->rx_endpoint_intf1->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf1, ictx, + ictx->rx_endpoint_intf1->bInterval); + + ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL); + + if (ret) { + err("%s: usb_submit_urb failed for intf1 (%d)", + __func__, ret); + goto urb_submit_failed; + } + + return ictx; + +urb_submit_failed: + if (ictx->touch) { + input_unregister_device(ictx->touch); + input_free_device(ictx->touch); + } +touch_setup_failed: +find_endpoint_failed: + mutex_unlock(&ictx->lock); + usb_free_urb(rx_urb); +rx_urb_alloc_failed: + dev_err(ictx->dev, "unable to initialize intf0, err %d\n", ret); + + return NULL; +} + +/* + * The 0x15c2:0xffdc device ID was used for umpteen different imon + * devices, and all of them constantly spew interrupts, even when there + * is no actual data to report. However, byte 6 of this buffer looks like + * its unique across device variants, so we're trying to key off that to + * figure out which display type (if any) and what IR protocol the device + * actually supports. + */ +static void imon_get_ffdc_type(struct imon_context *ictx) +{ + u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; + u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; + u8 ir_proto_mask = IMON_IR_PROTO_MASK_IMON; + + switch (ffdc_cfg_byte) { + /* iMON Knob, no display, iMON IR + vol knob */ + case 0x21: + dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR"); + ictx->display_supported = false; + break; + /* iMON VFD, no IR (does have vol knob tho) */ + case 0x35: + dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + ir_proto_mask = IMON_IR_PROTO_MASK_NONE; + break; + /* iMON VFD, iMON IR */ + case 0x24: + case 0x85: + dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + /* iMON LCD, MCE IR */ + case 0x9f: + dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); + detected_display_type = IMON_DISPLAY_TYPE_LCD; + ir_proto_mask = IMON_IR_PROTO_MASK_MCE; + break; + default: + dev_info(ictx->dev, "Unknown 0xffdc device, " + "defaulting to VFD and iMON IR"); + detected_display_type = IMON_DISPLAY_TYPE_VFD; + break; + } + + printk(" (id 0x%02x)\n", ffdc_cfg_byte); + + ictx->display_type = detected_display_type; + ictx->ir_proto_mask = ir_proto_mask; +} + +static void imon_set_display_type(struct imon_context *ictx, + struct usb_interface *intf) +{ + u8 configured_display_type = IMON_DISPLAY_TYPE_VFD; + + /* + * Try to auto-detect the type of display if the user hasn't set + * it by hand via the display_type modparam. Default is VFD. + */ + + if (display_type == IMON_DISPLAY_TYPE_AUTO) { + switch (ictx->product) { + case 0xffdc: + /* set in imon_get_ffdc_type() */ + configured_display_type = ictx->display_type; + break; + case 0x0034: + case 0x0035: + configured_display_type = IMON_DISPLAY_TYPE_VGA; + break; + case 0x0038: + case 0x0039: + case 0x0045: + configured_display_type = IMON_DISPLAY_TYPE_LCD; + break; + case 0x003c: + case 0x0041: + case 0x0042: + case 0x0043: + configured_display_type = IMON_DISPLAY_TYPE_NONE; + ictx->display_supported = false; + break; + case 0x0036: + case 0x0044: + default: + configured_display_type = IMON_DISPLAY_TYPE_VFD; + break; + } + } else { + configured_display_type = display_type; + if (display_type == IMON_DISPLAY_TYPE_NONE) + ictx->display_supported = false; + else + ictx->display_supported = true; + dev_info(ictx->dev, "%s: overriding display type to %d via " + "modparam\n", __func__, display_type); + } + + ictx->display_type = configured_display_type; +} + +static void imon_init_display(struct imon_context *ictx, + struct usb_interface *intf) +{ + int ret; + + dev_dbg(ictx->dev, "Registering iMON display with sysfs\n"); + + /* set up sysfs entry for built-in clock */ + ret = sysfs_create_group(&intf->dev.kobj, + &imon_display_attribute_group); + if (ret) + dev_err(ictx->dev, "Could not create display sysfs " + "entries(%d)", ret); + + if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) + ret = usb_register_dev(intf, &imon_lcd_class); + else + ret = usb_register_dev(intf, &imon_vfd_class); + if (ret) + /* Not a fatal error, so ignore */ + dev_info(ictx->dev, "could not get a minor number for " + "display\n"); + +} + +/** + * Callback function for USB core API: Probe + */ +static int __devinit imon_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *usbdev = NULL; + struct usb_host_interface *iface_desc = NULL; + struct usb_interface *first_if; + struct device *dev = &interface->dev; + int ifnum, code_length, sysfs_err; + int ret = 0; + struct imon_context *ictx = NULL; + struct imon_context *first_if_ctx = NULL; + u16 vendor, product; + const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x88 }; + + code_length = BUF_CHUNK_SIZE * 8; + + usbdev = usb_get_dev(interface_to_usbdev(interface)); + iface_desc = interface->cur_altsetting; + ifnum = iface_desc->desc.bInterfaceNumber; + vendor = le16_to_cpu(usbdev->descriptor.idVendor); + product = le16_to_cpu(usbdev->descriptor.idProduct); + + dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n", + __func__, vendor, product, ifnum); + + /* prevent races probing devices w/multiple interfaces */ + mutex_lock(&driver_lock); + + first_if = usb_ifnum_to_if(usbdev, 0); + first_if_ctx = (struct imon_context *)usb_get_intfdata(first_if); + + if (ifnum == 0) { + ictx = imon_init_intf0(interface); + if (!ictx) { + err("%s: failed to initialize context!\n", __func__); + ret = -ENODEV; + goto fail; + } + + if (product == 0xffdc) { + /* RF products *also* use 0xffdc... sigh... */ + sysfs_err = sysfs_create_group(&interface->dev.kobj, + &imon_rf_attribute_group); + if (sysfs_err) + err("%s: Could not create RF sysfs entries(%d)", + __func__, sysfs_err); + } + + } else { + /* this is the secondary interface on the device */ + ictx = imon_init_intf1(interface, first_if_ctx); + if (!ictx) { + err("%s: failed to attach to context!\n", __func__); + ret = -ENODEV; + goto fail; + } + + } + + usb_set_intfdata(interface, ictx); + + if (ifnum == 0) { + /* Enable front-panel buttons and/or knobs */ + memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet)); + ret = send_packet(ictx); + /* Not fatal, but warn about it */ + if (ret) + dev_info(dev, "failed to enable panel buttons " + "and/or knobs\n"); + + if (product == 0xffdc) + imon_get_ffdc_type(ictx); + else + ictx->ir_proto_mask = IMON_IR_PROTO_MASK_MCE | + IMON_IR_PROTO_MASK_IMON; + + imon_set_display_type(ictx, interface); + + if (ictx->display_supported) + imon_init_display(ictx, interface); + } + + /* set IR protocol/remote type */ + imon_set_ir_protocol(ictx); + + dev_info(dev, "iMON device (%04x:%04x, intf%d) on " + "usb<%d:%d> initialized\n", vendor, product, ifnum, + usbdev->bus->busnum, usbdev->devnum); + + mutex_unlock(&ictx->lock); + mutex_unlock(&driver_lock); + + return 0; + +fail: + mutex_unlock(&driver_lock); + dev_err(dev, "unable to register, err %d\n", ret); + + return ret; +} + +/** + * Callback function for USB core API: disconnect + */ +static void __devexit imon_disconnect(struct usb_interface *interface) +{ + struct imon_context *ictx; + struct device *dev; + int ifnum; + + /* prevent races with multi-interface device probing and display_open */ + mutex_lock(&driver_lock); + + ictx = usb_get_intfdata(interface); + dev = ictx->dev; + ifnum = interface->cur_altsetting->desc.bInterfaceNumber; + + mutex_lock(&ictx->lock); + + /* + * sysfs_remove_group is safe to call even if sysfs_create_group + * hasn't been called + */ + sysfs_remove_group(&interface->dev.kobj, + &imon_display_attribute_group); + sysfs_remove_group(&interface->dev.kobj, + &imon_rf_attribute_group); + + usb_set_intfdata(interface, NULL); + + /* Abort ongoing write */ + if (ictx->tx.busy) { + usb_kill_urb(ictx->tx_urb); + complete_all(&ictx->tx.finished); + } + + if (ifnum == 0) { + ictx->dev_present_intf0 = 0; + usb_kill_urb(ictx->rx_urb_intf0); + input_unregister_device(ictx->idev); + if (ictx->display_supported) { + if (ictx->display_type == IMON_DISPLAY_TYPE_LCD) + usb_deregister_dev(interface, &imon_lcd_class); + else + usb_deregister_dev(interface, &imon_vfd_class); + } + } else { + ictx->dev_present_intf1 = 0; + usb_kill_urb(ictx->rx_urb_intf1); + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) + input_unregister_device(ictx->touch); + } + + if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1) { + if (ictx->display_type == IMON_DISPLAY_TYPE_VGA) + del_timer_sync(&ictx->ttimer); + mutex_unlock(&ictx->lock); + if (!ictx->display_isopen) + free_imon_context(ictx); + } else { + if (ictx->ir_protocol == IMON_IR_PROTOCOL_MCE) + del_timer_sync(&ictx->itimer); + mutex_unlock(&ictx->lock); + } + + mutex_unlock(&driver_lock); + + dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n", + __func__, ifnum); +} + +static int imon_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct imon_context *ictx = usb_get_intfdata(intf); + int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + + if (ifnum == 0) + usb_kill_urb(ictx->rx_urb_intf0); + else + usb_kill_urb(ictx->rx_urb_intf1); + + return 0; +} + +static int imon_resume(struct usb_interface *intf) +{ + int rc = 0; + struct imon_context *ictx = usb_get_intfdata(intf); + int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; + + if (ifnum == 0) { + usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0, + usb_rcvintpipe(ictx->usbdev_intf0, + ictx->rx_endpoint_intf0->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf0, ictx, + ictx->rx_endpoint_intf0->bInterval); + + rc = usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC); + + } else { + usb_fill_int_urb(ictx->rx_urb_intf1, ictx->usbdev_intf1, + usb_rcvintpipe(ictx->usbdev_intf1, + ictx->rx_endpoint_intf1->bEndpointAddress), + ictx->usb_rx_buf, sizeof(ictx->usb_rx_buf), + usb_rx_callback_intf1, ictx, + ictx->rx_endpoint_intf1->bInterval); + + rc = usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC); + } + + return rc; +} + +static int __init imon_init(void) +{ + int rc; + + rc = usb_register(&imon_driver); + if (rc) { + err("%s: usb register failed(%d)", __func__, rc); + rc = -ENODEV; + } + + return rc; +} + +static void __exit imon_exit(void) +{ + usb_deregister(&imon_driver); +} + +module_init(imon_init); +module_exit(imon_exit); -- cgit v1.2.3 From e40b1127f994a427568319d1be9b9e5ab1f58dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 15 Apr 2010 18:46:00 -0300 Subject: V4L/DVB: ir-core: change duration to be coded as a u32 integer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch implements the agreed upon 1:31 integer encoded pulse/duration struct for ir-core raw decoders. All decoders have been tested after the change. Comments are welcome. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-core-priv.h | 49 ++++----- drivers/media/IR/ir-nec-decoder.c | 120 ++++++++++++--------- drivers/media/IR/ir-raw-event.c | 30 +++--- drivers/media/IR/ir-rc5-decoder.c | 105 +++++++++--------- drivers/media/IR/ir-rc6-decoder.c | 221 ++++++++++++++++++++------------------ 5 files changed, 271 insertions(+), 254 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index 8c1f84645eaf..77d0b94ede10 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -22,7 +22,7 @@ struct ir_raw_handler { struct list_head list; - int (*decode)(struct input_dev *input_dev, s64 duration); + int (*decode)(struct input_dev *input_dev, struct ir_raw_event event); int (*raw_register)(struct input_dev *input_dev); int (*raw_unregister)(struct input_dev *input_dev); }; @@ -36,26 +36,28 @@ struct ir_raw_event_ctrl { }; /* macros for IR decoders */ -#define PULSE(units) ((units)) -#define SPACE(units) (-(units)) -#define IS_RESET(duration) ((duration) == 0) -#define IS_PULSE(duration) ((duration) > 0) -#define IS_SPACE(duration) ((duration) < 0) -#define DURATION(duration) (abs((duration))) -#define IS_TRANSITION(x, y) ((x) * (y) < 0) -#define DECREASE_DURATION(duration, amount) \ - do { \ - if (IS_SPACE(duration)) \ - duration += (amount); \ - else if (IS_PULSE(duration)) \ - duration -= (amount); \ - } while (0) - -#define TO_UNITS(duration, unit_len) \ - ((int)((duration) > 0 ? \ - DIV_ROUND_CLOSEST(abs((duration)), (unit_len)) :\ - -DIV_ROUND_CLOSEST(abs((duration)), (unit_len)))) -#define TO_US(duration) ((int)TO_UNITS(duration, 1000)) +static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) { + return d1 > (d2 - margin); +} + +static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) { + return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); +} + +static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) { + return x->pulse != y->pulse; +} + +static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) { + if (duration > ev->duration) + ev->duration = 0; + else + ev->duration -= duration; +} + +#define TO_US(duration) (((duration) + 500) / 1000) +#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") +#define IS_RESET(ev) (ev.duration == 0) /* * Routines from ir-sysfs.c - Meant to be called only internally inside @@ -70,11 +72,6 @@ void ir_unregister_class(struct input_dev *input_dev); */ int ir_raw_event_register(struct input_dev *input_dev); void ir_raw_event_unregister(struct input_dev *input_dev); -static inline void ir_raw_event_reset(struct input_dev *input_dev) -{ - ir_raw_event_store(input_dev, 0); - ir_raw_event_handle(input_dev); -} int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); void ir_raw_init(void); diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 14609d9580a8..ba79233112ef 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c @@ -17,13 +17,15 @@ #define NEC_NBITS 32 #define NEC_UNIT 562500 /* ns */ -#define NEC_HEADER_PULSE PULSE(16) -#define NECX_HEADER_PULSE PULSE(8) /* Less common NEC variant */ -#define NEC_HEADER_SPACE SPACE(8) -#define NEC_REPEAT_SPACE SPACE(4) -#define NEC_BIT_PULSE PULSE(1) -#define NEC_BIT_0_SPACE SPACE(1) -#define NEC_BIT_1_SPACE SPACE(3) +#define NEC_HEADER_PULSE (16 * NEC_UNIT) +#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ +#define NEC_HEADER_SPACE (8 * NEC_UNIT) +#define NEC_REPEAT_SPACE (8 * NEC_UNIT) +#define NEC_BIT_PULSE (1 * NEC_UNIT) +#define NEC_BIT_0_SPACE (1 * NEC_UNIT) +#define NEC_BIT_1_SPACE (3 * NEC_UNIT) +#define NEC_TRAILER_PULSE (1 * NEC_UNIT) +#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ /* Used to register nec_decoder clients */ static LIST_HEAD(decoder_list); @@ -119,15 +121,14 @@ static struct attribute_group decoder_attribute_group = { /** * ir_nec_decode() - Decode one NEC pulse or space * @input_dev: the struct input_dev descriptor of the device - * @duration: duration in ns of pulse/space + * @duration: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_nec_decode(struct input_dev *input_dev, s64 duration) +static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); - int u; u32 scancode; u8 address, not_address, command, not_command; @@ -138,59 +139,88 @@ static int ir_nec_decode(struct input_dev *input_dev, s64 duration) if (!data->enabled) return 0; - if (IS_RESET(duration)) { + if (IS_RESET(ev)) { data->state = STATE_INACTIVE; return 0; } - u = TO_UNITS(duration, NEC_UNIT); - if (DURATION(u) == 0) - goto out; - - IR_dprintk(2, "NEC decode started at state %d (%i units, %ius)\n", - data->state, u, TO_US(duration)); + IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); switch (data->state) { case STATE_INACTIVE: - if (u == NEC_HEADER_PULSE || u == NECX_HEADER_PULSE) { - data->count = 0; - data->state = STATE_HEADER_SPACE; - } + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) && + !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) + break; + + data->count = 0; + data->state = STATE_HEADER_SPACE; return 0; case STATE_HEADER_SPACE: - if (u == NEC_HEADER_SPACE) { + if (ev.pulse) + break; + + if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) { data->state = STATE_BIT_PULSE; return 0; - } else if (u == NEC_REPEAT_SPACE) { + } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) { ir_repeat(input_dev); IR_dprintk(1, "Repeat last key\n"); data->state = STATE_TRAILER_PULSE; return 0; } + break; case STATE_BIT_PULSE: - if (u == NEC_BIT_PULSE) { - data->state = STATE_BIT_SPACE; - return 0; - } - break; + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2)) + break; + + data->state = STATE_BIT_SPACE; + return 0; case STATE_BIT_SPACE: - if (u != NEC_BIT_0_SPACE && u != NEC_BIT_1_SPACE) + if (ev.pulse) break; data->nec_bits <<= 1; - if (u == NEC_BIT_1_SPACE) + if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) data->nec_bits |= 1; + else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2)) + break; data->count++; - if (data->count != NEC_NBITS) { + if (data->count == NEC_NBITS) + data->state = STATE_TRAILER_PULSE; + else data->state = STATE_BIT_PULSE; - return 0; - } + + return 0; + + case STATE_TRAILER_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2)) + break; + + data->state = STATE_TRAILER_SPACE; + return 0; + + case STATE_TRAILER_SPACE: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2)) + break; address = bitrev8((data->nec_bits >> 24) & 0xff); not_address = bitrev8((data->nec_bits >> 16) & 0xff); @@ -210,34 +240,18 @@ static int ir_nec_decode(struct input_dev *input_dev, s64 duration) command; IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); } else { - /* normal NEC */ + /* Normal NEC */ scancode = address << 8 | command; IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); } ir_keydown(input_dev, scancode, 0); - data->state = STATE_TRAILER_PULSE; + data->state = STATE_INACTIVE; return 0; - - case STATE_TRAILER_PULSE: - if (u > 0) { - data->state = STATE_TRAILER_SPACE; - return 0; - } - break; - - case STATE_TRAILER_SPACE: - if (u < 0) { - data->state = STATE_INACTIVE; - return 0; - } - - break; } -out: - IR_dprintk(1, "NEC decode failed at state %d (%i units, %ius)\n", - data->state, u, TO_US(duration)); + IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state = STATE_INACTIVE; return -EINVAL; } diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 674442b2f0a8..59f173c45b9d 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -57,12 +57,12 @@ static struct work_struct wq_load; static void ir_raw_event_work(struct work_struct *work) { - s64 d; + struct ir_raw_event ev; struct ir_raw_event_ctrl *raw = container_of(work, struct ir_raw_event_ctrl, rx_work); - while (kfifo_out(&raw->kfifo, &d, sizeof(d)) == sizeof(d)) - RUN_DECODER(decode, raw->input_dev, d); + while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) + RUN_DECODER(decode, raw->input_dev, ev); } int ir_raw_event_register(struct input_dev *input_dev) @@ -114,21 +114,21 @@ void ir_raw_event_unregister(struct input_dev *input_dev) /** * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders * @input_dev: the struct input_dev device descriptor - * @duration: duration of the pulse or space in ns + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This routine (which may be called from an interrupt context) stores a * pulse/space duration for the raw ir decoding state machines. Pulses are * signalled as positive values and spaces as negative values. A zero value * will reset the decoding state machines. */ -int ir_raw_event_store(struct input_dev *input_dev, s64 duration) +int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) { struct ir_input_dev *ir = input_get_drvdata(input_dev); if (!ir->raw) return -EINVAL; - if (kfifo_in(&ir->raw->kfifo, &duration, sizeof(duration)) != sizeof(duration)) + if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) return -ENOMEM; return 0; @@ -151,6 +151,7 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ struct ir_input_dev *ir = input_get_drvdata(input_dev); ktime_t now; s64 delta; /* ns */ + struct ir_raw_event ev; int rc = 0; if (!ir->raw) @@ -163,16 +164,21 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ * being called for the first time, note that delta can't * possibly be negative. */ - if (delta > NSEC_PER_SEC || !ir->raw->last_type) + ev.duration = 0; + if (delta > IR_MAX_DURATION || !ir->raw->last_type) type |= IR_START_EVENT; + else + ev.duration = delta; if (type & IR_START_EVENT) ir_raw_event_reset(input_dev); - else if (ir->raw->last_type & IR_SPACE) - rc = ir_raw_event_store(input_dev, -delta); - else if (ir->raw->last_type & IR_PULSE) - rc = ir_raw_event_store(input_dev, delta); - else + else if (ir->raw->last_type & IR_SPACE) { + ev.pulse = false; + rc = ir_raw_event_store(input_dev, &ev); + } else if (ir->raw->last_type & IR_PULSE) { + ev.pulse = true; + rc = ir_raw_event_store(input_dev, &ev); + } else return 0; ir->raw->last_event = now; diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index dd5a4d5f25fd..23cdb1b1a3bc 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c @@ -25,8 +25,10 @@ #define RC5_NBITS 14 #define RC5X_NBITS 20 #define CHECK_RC5X_NBITS 8 -#define RC5X_SPACE SPACE(4) #define RC5_UNIT 888888 /* ns */ +#define RC5_BIT_START (1 * RC5_UNIT) +#define RC5_BIT_END (1 * RC5_UNIT) +#define RC5X_SPACE (4 * RC5_UNIT) /* Used to register rc5_decoder clients */ static LIST_HEAD(decoder_list); @@ -48,7 +50,7 @@ struct decoder_data { /* State machine control */ enum rc5_state state; u32 rc5_bits; - int last_unit; + struct ir_raw_event prev_ev; unsigned count; unsigned wanted_bits; }; @@ -124,17 +126,16 @@ static struct attribute_group decoder_attribute_group = { /** * ir_rc5_decode() - Decode one RC-5 pulse or space * @input_dev: the struct input_dev descriptor of the device - * @duration: duration of pulse/space in ns + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) +static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); u8 toggle; u32 scancode; - int u; data = get_decoder_data(ir_dev); if (!data) @@ -143,76 +144,65 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) if (!data->enabled) return 0; - if (IS_RESET(duration)) { + if (IS_RESET(ev)) { data->state = STATE_INACTIVE; return 0; } - u = TO_UNITS(duration, RC5_UNIT); - if (DURATION(u) == 0) + if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) goto out; again: - IR_dprintk(2, "RC5(x) decode started at state %i (%i units, %ius)\n", - data->state, u, TO_US(duration)); + IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - if (DURATION(u) == 0 && data->state != STATE_FINISHED) + if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2)) return 0; switch (data->state) { case STATE_INACTIVE: - if (IS_PULSE(u)) { - data->state = STATE_BIT_START; - data->count = 1; - /* We just need enough bits to get to STATE_CHECK_RC5X */ - data->wanted_bits = RC5X_NBITS; - DECREASE_DURATION(u, 1); - goto again; - } - break; + if (!ev.pulse) + break; + + data->state = STATE_BIT_START; + data->count = 1; + /* We just need enough bits to get to STATE_CHECK_RC5X */ + data->wanted_bits = RC5X_NBITS; + decrease_duration(&ev, RC5_BIT_START); + goto again; case STATE_BIT_START: - if (DURATION(u) == 1) { - data->rc5_bits <<= 1; - if (IS_SPACE(u)) - data->rc5_bits |= 1; - data->count++; - data->last_unit = u; - - /* - * If the last bit is zero, a space will merge - * with the silence after the command. - */ - if (IS_PULSE(u) && data->count == data->wanted_bits) { - data->state = STATE_FINISHED; - goto again; - } - - data->state = STATE_BIT_END; - return 0; - } - break; + if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2)) + break; + + data->rc5_bits <<= 1; + if (!ev.pulse) + data->rc5_bits |= 1; + data->count++; + data->prev_ev = ev; + data->state = STATE_BIT_END; + return 0; case STATE_BIT_END: - if (IS_TRANSITION(u, data->last_unit)) { - if (data->count == data->wanted_bits) - data->state = STATE_FINISHED; - else if (data->count == CHECK_RC5X_NBITS) - data->state = STATE_CHECK_RC5X; - else - data->state = STATE_BIT_START; - - DECREASE_DURATION(u, 1); - goto again; - } - break; + if (!is_transition(&ev, &data->prev_ev)) + break; + + if (data->count == data->wanted_bits) + data->state = STATE_FINISHED; + else if (data->count == CHECK_RC5X_NBITS) + data->state = STATE_CHECK_RC5X; + else + data->state = STATE_BIT_START; + + decrease_duration(&ev, RC5_BIT_END); + goto again; case STATE_CHECK_RC5X: - if (IS_SPACE(u) && DURATION(u) >= DURATION(RC5X_SPACE)) { + if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) { /* RC5X */ data->wanted_bits = RC5X_NBITS; - DECREASE_DURATION(u, DURATION(RC5X_SPACE)); + decrease_duration(&ev, RC5X_SPACE); } else { /* RC5 */ data->wanted_bits = RC5_NBITS; @@ -221,6 +211,9 @@ again: goto again; case STATE_FINISHED: + if (ev.pulse) + break; + if (data->wanted_bits == RC5X_NBITS) { /* RC5X */ u8 xdata, command, system; @@ -253,8 +246,8 @@ again: } out: - IR_dprintk(1, "RC5(x) decode failed at state %i (%i units, %ius)\n", - data->state, u, TO_US(duration)); + IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state = STATE_INACTIVE; return -EINVAL; } diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c index ccc5be240f82..2bf479f4f1bc 100644 --- a/drivers/media/IR/ir-rc6-decoder.c +++ b/drivers/media/IR/ir-rc6-decoder.c @@ -26,8 +26,12 @@ #define RC6_0_NBITS 16 #define RC6_6A_SMALL_NBITS 24 #define RC6_6A_LARGE_NBITS 32 -#define RC6_PREFIX_PULSE PULSE(6) -#define RC6_PREFIX_SPACE SPACE(2) +#define RC6_PREFIX_PULSE (6 * RC6_UNIT) +#define RC6_PREFIX_SPACE (2 * RC6_UNIT) +#define RC6_BIT_START (1 * RC6_UNIT) +#define RC6_BIT_END (1 * RC6_UNIT) +#define RC6_TOGGLE_START (2 * RC6_UNIT) +#define RC6_TOGGLE_END (2 * RC6_UNIT) #define RC6_MODE_MASK 0x07 /* for the header bits */ #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ @@ -63,7 +67,7 @@ struct decoder_data { enum rc6_state state; u8 header; u32 body; - int last_unit; + struct ir_raw_event prev_ev; bool toggle; unsigned count; unsigned wanted_bits; @@ -152,17 +156,16 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) { /** * ir_rc6_decode() - Decode one RC6 pulse or space * @input_dev: the struct input_dev descriptor of the device - * @duration: duration of pulse/space in ns + * @ev: the struct ir_raw_event descriptor of the pulse/space * * This function returns -EINVAL if the pulse violates the state machine */ -static int ir_rc6_decode(struct input_dev *input_dev, s64 duration) +static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) { struct decoder_data *data; struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); u32 scancode; u8 toggle; - int u; data = get_decoder_data(ir_dev); if (!data) @@ -171,140 +174,144 @@ static int ir_rc6_decode(struct input_dev *input_dev, s64 duration) if (!data->enabled) return 0; - if (IS_RESET(duration)) { + if (IS_RESET(ev)) { data->state = STATE_INACTIVE; return 0; } - u = TO_UNITS(duration, RC6_UNIT); - if (DURATION(u) == 0) + if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) goto out; again: - IR_dprintk(2, "RC6 decode started at state %i (%i units, %ius)\n", - data->state, u, TO_US(duration)); + IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); - if (DURATION(u) == 0 && data->state != STATE_FINISHED) + if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) return 0; switch (data->state) { case STATE_INACTIVE: - if (u >= RC6_PREFIX_PULSE - 1 && u <= RC6_PREFIX_PULSE + 1) { - data->state = STATE_PREFIX_SPACE; - data->count = 0; - return 0; - } - break; + if (!ev.pulse) + break; + + /* Note: larger margin on first pulse since each RC6_UNIT + is quite short and some hardware takes some time to + adjust to the signal */ + if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) + break; + + data->state = STATE_PREFIX_SPACE; + data->count = 0; + return 0; case STATE_PREFIX_SPACE: - if (u == RC6_PREFIX_SPACE) { - data->state = STATE_HEADER_BIT_START; - return 0; - } - break; + if (ev.pulse) + break; + + if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) + break; + + data->state = STATE_HEADER_BIT_START; + return 0; case STATE_HEADER_BIT_START: - if (DURATION(u) == 1) { - data->header <<= 1; - if (IS_PULSE(u)) - data->header |= 1; - data->count++; - data->last_unit = u; - data->state = STATE_HEADER_BIT_END; - return 0; - } - break; + if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) + break; + + data->header <<= 1; + if (ev.pulse) + data->header |= 1; + data->count++; + data->prev_ev = ev; + data->state = STATE_HEADER_BIT_END; + return 0; case STATE_HEADER_BIT_END: - if (IS_TRANSITION(u, data->last_unit)) { - if (data->count == RC6_HEADER_NBITS) - data->state = STATE_TOGGLE_START; - else - data->state = STATE_HEADER_BIT_START; + if (!is_transition(&ev, &data->prev_ev)) + break; - DECREASE_DURATION(u, 1); - goto again; - } - break; + if (data->count == RC6_HEADER_NBITS) + data->state = STATE_TOGGLE_START; + else + data->state = STATE_HEADER_BIT_START; + + decrease_duration(&ev, RC6_BIT_END); + goto again; case STATE_TOGGLE_START: - if (DURATION(u) == 2) { - data->toggle = IS_PULSE(u); - data->last_unit = u; - data->state = STATE_TOGGLE_END; - return 0; - } - break; + if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) + break; + + data->toggle = ev.pulse; + data->prev_ev = ev; + data->state = STATE_TOGGLE_END; + return 0; case STATE_TOGGLE_END: - if (IS_TRANSITION(u, data->last_unit) && DURATION(u) >= 2) { - data->state = STATE_BODY_BIT_START; - data->last_unit = u; - DECREASE_DURATION(u, 2); - data->count = 0; + if (!is_transition(&ev, &data->prev_ev) || + !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) + break; - if (!(data->header & RC6_STARTBIT_MASK)) { - IR_dprintk(1, "RC6 invalid start bit\n"); - break; - } + if (!(data->header & RC6_STARTBIT_MASK)) { + IR_dprintk(1, "RC6 invalid start bit\n"); + break; + } - switch (rc6_mode(data)) { - case RC6_MODE_0: - data->wanted_bits = RC6_0_NBITS; - break; - case RC6_MODE_6A: - /* This might look weird, but we basically - check the value of the first body bit to - determine the number of bits in mode 6A */ - if ((DURATION(u) == 0 && IS_SPACE(data->last_unit)) || DURATION(u) > 0) - data->wanted_bits = RC6_6A_LARGE_NBITS; - else - data->wanted_bits = RC6_6A_SMALL_NBITS; - break; - default: - IR_dprintk(1, "RC6 unknown mode\n"); - goto out; - } - goto again; + data->state = STATE_BODY_BIT_START; + data->prev_ev = ev; + decrease_duration(&ev, RC6_TOGGLE_END); + data->count = 0; + + switch (rc6_mode(data)) { + case RC6_MODE_0: + data->wanted_bits = RC6_0_NBITS; + break; + case RC6_MODE_6A: + /* This might look weird, but we basically + check the value of the first body bit to + determine the number of bits in mode 6A */ + if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || + geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) + data->wanted_bits = RC6_6A_LARGE_NBITS; + else + data->wanted_bits = RC6_6A_SMALL_NBITS; + break; + default: + IR_dprintk(1, "RC6 unknown mode\n"); + goto out; } - break; + goto again; case STATE_BODY_BIT_START: - if (DURATION(u) == 1) { - data->body <<= 1; - if (IS_PULSE(u)) - data->body |= 1; - data->count++; - data->last_unit = u; - - /* - * If the last bit is one, a space will merge - * with the silence after the command. - */ - if (IS_PULSE(u) && data->count == data->wanted_bits) { - data->state = STATE_FINISHED; - goto again; - } + if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) + break; - data->state = STATE_BODY_BIT_END; - return 0; - } - break; + data->body <<= 1; + if (ev.pulse) + data->body |= 1; + data->count++; + data->prev_ev = ev; + + data->state = STATE_BODY_BIT_END; + return 0; case STATE_BODY_BIT_END: - if (IS_TRANSITION(u, data->last_unit)) { - if (data->count == data->wanted_bits) - data->state = STATE_FINISHED; - else - data->state = STATE_BODY_BIT_START; + if (!is_transition(&ev, &data->prev_ev)) + break; - DECREASE_DURATION(u, 1); - goto again; - } - break; + if (data->count == data->wanted_bits) + data->state = STATE_FINISHED; + else + data->state = STATE_BODY_BIT_START; + + decrease_duration(&ev, RC6_BIT_END); + goto again; case STATE_FINISHED: + if (ev.pulse) + break; + switch (rc6_mode(data)) { case RC6_MODE_0: scancode = data->body & 0xffff; @@ -335,8 +342,8 @@ again: } out: - IR_dprintk(1, "RC6 decode failed at state %i (%i units, %ius)\n", - data->state, u, TO_US(duration)); + IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state = STATE_INACTIVE; return -EINVAL; } -- cgit v1.2.3 From 384f23e8c9b189888d6d8c84ae5ebd23b074a0b6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 20 Apr 2010 18:50:54 -0300 Subject: V4L/DVB: ir-core-priv.h: Fix a few CodingStyle errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As reported by checkpatch.pl: ERROR: open brace '{' following function declarations go on the next line +static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) { ERROR: open brace '{' following function declarations go on the next line +static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) { ERROR: open brace '{' following function declarations go on the next line +static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) { Cc: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-core-priv.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index 77d0b94ede10..f965024385d8 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -36,19 +36,23 @@ struct ir_raw_event_ctrl { }; /* macros for IR decoders */ -static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) { +static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) +{ return d1 > (d2 - margin); } -static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) { +static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) +{ return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); } -static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) { +static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) +{ return x->pulse != y->pulse; } -static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) { +static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) +{ if (duration > ev->duration) ev->duration = 0; else -- cgit v1.2.3 From bf670f641d478fa5a2dd60ed41bab3156cc780c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 15 Apr 2010 18:46:05 -0300 Subject: V4L/DVB: ir-core: Add JVC support to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a JVC decoder to ir-core. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 9 ++ drivers/media/IR/Makefile | 1 + drivers/media/IR/ir-core-priv.h | 7 + drivers/media/IR/ir-jvc-decoder.c | 320 ++++++++++++++++++++++++++++++++++++++ drivers/media/IR/ir-raw-event.c | 1 + drivers/media/IR/ir-sysfs.c | 4 + 6 files changed, 342 insertions(+) create mode 100644 drivers/media/IR/ir-jvc-decoder.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index dae5ea113867..e87242af9b35 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -37,6 +37,15 @@ config IR_RC6_DECODER Enable this option if you have an infrared remote control which uses the RC6 protocol, and you need software decoding support. +config IR_JVC_DECODER + tristate "Enable IR raw decoder for the JVC protocol" + depends on IR_CORE + default y + + ---help--- + Enable this option if you have an infrared remote control which + uses the JVC protocol, and you need software decoding support. + config IR_IMON tristate "SoundGraph iMON Receiver and Display" depends on USB_ARCH_HAS_HCD diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 57b145515d4f..937cbdedc7c1 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_IR) += ir-common.o obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o +obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o # stand-alone IR receivers/transmitters obj-$(CONFIG_IR_IMON) += imon.o diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index f965024385d8..464e392f24cf 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -109,4 +109,11 @@ void ir_raw_init(void); #define load_rc6_decode() 0 #endif +/* from ir-jvc-decoder.c */ +#ifdef CONFIG_IR_JVC_DECODER_MODULE +#define load_jvc_decode() request_module("ir-jvc-decoder") +#else +#define load_jvc_decode() 0 +#endif + #endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c new file mode 100644 index 000000000000..0b804944cbb0 --- /dev/null +++ b/drivers/media/IR/ir-jvc-decoder.c @@ -0,0 +1,320 @@ +/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol + * + * Copyright (C) 2010 by David Härdeman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "ir-core-priv.h" + +#define JVC_NBITS 16 /* dev(8) + func(8) */ +#define JVC_UNIT 525000 /* ns */ +#define JVC_HEADER_PULSE (16 * JVC_UNIT) /* lack of header -> repeat */ +#define JVC_HEADER_SPACE (8 * JVC_UNIT) +#define JVC_BIT_PULSE (1 * JVC_UNIT) +#define JVC_BIT_0_SPACE (1 * JVC_UNIT) +#define JVC_BIT_1_SPACE (3 * JVC_UNIT) +#define JVC_TRAILER_PULSE (1 * JVC_UNIT) +#define JVC_TRAILER_SPACE (35 * JVC_UNIT) + +/* Used to register jvc_decoder clients */ +static LIST_HEAD(decoder_list); +DEFINE_SPINLOCK(decoder_lock); + +enum jvc_state { + STATE_INACTIVE, + STATE_HEADER_SPACE, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_TRAILER_PULSE, + STATE_TRAILER_SPACE, +}; + +struct decoder_data { + struct list_head list; + struct ir_input_dev *ir_dev; + int enabled:1; + + /* State machine control */ + enum jvc_state state; + u16 jvc_bits; + u16 jvc_old_bits; + unsigned count; + bool first; + bool toggle; +}; + + +/** + * get_decoder_data() - gets decoder data + * @input_dev: input device + * + * Returns the struct decoder_data that corresponds to a device + */ +static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) +{ + struct decoder_data *data = NULL; + + spin_lock(&decoder_lock); + list_for_each_entry(data, &decoder_list, list) { + if (data->ir_dev == ir_dev) + break; + } + spin_unlock(&decoder_lock); + return data; +} + +static ssize_t store_enabled(struct device *d, + struct device_attribute *mattr, + const char *buf, + size_t len) +{ + unsigned long value; + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (strict_strtoul(buf, 10, &value) || value > 1) + return -EINVAL; + + data->enabled = value; + + return len; +} + +static ssize_t show_enabled(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (data->enabled) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); + +static struct attribute *decoder_attributes[] = { + &dev_attr_enabled.attr, + NULL +}; + +static struct attribute_group decoder_attribute_group = { + .name = "jvc_decoder", + .attrs = decoder_attributes, +}; + +/** + * ir_jvc_decode() - Decode one JVC pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @duration: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct decoder_data *data; + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + + data = get_decoder_data(ir_dev); + if (!data) + return -EINVAL; + + if (!data->enabled) + return 0; + + if (IS_RESET(ev)) { + data->state = STATE_INACTIVE; + return 0; + } + + if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2)) + goto out; + + IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2)) + break; + + data->count = 0; + data->first = true; + data->toggle = !data->toggle; + data->state = STATE_HEADER_SPACE; + return 0; + + case STATE_HEADER_SPACE: + if (ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2)) + break; + + data->state = STATE_BIT_PULSE; + return 0; + + case STATE_BIT_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2)) + break; + + data->state = STATE_BIT_SPACE; + return 0; + + case STATE_BIT_SPACE: + if (ev.pulse) + break; + + data->jvc_bits <<= 1; + if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) { + data->jvc_bits |= 1; + decrease_duration(&ev, JVC_BIT_1_SPACE); + } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2)) + decrease_duration(&ev, JVC_BIT_0_SPACE); + else + break; + data->count++; + + if (data->count == JVC_NBITS) + data->state = STATE_TRAILER_PULSE; + else + data->state = STATE_BIT_PULSE; + return 0; + + case STATE_TRAILER_PULSE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2)) + break; + + data->state = STATE_TRAILER_SPACE; + return 0; + + case STATE_TRAILER_SPACE: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2)) + break; + + if (data->first) { + u32 scancode; + scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) | + (bitrev8((data->jvc_bits >> 0) & 0xff) << 0); + IR_dprintk(1, "JVC scancode 0x%04x\n", scancode); + ir_keydown(input_dev, scancode, data->toggle); + data->first = false; + data->jvc_old_bits = data->jvc_bits; + } else if (data->jvc_bits == data->jvc_old_bits) { + IR_dprintk(1, "JVC repeat\n"); + ir_repeat(input_dev); + } else { + IR_dprintk(1, "JVC invalid repeat msg\n"); + break; + } + + data->count = 0; + data->state = STATE_BIT_PULSE; + return 0; + } + +out: + IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static int ir_jvc_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct decoder_data *data; + int rc; + + rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); + if (rc < 0) + return rc; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + return -ENOMEM; + } + + data->ir_dev = ir_dev; + data->enabled = 1; + + spin_lock(&decoder_lock); + list_add_tail(&data->list, &decoder_list); + spin_unlock(&decoder_lock); + + return 0; +} + +static int ir_jvc_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + static struct decoder_data *data; + + data = get_decoder_data(ir_dev); + if (!data) + return 0; + + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + + spin_lock(&decoder_lock); + list_del(&data->list); + spin_unlock(&decoder_lock); + + return 0; +} + +static struct ir_raw_handler jvc_handler = { + .decode = ir_jvc_decode, + .raw_register = ir_jvc_register, + .raw_unregister = ir_jvc_unregister, +}; + +static int __init ir_jvc_decode_init(void) +{ + ir_raw_handler_register(&jvc_handler); + + printk(KERN_INFO "IR JVC protocol handler initialized\n"); + return 0; +} + +static void __exit ir_jvc_decode_exit(void) +{ + ir_raw_handler_unregister(&jvc_handler); +} + +module_init(ir_jvc_decode_init); +module_exit(ir_jvc_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("JVC IR protocol decoder"); diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 59f173c45b9d..7eef6bf4404f 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -233,6 +233,7 @@ static void init_decoders(struct work_struct *work) load_nec_decode(); load_rc5_decode(); load_rc6_decode(); + load_jvc_decode(); /* If needed, we may later add some init code. In this case, it is needed to change the CONFIG_MODULE test at ir-core.h diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index ceec980552a4..3ec760a98061 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -63,6 +63,8 @@ static ssize_t show_protocol(struct device *d, s = "nec"; else if (ir_type == IR_TYPE_RC6) s = "rc6"; + else if (ir_type == IR_TYPE_JVC) + s = "jvc"; else s = "other"; @@ -100,6 +102,8 @@ static ssize_t store_protocol(struct device *d, ir_type |= IR_TYPE_PD; if (!strcasecmp(buf, "nec")) ir_type |= IR_TYPE_NEC; + if (!strcasecmp(buf, "jvc")) + ir_type |= IR_TYPE_JVC; } if (!ir_type) { -- cgit v1.2.3 From 3fe29c897272b18e18663832c43942c3936dffe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 15 Apr 2010 18:46:10 -0300 Subject: V4L/DVB: ir-core: Add Sony support to ir-core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a Sony12/15/20 decoder to ir-core. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/Kconfig | 9 ++ drivers/media/IR/Makefile | 1 + drivers/media/IR/ir-core-priv.h | 7 + drivers/media/IR/ir-raw-event.c | 1 + drivers/media/IR/ir-sony-decoder.c | 312 +++++++++++++++++++++++++++++++++++++ drivers/media/IR/ir-sysfs.c | 4 + 6 files changed, 334 insertions(+) create mode 100644 drivers/media/IR/ir-sony-decoder.c (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig index e87242af9b35..195c6cf359f6 100644 --- a/drivers/media/IR/Kconfig +++ b/drivers/media/IR/Kconfig @@ -46,6 +46,15 @@ config IR_JVC_DECODER Enable this option if you have an infrared remote control which uses the JVC protocol, and you need software decoding support. +config IR_SONY_DECODER + tristate "Enable IR raw decoder for the Sony protocol" + depends on IR_CORE + default y + + ---help--- + Enable this option if you have an infrared remote control which + uses the Sony protocol, and you need software decoding support. + config IR_IMON tristate "SoundGraph iMON Receiver and Display" depends on USB_ARCH_HAS_HCD diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile index 937cbdedc7c1..b998fcced2e4 100644 --- a/drivers/media/IR/Makefile +++ b/drivers/media/IR/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o +obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o # stand-alone IR receivers/transmitters obj-$(CONFIG_IR_IMON) += imon.o diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h index 464e392f24cf..9a5e65a471a5 100644 --- a/drivers/media/IR/ir-core-priv.h +++ b/drivers/media/IR/ir-core-priv.h @@ -116,4 +116,11 @@ void ir_raw_init(void); #define load_jvc_decode() 0 #endif +/* from ir-sony-decoder.c */ +#ifdef CONFIG_IR_SONY_DECODER_MODULE +#define load_sony_decode() request_module("ir-sony-decoder") +#else +#define load_sony_decode() 0 +#endif + #endif /* _IR_RAW_EVENT */ diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 7eef6bf4404f..ea68a3f2effa 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -234,6 +234,7 @@ static void init_decoders(struct work_struct *work) load_rc5_decode(); load_rc6_decode(); load_jvc_decode(); + load_sony_decode(); /* If needed, we may later add some init code. In this case, it is needed to change the CONFIG_MODULE test at ir-core.h diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c new file mode 100644 index 000000000000..9f440c5c060d --- /dev/null +++ b/drivers/media/IR/ir-sony-decoder.c @@ -0,0 +1,312 @@ +/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol + * + * Copyright (C) 2010 by David Härdeman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "ir-core-priv.h" + +#define SONY_UNIT 600000 /* ns */ +#define SONY_HEADER_PULSE (4 * SONY_UNIT) +#define SONY_HEADER_SPACE (1 * SONY_UNIT) +#define SONY_BIT_0_PULSE (1 * SONY_UNIT) +#define SONY_BIT_1_PULSE (2 * SONY_UNIT) +#define SONY_BIT_SPACE (1 * SONY_UNIT) +#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */ + +/* Used to register sony_decoder clients */ +static LIST_HEAD(decoder_list); +static DEFINE_SPINLOCK(decoder_lock); + +enum sony_state { + STATE_INACTIVE, + STATE_HEADER_SPACE, + STATE_BIT_PULSE, + STATE_BIT_SPACE, + STATE_FINISHED, +}; + +struct decoder_data { + struct list_head list; + struct ir_input_dev *ir_dev; + int enabled:1; + + /* State machine control */ + enum sony_state state; + u32 sony_bits; + unsigned count; +}; + + +/** + * get_decoder_data() - gets decoder data + * @input_dev: input device + * + * Returns the struct decoder_data that corresponds to a device + */ +static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) +{ + struct decoder_data *data = NULL; + + spin_lock(&decoder_lock); + list_for_each_entry(data, &decoder_list, list) { + if (data->ir_dev == ir_dev) + break; + } + spin_unlock(&decoder_lock); + return data; +} + +static ssize_t store_enabled(struct device *d, + struct device_attribute *mattr, + const char *buf, + size_t len) +{ + unsigned long value; + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (strict_strtoul(buf, 10, &value) || value > 1) + return -EINVAL; + + data->enabled = value; + + return len; +} + +static ssize_t show_enabled(struct device *d, + struct device_attribute *mattr, char *buf) +{ + struct ir_input_dev *ir_dev = dev_get_drvdata(d); + struct decoder_data *data = get_decoder_data(ir_dev); + + if (!data) + return -EINVAL; + + if (data->enabled) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); + +static struct attribute *decoder_attributes[] = { + &dev_attr_enabled.attr, + NULL +}; + +static struct attribute_group decoder_attribute_group = { + .name = "sony_decoder", + .attrs = decoder_attributes, +}; + +/** + * ir_sony_decode() - Decode one Sony pulse or space + * @input_dev: the struct input_dev descriptor of the device + * @ev: the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) +{ + struct decoder_data *data; + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + u32 scancode; + u8 device, subdevice, function; + + data = get_decoder_data(ir_dev); + if (!data) + return -EINVAL; + + if (!data->enabled) + return 0; + + if (IS_RESET(ev)) { + data->state = STATE_INACTIVE; + return 0; + } + + if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) + goto out; + + IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + + switch (data->state) { + + case STATE_INACTIVE: + if (!ev.pulse) + break; + + if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2)) + break; + + data->count = 0; + data->state = STATE_HEADER_SPACE; + return 0; + + case STATE_HEADER_SPACE: + if (ev.pulse) + break; + + if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2)) + break; + + data->state = STATE_BIT_PULSE; + return 0; + + case STATE_BIT_PULSE: + if (!ev.pulse) + break; + + data->sony_bits <<= 1; + if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2)) + data->sony_bits |= 1; + else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2)) + break; + + data->count++; + data->state = STATE_BIT_SPACE; + return 0; + + case STATE_BIT_SPACE: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2)) + break; + + decrease_duration(&ev, SONY_BIT_SPACE); + + if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) { + data->state = STATE_BIT_PULSE; + return 0; + } + + data->state = STATE_FINISHED; + /* Fall through */ + + case STATE_FINISHED: + if (ev.pulse) + break; + + if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2)) + break; + + switch (data->count) { + case 12: + device = bitrev8((data->sony_bits << 3) & 0xF8); + subdevice = 0; + function = bitrev8((data->sony_bits >> 4) & 0xFE); + break; + case 15: + device = bitrev8((data->sony_bits >> 0) & 0xFF); + subdevice = 0; + function = bitrev8((data->sony_bits >> 7) & 0xFD); + break; + case 20: + device = bitrev8((data->sony_bits >> 5) & 0xF8); + subdevice = bitrev8((data->sony_bits >> 0) & 0xFF); + function = bitrev8((data->sony_bits >> 12) & 0xFE); + break; + default: + IR_dprintk(1, "Sony invalid bitcount %u\n", data->count); + goto out; + } + + scancode = device << 16 | subdevice << 8 | function; + IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode); + ir_keydown(input_dev, scancode, 0); + data->state = STATE_INACTIVE; + return 0; + } + +out: + IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n", + data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + data->state = STATE_INACTIVE; + return -EINVAL; +} + +static int ir_sony_register(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + struct decoder_data *data; + int rc; + + rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); + if (rc < 0) + return rc; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + return -ENOMEM; + } + + data->ir_dev = ir_dev; + data->enabled = 1; + + spin_lock(&decoder_lock); + list_add_tail(&data->list, &decoder_list); + spin_unlock(&decoder_lock); + + return 0; +} + +static int ir_sony_unregister(struct input_dev *input_dev) +{ + struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); + static struct decoder_data *data; + + data = get_decoder_data(ir_dev); + if (!data) + return 0; + + sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); + + spin_lock(&decoder_lock); + list_del(&data->list); + spin_unlock(&decoder_lock); + + return 0; +} + +static struct ir_raw_handler sony_handler = { + .decode = ir_sony_decode, + .raw_register = ir_sony_register, + .raw_unregister = ir_sony_unregister, +}; + +static int __init ir_sony_decode_init(void) +{ + ir_raw_handler_register(&sony_handler); + + printk(KERN_INFO "IR Sony protocol handler initialized\n"); + return 0; +} + +static void __exit ir_sony_decode_exit(void) +{ + ir_raw_handler_unregister(&sony_handler); +} + +module_init(ir_sony_decode_init); +module_exit(ir_sony_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Härdeman "); +MODULE_DESCRIPTION("Sony IR protocol decoder"); diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 3ec760a98061..4c0bc32dcbaf 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -65,6 +65,8 @@ static ssize_t show_protocol(struct device *d, s = "rc6"; else if (ir_type == IR_TYPE_JVC) s = "jvc"; + else if (ir_type == IR_TYPE_SONY) + s = "sony"; else s = "other"; @@ -104,6 +106,8 @@ static ssize_t store_protocol(struct device *d, ir_type |= IR_TYPE_NEC; if (!strcasecmp(buf, "jvc")) ir_type |= IR_TYPE_JVC; + if (!strcasecmp(buf, "sony")) + ir_type |= IR_TYPE_SONY; } if (!ir_type) { -- cgit v1.2.3 From 1f71baef3edd8ba27f38f92da457950e52d88b5f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 20 Apr 2010 19:11:30 -0300 Subject: V4L/DVB: irmon: Cleanup some warning noise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driver is not properly initializing u64 constants on 32 bit systems: drivers/media/IR/imon.c:301: warning: integer constant is too large for ‘long’ type drivers/media/IR/imon.c:302: warning: integer constant is too large for ‘long’ type drivers/media/IR/imon.c:304: warning: integer constant is too large for ‘long’ type drivers/media/IR/imon.c:305: warning: integer constant is too large for ‘long’ type drivers/media/IR/imon.c:308: warning: integer constant is too large for ‘long’ type drivers/media/IR/imon.c:309: warning: integer constant is too large for ‘long’ type drivers/media/IR/imon.c:310: warning: integer constant is too large for ‘long’ type Fix also a few troubles at error printk handling: drivers/media/IR/imon.c: In function ‘imon_init_intf0’: drivers/media/IR/imon.c:1909: warning: ‘ret’ may be used uninitialized in this function drivers/media/IR/imon.c: In function ‘imon_init_intf1’: drivers/media/IR/imon.c:1989: warning: ‘ret’ may be used uninitialized in this function Cc: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 52 +++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index 170fb9f2ca26..d941b98eed3e 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -286,28 +286,28 @@ static const struct { u64 hw_code; u32 keycode; } imon_panel_key_table[] = { - { 0x000000000f00ffee, KEY_PROG1 }, /* Go */ - { 0x000000001f00ffee, KEY_AUDIO }, - { 0x000000002000ffee, KEY_VIDEO }, - { 0x000000002100ffee, KEY_CAMERA }, - { 0x000000002700ffee, KEY_DVD }, - { 0x000000002300ffee, KEY_TV }, - { 0x000000000500ffee, KEY_PREVIOUS }, - { 0x000000000700ffee, KEY_REWIND }, - { 0x000000000400ffee, KEY_STOP }, - { 0x000000003c00ffee, KEY_PLAYPAUSE }, - { 0x000000000800ffee, KEY_FASTFORWARD }, - { 0x000000000600ffee, KEY_NEXT }, - { 0x000000010000ffee, KEY_RIGHT }, - { 0x000001000000ffee, KEY_LEFT }, - { 0x000000003d00ffee, KEY_SELECT }, - { 0x000100000000ffee, KEY_VOLUMEUP }, - { 0x010000000000ffee, KEY_VOLUMEDOWN }, - { 0x000000000100ffee, KEY_MUTE }, + { 0x000000000f00ffeell, KEY_PROG1 }, /* Go */ + { 0x000000001f00ffeell, KEY_AUDIO }, + { 0x000000002000ffeell, KEY_VIDEO }, + { 0x000000002100ffeell, KEY_CAMERA }, + { 0x000000002700ffeell, KEY_DVD }, + { 0x000000002300ffeell, KEY_TV }, + { 0x000000000500ffeell, KEY_PREVIOUS }, + { 0x000000000700ffeell, KEY_REWIND }, + { 0x000000000400ffeell, KEY_STOP }, + { 0x000000003c00ffeell, KEY_PLAYPAUSE }, + { 0x000000000800ffeell, KEY_FASTFORWARD }, + { 0x000000000600ffeell, KEY_NEXT }, + { 0x000000010000ffeell, KEY_RIGHT }, + { 0x000001000000ffeell, KEY_LEFT }, + { 0x000000003d00ffeell, KEY_SELECT }, + { 0x000100000000ffeell, KEY_VOLUMEUP }, + { 0x010000000000ffeell, KEY_VOLUMEDOWN }, + { 0x000000000100ffeell, KEY_MUTE }, /* iMON Knob values */ - { 0x000100ffffffffee, KEY_VOLUMEUP }, - { 0x010000ffffffffee, KEY_VOLUMEDOWN }, - { 0x000008ffffffffee, KEY_MUTE }, + { 0x000100ffffffffeell, KEY_VOLUMEUP }, + { 0x010000ffffffffeell, KEY_VOLUMEDOWN }, + { 0x000008ffffffffeell, KEY_MUTE }, }; /* to prevent races between open() and disconnect(), probing, etc */ @@ -1906,7 +1906,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) struct urb *tx_urb; struct device *dev = &intf->dev; struct usb_host_interface *iface_desc; - int ret; + int ret = -ENOMEM; ictx = kzalloc(sizeof(struct imon_context), GFP_KERNEL); if (!ictx) { @@ -1938,9 +1938,11 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) ictx->vendor = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor); ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct); + ret = -ENODEV; iface_desc = intf->cur_altsetting; - if (!imon_find_endpoints(ictx, iface_desc)) + if (!imon_find_endpoints(ictx, iface_desc)) { goto find_endpoint_failed; + } ictx->idev = imon_init_idev(ictx); if (!ictx->idev) { @@ -1986,12 +1988,11 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf, { struct urb *rx_urb; struct usb_host_interface *iface_desc; - int ret; + int ret = -ENOMEM; rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!rx_urb) { err("%s: usb_alloc_urb failed for IR urb", __func__); - ret = -ENOMEM; goto rx_urb_alloc_failed; } @@ -2007,6 +2008,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf, ictx->dev_present_intf1 = 1; ictx->rx_urb_intf1 = rx_urb; + ret = -ENODEV; iface_desc = intf->cur_altsetting; if (!imon_find_endpoints(ictx, iface_desc)) goto find_endpoint_failed; -- cgit v1.2.3 From d46844300ccd99444d32e481751b6508c8c7834e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 15 Apr 2010 18:46:25 -0300 Subject: V4L/DVB: ir-core: fix double spinlock init in drivers/media/IR/rc-map.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a double initialization of the same spinlock in drivers/media/IR/rc-map.c. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 2 -- drivers/media/IR/rc-map.c | 5 ----- 2 files changed, 7 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 4c0bc32dcbaf..18cab0f59fdd 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -295,8 +295,6 @@ static int __init ir_core_init(void) /* Initialize/load the decoders/keymap code that will be used */ ir_raw_init(); - rc_map_init(); - return 0; } diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index 1a3f4b123a37..caf6a27b08c2 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c @@ -81,8 +81,3 @@ void ir_unregister_map(struct rc_keymap *map) } EXPORT_SYMBOL_GPL(ir_unregister_map); -void rc_map_init(void) -{ - spin_lock_init(&rc_map_lock); - -} -- cgit v1.2.3 From 42880cd438d6e74b6005648a7dc06867d4b30b44 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 May 2010 02:06:06 -0300 Subject: V4L/DVB: ir-core: fix table resize during keymap init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/IR/ir-keytable.c would alloc a suitably sized keymap table only to have it resized as it is populated with the initial keymap. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 1bb4e32f3dc3..ebe24579bf32 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -78,6 +78,7 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab) * @rc_tab: the struct ir_scancode_table to set the keycode in * @scancode: the scancode for the ir command * @keycode: the keycode for the ir command + * @resize: whether the keytable may be shrunk * @return: -EINVAL if the keycode could not be inserted, otherwise zero. * * This routine is used internally to manipulate the scancode->keycode table. @@ -85,7 +86,8 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab) */ static int ir_do_setkeycode(struct input_dev *dev, struct ir_scancode_table *rc_tab, - unsigned scancode, unsigned keycode) + unsigned scancode, unsigned keycode, + bool resize) { unsigned int i; int old_keycode = KEY_RESERVED; @@ -129,7 +131,7 @@ static int ir_do_setkeycode(struct input_dev *dev, if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) { /* No previous mapping found, we might need to grow the table */ - if (ir_resize_table(rc_tab)) + if (resize && ir_resize_table(rc_tab)) return -ENOMEM; IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n", @@ -177,7 +179,7 @@ static int ir_setkeycode(struct input_dev *dev, struct ir_scancode_table *rc_tab = &ir_dev->rc_tab; spin_lock_irqsave(&rc_tab->lock, flags); - rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode); + rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true); spin_unlock_irqrestore(&rc_tab->lock, flags); return rc; } @@ -204,7 +206,7 @@ static int ir_setkeytable(struct input_dev *dev, spin_lock_irqsave(&rc_tab->lock, flags); for (i = 0; i < from->size; i++) { rc = ir_do_setkeycode(dev, to, from->scan[i].scancode, - from->scan[i].keycode); + from->scan[i].keycode, false); if (rc) break; } -- cgit v1.2.3 From dd3f616d4b60a50328be152f66c93bd451461a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Thu, 15 Apr 2010 18:46:35 -0300 Subject: V4L/DVB: ir-core: fix some confusing comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix some confusing comments in drivers/media/IR/* Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 2 +- drivers/media/IR/ir-sysfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index ebe24579bf32..9374a006f43d 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -1,4 +1,4 @@ -/* ir-register.c - handle IR scancode->keycode tables +/* ir-keytable.c - handle IR scancode->keycode tables * * Copyright (C) 2009 by Mauro Carvalho Chehab * diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 18cab0f59fdd..002b14123319 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -1,4 +1,4 @@ -/* ir-register.c - handle IR scancode->keycode tables +/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc) * * Copyright (C) 2009-2010 by Mauro Carvalho Chehab * -- cgit v1.2.3 From 6718e8ad950f73fc895b98a413a63cb2add3b4d2 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 23 Apr 2010 02:27:11 -0300 Subject: V4L/DVB: IR/imon: convert to ir-core protocol change handling Drop the imon driver's internal protocol definitions in favor of using those provided by ir-core. Should make ir-keytable Just Work for switching protocol on the fly on the imon devices that support both the native imon remotes and mce remotes. The imon-no-pad-stabilize pseudo-protocol was dropped as a protocol, and converted to a separate modprobe option (which it probably should have been in the first place). On the TODO list is to convert this to an as yet unwritten protocol-specific options framework. While the mce remotes obviously map to IR_TYPE_RC6, I've yet to look at what the actual ir signals from the native imon remotes are, so for the moment, imon native ir is mapped to IR_TYPE_OTHER. Nailing it down more accurately is also on the TODO list. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 151 ++++++++++++++------------------- drivers/media/IR/keymaps/rc-imon-mce.c | 4 +- drivers/media/IR/keymaps/rc-imon-pad.c | 3 +- 3 files changed, 69 insertions(+), 89 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index d941b98eed3e..b65c31ab4a4f 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -127,8 +127,7 @@ struct imon_context { u32 kc; /* current input keycode */ u32 last_keycode; /* last reported input keycode */ - u8 ir_protocol; /* iMON or MCE (RC6) IR protocol? */ - u8 ir_proto_mask; /* supported IR protocol mask */ + u64 ir_type; /* iMON or MCE (RC6) IR protocol? */ u8 mce_toggle_bit; /* last mce toggle bit */ bool release_code; /* some keys send a release code */ @@ -173,20 +172,6 @@ enum { IMON_DISPLAY_TYPE_NONE = 4, }; -enum { - IMON_IR_PROTOCOL_AUTO = 0x0, - IMON_IR_PROTOCOL_MCE = 0x1, - IMON_IR_PROTOCOL_IMON = 0x2, - IMON_IR_PROTOCOL_IMON_NOPAD = 0x4, -}; - -enum { - IMON_IR_PROTO_MASK_NONE = 0x0, - IMON_IR_PROTO_MASK_MCE = IMON_IR_PROTOCOL_MCE, - IMON_IR_PROTO_MASK_IMON = IMON_IR_PROTOCOL_IMON | - IMON_IR_PROTOCOL_IMON_NOPAD, -}; - enum { IMON_KEY_IMON = 0, IMON_KEY_MCE = 1, @@ -330,12 +315,10 @@ module_param(display_type, int, S_IRUGO); MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, " "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)"); -/* IR protocol: native iMON, Windows MCE (RC-6), or iMON w/o PAD stabilize */ -static int ir_protocol; -module_param(ir_protocol, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ir_protocol, "Which IR protocol to use. 0=auto-detect, " - "1=Windows Media Center Ed. (RC-6), 2=iMON native, " - "4=iMON w/o PAD stabilize (default: auto-detect)"); +static int pad_stabilize = 1; +module_param(pad_stabilize, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD " + "presses in arrow key mode. 0=disable, 1=enable (default)."); /* * In certain use cases, mouse mode isn't really helpful, and could actually @@ -1007,72 +990,67 @@ static void imon_touch_display_timeout(unsigned long data) * really just RC-6), but only one or the other at a time, as the signals * are decoded onboard the receiver. */ -static void imon_set_ir_protocol(struct imon_context *ictx) +int imon_ir_change_protocol(void *priv, u64 ir_type) { int retval; + struct imon_context *ictx = priv; struct device *dev = ictx->dev; + bool pad_mouse; unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; - if (ir_protocol && !(ir_protocol & ictx->ir_proto_mask)) + if (!(ir_type & ictx->props->allowed_protos)) dev_warn(dev, "Looks like you're trying to use an IR protocol " "this device does not support\n"); - switch (ir_protocol) { - case IMON_IR_PROTOCOL_AUTO: - if (ictx->product == 0xffdc) { - if (ictx->ir_proto_mask & IMON_IR_PROTO_MASK_MCE) { - ir_proto_packet[0] = 0x01; - ictx->ir_protocol = IMON_IR_PROTOCOL_MCE; - ictx->pad_mouse = 0; - init_timer(&ictx->itimer); - ictx->itimer.data = (unsigned long)ictx; - ictx->itimer.function = imon_mce_timeout; - } else { - ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; - ictx->pad_mouse = 1; - } - } - break; - case IMON_IR_PROTOCOL_MCE: + switch (ir_type) { + case IR_TYPE_RC6: dev_dbg(dev, "Configuring IR receiver for MCE protocol\n"); ir_proto_packet[0] = 0x01; - ictx->ir_protocol = IMON_IR_PROTOCOL_MCE; - ictx->pad_mouse = 0; + pad_mouse = false; init_timer(&ictx->itimer); ictx->itimer.data = (unsigned long)ictx; ictx->itimer.function = imon_mce_timeout; break; - case IMON_IR_PROTOCOL_IMON: - dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); - /* ir_proto_packet[0] = 0x00; // already the default */ - ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; - ictx->pad_mouse = 1; - break; - case IMON_IR_PROTOCOL_IMON_NOPAD: - dev_dbg(dev, "Configuring IR receiver for iMON protocol " - "without PAD stabilize function enabled\n"); + case IR_TYPE_UNKNOWN: + case IR_TYPE_OTHER: + dev_dbg(dev, "Configuring IR receiver for iMON protocol"); + if (pad_stabilize) { + printk(KERN_CONT "\n"); + pad_mouse = true; + } else { + printk(KERN_CONT " (without PAD stabilization)\n"); + pad_mouse = false; + } /* ir_proto_packet[0] = 0x00; // already the default */ - ictx->ir_protocol = IMON_IR_PROTOCOL_IMON_NOPAD; - ictx->pad_mouse = 0; + ir_type = IR_TYPE_OTHER; break; default: - dev_info(dev, "%s: unknown IR protocol specified, will " - "just default to iMON protocol\n", __func__); - ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; - ictx->pad_mouse = 1; + dev_warn(dev, "Unsupported IR protocol specified, overriding " + "to iMON IR protocol"); + if (pad_stabilize) { + printk(KERN_CONT "\n"); + pad_mouse = true; + } else { + printk(KERN_CONT " (without PAD stabilization)\n"); + pad_mouse = false; + } + /* ir_proto_packet[0] = 0x00; // already the default */ + ir_type = IR_TYPE_OTHER; break; } memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet)); retval = send_packet(ictx); - if (retval) { - dev_info(dev, "%s: failed to set IR protocol, falling back " - "to standard iMON protocol mode\n", __func__); - ir_protocol = IMON_IR_PROTOCOL_IMON; - ictx->ir_protocol = IMON_IR_PROTOCOL_IMON; - } + if (retval) + goto out; + + ictx->ir_type = ir_type; + ictx->pad_mouse = pad_mouse; + +out: + return retval; } static inline int tv2int(const struct timeval *a, const struct timeval *b) @@ -1329,7 +1307,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) rel_x = buf[2]; rel_y = buf[3]; - if (ictx->ir_protocol == IMON_IR_PROTOCOL_IMON) { + if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); @@ -1386,7 +1364,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) buf[0] = 0x01; buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; - if (ictx->ir_protocol == IMON_IR_PROTOCOL_IMON) { + if (ictx->ir_type == IR_TYPE_OTHER && pad_stabilize) { dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); if (!dir) { @@ -1499,7 +1477,7 @@ static void imon_incoming_packet(struct imon_context *ictx, kc = imon_panel_key_lookup(panel_key); } else { remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff); - if (ictx->ir_protocol == IMON_IR_PROTOCOL_MCE) { + if (ictx->ir_type == IR_TYPE_RC6) { if (buf[0] == 0x80) ktype = IMON_KEY_MCE; kc = imon_mce_key_lookup(ictx, remote_key); @@ -1680,12 +1658,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) struct ir_dev_props *props; struct ir_input_dev *ir; int ret, i; - char *ir_codes = NULL; - - if (ir_protocol == IMON_IR_PROTOCOL_MCE) - ir_codes = RC_MAP_IMON_MCE; - else - ir_codes = RC_MAP_IMON_PAD; idev = input_allocate_device(); if (!idev) { @@ -1727,8 +1699,12 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) __set_bit(kc, idev->keybit); } + props->priv = ictx; props->driver_type = RC_DRIVER_SCANCODE; - props->allowed_protos = IR_TYPE_UNKNOWN; + /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */ + props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; + props->change_protocol = imon_ir_change_protocol; + ictx->props = props; ictx->ir = ir; memcpy(&ir->dev, ictx->dev, sizeof(struct device)); @@ -1738,7 +1714,7 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) input_set_drvdata(idev, ir); - ret = ir_input_register(idev, ir_codes, props, MOD_NAME); + ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); if (ret < 0) { dev_err(ictx->dev, "remote input dev register failed\n"); goto idev_register_failed; @@ -2058,13 +2034,14 @@ rx_urb_alloc_failed: * is no actual data to report. However, byte 6 of this buffer looks like * its unique across device variants, so we're trying to key off that to * figure out which display type (if any) and what IR protocol the device - * actually supports. + * actually supports. These devices have their IR protocol hard-coded into + * their firmware, they can't be changed on the fly like the newer hardware. */ static void imon_get_ffdc_type(struct imon_context *ictx) { u8 ffdc_cfg_byte = ictx->usb_rx_buf[6]; u8 detected_display_type = IMON_DISPLAY_TYPE_NONE; - u8 ir_proto_mask = IMON_IR_PROTO_MASK_IMON; + u64 allowed_protos = IR_TYPE_OTHER; switch (ffdc_cfg_byte) { /* iMON Knob, no display, iMON IR + vol knob */ @@ -2076,7 +2053,6 @@ static void imon_get_ffdc_type(struct imon_context *ictx) case 0x35: dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR"); detected_display_type = IMON_DISPLAY_TYPE_VFD; - ir_proto_mask = IMON_IR_PROTO_MASK_NONE; break; /* iMON VFD, iMON IR */ case 0x24: @@ -2088,7 +2064,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx) case 0x9f: dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR"); detected_display_type = IMON_DISPLAY_TYPE_LCD; - ir_proto_mask = IMON_IR_PROTO_MASK_MCE; + allowed_protos = IR_TYPE_RC6; break; default: dev_info(ictx->dev, "Unknown 0xffdc device, " @@ -2097,10 +2073,11 @@ static void imon_get_ffdc_type(struct imon_context *ictx) break; } - printk(" (id 0x%02x)\n", ffdc_cfg_byte); + printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte); ictx->display_type = detected_display_type; - ictx->ir_proto_mask = ir_proto_mask; + ictx->props->allowed_protos = allowed_protos; + ictx->ir_type = allowed_protos; } static void imon_set_display_type(struct imon_context *ictx, @@ -2255,9 +2232,6 @@ static int __devinit imon_probe(struct usb_interface *interface, if (product == 0xffdc) imon_get_ffdc_type(ictx); - else - ictx->ir_proto_mask = IMON_IR_PROTO_MASK_MCE | - IMON_IR_PROTO_MASK_IMON; imon_set_display_type(ictx, interface); @@ -2266,7 +2240,12 @@ static int __devinit imon_probe(struct usb_interface *interface, } /* set IR protocol/remote type */ - imon_set_ir_protocol(ictx); + ret = imon_ir_change_protocol(ictx, ictx->ir_type); + if (ret) { + dev_warn(dev, "%s: failed to set IR protocol, falling back " + "to standard iMON protocol mode\n", __func__); + ictx->ir_type = IR_TYPE_OTHER; + } dev_info(dev, "iMON device (%04x:%04x, intf%d) on " "usb<%d:%d> initialized\n", vendor, product, ifnum, @@ -2343,7 +2322,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface) if (!ictx->display_isopen) free_imon_context(ictx); } else { - if (ictx->ir_protocol == IMON_IR_PROTOCOL_MCE) + if (ictx->ir_type == IR_TYPE_RC6) del_timer_sync(&ictx->itimer); mutex_unlock(&ictx->lock); } diff --git a/drivers/media/IR/keymaps/rc-imon-mce.c b/drivers/media/IR/keymaps/rc-imon-mce.c index 9c6dda30c649..e49f350e3a0d 100644 --- a/drivers/media/IR/keymaps/rc-imon-mce.c +++ b/drivers/media/IR/keymaps/rc-imon-mce.c @@ -119,8 +119,8 @@ static struct rc_keymap imon_mce_map = { .map = { .scan = imon_mce, .size = ARRAY_SIZE(imon_mce), - /* its actually RC6, but w/a hardware decoder */ - .ir_type = IR_TYPE_UNKNOWN, + /* its RC6, but w/a hardware decoder */ + .ir_type = IR_TYPE_RC6, .name = RC_MAP_IMON_MCE, } }; diff --git a/drivers/media/IR/keymaps/rc-imon-pad.c b/drivers/media/IR/keymaps/rc-imon-pad.c index 331ba9066b46..bc4db72f02e6 100644 --- a/drivers/media/IR/keymaps/rc-imon-pad.c +++ b/drivers/media/IR/keymaps/rc-imon-pad.c @@ -133,7 +133,8 @@ static struct rc_keymap imon_pad_map = { .map = { .scan = imon_pad, .size = ARRAY_SIZE(imon_pad), - .ir_type = IR_TYPE_UNKNOWN, + /* actual protocol details unknown, hardware decoder */ + .ir_type = IR_TYPE_OTHER, .name = RC_MAP_IMON_PAD, } }; -- cgit v1.2.3 From 5a143b12ebbd37154cb06699a757e9c5845c5e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=A4rdeman?= Date: Sat, 24 Apr 2010 18:14:00 -0300 Subject: V4L/DVB: ir-core: remove IR_TYPE_PD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pulse-distance is not a protocol, it is a line coding (used by some protocols, like NEC). Looking at the uses of IR_TYPE_PD, the real protocol seems to be NEC in all cases (drivers/media/video/cx88/cx88-input.c is the only user). So, remove IR_TYPE_PD while it is still easy to do so. Signed-off-by: David Härdeman Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-sysfs.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 002b14123319..d7da63e16c92 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -57,8 +57,6 @@ static ssize_t show_protocol(struct device *d, s = "Unknown"; else if (ir_type == IR_TYPE_RC5) s = "rc-5"; - else if (ir_type == IR_TYPE_PD) - s = "pulse-distance"; else if (ir_type == IR_TYPE_NEC) s = "nec"; else if (ir_type == IR_TYPE_RC6) @@ -100,8 +98,6 @@ static ssize_t store_protocol(struct device *d, while ((buf = strsep((char **) &data, " \n")) != NULL) { if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) ir_type |= IR_TYPE_RC5; - if (!strcasecmp(buf, "pd") || !strcasecmp(buf, "pulse-distance")) - ir_type |= IR_TYPE_PD; if (!strcasecmp(buf, "nec")) ir_type |= IR_TYPE_NEC; if (!strcasecmp(buf, "jvc")) @@ -146,8 +142,6 @@ static ssize_t show_supported_protocols(struct device *d, buf += sprintf(buf, "unknown "); if (ir_dev->props->allowed_protos & IR_TYPE_RC5) buf += sprintf(buf, "rc-5 "); - if (ir_dev->props->allowed_protos & IR_TYPE_PD) - buf += sprintf(buf, "pulse-distance "); if (ir_dev->props->allowed_protos & IR_TYPE_NEC) buf += sprintf(buf, "nec "); if (buf == orgbuf) -- cgit v1.2.3 From 666a9ed8971657ea7dcf0bd9df17195db4dddf29 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Wed, 28 Apr 2010 14:37:29 -0300 Subject: V4L/DVB: IR/imon: minor change_protocol fixups This is a follow-up to my prior patch implementing ir-core's change_protocol functionality in the imon driver, which eliminates a false warning when change_protocol is called without a specific protocol selected yet (i.e., still IR_TYPE_UNKNOWN). It also removes some extraneous blank lines getting spewn into dmesg. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index b65c31ab4a4f..f5fb08fba637 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -999,7 +999,7 @@ int imon_ir_change_protocol(void *priv, u64 ir_type) unsigned char ir_proto_packet[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; - if (!(ir_type & ictx->props->allowed_protos)) + if (ir_type && !(ir_type & ictx->props->allowed_protos)) dev_warn(dev, "Looks like you're trying to use an IR protocol " "this device does not support\n"); @@ -1014,12 +1014,11 @@ int imon_ir_change_protocol(void *priv, u64 ir_type) break; case IR_TYPE_UNKNOWN: case IR_TYPE_OTHER: - dev_dbg(dev, "Configuring IR receiver for iMON protocol"); - if (pad_stabilize) { - printk(KERN_CONT "\n"); + dev_dbg(dev, "Configuring IR receiver for iMON protocol\n"); + if (pad_stabilize) pad_mouse = true; - } else { - printk(KERN_CONT " (without PAD stabilization)\n"); + else { + dev_dbg(dev, "PAD stabilize functionality disabled\n"); pad_mouse = false; } /* ir_proto_packet[0] = 0x00; // already the default */ @@ -1027,12 +1026,11 @@ int imon_ir_change_protocol(void *priv, u64 ir_type) break; default: dev_warn(dev, "Unsupported IR protocol specified, overriding " - "to iMON IR protocol"); - if (pad_stabilize) { - printk(KERN_CONT "\n"); + "to iMON IR protocol\n"); + if (pad_stabilize) pad_mouse = true; - } else { - printk(KERN_CONT " (without PAD stabilization)\n"); + else { + dev_dbg(dev, "PAD stabilize functionality disabled\n"); pad_mouse = false; } /* ir_proto_packet[0] = 0x00; // already the default */ -- cgit v1.2.3 From db190fc13af8e2e5e9d717c16b07342ea8bf9174 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 30 Apr 2010 16:06:12 -0300 Subject: V4L/DVB: IR/imon: add proper auto-repeat support Simplified from version 1, in that hacks heisted from ati_remote2.c aren't actually necessary, the real fix for too many repeats was from setting too long a timer release value (200ms) on repeats in mce mode -- this patch drops the release timeout to 33ms, matching the input subsystem default input_dev->rep[REP_PERIOD]. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index f5fb08fba637..27743eb0916d 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -146,7 +146,6 @@ struct imon_context { }; #define TOUCH_TIMEOUT (HZ/30) -#define MCE_TIMEOUT_MS 200 /* vfd character device file operations */ static const struct file_operations vfd_fops = { @@ -1392,6 +1391,8 @@ static int imon_parse_press_type(struct imon_context *ictx, unsigned char *buf, u8 ktype) { int press_type = 0; + int rep_delay = ictx->idev->rep[REP_DELAY]; + int rep_period = ictx->idev->rep[REP_PERIOD]; /* key release of 0x02XXXXXX key */ if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) @@ -1416,12 +1417,12 @@ static int imon_parse_press_type(struct imon_context *ictx, ictx->mce_toggle_bit = buf[2]; press_type = 1; mod_timer(&ictx->itimer, - jiffies + msecs_to_jiffies(MCE_TIMEOUT_MS)); + jiffies + msecs_to_jiffies(rep_delay)); /* repeat */ } else { press_type = 2; mod_timer(&ictx->itimer, - jiffies + msecs_to_jiffies(MCE_TIMEOUT_MS)); + jiffies + msecs_to_jiffies(rep_period)); } /* incoherent or irrelevant data */ @@ -1539,7 +1540,7 @@ static void imon_incoming_packet(struct imon_context *ictx, do_gettimeofday(&t); msec = tv2int(&t, &prev_time); prev_time = t; - if (msec < 200) + if (msec < idev->rep[REP_DELAY]) return; } @@ -1684,7 +1685,7 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev)); idev->phys = ictx->phys_idev; - idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL); idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); -- cgit v1.2.3 From f03900d696079fa1e93c91af0e49c55b9b7dd105 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 May 2010 08:37:33 -0300 Subject: V4L/DVB: media/IR/imon: precendence issue: ! vs == The original condition is always false because ! has higher precedence than == and neither 0 nor 1 is equal to IMON_DISPLAY_TYPE_VGA. Signed-off-by: Dan Carpenter Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index 27743eb0916d..9ca5e864d16f 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -974,7 +974,7 @@ static void imon_touch_display_timeout(unsigned long data) { struct imon_context *ictx = (struct imon_context *)data; - if (!ictx->display_type == IMON_DISPLAY_TYPE_VGA) + if (ictx->display_type != IMON_DISPLAY_TYPE_VGA) return; input_report_abs(ictx->touch, ABS_X, ictx->touch_x); -- cgit v1.2.3 From 5f6e3c8e34bc02800b499e09828ac1061e004977 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 May 2010 08:38:26 -0300 Subject: V4L/DVB: media/IR/imon: testing the wrong variable There is a typo here. We meant to test "ir" instead of "props". The "props" variable was tested earlier. Signed-off-by: Dan Carpenter Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index 9ca5e864d16f..d5d8d9331870 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -1671,7 +1671,7 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) } ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL); - if (!props) { + if (!ir) { dev_err(ictx->dev, "remote ir input dev allocation failed\n"); goto ir_dev_alloc_failed; } -- cgit v1.2.3 From 9723dbb034e45775037c5dd098652e1628a1c9ef Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 May 2010 08:36:34 -0300 Subject: V4L/DVB: media/IR/imon: potential double unlock on error If there is an error here we should unlock in the caller (which is imon_init_intf1()). We can remove this stray unlock. Signed-off-by: Dan Carpenter Acked-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index d5d8d9331870..ca2b49084d72 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -1776,7 +1776,6 @@ static struct input_dev *imon_init_touch(struct imon_context *ictx) touch_register_failed: input_free_device(ictx->touch); - mutex_unlock(&ictx->lock); touch_alloc_failed: return NULL; -- cgit v1.2.3 From a7b39036cfd1d3f868a6745e40bc99b2a8650bad Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Wed, 5 May 2010 12:20:21 -0300 Subject: V4L/DVB: media/IR: Add missing include file to rc-map.c This patch adds a missing include linux/delay.h to prevent build failures[1-5] Signed-off-by: Peter Huewe Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/rc-map.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c index caf6a27b08c2..46a8f1524b5b 100644 --- a/drivers/media/IR/rc-map.c +++ b/drivers/media/IR/rc-map.c @@ -14,6 +14,7 @@ #include #include +#include /* Used to handle IR raw handler extensions */ static LIST_HEAD(rc_map_list); -- cgit v1.2.3 From 083e472176999de97848e5659cc958516ef81ecb Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Tue, 4 May 2010 16:17:05 -0300 Subject: V4L/DVB: IR/imon: remove dead IMON_KEY_RELEASE_OFFSET On Tue, May 04, 2010 at 06:06:41PM +0200, Dan Carpenter wrote: > On Tue, May 04, 2010 at 10:03:18AM -0400, Jarod Wilson wrote: > > @@ -1205,7 +1204,7 @@ static u32 imon_panel_key_lookup(u64 hw_code) > > if (imon_panel_key_table[i].hw_code == (code | 0xffee)) > > break; > > > > - keycode = imon_panel_key_table[i % IMON_KEY_RELEASE_OFFSET].keycode; > > + keycode = imon_panel_key_table[i].keycode; > > > > return keycode; > > } > > There is still potentially a problem here because if we don't hit the > break statement, then we're one past the end of the array. D'oh. Okay, here's v2, should fix that buglet too. This hack was used when the imon driver was using internal key lookup routines, but became dead weight when the driver was converted to use ir-core's key lookup routines. These bits simply didn't get removed, drop 'em now. Pointed out by Dan Carpenter. v2: fix possible attempt to access beyond end of key table array, also pointed out by Dan. Signed-off-by: Jarod Wilson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/imon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/media/IR') diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index ca2b49084d72..5e2045670004 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -55,7 +55,6 @@ #define BIT_DURATION 250 /* each bit received is 250us */ #define IMON_CLOCK_ENABLE_PACKETS 2 -#define IMON_KEY_RELEASE_OFFSET 1000 /*** P R O T O T Y P E S ***/ @@ -1199,13 +1198,14 @@ static u32 imon_panel_key_lookup(u64 hw_code) { int i; u64 code = be64_to_cpu(hw_code); - u32 keycode; + u32 keycode = KEY_RESERVED; - for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) - if (imon_panel_key_table[i].hw_code == (code | 0xffee)) + for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) { + if (imon_panel_key_table[i].hw_code == (code | 0xffee)) { + keycode = imon_panel_key_table[i].keycode; break; - - keycode = imon_panel_key_table[i % IMON_KEY_RELEASE_OFFSET].keycode; + } + } return keycode; } -- cgit v1.2.3