前面我们介绍了简单的通用字符设备驱动程序,接下来,我们在它的基础上来实现GPIO的查询按键功能。
先附上驱动程序代码
1 /******************************
2 linux key_query
3 *****************************/
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14
15 #include 'mx257_gpio.h'
16 #include 'mx25_pins.h'
17 #include 'iomux.h'
18
19 #define Driver_NAME 'key_query'
20 #define DEVICE_NAME 'key_query'
21
22 #define GPIO2_21 MX25_PIN_CLKO
23 #define GPIO3_15 MX25_PIN_EXT_ARMCLK
24 #define GPIO2_10 MX25_PIN_A24
25 #define GPIO2_11 MX25_PIN_A25
26 #define GPIO2_8 MX25_PIN_A22
27 #define GPIO2_9 MX25_PIN_A23
28 #define GPIO2_6 MX25_PIN_A20
29 #define GPIO2_7 MX25_PIN_A21
30 //command
31 #define key_input 0
32 #define version 1
33 //用于保存主设备号
34 static int major=0;
35 //用于自动创建设备节点 代替了手动敲mknod命令
36 //auto to create device node
37 static struct class *drv_class = NULL;
38 static struct class_device *drv_class_dev = NULL;
39
40
41 /* 应用程序对设备文件/dev/key_query执行open(...)时,
42 * 就会调用key_open函数*/
43 static int key_open(struct inode *inode, struct file *file)
44 {
45 printk('<0>function open!nn');
46
47 return 0;
48 }
49 /*当应用程序中read(fd,buff,sizeof(buff))时调用此key_read函数*/
50 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
51 {
52 int ret;
53 //nt cnt=0;
54 unsigned char key_vals[8];
55 // reading the pins value
56 key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
57 key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
58 key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
59 key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
60 key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
61 key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
62 key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
63 key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
64
65 ret = copy_to_user(buff,key_vals,sizeof(key_vals));
66 if(ret){
67 ;
68 }
69
70 //printk('<0>%04d key pressed: %d %d %d %d %d %d %d %dn',cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]);
71
72 return sizeof(key_vals);
73 }
74 /* 当应用程序中使用write函数时,调用此函数**/
75 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
76 {
77 printk('<0>function write!nn');
78
79 return 1;
80 }
81
82 static int key_release(struct inode *inode, struct file *filp)
83 {
84 printk('<0>function release!nn');
85 return 0;
86 }
87 /* 当用户调用ioctl(fd,version,NULL);时,会进入此函数,
88 * 在SWITCH中配对command,然后执行相应的语句
89 * 注意command 一定为整数,需在前面定义*/
90 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
91 {
92 printk('<0>function ioctl!nn');
93 switch (command) {
94 case key_input:
95 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
96 gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
97 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
98 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
99 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
100 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
101 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
102 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
103 //设置所有引脚为上拉模式
104 mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
105 mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
106 //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
107 mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
108 mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
109 mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
110 mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
111 //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
112 break;
113 case version:
114 printk('<0>hello,the version is 0.1.0nn');
115 break;
116 default:
117 printk('<0>command error n');
118 printk('<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;n');
119 printk('<0>command:
120 return -1;
121 }
122 return 0;
123 }
124
125 /* 这个结构是字符设备驱动程序的核心
126 * 当应用程序操作设备文件时所调用的open、read、write等函数,
127 * 最终会调用这个结构中指定的对应函数
128 */
129 static struct file_operations key_fops = {
130 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
131 .open = key_open,
132 .read = key_read,
133 .write = key_write,
134 .release= key_release,
135 .ioctl = key_ioctl,
136 };
137
138 /*
139 * 执行insmod命令时就会调用这个函数
140 */
141 static int __init key_init(void)
142 {
143 printk('<0>nHello,this is %s module!nn',Driver_NAME);
144 //register and mknod
145 //注册字符设备,系统会自动分配一个主设备号,保存在major中
146 major = register_chrdev(0,Driver_NAME,&key_fops);
147 //自动在/dev/目录下创建设备节点
148 drv_class = class_create(THIS_MODULE,Driver_NAME);
149 drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME); /*/dev/key_query*/
150
151 //set all pins to GPIO mod ALF5
152 //设置所有的GPIO引脚为GPIO功能
153 mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
154 mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
155 mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
156 mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
157 mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
158 mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
159 mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
160 mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
161
162
163 printk('<0>have setting all pins to gpio input mod !n');
164 //request IOMUX GPIO
165 gpio_request(IOMUX_TO_GPIO(GPIO2_21), 'GPIO2_21');
166 gpio_request(IOMUX_TO_GPIO(GPIO3_15), 'GPIO3_15');
167 gpio_request(IOMUX_TO_GPIO(GPIO2_10), 'GPIO2_10');
168 gpio_request(IOMUX_TO_GPIO(GPIO2_11), 'GPIO2_11');
169 gpio_request(IOMUX_TO_GPIO(GPIO2_8), 'GPIO2_8');
170 gpio_request(IOMUX_TO_GPIO(GPIO2_9), 'GPIO2_9');