/* driver to support MAX6633 */ #include #include #include #include #include #include #define MAX6633_VERSION 0.1 #define MAX6633_DATE 20070301 //#define MAX633_SYSCTL_FUNC1 0x1000 //#define MAX6633_REG_GENERIX 0x0 int max6633_attach_adapter(struct i2c_adapter *adapter); int max6633_detach_client(struct i2c_client *client); int max6633_detect_client(struct i2c_adapter *adapter, int address, int kind); void max6633_cleanup(void); static struct i2c_driver max6633_driver = { .driver = { .name = "max6633", }, .attach_adapter = max6633_attach_adapter, .detach_client = max6633_detach_client, // .command = &max6633_command /* may be NULL */ }; struct max6633_data { struct i2c_client client; struct mutex update_lock; int sysctl_id; /* To keep the /proc directory entry */ char valid; u16 temp; unsigned long last_updated; }; /// TODO: create the function func1 or rename it here /* static ctl_table max6633_dir_table_template[]= { { MAX633_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real, &i2c_sysctl_real, NULL, &max6633_temp }, { 0 } }; */ void max6633_temp(struct i2c_client *client, int operation, int ctl_name, int *nrels_mag, long *results) { return; } int max6633_read_value(struct i2c_client *client, u8 reg) { return i2c_smbus_read_word_data(client,reg); } int max6633_write_value(struct i2c_client *client, u8 reg, u16 value) { return i2c_smbus_write_word_data(client,reg,value); } /// TODO: check all possible addresses /* scan 0x40, 0x41 and 0x42 */ static unsigned short normal_i2c[] = { 0x40, 0x41, 0x42, I2C_CLIENT_END }; /* Magic definition of all other variables and things */ I2C_CLIENT_INSMOD; int max6633_attach_adapter(struct i2c_adapter *adapter) { return i2c_probe(adapter, &addr_data,max6633_detect_client); } int max6633_detect_client(struct i2c_adapter *adapter, int address, int kind) { int err=0; //int i; struct i2c_client *new_client; struct max6633_data *data; /* Let's see wheter this adapter can support what we need */ if(!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE_DATA)) { printk("max6633: Adapter doesn't support functionality.\n"); goto ERROR0; } // const char *type_name=""; /* OK. For now, we presume we have a valid client. We no create the client structure, even though we cannot fill it completely yet. But it allows us to access several i2c functions safely */ if(!(data=kzalloc(sizeof(struct max6633_data), GFP_KERNEL))) { err=-ENOMEM; goto ERROR0; } new_client=&data->client; i2c_set_clientdata(new_client, data); new_client->addr=address; new_client->adapter=adapter; new_client->driver=&max6633_driver; new_client->flags=0; /* Now, we do the remaining detection. If no `force' parameter is used. */ /* First, the generic detection (if any), that is skipped if any force parameter was used. */ if(kind <0) { /* The bellow is of course bogus */ /* if(max6633_read_value(new_client, MAX633_REG_GENERIC) != MAX633_GENERIC_VALUE) goto ERROR1; */ } /* Fill in the remaining client fields. */ strcpy(new_client->name,"max6633"); data->valid=0; //init_MUTEX(&data->update_lock); /* only if you use this field */ /* Any other initialisation in data must be done here too. */ /* Tell the i2c layer a new client has arrived */ if((err=i2c_attach_client(new_client))) goto ERROR3; // type_name="chip1"; /* for /proc entry */ /* Register a new directory entry with module sensors. See above for the template structure. */ /* if((i=i2c_register_entry(new_client, type_name, max6633_dir_table_template, THIS_MODULE)) < 0) { err=i; goto ERROR4; } */ //data->sysctl_id=i; /* This function can write default values to the client registers, if needed. */ //max6633_init_client(new_client); printk(KERN_INFO "Found max6633 I2C temperature sensor.\n"); return 0; /* OK, this is not exactly good programming practice, usually. But it is ver code-efficient in this case. */ // ERROR4: // i2c_detach_client(new_client); ERROR3: // ERROR2: // ERROR1: kfree(data); ERROR0: return err; } int max6633_detach_client(struct i2c_client *client) { int err; /* Try to detach the client from i2c space */ if((err=i2c_detach_client(client))) return err; kfree(i2c_get_clientdata(client)); return 0; } /* Keep track of how far we got in the initialisation process. If several things have to initialized and we fail halfway, only those things have to be cleared up! */ static int __initdata max6633_initialized = 0; static int __init max6633_init(void) { int res; printk("max6633 version %f (%d)\n", MAX6633_VERSION, MAX6633_DATE); if((res=i2c_add_driver(&max6633_driver))) { printk("max6633: Driver registration failed, module not inserted.\n"); max6633_cleanup(); return res; } max6633_initialized ++; return 0; } void max6633_cleanup(void) { int res; if(max6633_initialized==1) { if((res=i2c_del_driver(&max6633_driver))) { printk("max6633: Driver registration failed, module not removed.\n"); return; } max6633_initialized --; } } MODULE_AUTHOR("Matthias Fechner "); MODULE_DESCRIPTION("Driver for MAX6633 temperature I2C device."); module_init(max6633_init); module_exit(max6633_cleanup);