1 #include 2 #include 3 #include 4 #include 5 #include 6 7 static dev_t pca9555_dev_number; 8 static struct cdev *driver_object; 9 static struct class *pca9555_class; 0 static struct device *pca9555_dev; 1 static struct i2c_adapter *adapter; 2 static struct i2c_client *slave; 3 4 static struct i2c_device_id pca9555_idtable[] = { 5 { "pca9555", 0 }, { } 6 }; 7 MODULE_DEVICE_TABLE(i2c, pca9555_idtable); 8 9 static struct i2c_board_info info_20 = { 0 I2C_BOARD_INFO("pca9555", 0x20), 1 }; 2 3 static ssize_t driver_write( struct file *instanz, 4 const char __user *user, size_t count, loff_t *offset ) 5 { 6 unsigned long not_copied, to_copy; 7 char value=0, buf[2]; 8 9 to_copy = min( count, sizeof(value) ); 0 not_copied=copy_from_user(&value, user, to_copy); 1 to_copy -= not_copied; 2 3 if( to_copy > 0 ) { 4 buf[0] = 0x02; // output port 0 5 buf[1] = value; 6 i2c_master_send( slave, buf, 2 ); 7 } 8 return to_copy; 9 } 0 static ssize_t driver_read( struct file *instanz, 1 char __user *user, size_t count, loff_t *offset ) 2 { 3 unsigned long not_copied, to_copy; 4 char value, command; 5 6 command = 0x01; // input port 1 7 i2c_master_send( slave, &command, 1 ); 8 i2c_master_recv( slave, &value, 1 ); 9 0 to_copy = min( count, sizeof(value) ); 1 not_copied=copy_to_user( user, &value, to_copy); 2 return to_copy - not_copied; 3 } 4 5 static int pca9555_probe( struct i2c_client *client, 6 const struct i2c_device_id *id ) 7 { 8 char buf[2]; 9 0 printk("pca9555_probe: %p %p \"%s\"- ",client,id,id->name); 1 printk("slaveaddr: %d, name: %s\n",client->addr,client->name); 2 if (client->addr != 0x20 ) { 3 printk("i2c_probe: not found\n"); 4 return -1; 5 } 6 // Konfiguration Port 0 als Output 7 buf[0] = 0x06; // direction port 0 8 buf[1] = 0x00; // output 9 i2c_master_send( client, buf, 2 ); 0 return 0; 1 } 2 3 static int pca9555_remove( struct i2c_client *client ) 4 { 5 return 0; 6 } 7 static struct file_operations fops = { 8 .owner= THIS_MODULE, 9 .write= driver_write, 0 .read = driver_read, 1 }; 2 3 static struct i2c_driver pca9555_driver = { 4 .driver = { 5 .name = "pca9555", 6 }, 7 .id_table = pca9555_idtable, 8 .probe = pca9555_probe, 9 .remove = pca9555_remove, 0 }; 1 2 static int __init mod_init( void ) 3 { 4 if( alloc_chrdev_region(&pca9555_dev_number,0,1,"pca9555")<0 ) 5 return -EIO; 6 driver_object = cdev_alloc(); 7 if( driver_object==NULL ) 8 goto free_device_number; 9 driver_object->owner = THIS_MODULE; 0 driver_object->ops = &fops; 1 if( cdev_add(driver_object,pca9555_dev_number,1) ) 2 goto free_cdev; 3 pca9555_class = class_create( THIS_MODULE, "pca9555" ); 4 if( IS_ERR( pca9555_class ) ) { 5 pr_err( "pca9555: no udev support\n"); 6 goto free_cdev; 7 } 8 pca9555_dev = device_create( pca9555_class, NULL, 9 pca9555_dev_number, NULL, "%s", "pca9555" ); 0 dev_info(pca9555_dev, "mod_init\n"); 1 2 if (i2c_add_driver(&pca9555_driver)) { 3 pr_err("i2c_add_driver failed\n"); 4 goto destroy_dev_class; 5 } 6 adapter = i2c_get_adapter(1); // Adapter sind durchnummeriert 7 if (adapter==NULL) { 8 pr_err("i2c_get_adapter failed\n"); 9 goto del_i2c_driver; 0 } 1 slave = i2c_new_device( adapter, &info_20 ); 2 if (slave==NULL) { 3 pr_err("i2c_new_device failed\n"); 4 goto del_i2c_driver; 5 } 6 return 0; 7 del_i2c_driver: 8 i2c_del_driver(&pca9555_driver); 9 destroy_dev_class: 0 device_destroy( pca9555_class, pca9555_dev_number ); 1 class_destroy( pca9555_class ); 2 free_cdev: 3 kobject_put( &driver_object->kobj ); 4 free_device_number: 5 unregister_chrdev_region( pca9555_dev_number, 1 ); 6 return -EIO; 7 } 8 9 static void __exit mod_exit( void ) 0 { 1 dev_info(pca9555_dev, "mod_exit"); 2 device_destroy( pca9555_class, pca9555_dev_number ); 3 class_destroy( pca9555_class ); 4 cdev_del( driver_object ); 5 unregister_chrdev_region( pca9555_dev_number, 1 ); 6 i2c_unregister_device( slave ); 7 i2c_del_driver(&pca9555_driver); 8 return; 9 } 0 module_init( mod_init ); 1 module_exit( mod_exit ); 2 MODULE_LICENSE("GPL");