|
原帖由 samurai2 于 2010-10-22 12:36 发表 
我的意思是希望ioctl后面的代码开源,不是控制接口开源,那样没有多大意思,希望飞控板开源,算法开源啊
来一段 ioctl 里面的实现代码:
-
- struct file_operations pwm_fops = {
- .ioctl = pwm_ioctl,
- .open = pwm_open,
- .release = pwm_release,
- };
- ...
- static int pwm_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
- {
- struct pwm_info *info = filp->private_data;
- struct pwm_device *dev = info->dev;
- struct pwm_ops *ops = dev->pwm_ops;
- int ret = 0;
- if (!ops)
- return -EINVAL;
- if (mutex_lock_interruptible(&dev->lock))
- return -ERESTARTSYS;
- switch (cmd) {
- case PWM_REQUEST:
- case PWM_RELEASE:
- {
- unsigned int pwm;
- if (get_user(pwm, (int __user *) arg)) {
- ret = -EFAULT;
- }
- if (cmd == PWM_REQUEST)
- ret = ioctl_pwm_request(info, pwm);
- else
- ret = ioctl_pwm_release(info, pwm);
- break;
- }
- case PWM_START:
- ret = ioctl_pwm_start(info);
- break;
- case PWM_STOP:
- ret = ioctl_pwm_stop(info);
- break;
- case PWM_SET_FREQ:
- {
- unsigned int pwm_freq;
- if (get_user(pwm_freq, (int __user *) arg)) {
- ret = -EFAULT;
- break;
- }
- ret = ioctl_pwm_set_freq(info, pwm_freq);
- break;
- }
- case PWM_SET_WIDTH:
- {
- unsigned int pwm_width;
- if (get_user(pwm_width, (int __user *) arg)) {
- ret = -EFAULT;
- break;
- }
- ret = ioctl_pwm_set_width(info, pwm_width);
- break;
- }
- case PWM_GET_FREQ:
- {
- unsigned int pwm_freq;
- ret = ioctl_pwm_get_freq(info, &pwm_freq);
- if (put_user(pwm_freq, (int __user *) arg)) {
- ret = -EFAULT;
- }
- break;
- }
- case PWM_GET_WIDTH:
- {
- unsigned int pwm_width;
- ret = ioctl_pwm_get_width(info, &pwm_width);
- if (put_user(pwm_width, (int __user *) arg)) {
- ret = -EFAULT;
- }
- break;
- }
- case PWM_MAX:
- {
- if (put_user(ops->pwm_max, (int __user *) arg))
- ret = -EFAULT;
- break;
- }
- default:
- ret = -ENOTTY;
- }
- mutex_unlock(&dev->lock);
- return ret;
- }
- ...
- static int ioctl_pwm_start(struct pwm_info *info)
- {
- struct pwm_device *dev = info->dev;
- struct pwm_ops *ops = dev->pwm_ops;
- int err;
- if (info->id_used == PWM_ID_NONE) {
- err = -EINVAL;
- goto exit;
- }
- err = ops->pwm_start(info->id_used);
- exit:
- return err;
- }
- ...
- struct pwm_ops s3c2412_pwm_ops = {
- .pwm_max = PWM_TIMER_MAX,
- .pwm_start = s3c2412pwm_start,
- .pwm_stop = s3c2412pwm_stop,
- .pwm_request = s3c2412pwm_request,
- .pwm_release = s3c2412pwm_release,
- .pwm_set_width = s3c2412pwm_set_width,
- .pwm_set_freq = s3c2412pwm_set_freq,
- .pwm_get_width = s3c2412pwm_get_width,
- .pwm_get_freq = s3c2412pwm_get_freq,
- .owner = THIS_MODULE,
- };
- ...
- static int s3c2412pwm_start(unsigned int timer)
- {
- unsigned long tcon;
- unsigned long flags;
- /* invert do we want to invert TOUT output
- * auto_reload
- * tout do we want to activate TOUT gpio
- */
- const int invert = 0, auto_reload = 1, tout = 1;
- if (timer > PWM_TIMER_MAX)
- return -EINVAL;
- /* if the TOUT is already active there will be some discontinuity :
- * the manual update will reset the engine, and make
- * TOUT = !invert
- *
- * We can do nothing and assume we don't care of the signal before the
- * start.
- */
- local_irq_save(flags);
- tcon = __raw_readl(S3C2410_TCON);
- /* 2 configure timer */
- tcon &= ~((S3C2410_TCON_T0START|S3C2410_TCON_T0INVERT|S3C2410_TCON_T0RELOAD)<<S3C2410_TCON_OFFSET(timer));
- if (invert)
- tcon |= S3C2410_TCON_T0INVERT<<S3C2410_TCON_OFFSET(timer);
- if (auto_reload)
- tcon |= S3C2410_TCON_T0RELOAD<<S3C2410_TCON_OFFSET(timer);
- tcon |= S3C2410_TCON_T0MANUALUPD<<S3C2410_TCON_OFFSET(timer);
- dprintk("tcon init : %08lx\n", tcon);
- __raw_writel(tcon, S3C2410_TCON);
- /* 3 start the timer */
- tcon &= ~(S3C2410_TCON_T0MANUALUPD<<S3C2410_TCON_OFFSET(timer));
- tcon |= S3C2410_TCON_T0START<<S3C2410_TCON_OFFSET(timer);
- dprintk("tcon start : %08lx\n", tcon);
- __raw_writel(tcon, S3C2410_TCON);
- local_irq_restore(flags);
- if (tout)
- s3c2410_gpio_cfgpin(S3C2410_GPB0+timer, S3C2410_GPIO_SFN2);
- return 0;
- }
复制代码 |
|