来自:http://blog.csdn.net/tjd0227/archive/2010/04/22/5517256.aspx 由于对sysfs的概念不是太清楚,只是知道sysfs是一种类似于/proc的虚拟文件系统,可以在用户空间读写sysfs中的相应文件访问或控制内核空间数据,后拜读各类文章后终于对sysfs及平台设备有了更深层次的理解,但读的再多不如亲手一试。恰巧公司需要为android系统提供一个马达驱动,并且android又恰巧很多驱动的读写方式都是通过sysfs操作的,于是开始行动…… #define VIBRA_MINOR 88 #define STARTUP_VIBRA_DELAY 150 static unsigned int onkey_stat; static struct timer_list vibra_timer; static void vibra_stop_vibration(unsigned long data) { struct micco_vibra *vibra = (void *)data; struct vibra_control *control = vibra->vibra_ctl; control->level = 0x0; micco_write(MICCO_VIBRA_CONTROL, control->level); } static int raw_vibrate(int level) //驱动马达,level控制转速 { u8 val; val = level & 0x00fe; DMSG("+/-vibra_ioctl\n"); micco_write(MICCO_VIBRA_CONTROL, val); return 0; } static int adv_vibrate(struct vibra_control *ctl) //驱动马达,level控制转速 { u8 val; val = ctl->level & 0x00fe; micco_write(MICCO_VIBRA_CONTROL, val); mod_timer(&vibra_timer, jiffies + msecs_to_jiffies(ctl->m_time)); return 0; } static int vibra_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) //用户空间通过ioctl操作马达 { int ret; unsigned int level; u8 val; unsigned int onkey_val; struct vibra_control ctl; switch(cmd) { case VIBRA_RAW_VIBTATION: ret = copy_from_user(&level, (void *)arg, sizeof(unsigned int)); ret = raw_vibrate(level); break; case VIBRA_ADV_VIBTATION: ret = copy_from_user(&ctl, (void *)arg, sizeof(struct vibra_control)); ret = adv_vibrate(&ctl); break; case VIBRA_POWERON_STAT_GET: ret = copy_to_user((void *)arg, &onkey_stat, sizeof(unsigned int)); break; case VIBRA_ONKEY_STAT_GET: ret = micco_read(MICCO_STATUS_A, &val); if (ret < 0) { printk("read MICCO_STATUS_A failed\n"); onkey_val = 0; } onkey_val = !(val & MICCO_STATUS_A_ONKEY); ret = copy_to_user((void *)arg, &onkey_val, sizeof(unsigned int)); break; default: if (cmd < 0xFF) ret = raw_vibrate(cmd); else ret = -ENOIOCTLCMD; } return ret; } /*用户空间读取马达运转时间*/ static ssize_t vibrator_mtime_show(struct device *dev, struct device_attribute *attr, char *buf) { struct micco_vibra *vibra = dev_get_drvdata(dev); struct vibra_control *control = vibra->vibra_ctl; return sprintf(buf, "%u\n", control->m_time); } /*用户空间修改马达运转时间*/ static ssize_t vibrator_mtime_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct micco_vibra *vibra = dev_get_drvdata(dev); struct vibra_control *control = vibra->vibra_ctl; char *endp; control->m_time = simple_strtoul(buf, &endp, 10); DMSG("vibrator_mtime_store: m_tme = %d\n",control->m_time ); adv_vibrate(control); return count; } /*属性设置及读写属性注册*/ static DEVICE_ATTR(mtime, 0664, vibrator_mtime_show, vibrator_mtime_store); /*用户空间读马达转速*/ static ssize_t vibrator_level_show(struct device *dev, struct device_attribute *attr, char *buf) { struct micco_vibra *vibra = dev_get_drvdata(dev); struct vibra_control *control = vibra->vibra_ctl; return sprintf(buf, "%u\n", control->level); } /*用户空间调整马达转速*/ static ssize_t vibrator_level_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct micco_vibra *vibra = dev_get_drvdata(dev); struct vibra_control *control = vibra->vibra_ctl; char *endp; control->level = simple_strtoul(buf, &endp, 10); DMSG("vibrator_level_store:raw_vibrate(%x)", control->level); adv_vibrate(control); return count; } /*属性设置及读写属性注册*/ static DEVICE_ATTR(level, 0664, vibrator_level_show, vibrator_level_store); static struct file_operations vibra_fops = { .owner = THIS_MODULE, .ioctl = vibra_ioctl, }; static struct miscdevice vibra_miscdev = { .minor = VIBRA_MINOR, .name = "micco_vibra", .fops = &vibra_fops, }; static int __devinit vibra_init(struct micco_vibra *vibra) { struct vibra_control *ctl; int ret; u8 val; ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); if (ctl == NULL) return -ENOMEM; vibra->vibra_ctl = ctl; ctl->level=0; ctl->m_time=0; vibra_timer.function = vibra_stop_vibration; vibra_timer.data = (unsigned long) vibra; init_timer(&vibra_timer); /*注册vibra_miscdev设备*/ ret = misc_register(&vibra_miscdev); if (ret < 0) { dev_err(&vibra->pdev->dev, "can't register vibra device\n"); goto err2; } printk("\nVIBRA Probe vibra_miscdev->minor=%d\n",vibra_miscdev.minor); ret = micco_read(MICCO_FAULT_LOG, &val); printk("Fault Log value is 0x%x---------->\n", val); ret = micco_read(MICCO_STATUS_A, &val); if (ret < 0) { printk("read MICCO_STATUS_A failed\n"); onkey_stat = 0; return 0; } onkey_stat = !(val & MICCO_STATUS_A_ONKEY); if (onkey_stat) { raw_vibrate(0x7e); mdelay(100); raw_vibrate(0x0); } /*创建sysfs文件系统节点*/ if (device_create_file(&vibra->pdev->dev, &dev_attr_level) < 0) goto err3; if (device_create_file(&vibra->pdev->dev, &dev_attr_mtime) < 0) goto err4; return 0; /* err5: device_remove_file(&vibra->pdev->dev, &dev_attr_vibrator_mtime); */ err4: device_remove_file(&vibra->pdev->dev, &dev_attr_level); err3: misc_deregister(&vibra_miscdev); err2: kfree(ctl); return ret; } static void __devexit vibra_exit(struct micco_vibra *vibra) { device_remove_file(&vibra->pdev->dev, &dev_attr_mtime); device_remove_file(&vibra->pdev->dev, &dev_attr_level); misc_deregister(&vibra_miscdev); } /**************************************************************************** * Initialization / Registeration / Removal ***************************************************************************/ static int vibra_probe(struct platform_device *pdev) { struct micco_vibra *vibra; int r = -ENODEV; vibra = kzalloc(sizeof(*vibra), GFP_KERNEL); if (vibra == NULL) return -ENOMEM; /*注册驱动数据 */ dev_set_drvdata(&pdev->dev, vibra); vibra->pdev = pdev; r = vibra_init(vibra); if (r) goto err1; return 0; err1: kfree(vibra); return r; } static int vibra_remove(struct platform_device *pdev) { struct micco_vibra *vibra = dev_get_drvdata(&pdev->dev); dev_dbg(&vibra->pdev->dev, "%s\n", __FUNCTION__); vibra_exit(vibra); kfree(vibra); return 0; } static struct platform_device vibra_plat_device = { .name = "micco-vibra", //sysfs设备目录“/sys/devices/platform/micco-vibra.0” .id = 0, }; static struct platform_driver vibra_plat_driver = { .driver = { .name = "micco-vibra", //和vibra_plat_device 的name名字相同 .owner = THIS_MODULE, }, .probe = vibra_probe, .remove = vibra_remove, }; static int __init plat_vibra_init(void) { int rc; printk("vibra driver initializing\n"); rc = platform_device_register(&vibra_plat_device); if (rc < 0) return rc; rc = platform_driver_register(&vibra_plat_driver); if (rc < 0) goto err_register_vibra_dev; return rc; err_register_vibra_dev: platform_device_unregister (&vibra_plat_device); return rc; } static void __exit plat_vibra_exit(void) { platform_driver_unregister(&vibra_plat_driver); platform_device_unregister (&vibra_plat_device); } module_init(plat_vibra_init); module_exit(plat_vibra_exit); |
sysfs方式实现马达驱动
最新推荐文章于 2024-02-20 14:21:46 发布