|
@@ -74,7 +74,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
|
|
|
int start, range, toggle, dev, code, ircode;
|
|
|
|
|
|
/* poll IR chip */
|
|
|
- if (size != i2c_master_recv(&ir->c,buf,size))
|
|
|
+ if (size != i2c_master_recv(ir->c, buf, size))
|
|
|
return -EIO;
|
|
|
|
|
|
/* split rc5 data block ... */
|
|
@@ -137,7 +137,7 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|
|
unsigned char b;
|
|
|
|
|
|
/* poll IR chip */
|
|
|
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
|
|
|
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
|
|
|
dprintk(1,"read error\n");
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -151,7 +151,7 @@ static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|
|
unsigned char b;
|
|
|
|
|
|
/* poll IR chip */
|
|
|
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
|
|
|
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
|
|
|
dprintk(1,"read error\n");
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -171,7 +171,7 @@ static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|
|
unsigned char buf[4];
|
|
|
|
|
|
/* poll IR chip */
|
|
|
- if (4 != i2c_master_recv(&ir->c,buf,4)) {
|
|
|
+ if (4 != i2c_master_recv(ir->c, buf, 4)) {
|
|
|
dprintk(1,"read error\n");
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -195,7 +195,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|
|
unsigned char b;
|
|
|
|
|
|
/* poll IR chip */
|
|
|
- if (1 != i2c_master_recv(&ir->c,&b,1)) {
|
|
|
+ if (1 != i2c_master_recv(ir->c, &b, 1)) {
|
|
|
dprintk(1,"read error\n");
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -222,12 +222,12 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
|
|
|
u32 *ir_key, u32 *ir_raw)
|
|
|
{
|
|
|
unsigned char subaddr, key, keygroup;
|
|
|
- struct i2c_msg msg[] = { { .addr = ir->c.addr, .flags = 0,
|
|
|
+ struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0,
|
|
|
.buf = &subaddr, .len = 1},
|
|
|
- { .addr = ir->c.addr, .flags = I2C_M_RD,
|
|
|
+ { .addr = ir->c->addr, .flags = I2C_M_RD,
|
|
|
.buf = &key, .len = 1} };
|
|
|
subaddr = 0x0d;
|
|
|
- if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
|
|
|
+ if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
|
|
|
dprintk(1, "read error\n");
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -237,7 +237,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
|
|
|
|
|
|
subaddr = 0x0b;
|
|
|
msg[1].buf = &keygroup;
|
|
|
- if (2 != i2c_transfer(ir->c.adapter, msg, 2)) {
|
|
|
+ if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
|
|
|
dprintk(1, "read error\n");
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -286,7 +286,7 @@ static void ir_work(struct work_struct *work)
|
|
|
|
|
|
/* MSI TV@nywhere Plus requires more frequent polling
|
|
|
otherwise it will miss some keypresses */
|
|
|
- if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30)
|
|
|
+ if (ir->c->adapter->id == I2C_HW_SAA7134 && ir->c->addr == 0x30)
|
|
|
polling_interval = 50;
|
|
|
|
|
|
ir_key_poll(ir);
|
|
@@ -295,34 +295,15 @@ static void ir_work(struct work_struct *work)
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|
|
|
-static int ir_attach(struct i2c_adapter *adap, int addr,
|
|
|
- unsigned short flags, int kind);
|
|
|
-static int ir_detach(struct i2c_client *client);
|
|
|
-static int ir_probe(struct i2c_adapter *adap);
|
|
|
-
|
|
|
-static struct i2c_driver driver = {
|
|
|
- .driver = {
|
|
|
- .name = "ir-kbd-i2c",
|
|
|
- },
|
|
|
- .id = I2C_DRIVERID_INFRARED,
|
|
|
- .attach_adapter = ir_probe,
|
|
|
- .detach_client = ir_detach,
|
|
|
-};
|
|
|
-
|
|
|
-static struct i2c_client client_template =
|
|
|
-{
|
|
|
- .name = "unset",
|
|
|
- .driver = &driver
|
|
|
-};
|
|
|
-
|
|
|
-static int ir_attach(struct i2c_adapter *adap, int addr,
|
|
|
- unsigned short flags, int kind)
|
|
|
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|
|
{
|
|
|
IR_KEYTAB_TYPE *ir_codes = NULL;
|
|
|
char *name;
|
|
|
int ir_type;
|
|
|
struct IR_i2c *ir;
|
|
|
struct input_dev *input_dev;
|
|
|
+ struct i2c_adapter *adap = client->adapter;
|
|
|
+ unsigned short addr = client->addr;
|
|
|
int err;
|
|
|
|
|
|
ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
|
|
@@ -332,14 +313,9 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|
|
goto err_out_free;
|
|
|
}
|
|
|
|
|
|
- ir->c = client_template;
|
|
|
+ ir->c = client;
|
|
|
ir->input = input_dev;
|
|
|
-
|
|
|
- ir->c.adapter = adap;
|
|
|
- ir->c.addr = addr;
|
|
|
- snprintf(ir->c.name, sizeof(ir->c.name), "ir-kbd");
|
|
|
-
|
|
|
- i2c_set_clientdata(&ir->c, ir);
|
|
|
+ i2c_set_clientdata(client, ir);
|
|
|
|
|
|
switch(addr) {
|
|
|
case 0x64:
|
|
@@ -414,24 +390,9 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|
|
snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name);
|
|
|
ir->ir_codes = ir_codes;
|
|
|
|
|
|
- /* register i2c device
|
|
|
- * At device register, IR codes may be changed to be
|
|
|
- * board dependent.
|
|
|
- */
|
|
|
- err = i2c_attach_client(&ir->c);
|
|
|
- if (err)
|
|
|
- goto err_out_free;
|
|
|
-
|
|
|
- /* If IR not supported or disabled, unregisters driver */
|
|
|
- if (ir->get_key == NULL) {
|
|
|
- err = -ENODEV;
|
|
|
- goto err_out_detach;
|
|
|
- }
|
|
|
-
|
|
|
- /* Phys addr can only be set after attaching (for ir->c.dev) */
|
|
|
snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
|
|
|
- dev_name(&ir->c.adapter->dev),
|
|
|
- dev_name(&ir->c.dev));
|
|
|
+ dev_name(&adap->dev),
|
|
|
+ dev_name(&client->dev));
|
|
|
|
|
|
/* init + register input device */
|
|
|
ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
|
|
@@ -441,7 +402,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|
|
|
|
|
err = input_register_device(ir->input);
|
|
|
if (err)
|
|
|
- goto err_out_detach;
|
|
|
+ goto err_out_free;
|
|
|
|
|
|
printk(DEVNAME ": %s detected at %s [%s]\n",
|
|
|
ir->input->name, ir->input->phys, adap->name);
|
|
@@ -452,135 +413,42 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
- err_out_detach:
|
|
|
- i2c_detach_client(&ir->c);
|
|
|
err_out_free:
|
|
|
input_free_device(input_dev);
|
|
|
kfree(ir);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static int ir_detach(struct i2c_client *client)
|
|
|
+static int ir_remove(struct i2c_client *client)
|
|
|
{
|
|
|
struct IR_i2c *ir = i2c_get_clientdata(client);
|
|
|
|
|
|
/* kill outstanding polls */
|
|
|
cancel_delayed_work_sync(&ir->work);
|
|
|
|
|
|
- /* unregister devices */
|
|
|
+ /* unregister device */
|
|
|
input_unregister_device(ir->input);
|
|
|
- i2c_detach_client(&ir->c);
|
|
|
|
|
|
/* free memory */
|
|
|
kfree(ir);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int ir_probe(struct i2c_adapter *adap)
|
|
|
-{
|
|
|
-
|
|
|
- /* The external IR receiver is at i2c address 0x34 (0x35 for
|
|
|
- reads). Future Hauppauge cards will have an internal
|
|
|
- receiver at 0x30 (0x31 for reads). In theory, both can be
|
|
|
- fitted, and Hauppauge suggest an external overrides an
|
|
|
- internal.
|
|
|
-
|
|
|
- That's why we probe 0x1a (~0x34) first. CB
|
|
|
- */
|
|
|
-
|
|
|
- static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
|
|
|
- static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, 0x2d, -1 };
|
|
|
- static const int probe_em28XX[] = { 0x30, 0x47, -1 };
|
|
|
- static const int probe_cx88[] = { 0x18, 0x6b, 0x71, -1 };
|
|
|
- static const int probe_cx23885[] = { 0x6b, -1 };
|
|
|
- const int *probe;
|
|
|
- struct i2c_msg msg = {
|
|
|
- .flags = I2C_M_RD,
|
|
|
- .len = 0,
|
|
|
- .buf = NULL,
|
|
|
- };
|
|
|
- int i, rc;
|
|
|
-
|
|
|
- switch (adap->id) {
|
|
|
- case I2C_HW_B_BT848:
|
|
|
- probe = probe_bttv;
|
|
|
- break;
|
|
|
- case I2C_HW_B_CX2341X:
|
|
|
- probe = probe_bttv;
|
|
|
- break;
|
|
|
- case I2C_HW_SAA7134:
|
|
|
- probe = probe_saa7134;
|
|
|
- break;
|
|
|
- case I2C_HW_B_EM28XX:
|
|
|
- probe = probe_em28XX;
|
|
|
- break;
|
|
|
- case I2C_HW_B_CX2388x:
|
|
|
- probe = probe_cx88;
|
|
|
- break;
|
|
|
- case I2C_HW_B_CX23885:
|
|
|
- probe = probe_cx23885;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; -1 != probe[i]; i++) {
|
|
|
- msg.addr = probe[i];
|
|
|
- rc = i2c_transfer(adap, &msg, 1);
|
|
|
- dprintk(1,"probe 0x%02x @ %s: %s\n",
|
|
|
- probe[i], adap->name,
|
|
|
- (1 == rc) ? "yes" : "no");
|
|
|
- if (1 == rc) {
|
|
|
- ir_attach(adap, probe[i], 0, 0);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Special case for MSI TV@nywhere Plus remote */
|
|
|
- if (adap->id == I2C_HW_SAA7134) {
|
|
|
- u8 temp;
|
|
|
-
|
|
|
- /* MSI TV@nywhere Plus controller doesn't seem to
|
|
|
- respond to probes unless we read something from
|
|
|
- an existing device. Weird... */
|
|
|
-
|
|
|
- msg.addr = 0x50;
|
|
|
- rc = i2c_transfer(adap, &msg, 1);
|
|
|
- dprintk(1, "probe 0x%02x @ %s: %s\n",
|
|
|
- msg.addr, adap->name,
|
|
|
- (1 == rc) ? "yes" : "no");
|
|
|
-
|
|
|
- /* Now do the probe. The controller does not respond
|
|
|
- to 0-byte reads, so we use a 1-byte read instead. */
|
|
|
- msg.addr = 0x30;
|
|
|
- msg.len = 1;
|
|
|
- msg.buf = &temp;
|
|
|
- rc = i2c_transfer(adap, &msg, 1);
|
|
|
- dprintk(1, "probe 0x%02x @ %s: %s\n",
|
|
|
- msg.addr, adap->name,
|
|
|
- (1 == rc) ? "yes" : "no");
|
|
|
- if (1 == rc)
|
|
|
- ir_attach(adap, msg.addr, 0, 0);
|
|
|
- }
|
|
|
-
|
|
|
- /* Special case for AVerMedia Cardbus remote */
|
|
|
- if (adap->id == I2C_HW_SAA7134) {
|
|
|
- unsigned char subaddr, data;
|
|
|
- struct i2c_msg msg[] = { { .addr = 0x40, .flags = 0,
|
|
|
- .buf = &subaddr, .len = 1},
|
|
|
- { .addr = 0x40, .flags = I2C_M_RD,
|
|
|
- .buf = &data, .len = 1} };
|
|
|
- subaddr = 0x0d;
|
|
|
- rc = i2c_transfer(adap, msg, 2);
|
|
|
- dprintk(1, "probe 0x%02x/0x%02x @ %s: %s\n",
|
|
|
- msg[0].addr, subaddr, adap->name,
|
|
|
- (2 == rc) ? "yes" : "no");
|
|
|
- if (2 == rc)
|
|
|
- ir_attach(adap, msg[0].addr, 0, 0);
|
|
|
- }
|
|
|
+static const struct i2c_device_id ir_kbd_id[] = {
|
|
|
+ /* Generic entry for any IR receiver */
|
|
|
+ { "ir_video", 0 },
|
|
|
+ /* IR device specific entries could be added here */
|
|
|
+ { }
|
|
|
+};
|
|
|
|
|
|
- return 0;
|
|
|
-}
|
|
|
+static struct i2c_driver driver = {
|
|
|
+ .driver = {
|
|
|
+ .name = "ir-kbd-i2c",
|
|
|
+ },
|
|
|
+ .probe = ir_probe,
|
|
|
+ .remove = ir_remove,
|
|
|
+ .id_table = ir_kbd_id,
|
|
|
+};
|
|
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
|
|