int chardev_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
struct my_dev *dev = file->private_data;
int retval = 0, tmp = 0;
if( _IOC_TYPE(cmd) != KF701_IOC_MAGIC )
return -ENOTTY;
if( _IOC_NR(cmd) > KF701_IOC_MAXNR )
return -ENOTTY;
switch(cmd)
{
case KF701_IO_RESET:
printk(KERN_DEBUG "%s:IO_RESET CMD\n",DEVICE);
break;
case KF701_IO_R:
printk(KERN_DEBUG "%s:IO READ CMD\n",DEVICE);
retval = put_user(dev->index, (int __user *)arg);
break;
case KF701_IO_W:
printk(KERN_DEBUG "%s:IO WRITE CMD\n",DEVICE);
retval = get_user(tmp, (int __user *)arg);
printk(KERN_DEBUG "CMD ARG = %d\n", tmp);
break;
case KF701_IO_RW:
printk(KERN_DEBUG "%s:IO W-R CMD\n",DEVICE);
break;
default:
return -ENOTTY;
}
return retval;
}
unsigned int chardev_poll(struct file * file, poll_table * wait)
{
struct my_dev *dev = file->private_data;
unsigned int mask = 0;
down(&dev->sem);
poll_wait(file,&dev->rq,wait);
if( 0 != dev->index )
mask |= POLLIN | POLLRDNORM;
up(&dev->sem);
return mask;
}
// 此函数在进程上下文之外运行,类似中断上下文,因此:
// 1. 不能访问用户空间
// 2. current指针没有意义
// 3. 不能调用可能引起体眠和调度的代码,信号量也不行。
// 4. 最好使用 spinlock
void timer_function(unsigned long arg)
{
struct my_dev *dev = (struct my_dev*)arg;
if( dev->index >= (dev->size - 1) )
return;
if( dev->timer_char > 'Z' )
dev->timer_char = 'A';
if( '\n' == dev->buf[dev->index-1] )
dev->index--;
dev->buf[dev->index++] = (dev->timer_char)++;
dev->buf[dev->index++] = '\n';
// 唤醒阻塞在 read 和 select 上的进程
wake_up_interruptible(&dev->rq);
dev->timer.expires += dev->timer_interval;
add_timer( &dev->timer );
}
module_init(chardev_init);
module_exit(chardev_exit);
MODULE_AUTHOR("kf701.ye at gmail.com");
MODULE_DESCRIPTION("Study for kf701");
MODULE_SUPPORTED_DEVICE(DEVICE);
MODULE_LICENSE("GPL");
阅读(762) | 评论(0) | 转发(0) |