From: Gerd Knorr Changes: * add some keytables which are used by both bttv and cx88 driver so they can be shared. * add IR decoding helper functions. Signed-off-by: Gerd Knorr Signed-off-by: Andrew Morton --- 25-akpm/drivers/media/common/ir-common.c | 164 ++++++++++++++++++++++++++++++- 25-akpm/include/media/ir-common.h | 6 - 2 files changed, 167 insertions(+), 3 deletions(-) diff -puN drivers/media/common/ir-common.c~v4l-ir-common-update drivers/media/common/ir-common.c --- 25/drivers/media/common/ir-common.c~v4l-ir-common-update 2005-03-11 12:32:17.000000000 -0800 +++ 25-akpm/drivers/media/common/ir-common.c 2005-03-11 12:32:17.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: ir-common.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $ + * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $ * * some common structs and functions to handle infrared remotes via * input layer ... @@ -23,7 +23,6 @@ #include #include - #include /* -------------------------------------------------------------------------- */ @@ -45,6 +44,7 @@ module_param(debug, int, 0644); /* generic RC5 keytable */ /* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */ +/* used by old (black) Hauppauge remotes */ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = { [ 0x00 ] = KEY_KP0, // 0 [ 0x01 ] = KEY_KP1, // 1 @@ -117,12 +117,102 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB }; EXPORT_SYMBOL_GPL(ir_codes_rc5_tv); +/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */ +IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { + [ 5 ] = KEY_KP1, + [ 6 ] = KEY_KP2, + [ 7 ] = KEY_KP3, + [ 9 ] = KEY_KP4, + [ 10 ] = KEY_KP5, + [ 11 ] = KEY_KP6, + [ 13 ] = KEY_KP7, + [ 14 ] = KEY_KP8, + [ 15 ] = KEY_KP9, + [ 18 ] = KEY_KP0, + + [ 0 ] = KEY_POWER, +// [ 27 ] = MTS button + [ 2 ] = KEY_TUNER, // TV/FM + [ 30 ] = KEY_VIDEO, +// [ 22 ] = display button + [ 4 ] = KEY_VOLUMEUP, + [ 8 ] = KEY_VOLUMEDOWN, + [ 12 ] = KEY_CHANNELUP, + [ 16 ] = KEY_CHANNELDOWN, + [ 3 ] = KEY_ZOOM, // fullscreen + [ 31 ] = KEY_SUBTITLE, // closed caption/teletext + [ 32 ] = KEY_SLEEP, +// [ 41 ] = boss key + [ 20 ] = KEY_MUTE, + [ 43 ] = KEY_RED, + [ 44 ] = KEY_GREEN, + [ 45 ] = KEY_YELLOW, + [ 46 ] = KEY_BLUE, + [ 24 ] = KEY_KPPLUS, //fine tune + + [ 25 ] = KEY_KPMINUS, //fine tune - +// [ 42 ] = picture in picture + [ 33 ] = KEY_KPDOT, + [ 19 ] = KEY_KPENTER, +// [ 17 ] = recall + [ 34 ] = KEY_BACK, + [ 35 ] = KEY_PLAYPAUSE, + [ 36 ] = KEY_NEXT, +// [ 37 ] = time shifting + [ 38 ] = KEY_STOP, + [ 39 ] = KEY_RECORD +// [ 40 ] = snapshot +}; +EXPORT_SYMBOL_GPL(ir_codes_winfast); + /* empty keytable, can be used as placeholder for not-yet created keytables */ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = { [ 42 ] = KEY_COFFEE, }; EXPORT_SYMBOL_GPL(ir_codes_empty); +/* 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 */ +IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = { + [ 0x00 ] = KEY_KP0, // 0 + [ 0x01 ] = KEY_KP1, // 1 + [ 0x02 ] = KEY_KP2, // 2 + [ 0x03 ] = KEY_KP3, // 3 + [ 0x04 ] = KEY_KP4, // 4 + [ 0x05 ] = KEY_KP5, // 5 + [ 0x06 ] = KEY_KP6, // 6 + [ 0x07 ] = KEY_KP7, // 7 + [ 0x08 ] = KEY_KP8, // 8 + [ 0x09 ] = KEY_KP9, // 9 + [ 0x0b ] = KEY_RED, // red button + [ 0x0c ] = KEY_OPTION, // black key without text + [ 0x0d ] = KEY_MENU, // menu + [ 0x0f ] = KEY_MUTE, // mute + [ 0x10 ] = KEY_VOLUMEUP, // volume + + [ 0x11 ] = KEY_VOLUMEDOWN, // volume - + [ 0x1e ] = KEY_NEXT, // 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_PREVIOUS, // 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, // play + [ 0x36 ] = KEY_STOP, // 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) +}; +EXPORT_SYMBOL(ir_codes_hauppauge_new); + /* -------------------------------------------------------------------------- */ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) @@ -192,6 +282,8 @@ void ir_input_keydown(struct input_dev * #endif } +/* -------------------------------------------------------------------------- */ + u32 ir_extract_bits(u32 data, u32 mask) { int mbit, vbit; @@ -209,10 +301,78 @@ u32 ir_extract_bits(u32 data, u32 mask) return value; } +static int inline getbit(u32 *samples, int bit) +{ + return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0; +} + +/* sump raw samples for visual debugging ;) */ +int ir_dump_samples(u32 *samples, int count) +{ + int i, bit, start; + + printk(KERN_DEBUG "ir samples: "); + start = 0; + for (i = 0; i < count * 32; i++) { + bit = getbit(samples,i); + if (bit) + start = 1; + if (0 == start) + continue; + printk("%s", bit ? "#" : "_"); + } + printk("\n"); + return 0; +} + +/* decode raw samples, biphase coding, used by rc5 for example */ +int ir_decode_biphase(u32 *samples, int count, int low, int high) +{ + int i,last,bit,len,flips; + u32 value; + + /* find start bit (1) */ + for (i = 0; i < 32; i++) { + bit = getbit(samples,i); + if (bit) + break; + } + + /* go decoding */ + len = 0; + flips = 0; + value = 1; + for (; i < count * 32; i++) { + if (len > high) + break; + if (flips > 1) + break; + last = bit; + bit = getbit(samples,i); + if (last == bit) { + len++; + continue; + } + if (len < low) { + len++; + flips++; + continue; + } + value <<= 1; + value |= bit; + flips = 0; + len = 1; + } + return value; +} + EXPORT_SYMBOL_GPL(ir_input_init); EXPORT_SYMBOL_GPL(ir_input_nokey); EXPORT_SYMBOL_GPL(ir_input_keydown); + EXPORT_SYMBOL_GPL(ir_extract_bits); +EXPORT_SYMBOL_GPL(ir_dump_samples); +EXPORT_SYMBOL_GPL(ir_decode_biphase); /* * Local variables: diff -puN include/media/ir-common.h~v4l-ir-common-update include/media/ir-common.h --- 25/include/media/ir-common.h~v4l-ir-common-update 2005-03-11 12:32:17.000000000 -0800 +++ 25-akpm/include/media/ir-common.h 2005-03-11 12:32:17.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: ir-common.h,v 1.6 2004/09/15 16:15:24 kraxel Exp $ + * $Id: ir-common.h,v 1.8 2005/02/22 12:28:40 kraxel Exp $ * * some common structs and functions to handle infrared remotes via * input layer ... @@ -47,7 +47,9 @@ struct ir_input_state { }; extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE]; void ir_input_init(struct input_dev *dev, struct ir_input_state *ir, int ir_type, IR_KEYTAB_TYPE *ir_codes); @@ -55,6 +57,8 @@ void ir_input_nokey(struct input_dev *de void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, u32 ir_key, u32 ir_raw); u32 ir_extract_bits(u32 data, u32 mask); +int ir_dump_samples(u32 *samples, int count); +int ir_decode_biphase(u32 *samples, int count, int low, int high); /* * Local variables: _