Android linux adc驱动(s5pv210)
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");