in busses/i2c-viperboard.c [113:216]
static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg)
{
int ret;
u16 remain_len, len1, len2, start = 0x0000;
struct vprbrd_i2c_read_msg *rmsg =
(struct vprbrd_i2c_read_msg *)vb->buf;
remain_len = msg->len;
rmsg->header.cmd = VPRBRD_I2C_CMD_READ;
while (remain_len > 0) {
rmsg->header.addr = cpu_to_le16(start + 0x4000);
if (remain_len <= 255) {
len1 = remain_len;
len2 = 0x00;
rmsg->header.len0 = remain_len;
rmsg->header.len1 = 0x00;
rmsg->header.len2 = 0x00;
rmsg->header.len3 = 0x00;
rmsg->header.len4 = 0x00;
rmsg->header.len5 = 0x00;
remain_len = 0;
} else if (remain_len <= 510) {
len1 = remain_len;
len2 = 0x00;
rmsg->header.len0 = remain_len - 255;
rmsg->header.len1 = 0xff;
rmsg->header.len2 = 0x00;
rmsg->header.len3 = 0x00;
rmsg->header.len4 = 0x00;
rmsg->header.len5 = 0x00;
remain_len = 0;
} else if (remain_len <= 512) {
len1 = remain_len;
len2 = 0x00;
rmsg->header.len0 = remain_len - 510;
rmsg->header.len1 = 0xff;
rmsg->header.len2 = 0xff;
rmsg->header.len3 = 0x00;
rmsg->header.len4 = 0x00;
rmsg->header.len5 = 0x00;
remain_len = 0;
} else if (remain_len <= 767) {
len1 = 512;
len2 = remain_len - 512;
rmsg->header.len0 = 0x02;
rmsg->header.len1 = 0xff;
rmsg->header.len2 = 0xff;
rmsg->header.len3 = remain_len - 512;
rmsg->header.len4 = 0x00;
rmsg->header.len5 = 0x00;
remain_len = 0;
} else if (remain_len <= 1022) {
len1 = 512;
len2 = remain_len - 512;
rmsg->header.len0 = 0x02;
rmsg->header.len1 = 0xff;
rmsg->header.len2 = 0xff;
rmsg->header.len3 = remain_len - 767;
rmsg->header.len4 = 0xff;
rmsg->header.len5 = 0x00;
remain_len = 0;
} else if (remain_len <= 1024) {
len1 = 512;
len2 = remain_len - 512;
rmsg->header.len0 = 0x02;
rmsg->header.len1 = 0xff;
rmsg->header.len2 = 0xff;
rmsg->header.len3 = remain_len - 1022;
rmsg->header.len4 = 0xff;
rmsg->header.len5 = 0xff;
remain_len = 0;
} else {
len1 = 512;
len2 = 512;
rmsg->header.len0 = 0x02;
rmsg->header.len1 = 0xff;
rmsg->header.len2 = 0xff;
rmsg->header.len3 = 0x02;
rmsg->header.len4 = 0xff;
rmsg->header.len5 = 0xff;
remain_len -= 1024;
start += 1024;
}
rmsg->header.tf1 = cpu_to_le16(len1);
rmsg->header.tf2 = cpu_to_le16(len2);
/* first read transfer */
ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len1);
if (ret < 0)
return ret;
/* copy the received data */
memcpy(msg->buf + start, rmsg, len1);
/* second read transfer if neccessary */
if (len2 > 0) {
ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len2);
if (ret < 0)
return ret;
/* copy the received data */
memcpy(msg->buf + start + 512, rmsg, len2);
}
}
return 0;
}