static ssize_t gnss_write()

in core.c [123:185]


static ssize_t gnss_write(struct file *file, const char __user *buf,
				size_t count, loff_t *pos)
{
	struct gnss_device *gdev = file->private_data;
	size_t written = 0;
	int ret;

	if (gdev->disconnected)
		return -EIO;

	if (!count)
		return 0;

	if (!(gdev->flags & GNSS_FLAG_HAS_WRITE_RAW))
		return -EIO;

	/* Ignoring O_NONBLOCK, write_raw() is synchronous. */

	ret = mutex_lock_interruptible(&gdev->write_mutex);
	if (ret)
		return -ERESTARTSYS;

	for (;;) {
		size_t n = count - written;

		if (n > GNSS_WRITE_BUF_SIZE)
			n = GNSS_WRITE_BUF_SIZE;

		if (copy_from_user(gdev->write_buf, buf, n)) {
			ret = -EFAULT;
			goto out_unlock;
		}

		/*
		 * Assumes write_raw can always accept GNSS_WRITE_BUF_SIZE
		 * bytes.
		 *
		 * FIXME: revisit
		 */
		down_read(&gdev->rwsem);
		if (!gdev->disconnected)
			ret = gdev->ops->write_raw(gdev, gdev->write_buf, n);
		else
			ret = -EIO;
		up_read(&gdev->rwsem);

		if (ret < 0)
			break;

		written += ret;
		buf += ret;

		if (written == count)
			break;
	}

	if (written)
		ret = written;
out_unlock:
	mutex_unlock(&gdev->write_mutex);

	return ret;
}