struct adc_sensor_t{ struct s3c_adc_client *client; struct class *class; struct cdev cdev; dev_t devno; int data; unsigned char channel; }; static struct adc_sensor_t adc_sensor_dev; static ssize_t adc_sensor_read(struct file *file, char __user *buff, size_t count, loff_t *offset) { //unsigned data; //unsigned ch; //data = 10; //ch = 0; adc_sensor_dev.data = s3c_adc_read(adc_sensor_dev.client, adc_sensor_dev.channel); DLOG(KERN_INFO "data AIN%d is %d\n", adc_sensor_dev.channel, adc_sensor_dev.data); if(copy_to_user(buff, (char *)&adc_sensor_dev.data, sizeof(int))) return -EFAULT; return 0; } static long adc_sensor_ioctl( struct file *filp,unsigned int cmd,unsigned long arg) { if(cmd == ADC_SENSOR_IOCTL_SETCH){ if(arg >= ADC_CHANNEL_NUM) return -1; adc_sensor_dev.channel = arg; } return 0; } static int adc_sensor_open(struct inode *inode, struct file *file) { return 0; } static int adc_sensor_release(struct inode *inode, struct file *file) { return 0; } static struct file_operations adc_sensor_fops = { .owner = THIS_MODULE, .unlocked_ioctl = adc_sensor_ioctl, .read = adc_sensor_read, .open = adc_sensor_open, .release = adc_sensor_release, }; static int __devinit adc_sensor_probe( struct platform_device *pdev ) { struct device *dev = &pdev->dev; int ret = -EINVAL; DLOG("%s start\n", __func__); adc_sensor_dev.devno = MKDEV(DEVICE_MAJOR, DEVICE_MINOR); ret = register_chrdev_region(adc_sensor_dev.devno, DEVICE_NUMBER, DEVICE_NAME); if(ret < 0){ ret = alloc_chrdev_region(&adc_sensor_dev.devno, 0, DEVICE_NUMBER, DEVICE_NAME); if(ret < 0){ dev_err(dev, "failed to register device number\n"); goto err_register_chrdev_region; } } cdev_init(&adc_sensor_dev.cdev, &adc_sensor_fops); adc_sensor_dev.cdev.owner = THIS_MODULE; ret = cdev_add(&adc_sensor_dev.cdev, adc_sensor_dev.devno, DEVICE_NUMBER); if( ret ){ dev_err(dev, "failed to add device\n"); goto err_cdev_add; } adc_sensor_dev.client = s3c_adc_register (pdev, NULL, NULL, 0); if(IS_ERR(adc_sensor_dev.client)){ dev_err(dev, "failed to register adc client\n"); goto err_s3c_adc_register; } adc_sensor_dev.class = class_create(THIS_MODULE, DEVICE_NAME); if(IS_ERR(adc_sensor_dev.class)){ DLOG(KERN_ERR "%s:failed to class_create\n", __func__); goto err_class_create; } device_create(adc_sensor_dev.class, NULL, adc_sensor_dev.devno, NULL, DEVICE_NAME); adc_sensor_dev.channel = 4; adc_sensor_dev.data = 0; return 0; err_class_create: err_s3c_adc_register: cdev_del(&adc_sensor_dev.cdev ); err_cdev_add: unregister_chrdev_region(adc_sensor_dev.devno, DEVICE_NUMBER); err_register_chrdev_region: return ret; } static int __devexit adc_sensor_remove(struct platform_device *pdev) { s3c_adc_release(adc_sensor_dev.client); cdev_del(&adc_sensor_dev.cdev ); device_destroy(adc_sensor_dev.class, adc_sensor_dev.devno); class_destroy(adc_sensor_dev.class); unregister_chrdev_region(adc_sensor_dev.devno, DEVICE_NUMBER); return 0; } static struct platform_driver adc_sensor_driver = { .driver = { .name = "adc", .owner = THIS_MODULE, }, .probe = adc_sensor_probe, .remove = __devexit_p(adc_sensor_remove) }; static int __init adc_sensor_init(void) { return platform_driver_register(&adc_sensor_driver ); } static void __exit adc_sensor_exit (void) { platform_driver_unregister(&adc_sensor_driver ); } module_init(adc_sensor_init); module_exit(adc_sensor_exit); MODULE_AUTHOR("jvaemape"); MODULE_DESCRIPTION("S3C2440 ADC Sensor Drive"); MODULE_LICENSE("Dual BSD/GPL");