AM2320 linux驱动程序

news/2024/11/24 8:26:22/

AM2320 linux驱动程序

采集,上报input 子系统

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/err.h>
#include <linux/i2c.h>#include <linux/leds.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/input.h>#include <linux/amlogic/jtag.h>
#include <linux/pwm.h>
#include <linux/amlogic/pwm_meson.h>
#include <linux/amlogic/aml_gpio_consumer.h>
#include <linux/device.h>
#include <linux/amlogic/i2c-amlogic.h>#include "am2320.h"static int i2c_read(struct i2c_adapter *i2c_adap,unsigned char address, unsigned char *wdata,unsigned int wlen, unsigned char *rdata,unsigned int rlen)
{struct i2c_msg msgs[2];int res;if (!rdata || !i2c_adap) {am2320_error("%s:line=%d,error\n",__func__,__LINE__);return -EINVAL;}msgs[0].addr = address;msgs[0].flags = 0;	/* write */msgs[0].buf = wdata;msgs[0].len = wlen;msgs[1].addr = address;msgs[1].flags = I2C_M_RD;msgs[1].buf = rdata;msgs[1].len = rlen;res = i2c_transfer(i2c_adap, &msgs[0], 1);udelay(2* 1000);res = i2c_transfer(i2c_adap, &msgs[1], 1);if (res == 1)return 0;else if(res == 0)return -EBUSY;elsereturn res;return res;
}static int i2c_rx_data(struct i2c_client *client, char * txData,int tlen,char *rxData, int rlen)
{int ret = 0;int i = 0;for (i = 0; i < 2; i++) {ret = i2c_read(client->adapter, client->addr, txData,tlen,rxData,rlen);if (ret < 0){am2320_error("haier_i2c_rx_data error\n");}else{break;}}return ret;
}static int i2c_write(struct i2c_adapter *i2c_adap,unsigned char address,unsigned int len, unsigned char const *data)
{struct i2c_msg msgs[1];int res;if (!i2c_adap) {am2320_error("%s:line=%d,error\n",__func__,__LINE__);return -EINVAL;}msgs[0].addr = address;msgs[0].flags = 0;msgs[0].buf = (unsigned char *)data;msgs[0].len = len;res = i2c_transfer(i2c_adap, msgs, 1);if (res == 1)return 0;else if(res == 0)return -EBUSY;elsereturn res;}static int i2c_tx_data(struct i2c_client *client, char *txData, int length)
{int ret = 0;int i = 0;for (i = 0; i < 3; i++) {ret = i2c_write(client->adapter, client->addr, length, txData);if (!ret)break;}return ret;
}static int am2320_read_data(struct am2320_driver *am2320_driver,char *w_data,int w_len,char *r_data,int r_len)
{int ret = 0;ret = i2c_tx_data(am2320_driver->client,NULL,0); // wake up deviceif (ret < 0){am2320_error("am2320_wake_up error\n");return ret;}ret = i2c_rx_data(am2320_driver->client,w_data,w_len,r_data,r_len);//get data if (ret < 0){am2320_error("am2320_read_data error\n");return ret;}return ret;
}static void am2320_schedele_work(struct work_struct *work)
{int m_temp = 0;int m_humidity = 0;struct am2320_driver *am2320_driver = container_of((struct delayed_work *)work,struct am2320_driver, work);unsigned long delay = msecs_to_jiffies(am2320_driver->delay);char w_temp_data[AM2320_TEMP_RETURN_LENGTH] = {0};char r_temp_data[AM2320_TEMP_RETURN_LENGTH] = {0};w_temp_data[0] = AM2320_FUNCTION_CODE;w_temp_data[1] = AM2320_TEMP_HUMIDITY_ADDR;w_temp_data[2] = AM2320_TEMP_HUMIDITY_LENGTH;am2320_read_data(am2320_driver,w_temp_data,AM2320_CMD_LEMGTH,r_temp_data,AM2320_TEMP_RETURN_LENGTH);m_temp = ((r_temp_data[4] << 8) | r_temp_data[5]);m_humidity = ((r_temp_data[2] << 8) | r_temp_data[3]);input_report_abs(am2320_driver->input_dev, ABS_MISC, m_temp);input_sync(am2320_driver->input_dev);  //reprot temp valueinput_report_abs(am2320_driver->input_dev, ABS_X, m_humidity);input_sync(am2320_driver->input_dev);  //report thumidity valueam2320_info("m_temp===%d\n",m_temp);am2320_info("m_humidity===%d\n",m_humidity);schedule_delayed_work(&am2320_driver->work, delay);
}static int am2320_probe(struct i2c_client *client,const struct i2c_device_id *id)
{int ret = 0;struct am2320_driver *am2320_driver = NULL;///static struct class *memc_class;am2320_driver = kzalloc(sizeof(struct am2320_driver), GFP_KERNEL);if (am2320_driver == NULL) {printk("failed to create our am2320_driver\n");return -ENOMEM;}am2320_driver->client = client;i2c_set_clientdata(client, am2320_driver);INIT_DELAYED_WORK(&am2320_driver->work, am2320_schedele_work);schedule_delayed_work(&am2320_driver->work, AM2320_SCHE_DELAY);am2320_driver->delay = AM2320_SCHE_DELAY;am2320_driver->input_dev= input_allocate_device();	if (!am2320_driver->input_dev) {am2320_error("input_allocate_device error\n");goto kfree_exit;	}am2320_driver->input_dev->name = DEVICE_NAME;am2320_driver->input_dev->id.bustype = BUS_I2C;input_set_capability(am2320_driver->input_dev, EV_ABS, ABS_MISC);input_set_abs_params(am2320_driver->input_dev, ABS_MISC, 0, 8192, 0, 0);input_set_abs_params(am2320_driver->input_dev, ABS_X, 0, 8192, 0, 0);input_set_drvdata(am2320_driver->input_dev, am2320_driver);ret = input_register_device(am2320_driver->input_dev);if (ret < 0) {input_free_device(am2320_driver->input_dev);goto kfree_exit;}mutex_init(&am2320_driver->mutex);return 0;kfree_exit:kfree(am2320_driver);return -ENODEV;}static int am2320_remove(struct i2c_client *client)
{struct am2320_driver *am2320_driver = i2c_get_clientdata(client);i2c_unregister_device(am2320_driver->client);kfree(am2320_driver);return 0;
}static const struct of_device_id i2c_am2320_of_match[] = {{ .compatible = "max,am2320" },{ }
};static const struct i2c_device_id am2320_device_id[] = {{DEVICE_NAME, 0 },{ }
};MODULE_DEVICE_TABLE(i2c, am2320_device_id);static struct i2c_driver am2320_driver = {.driver = {.name	= DRIVER_NAME,.owner  = THIS_MODULE,.of_match_table = of_match_ptr(i2c_am2320_of_match),},.probe = am2320_probe,.remove = am2320_remove,.id_table	= am2320_device_id,
};static int __init am2320_init(void)
{i2c_add_driver(&am2320_driver);return 0;
}static void __exit am2320_exit(void)
{i2c_del_driver(&am2320_driver);
}module_init(am2320_init);
module_exit(am2320_exit);MODULE_DESCRIPTION("Am2320 Temp and Humidity Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("738270732@qq.com");
#ifndef __AM2320_H_
#define __AM2320_H_#define DEVICE_NAME 	"am2320"
#define DRIVER_NAME     "am2320"struct am2320_driver {int  debug_level;int  delay;	int  enable;	struct mutex mutex;struct i2c_client	*client;struct device		*dev;struct delayed_work work;struct input_dev    *input_dev;
};
#define AM2320_FUNCTION_CODE 		0x03
#define AM2320_TEMP_HUMIDITY_ADDR   0x00
#define AM2320_HUMIDITY_ADDR        0x00
#define AM2320_TEMP_ADDR  			0x02
#define AM2320_DEVICE_ID_ADDR       0x08
#define AM2320_TEMP_HUMIDITY_LENGTH 0x04
#define AM2320_DEVICE_ID_LENGTH		0x07
#define AM2320_CMD_LEMGTH           0x03
#define AM2320_TEMP_RETURN_LENGTH  	0x08 
#define AM2320_DEVICE_RETURN_LENGTH 0x0B
#define AM2320_SCHE_DELAY			5000
#define LOG_LEVEL_NONE 		0
#define LOG_LEVEL_ERROR 	1
#define LOG_LEVEL_NOTICE	2
#define LOG_LEVEL_WARNING 	3
#define LOG_LEVEL_INFO 		4
#define LOG_LEVEL_VERBOSE 	5
#define AM2320_DEBUG_LEVEL 	5#define AM2320_LOG_DYNAMIC_CONTROL
#ifdef 	AM2320_LOG_DYNAMIC_CONTROL#define am2320_error(...){ \if(AM2320_DEBUG_LEVEL >= LOG_LEVEL_ERROR) { \printk(KERN_ERR "AM2320 Error: "  __VA_ARGS__); \}\}#define am2320_notice(...){ \if(AM2320_DEBUG_LEVEL >= LOG_LEVEL_NOTICE) { \printk(KERN_NOTICE "AM2320 Notice: "  __VA_ARGS__); \}\}#define am2320_warning(...){ \if(AM2320_DEBUG_LEVEL >= LOG_LEVEL_WARNING) { \printk(KERN_WARNING "AM2320 Warning: "  __VA_ARGS__); \}\}#define am2320_info(...){ \if(AM2320_DEBUG_LEVEL >= LOG_LEVEL_INFO) { \printk(KERN_INFO "AM2320 Info: "  __VA_ARGS__); \}\}#endif
#endif
&i2c1 {status = "okay";clock-frequency = <300000>;pinctrl-names="default";pinctrl-0=<&i2c1_h_pins>;am2320@5c{compatible = "max,am2320";reg = <0x5c>;status = "okay";};
};

App端测试

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>#include "android/log.h"
#include <cutils/properties.h>
#include <stdbool.h>
#include <linux/input.h>int main()
{struct input_event inputevent;int fd;int err;fd = open("/dev/input/event2", O_RDWR);if (fd < 0) {printf("Can't open file %s\r\n", "/dev/input/event2");return -1;}while (1) {err = read(fd, &inputevent, sizeof(inputevent));if (err > 0) {switch (inputevent.type) {case EV_ABS:printf("input_code==%d\n",inputevent.code);printf("input_type==%d\n",inputevent.type);printf("input_value==%d\n",inputevent.value);break;default:break;}}}return 0;
}

http://www.ppmy.cn/news/139322.html

相关文章

慧荣SM2320是什么主控?一文便知固态主控SM2320+固件下载

在移动SSD还没有兴起的时期&#xff0c;U盘被看做是传输数据非常好的载体。它身材小巧&#xff0c;性能不俗&#xff0c;偶然的不小心跌落也不会损坏数据。 不过随着固态硬盘的兴起&#xff0c;现在的移动硬盘也是以NAND存储介质为主流了&#xff0c;意味着它的体积可以进一步…

P2320 [HNOI2006]鬼谷子的钱袋

H y p e r l i n k Hyperlink Hyperlink https://www.luogu.com.cn/problem/P2320 D e s c r i p t i o n Description Description 求用若干个正整数表示 ∀ i ∈ [ 1 , n ] , i ∈ N \forall i\in[1,n],i\in \mathbb{N} ∀i∈[1,n],i∈N的最小正整数个数以及这些正整数 这…

AM2320单总线定时器中断方式驱动(stm32)

AM2320是一款具有I2C、单总线通信的温湿度传感器&#xff0c;精度也比较高&#xff0c;适合日常的一些应用场景。对于单总线通信&#xff0c;已经有很多人分享其实现的代码了&#xff0c;但多是使用延时法进行读取&#xff0c;今天给大家带来一个通过单总线定时器中断方式读取。…

洛谷 2320 bzoj 1192 题解 (思维,构造)

原题链接&#xff1a; 洛谷 bzoj 题意简述 给定一个 n ( < 1 e 9 ) n(<1e9) n(<1e9)&#xff0c;构造一个序列使得&#xff1a; [ 1 , n ] [1,n] [1,n]中所有整数是这个序列中某些元素的和字典序最小 输出这个序列 思路 我们一开始认为&#xff1a; n n n是 1 e…

一个通用的自适应prompt方法,突破了零样本学习的瓶颈

深度学习自然语言处理 原创作者&#xff1a;Winni 今天要给大家介绍一篇Google的研究&#xff0c;解决了大语言模型&#xff08;LLMs&#xff09;在零样本学习方面的困境。相比于少样本学习&#xff0c;LLMs在零样本学习上常常表现得比较弱&#xff0c;这主要是因为缺乏指导。而…

03 【数据代理 事件处理】

03 【数据代理 事件处理】 1.数据代理 了解数据代理需要js的一些知识&#xff1a;Object.defineProperty()&#xff0c;属性标志&#xff0c;属性描述符&#xff0c;getter&#xff0c;setter。。。 1.1数据代理 建议学习文章地址&#xff1a; https://zh.javascript.info/p…

php如何停止重启,取消正在执行的任务调度

前言:最近出现一个问题,同事误操作,开启了一个任务,找到我问能不能停止,我也是火急火燎查询方法帮忙解决,我觉得有必要做个记录,希望帮到有需要的人 之前我写过Laravel和thinkphp的定时任务的使用,不懂的人可以先去看看 Laravel定时任务 thinkphp开启定时任务的三种办法…

Redis学习手册(实例代码)

在下面的代码示例中&#xff0c;将给出两种最为常用的Redis命令操作方式&#xff0c;既普通调用方式和基于管线的调用方式。 注&#xff1a;在阅读代码时请留意注释。 1 #include <stdio.h>2 #include <stdlib.h>3 #include <stddef.h>4 #include <st…