diff options
| -rw-r--r-- | drivers/hid/hid-cp2112.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index a2dbbbe0d8d7..75398cb84fde 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c | |||
| @@ -511,13 +511,30 @@ static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, | |||
| 511 | if (!(msgs->flags & I2C_M_RD)) | 511 | if (!(msgs->flags & I2C_M_RD)) |
| 512 | goto finish; | 512 | goto finish; |
| 513 | 513 | ||
| 514 | ret = cp2112_read(dev, msgs->buf, msgs->len); | 514 | for (count = 0; count < msgs->len;) { |
| 515 | if (ret < 0) | 515 | ret = cp2112_read(dev, msgs->buf + count, msgs->len - count); |
| 516 | goto power_normal; | 516 | if (ret < 0) |
| 517 | if (ret != msgs->len) { | 517 | goto power_normal; |
| 518 | hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len); | 518 | if (ret == 0) { |
| 519 | ret = -EIO; | 519 | hid_err(hdev, "read returned 0\n"); |
| 520 | goto power_normal; | 520 | ret = -EIO; |
| 521 | goto power_normal; | ||
| 522 | } | ||
| 523 | count += ret; | ||
| 524 | if (count > msgs->len) { | ||
| 525 | /* | ||
| 526 | * The hardware returned too much data. | ||
| 527 | * This is mostly harmless because cp2112_read() | ||
| 528 | * has a limit check so didn't overrun our | ||
| 529 | * buffer. Nevertheless, we return an error | ||
| 530 | * because something is seriously wrong and | ||
| 531 | * it shouldn't go unnoticed. | ||
| 532 | */ | ||
| 533 | hid_err(hdev, "long read: %d > %zd\n", | ||
| 534 | ret, msgs->len - count + ret); | ||
| 535 | ret = -EIO; | ||
| 536 | goto power_normal; | ||
| 537 | } | ||
| 521 | } | 538 | } |
| 522 | 539 | ||
| 523 | finish: | 540 | finish: |
