#include <linux/init.h>
#include <linux/module.h>
#include<linux/i2c.h>
#include<linux/fs.h>
#include <linux/uaccess.h>
#include<linux/device.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>
#include"si7006.h"
struct cdev* cdev;
struct class *cls;
struct device *dev;
struct i2c_client *tclient;
struct device_node *node;
struct gpio_desc* gpiono1;//用于接收gpio编号
struct gpio_desc* gpiono2;
#if 1
unsigned int major=0;
#else
unsigned int majo=500;
#endif
int minor=0;
const int count=2;
//获取温湿度数据的函数
int i2c_read_hum_tem(unsigned char reg)
{
int ret;
//读消息的封装
char r_buf[]={reg};
unsigned short val;//读的数据
struct i2c_msg r_msg[]={
[0]={
.addr=tclient->addr,
.flags=0,
.len=1,
.buf=r_buf,
},
[1]={
.addr=tclient->addr,
.flags=1,
.len=2,
.buf=(char *)&val,
},
};
//消息的传输
ret=i2c_transfer(tclient->adapter,r_msg,ARRAY_SIZE(r_msg));
if(ret!=ARRAY_SIZE(r_msg))
{
printk("i2c获取温湿度数据失败\n");
return EAGAIN;
}
return val;
}
//匹配成功后执行probe
int si7006_open(struct inode *inode,struct file *file)
{
printk("open\n");
return 0;
}
ssize_t si7006_read(struct file *file,char *ubuf,size_t size,loff_t *off)
{
printk("read\n");
return 0;
}
ssize_t si7006_write(struct file *file,const char *ubuf,size_t size,loff_t *off)
{
printk("write\n");
return 0;
}
long si7006_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{
int tem,hum;
int ret;
int whitch;
switch(cmd)
{
case GET_HUM:
hum=i2c_read_hum_tem(0xe5);
ret=copy_to_user((void*)arg,(void*)&hum,sizeof(int));
if(ret)
{
printk("copy_to_user fild\n");
return EINVAL;
}
break;
case GET_TEM:
tem=i2c_read_hum_tem(0xe3);
ret=copy_to_user((void*)arg,(void*)&tem,sizeof(int));
if(ret)
{
printk("copy_to_user fild\n");
return EINVAL;
}
break;
case LED_ON:
ret=copy_from_user(&whitch,(void*)arg,sizeof(int));
if(ret)
{
printk("copy from user led on!!!!\n");
}
switch(whitch)
{
case LED1:
gpiod_set_value(gpiono1,1);
break;
case LED2:
gpiod_set_value(gpiono2,1);
break;
}
break;
case LED_OFF:
ret=copy_from_user(&whitch,(void*)arg,sizeof(int));
if(ret)
{
printk("copy from user led off!!!!\n");
}
switch(whitch)
{
case LED1:
gpiod_set_value(gpiono1,0);
break;
case LED2:
gpiod_set_value(gpiono2,0);
break;
}
break;
}
return 0;
}
int si7006_close(struct inode*inode,struct file *file)
{
printk("close\n");
return 0;
}
struct file_operations fops={
.open=si7006_open,
.read=si7006_read,
.write=si7006_write,
.unlocked_ioctl=si7006_ioctl,
.release=si7006_close,
};
int si7006_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
//把总线驱动指针变成全局的
tclient=client;
//注册字符设备驱动
major=register_chrdev(0,"si7006",&fops);
if(major<0)
{
printk("字符设备驱动注册失败\n");
return major;
}
printk("字符设备驱动注册成功\n");
//自动创建设备节点
cls=class_create(THIS_MODULE,"si7006");
if(IS_ERR(cls))
{
printk("向上提交目录失败\n");
return PTR_ERR(cls);
}
printk("向上提交目录成功\n");
//通过路径获取设备树节点信息
node=of_find_node_by_path("/myleds");
if(node==NULL)
{
printk("通过路径解析设备树节点失败\n");
return -EFAULT;
}
printk("成功解析设备树节点\n");
//获取申请gpio编号
gpiono1=gpiod_get_from_of_node(node,"myled1",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono1))
{
printk("获取gpio1编号失败\n");
return PTR_ERR(gpiono1);
}
gpiono2=gpiod_get_from_of_node(node,"myled2",0,GPIOD_OUT_LOW,NULL);
if(IS_ERR(gpiono2))
{
printk("获取gpio2编号失败\n");
return PTR_ERR(gpiono2);
}
printk("获取gpio编号成功\n");
//设置管脚为输出
gpiod_direction_output(gpiono1,0);
gpiod_direction_output(gpiono2,0);
return 0;
}
//设备分离后执行remove
int si7006_remove(struct i2c_client *client)
{
gpiod_set_value(gpiono1,0);
gpiod_set_value(gpiono2,0);
gpiod_put(gpiono1);
gpiod_put(gpiono2);
printk("%s:%d\n",__func__,__LINE__);
return 0;
}
//定义设备树匹配表
struct of_device_id oftable[]=
{
{.compatible="hqyj,si7006",},
{}
};
MODULE_DEVICE_TABLE(of,oftable);
//定义对象并且初始化
struct i2c_driver si7006={
.probe=si7006_probe,
.remove=si7006_remove,
.driver={
.name="tem_hum_driver",
.of_match_table=oftable,
},
};
module_i2c_driver(si7006);
MODULE_LICENSE("GPL");
22071day12驱动
最新推荐文章于 2024-07-20 19:39:28 发布