初级会员
- 积分
- 97
- 金钱
- 97
- 注册时间
- 2020-4-26
- 在线时间
- 9 小时
|
楼主 |
发表于 2020-5-15 18:02:05
|
显示全部楼层
完整代码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include "ap3216c.h"
#define AP3216C_SYSTEM_CONFIG 0x00 //Control of basic functions
#define AP3216C_INT_STATUS 0x01 //ALS and PS interrupt status output
#define AP3216C_INT_CLEAR_MANNER 0x02 //Auto/semi clear INT pin selector
#define AP3216C_IR_DATA_LOW 0X0a //Lower byte for IR ADC channel output
#define AP3216C_IR_DATA_HIG 0x0b //Higher byte for IR ADC channel
#define AP3216C_ALS_DATA_LOW 0x0c //Lower byte for ALS ADC channel output
#define AP3216C_ALS_DATA_HIG 0x0d
#define AP3216C_PS_DATA_LOW 0x0e //Lower byte for PS ADC channel output
#define AP3216C_PS_DATA_HIG 0x0f
struct ap3216c_desc{
struct class *cls;
struct device *dev;
struct i2c_client *client;
int dev_major;
};
struct ap3216c_desc *pf_ap3216;
int i2c_write_byte(struct i2c_client *client,char *buf,int count){
printk("------------------%s--------------\n",__FUNCTION__);
int ret;
struct i2c_adapter *adapter = client->adapter;
struct i2c_msg msgs[1];
msgs[0].addr = client->addr;
msgs[0].flags = 0;
msgs[0].len = count;
msgs[0].buf = buf;
ret = i2c_transfer(adapter, msgs, 1);
return ret == 1 ? count : ret;
}
int ap3216c_read_reg_byte(struct i2c_client *client,char reg){
//printk("------------------%s--------------\n",__FUNCTION__);
int ret;
struct i2c_adapter *adapter = client->adapter;
struct i2c_msg msgs[2];
char rxbuf[1];
msgs[0].flags = 0;//读之前先写,告诉寄存器准备
msgs[0].addr = client->addr;
msgs[0].len = 1;
msgs[0].buf = ®
msgs[1].flags = 1;
msgs[1].addr = client->addr;
msgs[1].len = 1;
msgs[1].buf = rxbuf;//读到rxbuf
ret = i2c_transfer(adapter, msgs, 2);
if(ret < 0)
{
printk("i2c_transfer read error\n");
return ret;
}
return rxbuf[0];
}
int ap3216c_drv_open(struct inode *inode, struct file *filep){
printk("------------------%s--------------\n",__FUNCTION__);
return 0;
}
ssize_t ap3216c_drv_read(struct file *filep, char __user *buf, size_t count){
//printk("------------------%s--------------\n",__FUNCTION__);
union ap3216c_data data;
short date[3];
long ret=0;
//读取ir
//先通过判断IO_RF位,看数据是否有效,有效在读取数据
data.ir = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_LOW) ;
if(data.ir & 0x80)
date[0] = 7;
else{
data.ir = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_LOW) | 0x03;
data.ir |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_IR_DATA_HIG)<<2;
date[0] = data.ir;
}
//读als 不用判断,直接读取
data.als = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_LOW);
data.als |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_HIG)<<8;
date[1] = data.als;
//读ps
//先通过判断IO_RF位,看数据是否有效,有效在读取数据
data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW);
if(data.ps & 0x40)
date[2] = 8;// 为1,则无效
else{
data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW) | 0xf;
data.ps |= (ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_HIG) | 0x3f)<<4;
date[2] = data.ps;
}
ret = copy_to_user(buf, date, sizeof(data));
return 0;
}
int ap3216c_drv_close(struct inode *inode, struct file *filep){
printk("------------------%s--------------\n",__FUNCTION__);
return 0;
}
long ap3216c_drv_ioctl(struct file *filep, unsigned int cmd , unsigned long args){
printk("------------------%s--------------\n",__FUNCTION__);
/*
union ap3216c_data data;
switch(cmd){
case IOC_GET_ALS :
data.als = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_LOW);
data.als |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_HIG)<<8;
case IOC_GET_PS :
data.ps = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_LOW);
data.ps |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_PS_DATA_HIG)<<8;
case IOC_GET_LED :
data.led = ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_LOW);
data.led |= ap3216c_read_reg_byte(pf_ap3216->client ,AP3216C_ALS_DATA_HIG)<<8;
}
*/
return 0;
}
const struct file_operations fops = {
.open = ap3216c_drv_open,
.read = ap3216c_drv_read,
.release = ap3216c_drv_close,
.unlocked_ioctl = ap3216c_drv_ioctl,
};
int ap3216c_drv_probe(struct i2c_client *client, const struct i2c_device_id *id){
int ret;
printk("------------------%s--------------\n",__FUNCTION__);
pf_ap3216 = kzalloc(sizeof(struct ap3216c_desc), GFP_KERNEL);
if(pf_ap3216 == NULL){
printk("kzalloc failed\n");
return -ENOMEM;
}
pf_ap3216->client = client;//client,是在i2c_core.c中和adapter匹配成功后传过来的
//申请主设备号
pf_ap3216->dev_major = register_chrdev(0, "i2c_chrdev", &fops);
if(pf_ap3216->dev_major<0)
{
printk(KERN_ERR "regist_chardev error\n");
ret = -ENODEV;
}
//创建设备节点
pf_ap3216->cls = class_create(THIS_MODULE,"i2c_cls");
if(IS_ERR(pf_ap3216->cls))
{
printk(KERN_ERR "class_create error\n");
ret=PTR_ERR(pf_ap3216->cls);//将指针出错的具体原因转换成出错码
}
pf_ap3216->dev = device_create(pf_ap3216->cls, NULL,
MKDEV(pf_ap3216->dev_major,0), NULL, "ap3216c_sensor");
if(IS_ERR(pf_ap3216->dev))
{
printk(KERN_ERR "device_create error\n");
ret=PTR_ERR(pf_ap3216->dev);//将指针出错的具体原因转换成出错码
}
/*初始化i2c从设备*/
//When the host writes this setting(0x04),
//the all registers of device will become the default value after 10ms. Please don’t
//force command during these period of 10ms to avoid abnormal operation
char buf1[2] = {AP3216C_SYSTEM_CONFIG,0x04};//For SW reset (100)
i2c_write_byte(pf_ap3216->client,buf1,2);
mdelay(20);//至少延时10ms,否则上一步设置失效
char buf2[2] = {AP3216C_SYSTEM_CONFIG,0x03};
i2c_write_byte(pf_ap3216->client,buf2,2);//ALS and PS+IR
return 0;
}
int ap3216c_drv_remove(struct i2c_client *client){
printk("-----%s----\n", __FUNCTION__);
device_destroy(pf_ap3216->cls, MKDEV(pf_ap3216->dev_major, 0));
class_destroy(pf_ap3216->cls);
unregister_chrdev(pf_ap3216->dev_major, "i2c_chrdev");
kfree(pf_ap3216);
return 0;
}
/* 传统匹配方式 ID 列表 */
static const struct i2c_device_id ap3216c_id[] = {
{"peifeng,ap3216c", 0},
{}
};
const struct of_device_id of_match_id[] = {
{.compatible = "peifeng,ap3216c"},//用于和设备树compatible = "peifeng,ap3216c"匹配
{}
};
struct i2c_driver ap3216c_drv = {
.probe = ap3216c_drv_probe,
.remove = ap3216c_drv_remove,
.driver = {
.name = "ap3216c_drv_peifeng",
//.of_match_table = of_match_ptr(of_match_id),//@of_match_table: The open firmware table.
.of_match_table = of_match_id,
},
.id_table = ap3216c_id,
};
static int __init i2c_drv_init(void){
printk("------------------%s--------------\n",__FUNCTION__);
return i2c_add_driver(&ap3216c_drv);
//i2c_register_driver(THIS_MODULE, &ap3216c_drv);
}
static void __exit i2c_drv_exit(void){
printk("------------------%s--------------\n",__FUNCTION__);
i2c_del_driver( &ap3216c_drv);
}
module_init(i2c_drv_init);
module_exit(i2c_drv_exit);
MODULE_LICENSE("GPL");
|
|