#include <linux/i2c.h>
#include <linux/workqueue.h>
#include <asm/semaphore.h>
+
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
[ 28 ] = KEY_MEDIA, /* PC/TV */
};
-static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
- [ 0x3 ] = KEY_POWER,
- [ 0x6f ] = KEY_MUTE,
- [ 0x10 ] = KEY_BACKSPACE, /* Recall */
-
- [ 0x11 ] = KEY_KP0,
- [ 0x4 ] = KEY_KP1,
- [ 0x5 ] = KEY_KP2,
- [ 0x6 ] = KEY_KP3,
- [ 0x8 ] = KEY_KP4,
- [ 0x9 ] = KEY_KP5,
- [ 0xa ] = KEY_KP6,
- [ 0xc ] = KEY_KP7,
- [ 0xd ] = KEY_KP8,
- [ 0xe ] = KEY_KP9,
- [ 0x12 ] = KEY_KPDOT, /* 100+ */
-
- [ 0x7 ] = KEY_VOLUMEUP,
- [ 0xb ] = KEY_VOLUMEDOWN,
- [ 0x1a ] = KEY_KPPLUS,
- [ 0x18 ] = KEY_KPMINUS,
- [ 0x15 ] = KEY_UP,
- [ 0x1d ] = KEY_DOWN,
- [ 0xf ] = KEY_CHANNELUP,
- [ 0x13 ] = KEY_CHANNELDOWN,
- [ 0x48 ] = KEY_ZOOM,
-
- [ 0x1b ] = KEY_VIDEO, /* Video source */
- [ 0x49 ] = KEY_LANGUAGE, /* MTS Select */
- [ 0x19 ] = KEY_SEARCH, /* Auto Scan */
-
- [ 0x4b ] = KEY_RECORD,
- [ 0x46 ] = KEY_PLAY,
- [ 0x45 ] = KEY_PAUSE, /* Pause */
- [ 0x44 ] = KEY_STOP,
- [ 0x40 ] = KEY_FORWARD, /* Forward ? */
- [ 0x42 ] = KEY_REWIND, /* Backward ? */
-
-};
-
/* ----------------------------------------------------------------------- */
/* insmod parameters */
return 1;
}
-static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+/* The new pinnacle PCTV remote (with the colored buttons)
+ *
+ * Ricardo Cerqueira <v4l@cerqueira.org>
+ */
+
+int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
{
- unsigned char b;
+ unsigned char b[4];
+ unsigned int start = 0,parity = 0,code = 0;
/* poll IR chip */
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
- dprintk(1,"read error\n");
+ if (4 != i2c_master_recv(&ir->c,b,4)) {
+ dprintk(2,"read error\n");
return -EIO;
}
- /* no button press */
- if (b==0)
+ for (start = 0; start<4; start++) {
+ if (b[start] == 0x80) {
+ code=b[(start+3)%4];
+ parity=b[(start+2)%4];
+ }
+ }
+
+ /* Empty Request */
+ if (parity==0)
return 0;
- /* repeating */
- if (b & 0x80)
- return 1;
+ /* Repeating... */
+ 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
+ */
+
+ code %= 0x88;
+
+ *ir_raw = code;
+ *ir_key = code;
+
+ dprintk(1,"Pinnacle PCTV key %02x\n", code);
- *ir_key = b;
- *ir_raw = b;
return 1;
}
+
+EXPORT_SYMBOL_GPL(get_key_pinnacle);
+
/* ----------------------------------------------------------------------- */
static void ir_key_poll(struct IR_i2c *ir)
static struct i2c_driver driver = {
.name = "ir remote kbd driver",
- .id = I2C_DRIVERID_EXP3, /* FIXME */
+ .id = I2C_DRIVERID_INFRARED,
.flags = I2C_DF_NOTIFY,
.attach_adapter = ir_probe,
.detach_client = ir_detach,
IR_KEYTAB_TYPE *ir_codes = NULL;
char *name;
int ir_type;
- struct IR_i2c *ir;
+ struct IR_i2c *ir;
struct input_dev *input_dev;
- ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL);
+ ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
input_dev = input_allocate_device();
if (!ir || !input_dev) {
kfree(ir);
input_free_device(input_dev);
- return -ENOMEM;
+ return -ENOMEM;
}
ir->c = client_template;
ir_codes = ir_codes_empty;
break;
case 0x7a:
- name = "Purple TV";
- ir->get_key = get_key_purpletv;
+ case 0x47:
+ /* Handled by saa7134-input */
+ name = "SAA713x remote";
ir_type = IR_TYPE_OTHER;
- ir_codes = ir_codes_purpletv;
break;
-
default:
/* shouldn't happen */
printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
return -1;
}
- /* Sets name and its physical addr */
+ /* Sets name */
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
- snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
- ir->c.adapter->dev.bus_id,
- ir->c.dev.bus_id);
ir->ir_codes=ir_codes;
/* register i2c device
* At device register, IR codes may be changed to be
* board dependent.
- */
+ */
i2c_attach_client(&ir->c);
+ /* If IR not supported or disabled, unregisters driver */
+ if (ir->get_key == NULL) {
+ i2c_detach_client(&ir->c);
+ kfree(ir);
+ return -1;
+ }
+
+ /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
+ snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
+ ir->c.adapter->dev.bus_id,
+ ir->c.dev.bus_id);
+
/* init + register input device */
ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
input_dev->id.bustype = BUS_I2C;
*/
static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
- static const int probe_saa7134[] = { 0x7a, -1 };
- static const int probe_em2820[] = { 0x30, 0x47, -1 };
+ static const int probe_saa7134[] = { 0x7a, 0x47, -1 };
+ static const int probe_em28XX[] = { 0x30, 0x47, -1 };
const int *probe = NULL;
struct i2c_client c;
unsigned char buf;
case I2C_HW_SAA7134:
probe = probe_saa7134;
break;
- case I2C_HW_B_EM2820:
- probe = probe_em2820;
+ case I2C_HW_B_EM28XX:
+ probe = probe_em28XX;
break;
}
if (NULL == probe)