64bit系统使用32bit的库对i2c进行I2C_RDWR操作失败(Error during I2C_RDWR ioctl with error code: -1)_I~T_T的博客-程序员秘密_i2c_rdwr

技术标签: android  

使用的系统是64位的系统,而要求使用32位的库对i2c进行I2C_RDWR操作时出现问题,当使用32位的库进行2C_RDWR操作时总是失败,提示i2c_core_read fd(/dev/i2c-0) addr(12) reg(f0) nCnt(3)Error during I2C_RDWR ioctl with error code: -1,原本以为直接将arg参数直接转换一下就行了(compat_ptr(arg)),转换后发现还是不行,原因是参数的结构类型比较复杂的问题。具体可参考如下

具体的修改如下:

diff --git a/kernel-3.10/drivers/i2c/i2c-dev.c b/kernel-3.10/drivers/i2c/i2c-dev.c
index 2ac450f..3e6f811 100644
--- a/kernel-3.10/drivers/i2c/i2c-dev.c
+++ b/kernel-3.10/drivers/i2c/i2c-dev.c
@@ -41,6 +41,10 @@
 #include <linux/uaccess.h>
 #include <linux/dma-mapping.h>
 
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+#endif
+
 #define MAX_DMA_TRANSACTION_LEN 1024
 #define SUPPORT_I2C_DMA     1
 
@@ -49,6 +53,29 @@ static u8*gpDMABuf_va = NULL;
 static dma_addr_t gpDMABuf_pa ;	/* = NULL; */
 #endif 
 
