aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2012-05-30 04:55:34 -0400
committerJean Delvare <khali@endymion.delvare>2012-05-30 04:55:34 -0400
commit838bfa6049fb84dc66c9c9bbeb3a968ec987fd3d (patch)
tree5c6cf6d3d7dee7514f62b874b50bf88726144b11 /drivers
parent731a7378b81c2f5fa88ca1ae20b83d548d5613dc (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')
-rw-r--r--drivers/i2c/i2c-dev.c30
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;