static ssize_t hsc_read()

in clients/hsi_char.c [412:469]


static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
						loff_t *ppos __maybe_unused)
{
	struct hsc_channel *channel = file->private_data;
	struct hsi_msg *msg;
	ssize_t ret;

	if (len == 0)
		return 0;
	if (!IS_ALIGNED(len, sizeof(u32)))
		return -EINVAL;
	if (len > max_data_size)
		len = max_data_size;
	if (channel->ch >= channel->cl->rx_cfg.num_hw_channels)
		return -ECHRNG;
	if (test_and_set_bit(HSC_CH_READ, &channel->flags))
		return -EBUSY;
	msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
	if (!msg) {
		ret = -ENOSPC;
		goto out;
	}
	hsc_msg_len_set(msg, len);
	msg->complete = hsc_rx_completed;
	msg->destructor = hsc_rx_msg_destructor;
	ret = hsi_async_read(channel->cl, msg);
	if (ret < 0) {
		hsc_add_tail(channel, msg, &channel->free_msgs_list);
		goto out;
	}

	ret = wait_event_interruptible(channel->rx_wait,
					!list_empty(&channel->rx_msgs_queue));
	if (ret < 0) {
		clear_bit(HSC_CH_READ, &channel->flags);
		hsi_flush(channel->cl);
		return -EINTR;
	}

	msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue);
	if (msg) {
		if (msg->status != HSI_STATUS_ERROR) {
			ret = copy_to_user((void __user *)buf,
			sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg));
			if (ret)
				ret = -EFAULT;
			else
				ret = hsc_msg_len_get(msg);
		} else {
			ret = -EIO;
		}
		hsc_add_tail(channel, msg, &channel->free_msgs_list);
	}
out:
	clear_bit(HSC_CH_READ, &channel->flags);

	return ret;
}