+#ifdef CONFIG_COMPAT
+struct i2c_msg_compat {
+	__u16 addr;	/* slave address			*/
+	__u16 flags;
+#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
+#define I2C_M_RD		0x0001	/* read data, from slave to master */
+#define I2C_M_STOP		0x8000	/* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_NOSTART */
+#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
+	__u16 len;		/* msg length				*/
+	compat_uptr_t buf;		/* pointer to msg data		__u8 *buf;	*/
+	__u32 timing;			/* paramters of timings		*/
+	__u32 ext_flag;
+};
+
+struct i2c_rdwr_ioctl_data_compat {
+	compat_uptr_t msgs;	/* pointers to i2c_msgs */
+	__u32 nmsgs;			/* number of i2c_msgs */
+};
+#endif
 /*
  * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
  * slave (i2c_client) with which messages will be exchanged.  It's coupled
@@ -243,6 +270,181 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
 	return result;
 }
 
+#ifdef CONFIG_COMPAT
+static void compat_get_info_struct(
+            struct i2c_msg_compat *data32,
+            struct i2c_msg *data, int num)
+{
+    int i;
+	for (i=0; i<num; i++) {
+		data[i].addr = data32[i].addr;
+		data[i].flags = data32[i].flags;
+		data[i].len = data32[i].len;
+		data[i].buf = compat_ptr(data32[i].buf);
+		data[i].timing = data32[i].timing;
+		data[i].ext_flag = data32[i].ext_flag;
+	}
+}
+
+static noinline int i2cdev_ioctl_rdrw_compat(struct i2c_client *client,
+		unsigned long arg)
+{
+	struct i2c_rdwr_ioctl_data_compat  rdwr_arg;
+	struct i2c_msg_compat *rdwr_pa32;
+	struct i2c_msg *rdwr_pa;
+	u8 __user **data_ptrs;
+	int i, res;
+
+	if (copy_from_user(&rdwr_arg,(void __user *)arg,sizeof(rdwr_arg)))
+		return -EFAULT;
+
+	/* Put an arbitrary limit on the number of messages that can
+	 * be sent at once */
+	if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
+		return -EINVAL;
+	pr_debug("i2cdev_ioctl_rdrw_compat rdwr_arg.nmsgs = %d\n", rdwr_arg.nmsgs);
+	rdwr_pa32 = memdup_user(compat_ptr(rdwr_arg.msgs),
+			      rdwr_arg.nmsgs * sizeof(struct i2c_msg_compat));
+
+	if (IS_ERR(rdwr_pa32))
+		return PTR_ERR(rdwr_pa32);
+
+	rdwr_pa = kmalloc(rdwr_arg.nmsgs * sizeof(*rdwr_pa), GFP_KERNEL);
+	compat_get_info_struct(rdwr_pa32, rdwr_pa, rdwr_arg.nmsgs);
+
+    #if SUPPORT_I2C_DMA
+    for(i = 0; i < rdwr_arg.nmsgs; i++)
+    {
+        if(rdwr_pa[i].timing == 0)
+        {
+            rdwr_pa[i].timing = client->timing;
+        }
+        rdwr_pa[i].ext_flag = client->ext_flag;
+    }
+    #endif
+
+	data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+	if (data_ptrs == NULL) {
+		kfree(rdwr_pa);
+		return -ENOMEM;
+	}
+
+	res = 0;
+	for (i = 0; i < rdwr_arg.nmsgs; i++) {
+		/* Limit the size of the message to a sane amount */
+		if (rdwr_pa[i].len > 8192) {
+			res = -EINVAL;
+			break;
+		}
+
+		data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
+        #if SUPPORT_I2C_DMA
+        if(rdwr_pa[i].len > 8)
+        {
+            if (gpDMABuf_va == NULL)
+            {
+                gpDMABuf_va = dma_alloc_coherent(&client->dev,MAX_DMA_TRANSACTION_LEN, &gpDMABuf_pa, GFP_KERNEL);
+            }
+
+            if(copy_from_user(gpDMABuf_va,data_ptrs[i],rdwr_pa[i].len))
+				return -EFAULT;
+            rdwr_pa[i].buf = (u8 *)gpDMABuf_pa;
+            if(rdwr_pa[i].timing >= 300)
+            {
+                rdwr_pa[i].ext_flag = rdwr_pa[i].ext_flag|I2C_DMA_FLAG|I2C_HS_FLAG|I2C_RS_FLAG|I2C_PUSHPULL_FLAG;
+            }
+            else
+            {
+                rdwr_pa[i].ext_flag = rdwr_pa[i].ext_flag|I2C_DMA_FLAG|I2C_RS_FLAG|I2C_PUSHPULL_FLAG;
+            }
+        }
+        else
+        {
+            rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len);
+            rdwr_pa[i].ext_flag = rdwr_pa[i].ext_flag |I2C_RS_FLAG|I2C_PUSHPULL_FLAG;
+        }
+        #else
+		rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len);
+        #endif
+		if (IS_ERR(rdwr_pa[i].buf)) {
+			res = PTR_ERR(rdwr_pa[i].buf);
+			break;
+		}
+
+		/*
+		 * If the message length is received from the slave (similar
+		 * to SMBus block read), we must ensure that the buffer will
+		 * be large enough to cope with a message length of
+		 * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus
+		 * drivers allow. The first byte in the buffer must be
+		 * pre-filled with the number of extra bytes, which must be
+		 * at least one to hold the message length, but can be
+		 * greater (for example to account for a checksum byte at
+		 * the end of the message.)
+		 */
+		if (rdwr_pa[i].flags & I2C_M_RECV_LEN) {
+			if (!(rdwr_pa[i].flags & I2C_M_RD) ||
+			    rdwr_pa[i].buf[0] < 1 ||
+			    rdwr_pa[i].len < rdwr_pa[i].buf[0] +
+					     I2C_SMBUS_BLOCK_MAX) {
+				res = -EINVAL;
+				break;
+			}
+
+			rdwr_pa[i].len = rdwr_pa[i].buf[0];
+		}
+	}
+	if (res < 0) {
+		int j;
+		for (j = 0; j < i; ++j)
+		{
+		    #if SUPPORT_I2C_DMA
+            if(rdwr_pa[i].ext_flag & I2C_DMA_FLAG)
+            {
+                rdwr_pa[j].buf = NULL;
+            }
+            #endif
+            {
+		        kfree(rdwr_pa[j].buf);
+            }
+        }
+		kfree(data_ptrs);
+		kfree(rdwr_pa);
+		return res;
+	}
+
+	res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
+	while (i-- > 0) {
+        #if SUPPORT_I2C_DMA
+        if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD) && (rdwr_pa[i].ext_flag & I2C_DMA_FLAG))
+        {
+            if (copy_to_user(data_ptrs[i], gpDMABuf_va, rdwr_pa[i].len))
+				res = -EFAULT;
+        }
+        else
+        #endif
+        {
+			if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
+				if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, rdwr_pa[i].len))
+					res = -EFAULT;
+			}
+        }
+        #if SUPPORT_I2C_DMA
+        if(rdwr_pa[i].ext_flag & I2C_DMA_FLAG)
+        {
+            rdwr_pa[i].buf = NULL;
+        }
+        #endif
+        {
+	        kfree(rdwr_pa[i].buf);
+        }
+	}
+	kfree(data_ptrs);
+	kfree(rdwr_pa);
+       kfree(rdwr_pa32);
+	return res;
+}
+#endif
+
 static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
 		unsigned long arg)
 {
@@ -556,6 +758,17 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	return 0;
 }
 
