📄 tveeprom.c
字号:
++i; } else { TVEEPROM_KERN_ERR("Encountered bad packet header [%02x]. " "Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]); return; } dprintk(1, "%3d [%02x] ", len, eeprom_data[i]); for(j = 1; j < len; j++) { dprintk(1, "%02x ", eeprom_data[i + j]); } dprintk(1, "\n"); /* process by tag */ tag = eeprom_data[i]; switch (tag) { case 0x00: tuner = eeprom_data[i+6]; t_format = eeprom_data[i+5]; tvee->has_radio = eeprom_data[i+len-1]; tvee->model = eeprom_data[i+8] + (eeprom_data[i+9] << 8); tvee->revision = eeprom_data[i+10] + (eeprom_data[i+11] << 8) + (eeprom_data[i+12] << 16); break; case 0x01: tvee->serial_number = eeprom_data[i+6] + (eeprom_data[i+7] << 8) + (eeprom_data[i+8] << 16); break; case 0x02: tvee->audio_processor = eeprom_data[i+2] & 0x0f; break; case 0x04: tvee->serial_number = eeprom_data[i+5] + (eeprom_data[i+6] << 8) + (eeprom_data[i+7] << 16); break; case 0x05: tvee->audio_processor = eeprom_data[i+1] & 0x0f; break; case 0x06: tvee->model = eeprom_data[i+1] + (eeprom_data[i+2] << 8); tvee->revision = eeprom_data[i+5] + (eeprom_data[i+6] << 8) + (eeprom_data[i+7] << 16); break; case 0x0a: tuner = eeprom_data[i+2]; t_format = eeprom_data[i+1]; break; case 0x0e: tvee->has_radio = eeprom_data[i+1]; break; default: dprintk(1, "Not sure what to do with tag [%02x]\n", tag); /* dump the rest of the packet? */ } } if (!done) { TVEEPROM_KERN_ERR("Ran out of data!\n"); return; } if (tvee->revision != 0) { tvee->rev_str[0] = 32 + ((tvee->revision >> 18) & 0x3f); tvee->rev_str[1] = 32 + ((tvee->revision >> 12) & 0x3f); tvee->rev_str[2] = 32 + ((tvee->revision >> 6) & 0x3f); tvee->rev_str[3] = 32 + ( tvee->revision & 0x3f); tvee->rev_str[4] = 0; } if (hasRadioTuner(tuner) && !tvee->has_radio) { TVEEPROM_KERN_INFO("The eeprom says no radio is present, but the tuner type\n"); TVEEPROM_KERN_INFO("indicates otherwise. I will assume that radio is present.\n"); tvee->has_radio = 1; } if (tuner < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { tvee->tuner_type = hauppauge_tuner[tuner].id; t_name = hauppauge_tuner[tuner].name; } else { t_name = "<unknown>"; } tvee->tuner_formats = 0; t_fmt_name = "<none>"; for (i = 0; i < 8; i++) { if (t_format & (1<<i)) { tvee->tuner_formats |= hauppauge_tuner_fmt[i].id; /* yuck */ t_fmt_name = hauppauge_tuner_fmt[i].name; } }#if 0 if (t_format < sizeof(hauppauge_tuner_fmt)/sizeof(struct HAUPPAUGE_TUNER_FMT)) { tvee->tuner_formats = hauppauge_tuner_fmt[t_format].id; t_fmt_name = hauppauge_tuner_fmt[t_format].name; } else { t_fmt_name = "<unknown>"; }#endif TVEEPROM_KERN_INFO("Hauppauge: model = %d, rev = %s, serial# = %d\n", tvee->model, tvee->rev_str, tvee->serial_number); TVEEPROM_KERN_INFO("tuner = %s (idx = %d, type = %d)\n", t_name, tuner, tvee->tuner_type); TVEEPROM_KERN_INFO("tuner fmt = %s (eeprom = 0x%02x, v4l2 = 0x%08x)\n", t_fmt_name, t_format, tvee->tuner_formats); TVEEPROM_KERN_INFO("audio_processor = %s (type = %d)\n", STRM(sndtype,tvee->audio_processor), tvee->audio_processor);}EXPORT_SYMBOL(tveeprom_hauppauge_analog);/* ----------------------------------------------------------------------- *//* generic helper functions */int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len){ unsigned char buf; int err; dprintk(1, "%s\n",__FUNCTION__); buf = 0; if (1 != (err = i2c_master_send(c,&buf,1))) { printk(KERN_INFO "tveeprom(%s): Huh, no eeprom present (err=%d)?\n", c->name,err); return -1; } if (len != (err = i2c_master_recv(c,eedata,len))) { printk(KERN_WARNING "tveeprom(%s): i2c eeprom read error (err=%d)\n", c->name,err); return -1; } return 0;}EXPORT_SYMBOL(tveeprom_read);int tveeprom_dump(unsigned char *eedata, int len){ int i; dprintk(1, "%s\n",__FUNCTION__); for (i = 0; i < len; i++) { if (0 == (i % 16)) printk(KERN_INFO "tveeprom: %02x:",i); printk(" %02x",eedata[i]); if (15 == (i % 16)) printk("\n"); } return 0;}EXPORT_SYMBOL(tveeprom_dump);/* ----------------------------------------------------------------------- *//* needed for ivtv.sf.net at the moment. Should go away in the long *//* run, just call the exported tveeprom_* directly, there is no point in *//* using the indirect way via i2c_driver->command() */#ifndef I2C_DRIVERID_TVEEPROM# define I2C_DRIVERID_TVEEPROM I2C_DRIVERID_EXP2#endifstatic unsigned short normal_i2c[] = { 0xa0 >> 1, I2C_CLIENT_END,};static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };I2C_CLIENT_INSMOD;struct i2c_driver i2c_driver_tveeprom;static inttveeprom_command(struct i2c_client *client, unsigned int cmd, void *arg){ struct tveeprom eeprom; u32 *eeprom_props = arg; u8 *buf; switch (cmd) { case 0: buf = kmalloc(256,GFP_KERNEL); memset(buf,0,256); tveeprom_read(client,buf,256); tveeprom_hauppauge_analog(&eeprom,buf); kfree(buf); eeprom_props[0] = eeprom.tuner_type; eeprom_props[1] = eeprom.tuner_formats; eeprom_props[2] = eeprom.model; eeprom_props[3] = eeprom.revision; break; default: return -EINVAL; } return 0;}static inttveeprom_detect_client(struct i2c_adapter *adapter, int address, int kind){ struct i2c_client *client; dprintk(1,"%s: id 0x%x @ 0x%x\n",__FUNCTION__, adapter->id, address << 1); client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (NULL == client) return -ENOMEM; memset(client, 0, sizeof(struct i2c_client)); client->addr = address; client->adapter = adapter; client->driver = &i2c_driver_tveeprom; client->flags = I2C_CLIENT_ALLOW_USE; snprintf(client->name, sizeof(client->name), "tveeprom"); i2c_attach_client(client); return 0;}static inttveeprom_attach_adapter (struct i2c_adapter *adapter){ dprintk(1,"%s: id 0x%x\n",__FUNCTION__,adapter->id); if (adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848)) return 0; return i2c_probe(adapter, &addr_data, tveeprom_detect_client);}static inttveeprom_detach_client (struct i2c_client *client){ int err; err = i2c_detach_client(client); if (err < 0) return err; kfree(client); return 0;}struct i2c_driver i2c_driver_tveeprom = { .owner = THIS_MODULE, .name = "tveeprom", .id = I2C_DRIVERID_TVEEPROM, .flags = I2C_DF_NOTIFY, .attach_adapter = tveeprom_attach_adapter, .detach_client = tveeprom_detach_client, .command = tveeprom_command,};static int __init tveeprom_init(void){ return i2c_add_driver(&i2c_driver_tveeprom);}static void __exit tveeprom_exit(void){ i2c_del_driver(&i2c_driver_tveeprom);}module_init(tveeprom_init);module_exit(tveeprom_exit);/* * Local variables: * c-basic-offset: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -