Commit b93eedb6 authored by Sylvain Pasche's avatar Sylvain Pasche Committed by Mauro Carvalho Chehab

V4L/DVB (4023): Subject: Pinnacle PCTV grey remote control support

This adds support for the older (?) Pinnacle PCTV remotes (with all buttons
colored in grey). There's no autodetection for the type of remote, though;
saa7134 defaults to the colored one, to use the grey remote the 
"pinnacle_remote=1" option must be passed to the saa7134 module
Signed-off-by: default avatarSylvain Pasche <sylvain.pasche@gmail.com>
Signed-off-by: default avatarRicardo Cerqueira <v4l@cerqueira.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent e48a9c62
......@@ -618,7 +618,7 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
EXPORT_SYMBOL_GPL(ir_codes_em_terratec);
IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = {
[ 0x3a ] = KEY_0,
[ 0x31 ] = KEY_1,
[ 0x32 ] = KEY_2,
......@@ -670,7 +670,7 @@ IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
[ 0x27 ] = KEY_RECORD,
};
EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb);
EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey);
IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
[ 0x0f ] = KEY_0,
......@@ -1290,7 +1290,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
EXPORT_SYMBOL_GPL(ir_codes_winfast);
IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = {
[ 0x59 ] = KEY_MUTE,
[ 0x4a ] = KEY_POWER,
......@@ -1348,7 +1348,7 @@ IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
[ 0x0a ] = KEY_BACKSPACE,
};
EXPORT_SYMBOL_GPL(ir_codes_pinnacle);
EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color);
/* Hauppauge: the newer, gray remotes (seems there are multiple
* slightly different versions), shipped with cx88+ivtv cards.
......
......@@ -105,7 +105,7 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
unsigned char buf[3];
......@@ -148,8 +148,8 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)");
break;
case (EM2820_BOARD_PINNACLE_USB_2):
ir->ir_codes = ir_codes_em_pinnacle_usb;
ir->get_key = get_key_pinnacle_usb;
ir->ir_codes = ir_codes_pinnacle_grey;
ir->get_key = get_key_pinnacle_usb_grey;
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)");
break;
case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
......
......@@ -150,12 +150,11 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
/* The new pinnacle PCTV remote (with the colored buttons)
/* Common (grey or coloured) pinnacle PCTV remote handling
*
* Ricardo Cerqueira <v4l@cerqueira.org>
*/
int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
int parity_offset, int marker, int code_modulo)
{
unsigned char b[4];
unsigned int start = 0,parity = 0,code = 0;
......@@ -167,9 +166,9 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
}
for (start = 0; start<4; start++) {
if (b[start] == 0x80) {
code=b[(start+3)%4];
parity=b[(start+2)%4];
if (b[start] == marker) {
code=b[(start+parity_offset+1)%4];
parity=b[(start+parity_offset)%4];
}
}
......@@ -181,16 +180,14 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
if (ir->old == parity)
return 0;
ir->old = parity;
/* Reduce code value to fit inside IR_KEYTAB_SIZE
*
* this is the only value that results in 42 unique
* codes < 128
*/
/* drop special codes when a key is held down a long time for the grey controller
In this case, the second bit of the code is asserted */
if (marker == 0xfe && (code & 0x40))
return 0;
code %= 0x88;
code %= code_modulo;
*ir_raw = code;
*ir_key = code;
......@@ -200,7 +197,40 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
EXPORT_SYMBOL_GPL(get_key_pinnacle);
/* The grey pinnacle PCTV remote
*
* There are one issue with this remote:
* - I2c packet does not change when the same key is pressed quickly. The workaround
* is to hold down each key for about half a second, so that another code is generated
* in the i2c packet, and the function can distinguish key presses.
*
* Sylvain Pasche <sylvain.pasche@gmail.com>
*/
int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
}
EXPORT_SYMBOL_GPL(get_key_pinnacle_grey);
/* The new pinnacle PCTV remote (with the colored buttons)
*
* Ricardo Cerqueira <v4l@cerqueira.org>
*/
int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
*
* this is the only value that results in 42 unique
* codes < 128
*/
return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
}
EXPORT_SYMBOL_GPL(get_key_pinnacle_color);
/* ----------------------------------------------------------------------- */
......
......@@ -37,6 +37,10 @@ static unsigned int ir_debug = 0;
module_param(ir_debug, int, 0644);
MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
static int pinnacle_remote = 0;
module_param(pinnacle_remote, int, 0644); /* Choose Pinnacle PCTV remote */
MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
#define dprintk(fmt, arg...) if (ir_debug) \
printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
#define i2cdprintk(fmt, arg...) if (ir_debug) \
......@@ -316,8 +320,13 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
switch (dev->board) {
case SAA7134_BOARD_PINNACLE_PCTV_110i:
snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
ir->get_key = get_key_pinnacle;
ir->ir_codes = ir_codes_pinnacle;
if (pinnacle_remote == 0) {
ir->get_key = get_key_pinnacle_color;
ir->ir_codes = ir_codes_pinnacle_color;
} else {
ir->get_key = get_key_pinnacle_grey;
ir->ir_codes = ir_codes_pinnacle_grey;
}
break;
case SAA7134_BOARD_UPMOST_PURPLE_TV:
snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
......
......@@ -73,7 +73,7 @@ extern IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE];
......@@ -87,7 +87,7 @@ extern IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE];
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_pinnacle[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
#endif
......
......@@ -20,5 +20,6 @@ struct IR_i2c {
int (*get_key)(struct IR_i2c*, u32*, u32*);
};
int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment