beep {
#address-cells = <1>;
#size-cells = <1>;
compatible = "glen-beep";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_beep>; /* 属性设置蜂鸣器所使用的PIN对应的pinctrl节点 */
beep-gpio = <&gpio5 1 GPIO_ACTIVE_LOW>; /* 属性指定了蜂鸣器所使用的GPIO, 在这里就是GPIO5的IO01, 低电平有效 */
status = "okay";
};
/*
* 文件名 : miscbeep.c
* 作者 : glen
* 描述 : miscbeep驱动文件
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MISCBEEP_NAME "miscbeep" /* 名字 */
#define MISCBEEP_MINOR 200
#define BEEPOFF "OFF"
#define BEEPON "ON"
/* miscbeep设备结构体 */
struct miscbeep_dev {
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
struct device_node *nd; /* 设备节点 */
int beep_gpio; /* beep所使用的GPIO编号 */
};
struct miscbeep_dev miscbeepdev;/* beep设备 */
/**
* \brief 打开设备
* \param inode 传递给驱动的inode
* filp 设备文件
* \retval 0 成功 其他 失败
*/
static int miscbeep_open(struct inode *inode, struct file *filp)
{
filp->private_data = &miscbeepdev;
return 0;
}
/**
* \brief 向设备写数据
* \param filp 设备文件,表示打开的文件描述符
* buf 要写给设备写入的数据
* cnt 要写入的数据长度
* offt 相对于文件首地址的偏移
* \retval 写入的字节数,如果为负值,表示写入失败
*/
static ssize_t miscbeep_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
int ret;
char data_buf[4];
struct miscbeep_dev *dev = filp->private_data;
ret = copy_from_user(data_buf, buf, (cnt < sizeof(data_buf) ? cnt : sizeof(data_buf)));
if (ret < 0) {
printk("kernel write failure!\r\n");
return -EFAULT;
}
if (strcmp(data_buf, BEEPON) == 0) {
gpio_set_value(dev->beep_gpio, 0);
} else if (strcmp(data_buf, BEEPOFF) == 0) {
gpio_set_value(dev->beep_gpio, 1);
}
return 0;
}
/*
* 设备操作函数
*/
static struct file_operations miscbeep_fops = {
.owner = THIS_MODULE,
.open = miscbeep_open,
.write = miscbeep_write,
};
/*
* MISC设备结构体
*/
static struct miscdevice beep_miscdev = {
.minor = MISCBEEP_MINOR,
.name = MISCBEEP_NAME,
.fops = &miscbeep_fops,
};
/**
* \brief platform驱动的probe函数,当驱动与设备匹配以后此函数执行
* \param dev platform设备
* \retval 0 成功 其他负值 失败
*/
static int miscbeep_probe(struct platform_device *dev)
{
int ret = 0;
printk("beep driver and device was matched!\r\n");
/* 设置BEEP所使用的GPIO */
/* 获取设备节点 */
miscbeepdev.nd = of_find_node_by_path("/beep");
if (miscbeepdev.nd == NULL) {
printk("beep node not found!\r\n");
return -EINVAL;
}
/* 获取设备树中的gpio属性,得到BEEP所使用的BEEP编号 */
miscbeepdev.beep_gpio = of_get_named_gpio(miscbeepdev.nd, "beep-gpio", 0);
if (miscbeepdev.beep_gpio < 0) {
printk("can't get beep-gpio!\r\n");
return -EINVAL;
}
/* 设置GPIO5_IO01为输出, 并且输出高电平, 默认关闭BEEP */
ret = gpio_direction_output(miscbeepdev.beep_gpio, 1);
if (ret < 0) {
printk("can't set gpio!\r\n");
}
/* 注册MISC设备 */
ret = misc_register(&beep_miscdev);
if (ret < 0) {
printk("misc device register failed!\r\n");
return -EFAULT;
}
return 0;
}
/**
* \brief remove函数,移除platform驱动的时候此函数会执行
* \param dev platform设备
* \return 0 成功 其他值 失败
*/
static int miscbeep_remove(struct platform_device *dev)
{
/* 销毁设备的时候关闭BEEP */
gpio_set_value(miscbeepdev.beep_gpio, 1);
/* 注销misc设备驱动 */
misc_deregister(&beep_miscdev);
return 0;
}
/* 匹配列表 */
static const struct of_device_id beep_of_match[] = {
{.compatible = "glen-beep"},
{}
};
/* platform驱动结构体 */
static struct platform_driver beep_driver = {
.driver = {
.name = "glen-beep",
.of_match_table = beep_of_match,
},
.probe = miscbeep_probe,
.remove = miscbeep_remove,
};
/**
* \brief 驱动模块加载函数
* \param 无
* \retval 无
*/
static int __init miscbeep_init(void)
{
return platform_driver_register(&beep_driver);
}
/**
* \brief 驱动模块缷载函数
* \param 无
* \return 无
*/
static void __exit miscbeep_exit(void)
{
platform_driver_unregister(&beep_driver);
}
/* 设备注册入口, 展开后
* static initcall_t \
* __initcall_miscbeep_init6 \
* __used \
* __attribute__((__section__(".initcall6.init"))) \
* = miscbeep_init;
*/
module_init(miscbeep_init);
/* 设备注册出口, 展开后
* static exitcall_t \
* __exitcall_miscbeep_exit \
* __exit_call \
* = miscbeep_exit;
*/
module_exit(miscbeep_exit);
/* 模块的许可证声明, 展开后
* static const char __UNIQUE_ID_license__COUNTER__[] \
* __used __attribute__((section(".modinfo"), unused, aligned(1))) \
* = "license=GPL";
*/
MODULE_LICENSE("GPL");
/* 模块的作者声明, 展开后
* static const char __UNIQUE_ID_author__COUNTER__[] \
* __used __attribute__((section(".modinfo"), unused, aligned(1))) \
* = "author=glen_cao"
*/
MODULE_AUTHOR("glen");
/*
* 文件名 : miscbeep_test.c
* 作者 : glen
* 描述 : miscbeep测试程序
*/
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "poll.h"
#include "sys/select.h"
#include "sys/time.h"
#include "linux/ioctl.h"
#include "signal.h"
/**
* @brief : main函数
* @par : argc argv数组元素的个数
* argv 参数数组
* @retval : 0 成功 其它 失败
*/
int main(int argc, char *argv[])
{
static int fd = 0; /* 文件描述符 */
int ret = 0;
char *filename;
if (argc != 3) {
printf("Error Usage!\r\n");
return -1;
}
filename = argv[1];
/* 打开驱动文件 */
fd = open(filename, O_RDWR); /* 阻塞访问 */
if (fd < 0) {
printf("Can't open file %s\r\n", filename);
return -1;
}
ret = write(fd, argv[2], sizeof(argv[2]));
if (ret < 0) {
printf("BEEP control failure!\r\n");
close(fd);
return -1;
}
/* 关闭文件 */
ret = close(fd);
if (ret < 0) {
printf("file %s close failed!\r\n", argv[1]);
return -1;
}
return 0;
}
拷贝到NFS文件系统目录下
glen@ubuntu:~/linux/imx6ull/linux/driver/17_miscbeep$ sudo cp miscbeep.ko miscbeep_test ~/linux/nfs/rootfs/lib/modules/4.1.15
/lib/modules/4.1.15 # insmod miscbeep.ko
beep driver and device was matched!
4.2 查看杂项驱动目录下信息(miscbeep)
/lib/modules/4.1.15 # ls /sys/class/misc
autofs loop-control network_throughput
cpu_dma_latency memory_bandwidth rfkill
fuse miscbeep ubi_ctrl
hw_random network_latency watchdog
4.3 测试,在终输入下面信息,可以听到蜂鸣器开/关
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep ON
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep OFF
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep OFF
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep ON
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep OFF
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep ON
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep OFF
/lib/modules/4.1.15 # ./miscbeep_test /dev/miscbeep ON
/lib/modules/4.1.15 # rmmod miscbeep