+#ifdef CONFIG_COMPAT
+static long i2cdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	pr_debug("i2cdev_ioctl_compat cmd = %d arg=0x%02lx\n", cmd, arg);
+	if (cmd == I2C_RDWR) {
+		return i2cdev_ioctl_rdrw_compat(file->private_data, arg);
+	}
+    return i2cdev_ioctl(file, cmd, compat_ptr(arg));
+}
+#endif
+
 static int i2cdev_open(struct inode *inode, struct file *file)
 {
 	unsigned int minor = iminor(inode);
@@ -608,6 +821,9 @@ static const struct file_operations i2cdev_fops = {
 	.read		= i2cdev_read,
 	.write		= i2cdev_write,
 	.unlocked_ioctl	= i2cdev_ioctl,
+#ifdef CONFIG_COMPAT
+    .compat_ioctl = i2cdev_ioctl_compat,
+#endif
 	.open		= i2cdev_open,
 	.release	= i2cdev_release,
 };

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010867436/article/details/100554991

智能推荐

2.1.1.4 搭建Metasploitable2虚拟机环境_lushan0719的博客-程序员秘密

进入metasploitable2官网https://sourceforge.net/projects/metasploitable/,下载解压后,双击vmx文件。账号:msfadmin 密码:msfadmin

(转帖)小菜编程成长记(八 用“策略模式”是一种好策略) _Oneil_Sally的博客-程序员秘密

小菜次日来找大鸟,说:“《深入浅出设计模式》的第一章我看完了,它讲的是策略模式(Strategy)。『策略模式』定义了算法家族,分别封装起来,让它们之间可以互相替换, 此模式让算法的变化, 不会影响到使用算法的客户。看来商场收银系统应该考虑用策略模式?”      “你问我?你说呢?”大鸟笑道,“商场收银时如何促销,用打折还是返利,其实都是一些算法,用工厂来生成算法对象,感觉是不是很怪?而最重要的

网络开源音视频测试源_coloriy的博客-程序员秘密

Resources for Additional Test Clips or SamplesDemolandia(4K and 3D trailers trailers) Big Buck Bunny(test suite with 2D, 3D and 4K clips) CNXSoft's samples/links W6RZ MPEG2 clips The Digital Theater(several excellent ATMOS, 3D, IMAX, etc. trai...

android+最新手机,安兔兔发布2018年8月Android手机性价比排行榜_weixin_39762075的博客-程序员秘密

注:性价比分值=机型平均跑分(V7版)÷当前价格(参考京东官方店铺)统计时间:2018年8月1日至8月31日;单一机型总记录数&gt;10000-999元现如今的千元机早已不是几年前那种接近于粗制滥造的千元机,即便是几百元的价格,其实也能买到一款各方面都让人基本满意的产品,只是拍照和部分大型3D游戏性能不如旗舰产品而已。第一名:红米Note 5(3GB+32GB)平均跑分成绩:114453性价比值...

谷歌浏览器Google Chrome67版本以上离线安装crx插件_lican_2017的博客-程序员秘密

换了台电脑重新下载了Chrome,发现不能离线安装crx了后来才知道Goole谷歌自Chrome 67版本开始,只允许从Chrome网上商店安装扩展,其它的方式的安装都已经被删除。下面介绍一款软件完美解决(内附教程,此压缩文件为7z格式请用7-zip软件解压)链接 :链接: https://pan.baidu.com/s/1oVSxjhiSHMB99TK5VBUpYQ 提取码: 7ezj...

Python入门基础篇 No.1 —— 缩进_行注释_段注释_0FF1ine404的博客-程序员秘密

Python入门基础篇 No.1 —— 缩进_行注释_段注释缩进_行注释_段注释Python入门基础篇 No.1 —— 缩进_行注释_段注释程序基本格式恰当的空格,缩进问题Python区分大小写注释程序基本格式恰当的空格,缩进问题逻辑行首的空白(空格和制表符)用来决定逻辑行的缩进层次,从而用来决定语句的分组。语句从新行的第一列开始。缩进风格统一:每个缩进层次的使用 单个制表符 或者四个空格(一个制表符相当于四个空格)Python用缩进而不是{}表示程序块下面展示

随便推点

人人开源(后台代码、前端项目、代码自动生成)_liangjiayy的博客-程序员秘密

人人开源 renren-fast renren-fast-vue renren-generator 人人开源(后台代码、前端项目、代码自动生成)

【SpringMVC】源码阅读_springmvc 源码阅读_hancoder的博客-程序员秘密

一、框架预览二、定义与对象首先必须了解处理器即handler是什么:你在前期可以直接理解为controller方法HttpServlet定义了规范, 但是如果不重写doGet方法的话就会报错FrameworkServlet重写了doGet(),实现了HttpServletBeanDispatcherServlet:派发到处理器上HanlderInterceptor,接口3个方法preHandle//请求开始之前postHandle//请求结束之后,画面渲染之前af.

android-----Activity生命周期_她说巷尾的樱花开了的博客-程序员秘密

android四大组件的生命周期对于学习android开发的人来说是必学的知识啦,接下来的几天准备总结一下,首先从Activity的生命周期开始:       Activity类中有关生命周期的方法有一下几种:       (1)onCreate(): 当活动第一次启动的时候会触发该方法,可以在此完成活动的初始化工作,该方法有一个参数,该参数可以是null,也可以是之前调用onSave

3dsmax2019 中arnold standard surface 贴图连接方法_esau2的博客-程序员秘密

3dsmax2019 中arnold standard surface 贴图连接方法max和maya现在都同样使用arnold渲染器之后,两边的ai标准材质属性基本一致,贴图也可以共用。maya中的贴图一般包括 basecolor metalness normal opecula roughness这5种如果要转到max中进行制作,贴图要重新链接到mas中的arnold ...

cocos2d-x 3.0 制作我的微信飞机大战_decajes的博客-程序员秘密

花了3天时间,把这个游戏简单地实现了遍,途中也遇到不少问题,不过感谢两位大神的博客专栏,一个为http://blog.csdn.net/column/details/jackyairplane.html,另一个为http://www.zaojiahua.com/category/cocos2d-xdemo/,在完成代码的过程中遇到的一些小问题都在在上面的博客中找到了答案。

推荐文章

热门文章

相关标签