1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14
15 #include
16 #include
17
18 #include
19
20 #define BUZZER_DEVICE_NAME "mybuzzer"
21 #define BUZZER_CLASS_NAME "mybuzzer" //sys/class/mybuzzer
22 #define BUZZER_DEVICE_NUM 1 //设备节点的编号最终生成节点的名字为/dev/buzzer-1
23
24
25 #define BUZZER_GPIO_SWITCH 1 //是否设置buzzer的gpio的初始化,另一个驱动已经初始化GPIO
26 #define BUZZER_DELAY_TIME_HIGHT (190000) //2.7KHZ
27 #define BUZZER_DELAY_TIME_LOW (190000) //2.7KHZ
28 #define DE_BUG 1
29
30 #if DE_BUG
31 #define prdebug(fmt,arg...) printk("zbzhuang"KERN_ERR fmt"\n",##arg)
32 #else
33 #define prdebug(fmt,arg...) do{}while(0);
34 #endif
35
36
37
38 typedef enum{39 BUZZER_DISABLE = 0,40 BUZZER_ENABLE,41 }BUZZER_STATUS_t;42
43 //buzzer的设备对象
44 structbuzzer_chip{45 dev_t devno;46 struct cdev *cdev;47 struct class *cls;48 struct device *dev;49 unsigned long count; //从应用空间读取的数据
50 structsemaphore sem;51 structhrtimer mytimer;52 ktime_t kt; //设置定时时间
53 wait_queue_head_t wait_queue;54 BUZZER_STATUS_t status;55 };56
57
58
59
60 static int count = 1000;61 struct buzzer_chip *buzzer_dev;62
63 static void buzzer_test(void);64 static void buzzer_gpio_start(void);65 static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer);66
67
68 int buzzer_drv_open (struct inode * inode, struct file *filp)69 {70 intminor;71 intmajor;72
73
74 prdebug("--------------%s----------------",__func__);75
76 minor =iminor(inode);77 major =imajor(inode);78
79 prdebug("\r\nmajor = %d minor = %d\rn",major,minor);80 filp->private_data = (void *)minor;81
82 if(down_interruptible(&buzzer_dev->sem))83 return -ERESTARTSYS;84
85 return 0;86 }87 ssize_t buzzer_drv_read (struct file *filp, char __user *userbuf, size_t count, loff_t *fpos)88 {89 intret;90
91 prdebug("--------------%s----------------",__func__);92
93 if(filp->f_flags &O_NONBLOCK){94 return -EAGAIN;95 }96
97 ret = copy_to_user(userbuf,&buzzer_dev->count,count);98 if(ret > 0){99 prdebug("error copy_to_user");100 return -EFAULT;101 }102 prdebug("%s :read count = %ld",__func__,buzzer_dev->count);103
104 returncount;105 }106 ssize_t buzzer_drv_write (struct file *filp, const char __user *userbuf, size_t count, loff_t *fpos)107 {108 intret;109
110 prdebug("--------------%s----------------",__func__);111 prdebug("task pid[%d] context[%s]",current->pid,current->comm);112
113 ret = copy_from_user(&buzzer_dev->count,userbuf,count);114 if(ret > 0){115 prdebug("error copy_from_user");116 return -EFAULT;117 }118
119 prdebug("%s :write count = %ld",__func__,buzzer_dev->count);120
121
122
123
124 if(buzzer_dev->count){125 if(buzzer_dev->status ==BUZZER_DISABLE){126 //启动定时器
127 prdebug("-----------start hrtimer timer-------------");128 buzzer_dev->status =BUZZER_ENABLE;129 buzzer_gpio_start();130 wait_event(buzzer_dev->wait_queue, buzzer_dev->status ==BUZZER_DISABLE);131 prdebug("------------wake up queue-------------------------------");132 }else{133 prdebug("buzzer_aready work");134 }135
136 }else{137
138 }139
140
141 returncount;142
143 }144 int buzzer_drv_close (struct inode *inode, struct file *filp)145 {146
147 prdebug("--------------%s----------------",__func__);148 up(&buzzer_dev->sem);149
150 return 0;151
152 }153
154 const struct file_operations buzzer_fops ={155 .open =buzzer_drv_open,156 .write =buzzer_drv_write,157 .read =buzzer_drv_read,158 .release =buzzer_drv_close,159
160 };161
162 static int buzzer_gpio_init(void)163 {164 int ret = -1;165
166 if(gpio_request(BUZZER_IO, "BUZZER_GPIO")){167 prdebug("error buzzer_gpio_init");168 returnret;169
170 }else{171 gpio_direction_output(BUZZER_IO, 1);172 gpio_set_value(BUZZER_IO, 1);173 buzzer_dev->status =BUZZER_DISABLE;174 }175
176 return 0;177
178 }179
180 static void buzzer_gpio_exit(void)181 {182 gpio_set_value(BUZZER_IO, 1);183 gpio_free(BUZZER_IO);184 }185
186 static void buzzer_gpio_start(void)187 {188 prdebug("-----------buzzer_gpio_start------------");189
190
191
192 //高精度定时器
193 hrtimer_init(&buzzer_dev->mytimer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);194 buzzer_dev->mytimer.function =hrtimer_handler;195 buzzer_dev->kt = ktime_set(0, BUZZER_DELAY_TIME_LOW);196 hrtimer_start(&buzzer_dev->mytimer,buzzer_dev->kt,HRTIMER_MODE_REL);197
198
199
200 }201
202 static void buzzer_test(void)203 {204 unsigned longi;205
206 prdebug("-----------start test buzzer------------");207 for(i = 0;i < 10000;i ++){208 gpio_set_value(BUZZER_IO, 0);209 udelay(150);210 gpio_set_value(BUZZER_IO, 1);211 udelay(150);212 }213 prdebug("-----------end test buzzer------------");214 }215
216 static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)217 {218
219
220 //prdebug("--------------%s----------------",__func__);
221
222 if(buzzer_dev->count != 1){223
224 if (gpio_get_value(BUZZER_IO) == 1) {225 gpio_set_value(BUZZER_IO, 0);226
227 buzzer_dev->kt = ktime_set(0, BUZZER_DELAY_TIME_LOW);228 hrtimer_forward_now(&buzzer_dev->mytimer, buzzer_dev->kt);229
230 } else{231 gpio_set_value(BUZZER_IO, 1);232
233 buzzer_dev->kt = ktime_set(0, BUZZER_DELAY_TIME_HIGHT);234 hrtimer_forward_now(&buzzer_dev->mytimer, buzzer_dev->kt);235 }236 buzzer_dev->count --;237 returnHRTIMER_RESTART;238 }else{239 buzzer_dev->count --;240 buzzer_dev->status =BUZZER_DISABLE;241 prdebug("buzzer_dev->count = %d",buzzer_dev->count);242 prdebug("-----------finsh hrtimer timer-------------");243 wake_up(&buzzer_dev->wait_queue);244 returnHRTIMER_NORESTART;245 }246
247
248 }249
250
251 static int __init buzzer_drv_init(void)252 {253 intret;254
255
256 prdebug("--------------%s----------------",__func__);257
258 buzzer_dev = kzalloc(sizeof(structbuzzer_chip),GFP_KERNEL);259 if(buzzer_dev ==NULL){260 prdebug("kzalloc error");261 return -ENOMEM;262 }263
264 //动态的申请设备号
265 ret = alloc_chrdev_region(&buzzer_dev->devno,0,1,BUZZER_DEVICE_NAME);266 if(ret != 0){267 prdebug("error alloc_chrdev_region");268 gotoerr_free;269 }270
271 //分配cdev对象
272 buzzer_dev->cdev =cdev_alloc();273 cdev_init(buzzer_dev->cdev,&buzzer_fops);274 cdev_add(buzzer_dev->cdev,buzzer_dev->devno,1);275
276 //自动创建设备节点
277 buzzer_dev->cls =class_create(THIS_MODULE,BUZZER_CLASS_NAME);278 if(IS_ERR(buzzer_dev->cls)){279 prdebug("error class_create");280 ret = PTR_ERR(buzzer_dev->cls);281 gotoerr_unregister;282 }283
284 buzzer_dev->dev = device_create(buzzer_dev->cls,NULL,buzzer_dev->devno,NULL,"buzzer-%d",BUZZER_DEVICE_NUM);285 if(IS_ERR(buzzer_dev->dev)){286 prdebug("error device_create");287 ret =PTR_ERR(buzzer_dev);288 gotoerr_class_error;289 }290
291 //信号量
292 sema_init(&buzzer_dev->sem,1);293
294 init_waitqueue_head(&buzzer_dev->wait_queue);295
296
297
298
299
300 #if BUZZER_GPIO_SWITCH
301 //初始化Buzzer的GPIO
302 ret =buzzer_gpio_init();303 if(ret !=0){304 prdebug("error buzzer_gpio_init");305 gotoerr_device_create;306 }307
308 #endif
309
310
311
312 return 0;313
314 #if BUZZER_GPIO_SWITCH
315 err_device_create:316 device_destroy(buzzer_dev->cls,buzzer_dev->devno);317 #endif
318
319 err_class_error:320 class_destroy(buzzer_dev->cls);321
322 err_unregister:323 cdev_del(buzzer_dev->cdev);324 unregister_chrdev_region(buzzer_dev->devno,1);325
326 err_free:327 kfree(buzzer_dev);328 returnret;329
330
331 }332
333 static void __exit buzzer_drv_exit(void)334 {335 prdebug("--------------%s----------------",__func__);336 #if BUZZER_GPIO_SWITCH
337 buzzer_gpio_exit();338 #endif
339 device_destroy(buzzer_dev->cls,buzzer_dev->devno);340 class_destroy(buzzer_dev->cls);341 cdev_del(buzzer_dev->cdev);342 unregister_chrdev_region(buzzer_dev->devno,1);343 kfree(buzzer_dev);344
345 }346
347 module_init(buzzer_drv_init);348 module_exit(buzzer_drv_exit);349 MODULE_LICENSE("GPL");350 MODULE_AUTHOR("zhuang zebin@qq.com");