S3C2440独立键盘Linux设备驱动(3)


/*********************************************************************************************
*注册设备,创建设备节点
**********************************************************************************************/
static  int key_setup_cdev(struct key_dev *dev,int index)
{
 int err;
 int devno = MKDEV(KEYBOARD_MAJOR,index);
 
 cdev_init(&dev->cdev,&key_fops);
 dev->cdev.owner = THIS_MODULE;
 dev->cdev.ops = &key_fops;
 
 err = cdev_add(&dev->cdev,devno,1);     //向系统注册设备
 if(err) printk(KERN_ALERT "Error %d adding key %d",err,index);

//注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
 key_class = class_create(THIS_MODULE, DEVICE_NAME);
 if(IS_ERR(key_class))
 {
  printk("Err: failed in led class. \n");
  return -1;
 }
 //创建一个设备节点,节点名为DEVICE_NAME
 class_device_create(key_class, NULL, MKDEV(keyboard_major, 0), NULL, DEVICE_NAME);
 return 0;
}


/*********************************************************************************************
 * 执行“insmod key.ko”命令时就会调用这个函数
 *********************************************************************************************/
static int __init key_init(void)
{
 int ret,i;
 printk(info);

/* 注册字符设备驱动程序
  * 参数为主设备号、设备名字、file_operations结构;
  * 这样,主设备号就和具体的file_operations结构联系起来了,
  * 操作主设备为BUTTON_MAJOR的设备文件时,就会调用key_fops中的相关成员函数
  * keyboard_major可以设为0,表示由内核自动分配主设备号
 */
 dev_t devno = MKDEV(keyboard_major,0);
 
 if(keyboard_major) ret=register_chrdev_region(devno,1,DEVICE_NAME); //注册主设备号
 else                 //申请主设备号
 {
  ret = alloc_chrdev_region(devno,0,1,DEVICE_NAME);
  keyboard_major = MAJOR(devno);
  }
 if(ret<0) return ret;

key_devp = kmalloc(sizeof(struct key_dev),GFP_KERNEL); // 动态申请设备结构体的内存
 if(!key_devp)
 {
  ret = -ENOMEM;
  goto fail_malloc;
 }
 memset(key_devp,0,sizeof(struct key_dev));
 
 key_setup_cdev(key_devp,0);

for(i=0;i<KEY_NUM;i++)
  key_devp->key_status[i]=KEYSTATUS_UP;    //初始化键盘状态
 for(i=0;i<KEY_NUM;i++)
  key_devp->key_values[i]=0;       //初始化键值
 key_devp->key_values_flag=0;        //表示四个按键都没有被按下
 init_waitqueue_head(&key_devp->key_waitq);
 
 for(i=0;i<KEY_NUM;i++)
  setup_timer(&key_timer[i],key_timer_handler,(void *)&key_irqs[i]); //将&key_irqs[i]作为参数传入定时器中断处理程序
 return 0;
 
 fail_malloc: unregister_chrdev_region(devno,1);
 return ret;
}

/***********************************************************************************************
* 执行”rmmod key.ko”命令时就会调用这个函数
************************************************************************************************/
static void __exit key_exit(void)
{
 /* 卸载驱动程序 */
 printk(KERN_ALERT "******************unregister keyboard driver*************************\n");
 cdev_del(&key_devp->cdev);            //注消cdev
 kfree(key_devp);
 class_device_destroy(key_class, MKDEV(keyboard_major, 0)); //删掉类
 class_destroy(key_class);            //注销类结构体
 unregister_chrdev_region(MKDEV(keyboard_major,0),1);   // 释放设备号
}

/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(key_init);
module_exit(key_exit);

/* 描述驱动程序的一些信息,不是必须的 */
MODULE_AUTHOR("Ma Dongpeng<madongpeng@hrbeu.edu.cn>");   // 驱动程序的作者
MODULE_DESCRIPTION("keyborad Driver");         // 一些描述信息
MODULE_LICENSE("GPL");              // 遵循的协议

makefile文件:

CC = arm-linux-gcc

HOSTCC = gcc

#######################################################################

KERNELDIR = /opt/S3C2440/linux-2.6.25.9

#######################################################################

obj-m := keybord.o

#module-objs := keybord.o

all:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:

rm -rf *.o

应用程序:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwsyxy.html