Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
7d5cb456
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
6
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7d5cb456
编写于
9月 20, 2017
作者:
A
Al Viro
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
i2c compat ioctls: move to ->compat_ioctl()
Signed-off-by:
N
Al Viro
<
viro@zeniv.linux.org.uk
>
上级
abca5fc5
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
180 addition
and
210 deletion
+180
-210
drivers/i2c/i2c-dev.c
drivers/i2c/i2c-dev.c
+180
-88
fs/compat_ioctl.c
fs/compat_ioctl.c
+0
-122
未找到文件。
drivers/i2c/i2c-dev.c
浏览文件 @
7d5cb456
...
...
@@ -35,6 +35,7 @@
#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/compat.h>
/*
* An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
...
...
@@ -238,46 +239,29 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
}
static
noinline
int
i2cdev_ioctl_rdwr
(
struct
i2c_client
*
client
,
unsigned
long
arg
)
unsigned
nmsgs
,
struct
i2c_msg
*
msgs
)
{
struct
i2c_rdwr_ioctl_data
rdwr_arg
;
struct
i2c_msg
*
rdwr_pa
;
u8
__user
**
data_ptrs
;
int
i
,
res
;
if
(
copy_from_user
(
&
rdwr_arg
,
(
struct
i2c_rdwr_ioctl_data
__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_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
rdwr_pa
=
memdup_user
(
rdwr_arg
.
msgs
,
rdwr_arg
.
nmsgs
*
sizeof
(
struct
i2c_msg
));
if
(
IS_ERR
(
rdwr_pa
))
return
PTR_ERR
(
rdwr_pa
);
data_ptrs
=
kmalloc
(
rdwr_arg
.
nmsgs
*
sizeof
(
u8
__user
*
),
GFP_KERNEL
);
data_ptrs
=
kmalloc
(
nmsgs
*
sizeof
(
u8
__user
*
),
GFP_KERNEL
);
if
(
data_ptrs
==
NULL
)
{
kfree
(
rdwr_pa
);
kfree
(
msgs
);
return
-
ENOMEM
;
}
res
=
0
;
for
(
i
=
0
;
i
<
rdwr_arg
.
nmsgs
;
i
++
)
{
for
(
i
=
0
;
i
<
nmsgs
;
i
++
)
{
/* Limit the size of the message to a sane amount */
if
(
rdwr_pa
[
i
].
len
>
8192
)
{
if
(
msgs
[
i
].
len
>
8192
)
{
res
=
-
EINVAL
;
break
;
}
data_ptrs
[
i
]
=
(
u8
__user
*
)
rdwr_pa
[
i
].
buf
;
rdwr_pa
[
i
].
buf
=
memdup_user
(
data_ptrs
[
i
],
rdwr_pa
[
i
].
len
);
if
(
IS_ERR
(
rdwr_pa
[
i
].
buf
))
{
res
=
PTR_ERR
(
rdwr_pa
[
i
].
buf
);
data_ptrs
[
i
]
=
(
u8
__user
*
)
msgs
[
i
].
buf
;
msgs
[
i
].
buf
=
memdup_user
(
data_ptrs
[
i
],
msgs
[
i
].
len
);
if
(
IS_ERR
(
msgs
[
i
].
buf
))
{
res
=
PTR_ERR
(
msgs
[
i
].
buf
);
break
;
}
...
...
@@ -292,121 +276,117 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
* 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
]
+
if
(
msgs
[
i
].
flags
&
I2C_M_RECV_LEN
)
{
if
(
!
(
msgs
[
i
].
flags
&
I2C_M_RD
)
||
msgs
[
i
].
buf
[
0
]
<
1
||
msgs
[
i
].
len
<
msgs
[
i
].
buf
[
0
]
+
I2C_SMBUS_BLOCK_MAX
)
{
res
=
-
EINVAL
;
break
;
}
rdwr_pa
[
i
].
len
=
rdwr_pa
[
i
].
buf
[
0
];
msgs
[
i
].
len
=
msgs
[
i
].
buf
[
0
];
}
}
if
(
res
<
0
)
{
int
j
;
for
(
j
=
0
;
j
<
i
;
++
j
)
kfree
(
rdwr_pa
[
j
].
buf
);
kfree
(
msgs
[
j
].
buf
);
kfree
(
data_ptrs
);
kfree
(
rdwr_pa
);
kfree
(
msgs
);
return
res
;
}
res
=
i2c_transfer
(
client
->
adapter
,
rdwr_pa
,
rdwr_arg
.
nmsgs
);
res
=
i2c_transfer
(
client
->
adapter
,
msgs
,
nmsgs
);
while
(
i
--
>
0
)
{
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
))
if
(
res
>=
0
&&
(
msgs
[
i
].
flags
&
I2C_M_RD
))
{
if
(
copy_to_user
(
data_ptrs
[
i
],
msgs
[
i
].
buf
,
msgs
[
i
].
len
))
res
=
-
EFAULT
;
}
kfree
(
rdwr_pa
[
i
].
buf
);
kfree
(
msgs
[
i
].
buf
);
}
kfree
(
data_ptrs
);
kfree
(
rdwr_pa
);
kfree
(
msgs
);
return
res
;
}
static
noinline
int
i2cdev_ioctl_smbus
(
struct
i2c_client
*
client
,
unsigned
long
arg
)
u8
read_write
,
u8
command
,
u32
size
,
union
i2c_smbus_data
__user
*
data
)
{
struct
i2c_smbus_ioctl_data
data_arg
;
union
i2c_smbus_data
temp
=
{};
int
datasize
,
res
;
if
(
copy_from_user
(
&
data_arg
,
(
struct
i2c_smbus_ioctl_data
__user
*
)
arg
,
sizeof
(
struct
i2c_smbus_ioctl_data
)))
return
-
EFAULT
;
if
((
data_arg
.
size
!=
I2C_SMBUS_BYTE
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_QUICK
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_BYTE_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_WORD_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_PROC_CALL
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_BLOCK_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_I2C_BLOCK_BROKEN
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_I2C_BLOCK_DATA
)
&&
(
data_arg
.
size
!=
I2C_SMBUS_BLOCK_PROC_CALL
))
{
if
((
size
!=
I2C_SMBUS_BYTE
)
&&
(
size
!=
I2C_SMBUS_QUICK
)
&&
(
size
!=
I2C_SMBUS_BYTE_DATA
)
&&
(
size
!=
I2C_SMBUS_WORD_DATA
)
&&
(
size
!=
I2C_SMBUS_PROC_CALL
)
&&
(
size
!=
I2C_SMBUS_BLOCK_DATA
)
&&
(
size
!=
I2C_SMBUS_I2C_BLOCK_BROKEN
)
&&
(
size
!=
I2C_SMBUS_I2C_BLOCK_DATA
)
&&
(
size
!=
I2C_SMBUS_BLOCK_PROC_CALL
))
{
dev_dbg
(
&
client
->
adapter
->
dev
,
"size out of range (%x) in ioctl I2C_SMBUS.
\n
"
,
data_arg
.
size
);
size
);
return
-
EINVAL
;
}
/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
so the check is valid if size==I2C_SMBUS_QUICK too. */
if
((
data_arg
.
read_write
!=
I2C_SMBUS_READ
)
&&
(
data_arg
.
read_write
!=
I2C_SMBUS_WRITE
))
{
if
((
read_write
!=
I2C_SMBUS_READ
)
&&
(
read_write
!=
I2C_SMBUS_WRITE
))
{
dev_dbg
(
&
client
->
adapter
->
dev
,
"read_write out of range (%x) in ioctl I2C_SMBUS.
\n
"
,
data_arg
.
read_write
);
read_write
);
return
-
EINVAL
;
}
/* Note that command values are always valid! */
if
((
data_arg
.
size
==
I2C_SMBUS_QUICK
)
||
((
data_arg
.
size
==
I2C_SMBUS_BYTE
)
&&
(
data_arg
.
read_write
==
I2C_SMBUS_WRITE
)))
if
((
size
==
I2C_SMBUS_QUICK
)
||
((
size
==
I2C_SMBUS_BYTE
)
&&
(
read_write
==
I2C_SMBUS_WRITE
)))
/* These are special: we do not use data */
return
i2c_smbus_xfer
(
client
->
adapter
,
client
->
addr
,
client
->
flags
,
data_arg
.
read_write
,
data_arg
.
command
,
data_arg
.
size
,
NULL
);
client
->
flags
,
read_write
,
command
,
size
,
NULL
);
if
(
data
_arg
.
data
==
NULL
)
{
if
(
data
==
NULL
)
{
dev_dbg
(
&
client
->
adapter
->
dev
,
"data is NULL pointer in ioctl I2C_SMBUS.
\n
"
);
return
-
EINVAL
;
}
if
((
data_arg
.
size
==
I2C_SMBUS_BYTE_DATA
)
||
(
data_arg
.
size
==
I2C_SMBUS_BYTE
))
datasize
=
sizeof
(
data
_arg
.
data
->
byte
);
else
if
((
data_arg
.
size
==
I2C_SMBUS_WORD_DATA
)
||
(
data_arg
.
size
==
I2C_SMBUS_PROC_CALL
))
datasize
=
sizeof
(
data
_arg
.
data
->
word
);
if
((
size
==
I2C_SMBUS_BYTE_DATA
)
||
(
size
==
I2C_SMBUS_BYTE
))
datasize
=
sizeof
(
data
->
byte
);
else
if
((
size
==
I2C_SMBUS_WORD_DATA
)
||
(
size
==
I2C_SMBUS_PROC_CALL
))
datasize
=
sizeof
(
data
->
word
);
else
/* size == smbus block, i2c block, or block proc. call */
datasize
=
sizeof
(
data
_arg
.
data
->
block
);
datasize
=
sizeof
(
data
->
block
);
if
((
data_arg
.
size
==
I2C_SMBUS_PROC_CALL
)
||
(
data_arg
.
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
data_arg
.
size
==
I2C_SMBUS_I2C_BLOCK_DATA
)
||
(
data_arg
.
read_write
==
I2C_SMBUS_WRITE
))
{
if
(
copy_from_user
(
&
temp
,
data
_arg
.
data
,
datasize
))
if
((
size
==
I2C_SMBUS_PROC_CALL
)
||
(
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
size
==
I2C_SMBUS_I2C_BLOCK_DATA
)
||
(
read_write
==
I2C_SMBUS_WRITE
))
{
if
(
copy_from_user
(
&
temp
,
data
,
datasize
))
return
-
EFAULT
;
}
if
(
data_arg
.
size
==
I2C_SMBUS_I2C_BLOCK_BROKEN
)
{
if
(
size
==
I2C_SMBUS_I2C_BLOCK_BROKEN
)
{
/* Convert old I2C block commands to the new
convention. This preserves binary compatibility. */
data_arg
.
size
=
I2C_SMBUS_I2C_BLOCK_DATA
;
if
(
data_arg
.
read_write
==
I2C_SMBUS_READ
)
size
=
I2C_SMBUS_I2C_BLOCK_DATA
;
if
(
read_write
==
I2C_SMBUS_READ
)
temp
.
block
[
0
]
=
I2C_SMBUS_BLOCK_MAX
;
}
res
=
i2c_smbus_xfer
(
client
->
adapter
,
client
->
addr
,
client
->
flags
,
data_arg
.
read_write
,
data_arg
.
command
,
data_arg
.
size
,
&
temp
);
if
(
!
res
&&
((
data_arg
.
size
==
I2C_SMBUS_PROC_CALL
)
||
(
data_arg
.
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
data_arg
.
read_write
==
I2C_SMBUS_READ
)))
{
if
(
copy_to_user
(
data
_arg
.
data
,
&
temp
,
datasize
))
read_write
,
command
,
size
,
&
temp
);
if
(
!
res
&&
((
size
==
I2C_SMBUS_PROC_CALL
)
||
(
size
==
I2C_SMBUS_BLOCK_PROC_CALL
)
||
(
read_write
==
I2C_SMBUS_READ
)))
{
if
(
copy_to_user
(
data
,
&
temp
,
datasize
))
return
-
EFAULT
;
}
return
res
;
...
...
@@ -454,12 +434,39 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
funcs
=
i2c_get_functionality
(
client
->
adapter
);
return
put_user
(
funcs
,
(
unsigned
long
__user
*
)
arg
);
case
I2C_RDWR
:
return
i2cdev_ioctl_rdwr
(
client
,
arg
);
case
I2C_RDWR
:
{
struct
i2c_rdwr_ioctl_data
rdwr_arg
;
struct
i2c_msg
*
rdwr_pa
;
if
(
copy_from_user
(
&
rdwr_arg
,
(
struct
i2c_rdwr_ioctl_data
__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_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
case
I2C_SMBUS
:
return
i2cdev_ioctl_smbus
(
client
,
arg
);
rdwr_pa
=
memdup_user
(
rdwr_arg
.
msgs
,
rdwr_arg
.
nmsgs
*
sizeof
(
struct
i2c_msg
));
if
(
IS_ERR
(
rdwr_pa
))
return
PTR_ERR
(
rdwr_pa
);
return
i2cdev_ioctl_rdwr
(
client
,
rdwr_arg
.
nmsgs
,
rdwr_pa
);
}
case
I2C_SMBUS
:
{
struct
i2c_smbus_ioctl_data
data_arg
;
if
(
copy_from_user
(
&
data_arg
,
(
struct
i2c_smbus_ioctl_data
__user
*
)
arg
,
sizeof
(
struct
i2c_smbus_ioctl_data
)))
return
-
EFAULT
;
return
i2cdev_ioctl_smbus
(
client
,
data_arg
.
read_write
,
data_arg
.
command
,
data_arg
.
size
,
data_arg
.
data
);
}
case
I2C_RETRIES
:
client
->
adapter
->
retries
=
arg
;
break
;
...
...
@@ -480,6 +487,90 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return
0
;
}
#ifdef CONFIG_COMPAT
struct
i2c_smbus_ioctl_data32
{
u8
read_write
;
u8
command
;
u32
size
;
compat_caddr_t
data
;
/* union i2c_smbus_data *data */
};
struct
i2c_msg32
{
u16
addr
;
u16
flags
;
u16
len
;
compat_caddr_t
buf
;
};
struct
i2c_rdwr_ioctl_data32
{
compat_caddr_t
msgs
;
/* struct i2c_msg __user *msgs */
u32
nmsgs
;
};
static
long
compat_i2cdev_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
i2c_client
*
client
=
file
->
private_data
;
unsigned
long
funcs
;
switch
(
cmd
)
{
case
I2C_FUNCS
:
funcs
=
i2c_get_functionality
(
client
->
adapter
);
return
put_user
(
funcs
,
(
compat_ulong_t
__user
*
)
arg
);
case
I2C_RDWR
:
{
struct
i2c_rdwr_ioctl_data32
rdwr_arg
;
struct
i2c_msg32
*
p
;
struct
i2c_msg
*
rdwr_pa
;
int
i
;
if
(
copy_from_user
(
&
rdwr_arg
,
(
struct
i2c_rdwr_ioctl_data32
__user
*
)
arg
,
sizeof
(
rdwr_arg
)))
return
-
EFAULT
;
if
(
rdwr_arg
.
nmsgs
>
I2C_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
rdwr_pa
=
kmalloc_array
(
rdwr_arg
.
nmsgs
,
sizeof
(
struct
i2c_msg
),
GFP_KERNEL
);
if
(
!
rdwr_pa
)
return
-
ENOMEM
;
p
=
compat_ptr
(
rdwr_arg
.
msgs
);
for
(
i
=
0
;
i
<
rdwr_arg
.
nmsgs
;
i
++
)
{
struct
i2c_msg32
umsg
;
if
(
copy_from_user
(
&
umsg
,
p
+
i
,
sizeof
(
umsg
)))
{
kfree
(
rdwr_pa
);
return
-
EFAULT
;
}
rdwr_pa
[
i
]
=
(
struct
i2c_msg
)
{
.
addr
=
umsg
.
addr
,
.
flags
=
umsg
.
flags
,
.
len
=
umsg
.
len
,
.
buf
=
compat_ptr
(
umsg
.
buf
)
};
}
return
i2cdev_ioctl_rdwr
(
client
,
rdwr_arg
.
nmsgs
,
rdwr_pa
);
}
case
I2C_SMBUS
:
{
struct
i2c_smbus_ioctl_data32
data32
;
if
(
copy_from_user
(
&
data32
,
(
void
__user
*
)
arg
,
sizeof
(
data32
)))
return
-
EFAULT
;
return
i2cdev_ioctl_smbus
(
client
,
data32
.
read_write
,
data32
.
command
,
data32
.
size
,
compat_ptr
(
data32
.
data
));
}
default:
return
i2cdev_ioctl
(
file
,
cmd
,
arg
);
}
}
#else
#define compat_i2cdev_ioctl NULL
#endif
static
int
i2cdev_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
unsigned
int
minor
=
iminor
(
inode
);
...
...
@@ -527,6 +618,7 @@ static const struct file_operations i2cdev_fops = {
.
read
=
i2cdev_read
,
.
write
=
i2cdev_write
,
.
unlocked_ioctl
=
i2cdev_ioctl
,
.
compat_ioctl
=
compat_i2cdev_ioctl
,
.
open
=
i2cdev_open
,
.
release
=
i2cdev_release
,
};
...
...
fs/compat_ioctl.c
浏览文件 @
7d5cb456
...
...
@@ -53,8 +53,6 @@
#include <linux/if_tun.h>
#include <linux/ctype.h>
#include <linux/syscalls.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/atalk.h>
#include <linux/gfp.h>
#include <linux/cec.h>
...
...
@@ -136,22 +134,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return
vfs_ioctl
(
file
,
cmd
,
arg
);
}
static
int
w_long
(
struct
file
*
file
,
unsigned
int
cmd
,
compat_ulong_t
__user
*
argp
)
{
int
err
;
unsigned
long
__user
*
valp
=
compat_alloc_user_space
(
sizeof
(
*
valp
));
if
(
valp
==
NULL
)
return
-
EFAULT
;
err
=
do_ioctl
(
file
,
cmd
,
(
unsigned
long
)
valp
);
if
(
err
)
return
err
;
if
(
convert_in_user
(
valp
,
argp
))
return
-
EFAULT
;
return
0
;
}
struct
compat_video_event
{
int32_t
type
;
compat_time_t
timestamp
;
...
...
@@ -670,96 +652,6 @@ static int serial_struct_ioctl(struct file *file,
return
err
;
}
/*
* I2C layer ioctls
*/
struct
i2c_msg32
{
u16
addr
;
u16
flags
;
u16
len
;
compat_caddr_t
buf
;
};
struct
i2c_rdwr_ioctl_data32
{
compat_caddr_t
msgs
;
/* struct i2c_msg __user *msgs */
u32
nmsgs
;
};
struct
i2c_smbus_ioctl_data32
{
u8
read_write
;
u8
command
;
u32
size
;
compat_caddr_t
data
;
/* union i2c_smbus_data *data */
};
struct
i2c_rdwr_aligned
{
struct
i2c_rdwr_ioctl_data
cmd
;
struct
i2c_msg
msgs
[
0
];
};
static
int
do_i2c_rdwr_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
struct
i2c_rdwr_ioctl_data32
__user
*
udata
)
{
struct
i2c_rdwr_aligned
__user
*
tdata
;
struct
i2c_msg
__user
*
tmsgs
;
struct
i2c_msg32
__user
*
umsgs
;
compat_caddr_t
datap
;
u32
nmsgs
;
int
i
;
if
(
get_user
(
nmsgs
,
&
udata
->
nmsgs
))
return
-
EFAULT
;
if
(
nmsgs
>
I2C_RDWR_IOCTL_MAX_MSGS
)
return
-
EINVAL
;
if
(
get_user
(
datap
,
&
udata
->
msgs
))
return
-
EFAULT
;
umsgs
=
compat_ptr
(
datap
);
tdata
=
compat_alloc_user_space
(
sizeof
(
*
tdata
)
+
nmsgs
*
sizeof
(
struct
i2c_msg
));
tmsgs
=
&
tdata
->
msgs
[
0
];
if
(
put_user
(
nmsgs
,
&
tdata
->
cmd
.
nmsgs
)
||
put_user
(
tmsgs
,
&
tdata
->
cmd
.
msgs
))
return
-
EFAULT
;
for
(
i
=
0
;
i
<
nmsgs
;
i
++
)
{
if
(
copy_in_user
(
&
tmsgs
[
i
].
addr
,
&
umsgs
[
i
].
addr
,
3
*
sizeof
(
u16
)))
return
-
EFAULT
;
if
(
get_user
(
datap
,
&
umsgs
[
i
].
buf
)
||
put_user
(
compat_ptr
(
datap
),
&
tmsgs
[
i
].
buf
))
return
-
EFAULT
;
}
return
do_ioctl
(
file
,
cmd
,
(
unsigned
long
)
tdata
);
}
static
int
do_i2c_smbus_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
struct
i2c_smbus_ioctl_data32
__user
*
udata
)
{
struct
i2c_smbus_ioctl_data
__user
*
tdata
;
union
{
/* beginnings of those have identical layouts */
struct
i2c_smbus_ioctl_data32
data32
;
struct
i2c_smbus_ioctl_data
data
;
}
v
;
tdata
=
compat_alloc_user_space
(
sizeof
(
*
tdata
));
if
(
tdata
==
NULL
)
return
-
ENOMEM
;
memset
(
&
v
,
0
,
sizeof
(
v
));
if
(
copy_from_user
(
&
v
.
data32
,
udata
,
sizeof
(
v
.
data32
)))
return
-
EFAULT
;
v
.
data
.
data
=
compat_ptr
(
v
.
data32
.
data
);
if
(
copy_to_user
(
tdata
,
&
v
.
data
,
sizeof
(
v
.
data
)))
return
-
EFAULT
;
return
do_ioctl
(
file
,
cmd
,
(
unsigned
long
)
tdata
);
}
#define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t)
#define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t)
#define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t)
...
...
@@ -1282,13 +1174,6 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER)
COMPATIBLE_IOCTL
(
PCIIOC_MMAP_IS_IO
)
COMPATIBLE_IOCTL
(
PCIIOC_MMAP_IS_MEM
)
COMPATIBLE_IOCTL
(
PCIIOC_WRITE_COMBINE
)
/* i2c */
COMPATIBLE_IOCTL
(
I2C_SLAVE
)
COMPATIBLE_IOCTL
(
I2C_SLAVE_FORCE
)
COMPATIBLE_IOCTL
(
I2C_TENBIT
)
COMPATIBLE_IOCTL
(
I2C_PEC
)
COMPATIBLE_IOCTL
(
I2C_RETRIES
)
COMPATIBLE_IOCTL
(
I2C_TIMEOUT
)
/* hiddev */
COMPATIBLE_IOCTL
(
HIDIOCGVERSION
)
COMPATIBLE_IOCTL
(
HIDIOCAPPLICATION
)
...
...
@@ -1463,13 +1348,6 @@ static long do_ioctl_trans(unsigned int cmd,
case
TIOCGSERIAL
:
case
TIOCSSERIAL
:
return
serial_struct_ioctl
(
file
,
cmd
,
argp
);
/* i2c */
case
I2C_FUNCS
:
return
w_long
(
file
,
cmd
,
argp
);
case
I2C_RDWR
:
return
do_i2c_rdwr_ioctl
(
file
,
cmd
,
argp
);
case
I2C_SMBUS
:
return
do_i2c_smbus_ioctl
(
file
,
cmd
,
argp
);
/* Not implemented in the native kernel */
case
RTC_IRQP_READ32
:
case
RTC_IRQP_SET32
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录