通过字符设备驱动分步注册方式编写LED驱动,完成设备文件和设备的绑定,发布CSDN
用户层程序app
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include "head.h"
- int main(int argc, const char *argv[])
- {
- char buf[128] = "";
- int a;
- int fd;
- while (1)
- {
- printf("请选择要打开的灯(1,2,3)\n");
- scanf(" %d", &a);
- switch (a)
- {
- case 1:
- fd = open("/dev/myled0", O_RDWR);
- if (fd < 0)
- {
- printf("设备文件打开失败\n");
- exit(-1);
- }
- printf("打开文件%d成功\n",a-1);
- break;
- case 2:
- fd = open("/dev/myled1", O_RDWR);
- if (fd < 0)
- {
- printf("设备文件打开失败\n");
- exit(-1);
- }
- printf("打开文件%d成功\n",a-1);
- break;
- case 3:
- fd = open("/dev/myled2", O_RDWR);
- if (fd < 0)
- {
- printf("设备文件打开失败\n");
- exit(-1);
- }
- printf("打开文件%d成功\n",a-1);
- break;
- default:
- printf("请输入范围内的数\n");
- }
-
- int b;
- printf("请开灯关灯(0/1)\n");
- scanf(" %d",&b);
- switch(b)
- {
- case 1:
- ioctl(fd,LED_ON);
- break;
- case 0:
- ioctl(fd,LED_OF);
- break;
- default:
- printf("请输入'0'或'1'\n");
- }
- close(fd);
- printf("关闭文件%d\n",a-1);
- }
-
- return 0;
- }
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/uaccess.h>
- #include <linux/compiler.h>
- #include <linux/io.h>
- #include <linux/device.h>
- #include <linux/slab.h>
- #include <linux/cdev.h>
- #include "head.h"
- unsigned int major;
- struct class *cls;
- struct device *dev;
- char kbuf[128] = "";
- unsigned int *vir_modere;
- unsigned int *vir_moderf;
- unsigned int *vir_rcc;
- unsigned int *vir_odre;
- unsigned int *vir_odrf;
- struct cdev *cdev;
- unsigned int major = 240;
- unsigned int minor = 0;
- struct class *cls;
- struct device *dev;
-
- int ret;
- dev_t devno;
-
- int mycdev_open(struct inode *inode, struct file *file)
- {
- int num=MINOR(inode->i_rdev);
- file->private_data=(void*)num;
-
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- return 0;
- }
- ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
- {
-
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- return 0;
- }
- ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
- {
-
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- return 0;
- }
- int mycdev_close(struct inode *inode, struct file *file)
- {
- printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
- return 0;
- }
- long myled_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
- {
- int num=(int)file->private_data;
- switch(num)
- {
- case 0://控制LED1
- switch(cmd)
- {
- case LED_ON:
- (*vir_odre) |= (0x1 << 10);
- break;
- case LED_OF:
- (*vir_odre) &= (~(0x1 << 10));
- }
- break;
- case 1://控制LED2
- switch(cmd)
- {
-
- case LED_ON:
- (*vir_odrf) |= (0x1 << 10);
- break;
- case LED_OF:
- (*vir_odrf) &= (~(0x1 << 10));
- }
- break;
- case 2://控制LED3
- switch(cmd)
- {
-
- case LED_ON:
- (*vir_odre) |= (0x1 << 8);
- break;
- case LED_OF:
- (*vir_odre) &= (~(0x1 << 8));
- }
- }
- return 0;
- }
- struct file_operations fops = {
- .open = mycdev_open,
- .read = mycdev_read,
- .write = mycdev_write,
- .release = mycdev_close,
- .unlocked_ioctl=myled_ioctl,
- };
- int led_init(void)
- {
- vir_rcc = ioremap(LED_RCC, 4);
- if (vir_rcc == NULL)
- {
- printk("物理映射失败%d\n", __LINE__);
- }
- vir_modere = ioremap(LED_MODERE, 4);
- if (vir_rcc == NULL)
- {
- printk("物理映射失败%d\n", __LINE__);
- }
- vir_moderf = ioremap(LED_MODERF, 4);
- if (vir_rcc == NULL)
- {
- printk("物理映射失败%d\n", __LINE__);
- }
- vir_odre = ioremap(LED_ODRE, 4);
- if (vir_rcc == NULL)
- {
- printk("物理映射失败%d\n", __LINE__);
- }
- vir_odrf = ioremap(LED_ODRF, 4);
- if (vir_rcc == NULL)
- {
- printk("物理映射失败%d\n", __LINE__);
- }
-
- // rcc使能
- (*vir_rcc) |= (0x1 << 4);
- (*vir_rcc) |= (0x1 << 5);
- // moder设置输出模式
- // led1,PE10
- (*vir_modere) &= (~(0x3 << 20));
- (*vir_modere) |= (0x1 << 20);
- // led2,PF10
- (*vir_moderf) &= (~(0x3 << 20));
- (*vir_moderf) |= (0x1 << 20);
- // led3,PE8
- (*vir_modere) &= (~(0x3 << 16));
- (*vir_modere) |= (0x1 << 16);
- // 设置默认为关灯
- (*vir_odre) &= (~(0x1 << 10));
- (*vir_odrf) &= (~(0x1 << 10));
- (*vir_odre) &= (~(0x1 << 8));
- return 0;
- }
- static int __init mycdev_init(void)
- {
- // 字符设备驱动注册
- /* major = register_chrdev(0,"mychrdev",&fops);
- if(major < 0)
- {
- printk("字符设备驱动注册失败\n");
- return major;
- }
- printk("字符设备驱动注册成功%d\n",major);
- */
- // 申请空间
- cdev = cdev_alloc();
- if (cdev == NULL)
- {
- printk("空间申请失败\n");
- ret = -EFAULT;
- goto out1;
- }
- printk("申请空间成功\n");
- // 字符设备初始化
- cdev_init(cdev, &fops);
- if (major > 0)
- {
- // 静态申请设备号
- ret = register_chrdev_region(MKDEV(major,minor), 3, "myled");
- if (ret)
- {
- printk("静态指定设备号失败\n");
- goto out2;
- }
- }
- else
- {
- // 动态申请设备号
- ret = alloc_chrdev_region(&devno, minor, 3, "myled");
- if (ret)
- {
- printk("动态申请设备号失败\n");
- // 释放空间
- goto out2;
- }
-
- // 获取主次设备号,因为静态动态申请不一样,在下面注册中要用到设备号
- major = MAJOR(devno); // 主设备号
- minor = MINOR(devno); // 次设备号
- }
- printk("申请设备号成功\n");
- // 注册驱动
- ret = cdev_add(cdev, MKDEV(major, minor), 3);
- if (ret)
- {
- printk("注册字符设备驱动对象\n");
- goto out3;
- }
- printk("注册字符设备驱动对象成功");
- // 进行映射
- led_init();
- // 向上提交目录信息
- cls = class_create(THIS_MODULE, "myled");
- if (IS_ERR(cls))
- {
- printk("向上提供目录\n");
- ret = -PTR_ERR(cls);
- goto out4;
- }
- printk("向上提交目录成功\n");
- //向上提交节点信息
- int i;
- for (i = 0; i < 3; i++)
- {
- dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
- if (IS_ERR(dev))
- {
- printk("向上提交设备节点信息失败\n");
- ret = -PTR_ERR(dev);
- goto out5;
- }
- printk("向上提交设备节点信息成功\n");
- }
- return 0;
- out5:
- for(--i;i>=0;i--)
- {
- device_destroy(cls, MKDEV(major, i));
- }
- class_destroy(cls);
- out4:
- cdev_del(cdev);
- out3:
- unregister_chrdev_region(MKDEV(major, minor), 3);
- out2:
- kfree(cdev);
- out1: return ret;
- }
-
- static void __exit mycdev_exit(void)
- {
- // unregister_chrdev(major,"mychrdev");
- int i;
- for(i=0;i<3;i++)
- {
- device_destroy(cls,MKDEV(major,i));
- }
- class_destroy(cls);
- cdev_del(cdev);
- unregister_chrdev_region(MKDEV(major,minor),3);
- kfree(cdev);
-
- iounmap(vir_rcc);
- iounmap(vir_modere);
- iounmap(vir_moderf);
- iounmap(vir_odre);
- iounmap(vir_odrf);
- }
-
- module_init(mycdev_init);
- module_exit(mycdev_exit);
- MODULE_LICENSE("GPL");
头文件
- #ifndef __H__
- #define __H__
- #define LED_MODERE 0X50006000
- #define LED_MODERF 0X50007000
- #define LED_ODRE 0X50006014
- #define LED_ODRF 0X50007014
- #define LED_RCC 0X50000A28
- #define LED_ON _IO('l',1)
- #define LED_OF _IO('l',0)
-
-
- #endif