in fsi-occ.c [138:194]
static ssize_t occ_write(struct file *file, const char __user *buf,
size_t len, loff_t *offset)
{
struct occ_client *client = file->private_data;
size_t rlen, data_length;
ssize_t rc;
u8 *cmd;
if (!client)
return -ENODEV;
if (len > (OCC_CMD_DATA_BYTES + 3) || len < 3)
return -EINVAL;
mutex_lock(&client->lock);
/* Construct the command */
cmd = client->buffer;
/*
* Copy the user command (assume user data follows the occ command
* format)
* byte 0: command type
* bytes 1-2: data length (msb first)
* bytes 3-n: data
*/
if (copy_from_user(&cmd[1], buf, len)) {
rc = -EFAULT;
goto done;
}
/* Extract data length */
data_length = (cmd[2] << 8) + cmd[3];
if (data_length > OCC_CMD_DATA_BYTES) {
rc = -EINVAL;
goto done;
}
/* Submit command; 4 bytes before the data and 2 bytes after */
rlen = PAGE_SIZE;
rc = fsi_occ_submit(client->occ->dev, cmd, data_length + 6, cmd,
&rlen);
if (rc)
goto done;
/* Set read tracking data */
client->data_size = rlen;
client->read_offset = 0;
/* Done */
rc = len;
done:
mutex_unlock(&client->lock);
return rc;
}