/***************************************************************
Copyright 2024-2029. All rights reserved.
文件名 : drv_09_tree_hs0038.c
作者 : [email protected]
版本 : V1.0
描述 : HS0038 驱动程序, GPIO4_PIN17-----HS0038 IO port
其他 : 无
日志 : 初版V1.0 2024/1/30
使用方法:
1) 在.dts文件中定义节点信息
//mftang: user's HS0038, 2024-1-30
// IO: GPIO-4-PIN17
mftanghs0038 {
compatible = "atk-dl6y2c,hs0038";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpio_mftanghs0038>;
gpios = <&gpio4 17 GPIO_ACTIVE_HIGH>;
status = "okay";
};
2) 在驱动匹配列表
static const struct of_device_id hs0038_of_match[] = {
{ .compatible = "atk-dl6y2c,hs0038" },
{ } // Sentinel
};
驱动程序用法:
typedef struct{
int code;
int sign; // -1: error, 0: success
}HS0038Stru;
HS0038Stru stru_hs0038;
if (read(fd, &stru_hs0038, sizeof( HS0038Stru )) == sizeof( HS0038Stru ))
{
if( !stru_hs0038.sign )
{
printf("get hs0038 : 0x%x \r\n", stru_hs0038.code);
}
}
***************************************************************/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/ktime.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define DEVICE_NAME "treehs0038" // dev/treehs0038
#define OFF 0
#define ON 1
/* hs0038dev设备结构体 */
struct hs0038stru_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
struct device_node *node; /* hs0038设备节点 */
int userhs0038; /* hs0038 GPIO标号*/
struct gpio_desc *pin;
};
struct hs0038stru_dev hs0038dev; /* hs0038设备 */
typedef struct{
int code;
int sign; // -1: error, 0: sucess
}HS0038Stru;
HS0038Stru stru_hs0038;
static u64 hs0038_edge_time[100];
static wait_queue_head_t hs0038_wq;
static int irq;
static int hs0038_edge_cnt = 0;
static unsigned int hs0038_data = 0;
static unsigned int hs0038_data_buf[8];
static int r, w;
static void put_data(unsigned int val)
{
if (((w+1) & 7) != r)
{
hs0038_data_buf[w] = val;
w = (w + 1) & 7;
}
}
static int get_data(unsigned int *val)
{
if (r == w)
{
return -1;
}
else
{
*val = hs0038_data_buf[r];
r = (r + 1) & 7;
return 0;
}
}
static int has_data(void)
{
if (r == w)
return 0;
else
return 1;
}
int hs0038_parse_data(unsigned int *val)
{
u64 tmp;
unsigned char data[4];
int i, j, m;
/* 判断是否重复码 */
if (hs0038_edge_cnt == 4)
{
tmp = hs0038_edge_time[1] - hs0038_edge_time[0];
if (tmp > 8000000 && tmp < 10000000)
{
tmp = hs0038_edge_time[2] - hs0038_edge_time[1];
if (tmp < 3000000)
{
/* 获得了重复码 */
*val = hs0038_data;
return 0;
}
}
}
/* 接收到了68次中断 */
m = 3;
if (hs0038_edge_cnt >= 68)
{
/* 解析到了数据 */
for (i = 0; i < 4; i++)
{
data[i] = 0;
/* 先接收到bit0 */
for (j = 0; j < 8; j++)
{
/* 数值: 1 */
if (hs0038_edge_time[m+1] - hs0038_edge_time[m] > 1000000)
data[i] |= (1<<j);
m += 2;
}
}
/* 检验数据 */
data[1] = ~data[1];
if (data[0] != data[1])
{
return -2;
}
data[3] = ~data[3];
if (data[2] != data[3])
{
return -2;
}
hs0038_data = (data[0] << 8) | (data[2]);
*val = hs0038_data;
return 0;
}
else
{
/* 数据没接收完毕 */
return -1;
}
}
static irqreturn_t hs0038_isr(int irq, void *dev_id)
{
unsigned int val;
int ret;
hs0038_edge_time[hs0038_edge_cnt++] = ktime_get_boot_ns();
/* 判断超时 */
if (hs0038_edge_cnt >= 2)
{
if (hs0038_edge_time[hs0038_edge_cnt-1] - hs0038_edge_time[hs0038_edge_cnt-2] > 60000000)
{
/* 超时 */
hs0038_edge_time[0] = hs0038_edge_time[hs0038_edge_cnt-1];
hs0038_edge_cnt = 1;
return IRQ_HANDLED; // IRQ_WAKE_THREAD;
}
}
ret = hs0038_parse_data(&val);
if (!ret)
{
/* 解析成功 */
hs0038_edge_cnt = 0;
printk("%s line %d : get ir code = 0x%x \r\n", __FUNCTION__, __LINE__, val);
put_data(val);
wake_up(&hs0038_wq);
stru_hs0038.code = val;
stru_hs0038.sign = 0;
}
else if (ret == -2)
{
/* 解析失败 */
stru_hs0038.sign = -1;
hs0038_edge_cnt = 0;
}
return IRQ_HANDLED; // IRQ_WAKE_THREAD;
}
/*
linux driver 驱动接口:
实现对应的open/read/write等函数,填入file_operations结构体
*/
static ssize_t hs0038_drv_read (struct file *file, char __user *buf,
size_t size, loff_t *offset)
{
unsigned int val;
int err;
printk(" %s line %d \r\n", __FUNCTION__, __LINE__);
wait_event_interruptible(hs0038_wq, has_data());
get_data(&val);
err = copy_to_user(buf, &stru_hs0038, sizeof(HS0038Stru));
return sizeof(HS0038Stru);
}
static int hs0038_drv_close(struct inode *node, struct file *file)
{
printk(" %s line %d \r\n", __FUNCTION__, __LINE__);
return 0;
}
static int hs0038_drv_open(struct inode *inode, struct file *filp)
{
filp->private_data = &hs0038dev; /* 设置私有数据 */
return 0;
}
/*
定义driver的file_operations结构体
*/
static struct file_operations hs0038_fops = {
.owner = THIS_MODULE,
.read = hs0038_drv_read,
.open = hs0038_drv_open,
.release = hs0038_drv_close,
};
/* 1. 从platform_device获得GPIO
* 2. gpio=>irq
* 3. request_irq
*/
static int hs0038_probe(struct platform_device *pdev)
{
int result;
printk("hs0038 driver and device was matched!\r\n");
/* 1. 获得硬件信息 */
hs0038dev.pin = gpiod_get(&pdev->dev, NULL, 0);
if (IS_ERR(hs0038dev.pin))
{
printk("%s line %d get pin parameter error! \n", __FUNCTION__, __LINE__);
}
/* register irq*/
irq = gpiod_to_irq(hs0038dev.pin);
result = request_irq(irq, hs0038_isr, IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "hs0038", NULL);
/* 2. device_create */
device_create( hs0038dev.class, NULL,
MKDEV( hs0038dev.major, 0 ), NULL,
DEVICE_NAME); // device name
return 0;
}
static int hs0038_remove(struct platform_device *pdev)
{
printk("%s line %d\n", __FUNCTION__, __LINE__);
device_destroy( hs0038dev.class, MKDEV( hs0038dev.major, 0));
free_irq(irq, NULL);
gpiod_put(hs0038dev.pin);
return 0;
}
static const struct of_device_id atk_dl6y2c_hs0038[] = {
{ .compatible =
linux platform tree下hs0038驱动程序
需积分: 0 170 浏览量
2024-02-21
22:28:33
上传
评论
收藏 4KB ZIP 举报
mftang
- 粉丝: 2802
- 资源: 82
最新资源
- 设计1.ms14
- vscode-1.64.1.tar源码文件
- vscode-1.64.0.tar源码文件
- vscode-1.52.0.tar源码文件
- Music-Player +PlayerActivity+ rockplayer+ SeeJoPlayer 播放器JAVA源码
- vscode-1.46.0.tar源码文件
- 最近很火植物大战僵尸杂交版2.08苹果+安卓+PC+防闪退工具V2+修改工具+高清工具+通关存档整合包更新
- 超级好用的截图工具PixPin,可录制Gif图
- Screenshot_2024-05-21-17-06-42-64_2332cb9b27b851b548ba47a91682926c.jpg
- 毕业设计参考 - 基于树莓派、OpenCV及Python的人脸识别
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