转自:http://bbs.elecfans.com/jishu_903104_1_1.html
buzzer_drv.h
#ifndef _BUZZER_DRV_H
#define _BUZZER_DRV_H
#define BUZZER_IOC_MAGIC 'B'
#define BUZZER_ON _IO(BUZZER_IOC_MAGIC, 1)
#define BUZZER_OFF _IO(BUZZER_IOC_MAGIC, 0)
#define BUZZER_IOCTL_MAXNR 2
#endif /*_BUZZER_DRV_H*/
~
buzzer_drv.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/version.h>
#include <asm/mach/arch.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include "buzzer_drv.h"
static int major;
static int minor;
struct cdev *buzzer; /* cdev 数据结构 */
static dev_t devno; /* 设备编号 */
static struct class *buzzer_class;
#define DEVICE_NAME "buzzer"
#define GPIO_BUZZER_PIN_NUM (0*32 + 2) /*gpio0_2 */
static int buzzer_open(struct inode *inode,struct file *file )
{
try_module_get(THIS_MODULE);
gpio_direction_output(GPIO_BUZZER_PIN_NUM, 1);
return 0;
}
static int buzzer_release(struct inode*inode, struct file *file )
{
module_put(THIS_MODULE);
gpio_direction_output(GPIO_BUZZER_PIN_NUM, 1);
return 0;
}
static int buzzer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
if(_IOC_TYPE(cmd) != BUZZER_IOC_MAGIC) {
return -ENOTTY;
}
if(_IOC_NR(cmd) > BUZZER_IOCTL_MAXNR) {
return -ENOTTY;
}
switch(cmd){
case BUZZER_ON:
gpio_set_value(GPIO_BUZZER_PIN_NUM, 1);
break;
case BUZZER_OFF:
gpio_set_value(GPIO_BUZZER_PIN_NUM, 0);
break;
default:
break;
}
return 0;
}
struct file_operations buzzer_fops = {
.owner = THIS_MODULE,
.open = buzzer_open,
.release = buzzer_release,
.unlocked_ioctl = buzzer_ioctl,
};
static int __init buzzer_init(void)
{
int ret;
gpio_free(GPIO_BUZZER_PIN_NUM);
if(gpio_request(GPIO_BUZZER_PIN_NUM, "buzzer_bee")) {
printk("request %s gpio faile \n", "buzzer");
return -1;
}
ret = alloc_chrdev_region(&devno, minor, 1, "buzzer"); /* 从系统获取主设备号 */
major= MAJOR(devno);
if(ret < 0) {
printk(KERN_ERR"cannot get major %d \n", major);
return -1;
}
buzzer = cdev_alloc(); /* 分配 buzzer 结构 */
if(buzzer != NULL) {
cdev_init(buzzer,&buzzer_fops); /* 初始化 buzzer 结构 */
buzzer->owner = THIS_MODULE;
if(cdev_add(buzzer, devno, 1) != 0) { /* 增加 buzzer 到系统中 */
printk(KERN_ERR"add cdev error!\n");
goto error;
}
}else {
printk(KERN_ERR"cdev_alloc error!\n");
return -1;
}
buzzer_class = class_create(THIS_MODULE, "buzzer_class");
if(IS_ERR(buzzer_class)) {
printk(KERN_INFO"create class error\n");
return -1;
}
device_create(buzzer_class,NULL, devno, NULL, "buzzer");
return 0;
error:
unregister_chrdev_region(devno,1); /* 释放已经获得的设备号 */
return ret;
}
static void __exit buzzer_exit(void)
{
cdev_del(buzzer);/* 移除字符设备 */
unregister_chrdev_region(devno,1); /* 释放设备号 */
device_destroy(buzzer_class,devno);
class_destroy(buzzer_class);
}
MODULE_LICENSE("GPL");
module_init(buzzer_init);
module_exit(buzzer_exit);
MODULE_AUTHOR("Xiaoxin");
Makefile:
PWD := $(shell pwd)
ARCH=arm
CROSS_COMPILE=/home/goembed/B1/335x-B1-CROSS_COMPILE/usr/bin/arm-linux-gnueabihf-
obj-m += buzzer_drv.o
KDIR = /home/goembed/B4/project_kernel/335x-B1-LINUX/
all:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
arm-linux-gcc buzzer_test.c -o buzzer_test
clean:
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) clean
rm buzzer_test
buzzer_test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include "buzzer_drv.h"
#define DEV_NAME "/dev/buzzer"
int main(int argc, char *argv[])
{
int i;
int fd = 0;
fd = open (DEV_NAME, O_RDONLY);
if(fd < 0) {
perror("Open"DEV_NAME" Failed!\n");
exit(1);
}
while(1){
ioctl(fd,BUZZER_ON);
printf("BUZZER_ON\n");
sleep(1);
ioctl(fd,BUZZER_OFF);
printf("BUZZER_OFF\n");
sleep(1);
}
close(fd);
return 0;
}
~
查看是否加载成功: ls /dev/buzz* 如果有buzzer(节点名),则加载成功
卸载: rmmod buzzer_drv 注意不要后缀名.ko