diff options
author | Jean Delvare <khali@linux-fr.org> | 2012-05-30 04:55:34 -0400 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-05-30 04:55:34 -0400 |
commit | 838bfa6049fb84dc66c9c9bbeb3a968ec987fd3d (patch) | |
tree | 5c6cf6d3d7dee7514f62b874b50bf88726144b11 /drivers/i2c/i2c-dev.c | |
parent | 731a7378b81c2f5fa88ca1ae20b83d548d5613dc (diff) |
i2c-dev: Add support for I2C_M_RECV_LEN
As the bus driver side implementation of I2C_M_RECV_LEN is heavily
tied to SMBus, we can't support received length over 32 bytes, but
let's at least support that.
In practice, the caller will have to setup a buffer large enough to
cover the case where received length byte has value 32, so minimum
32 + 1 = 33 bytes, possibly more if there is a fixed number of bytes
added for the specific slave (for example a checksum.)
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Tested-by: Douglas Gilbert <dgilbert@interlog.com>
Diffstat (limited to 'drivers/i2c/i2c-dev.c')
-rw-r--r-- | drivers/i2c/i2c-dev.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 45048323b75e..5ec2261574ec 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -265,19 +265,41 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, | |||
265 | 265 | ||
266 | res = 0; | 266 | res = 0; |
267 | for (i = 0; i < rdwr_arg.nmsgs; i++) { | 267 | for (i = 0; i < rdwr_arg.nmsgs; i++) { |
268 | /* Limit the size of the message to a sane amount; | 268 | /* Limit the size of the message to a sane amount */ |
269 | * and don't let length change either. */ | 269 | if (rdwr_pa[i].len > 8192) { |
270 | if ((rdwr_pa[i].len > 8192) || | ||
271 | (rdwr_pa[i].flags & I2C_M_RECV_LEN)) { | ||
272 | res = -EINVAL; | 270 | res = -EINVAL; |
273 | break; | 271 | break; |
274 | } | 272 | } |
273 | |||
275 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; | 274 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; |
276 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); | 275 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); |
277 | if (IS_ERR(rdwr_pa[i].buf)) { | 276 | if (IS_ERR(rdwr_pa[i].buf)) { |
278 | res = PTR_ERR(rdwr_pa[i].buf); | 277 | res = PTR_ERR(rdwr_pa[i].buf); |
279 | break; | 278 | break; |
280 | } | 279 | } |
280 | |||
281 | /* | ||
282 | * If the message length is received from the slave (similar | ||
283 | * to SMBus block read), we must ensure that the buffer will | ||
284 | * be large enough to cope with a message length of | ||
285 | * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus | ||
286 | * drivers allow. The first byte in the buffer must be | ||
287 | * pre-filled with the number of extra bytes, which must be | ||
288 | * at least one to hold the message length, but can be | ||
289 | * greater (for example to account for a checksum byte at | ||
290 | * the end of the message.) | ||
291 | */ | ||
292 | if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { | ||
293 | if (!(rdwr_pa[i].flags & I2C_M_RD) || | ||
294 | rdwr_pa[i].buf[0] < 1 || | ||
295 | rdwr_pa[i].len < rdwr_pa[i].buf[0] + | ||
296 | I2C_SMBUS_BLOCK_MAX) { | ||
297 | res = -EINVAL; | ||
298 | break; | ||
299 | } | ||
300 | |||
301 | rdwr_pa[i].len = rdwr_pa[i].buf[0]; | ||
302 | } | ||
281 | } | 303 | } |
282 | if (res < 0) { | 304 | if (res < 0) { |
283 | int j; | 305 | int j; |