Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fbeeafd0 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "radio: RTC6226: implement file read for rtc6226 driver"

parents bc55d36b f5498bc7
Loading
Loading
Loading
Loading
+39 −46
Original line number Diff line number Diff line
@@ -1485,60 +1485,53 @@ int rtc6226_power_up(struct rtc6226_device *radio)
 **************************************************************************/

/*
 * rtc6226_fops_read - read RDS data
 * rtc6226_fops_read - read event data
 */
static ssize_t rtc6226_fops_read(struct file *file, char __user *buf,
static ssize_t rtc6226_fops_read(struct file *file, char __user *buffer,
		size_t count, loff_t *ppos)
{
	struct rtc6226_device *radio = video_drvdata(file);
	int retval = 0;
	unsigned int block_count = 0;
	struct rtc6226_device *radio = video_get_drvdata(video_devdata(file));
	enum rtc6226_buf_t buf_type = -1;
	u8 buf_fifo[STD_BUF_SIZE] = {0};
	struct kfifo *data_fifo = NULL;
	int len = 0, retval = -1;
	u32 bytesused = 0;

	/* switch on rds reception */
	mutex_lock(&radio->lock);
	/* if RDS is not on, then turn on RDS */
	if ((radio->registers[SYSCFG] & SYSCFG_CSR0_RDS_EN) == 0)
		rtc6226_rds_on(radio);
	if ((radio == NULL) || (buffer == NULL)) {
		FMDERR("%s radio/buffer is NULL\n", __func__);
		return -ENXIO;
	}

	/* block if no new data available */
	while (radio->wr_index == radio->rd_index) {
		if (file->f_flags & O_NONBLOCK) {
			retval = -EWOULDBLOCK;
			goto done;
	buf_type = count;
	len = STD_BUF_SIZE;
	FMDBG("%s: requesting buffer %d\n", __func__, buf_type);

	if ((buf_type < RTC6226_FM_BUF_MAX) && (buf_type >= 0)) {
		data_fifo = &radio->data_buf[buf_type];
		if (buf_type == RTC6226_FM_BUF_EVENTS) {
			if (wait_event_interruptible(radio->event_queue,
						kfifo_len(data_fifo)) < 0) {
				return -EINTR;
			}
		if (wait_event_interruptible(radio->read_queue,
				radio->wr_index != radio->rd_index) < 0) {
			retval = -EINTR;
			goto done;
		}
	} else {
		FMDERR("%s invalid buffer type\n", __func__);
		return -EINVAL;
	}

	/* calculate block count from byte count */
	count /= 3;
	FMDBG("%s : count = %zu\n", __func__, count);

	/* copy RDS block out of internal buffer and to user buffer */
	while (block_count < count) {
		if (radio->rd_index == radio->wr_index)
			break;
		/* always transfer rds complete blocks */
		if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
			/* retval = -EFAULT; */
			break;
		/* increment and wrap read pointer */
		radio->rd_index += 3;
		if (radio->rd_index >= radio->buf_size)
			radio->rd_index = 0;
		/* increment counters */
		block_count++;
		buf += 3;
		retval += 3;
		FMDBG("%s : block_count = %d, count = %zu\n", __func__,
			block_count, count);
	if (len <= STD_BUF_SIZE) {
		bytesused = kfifo_out_locked(data_fifo, &buf_fifo[0],
				len, &radio->buf_lock[buf_type]);
	} else {
		FMDERR("%s kfifo_out_locked can not use len more than 128\n",
			__func__);
		return -EINVAL;
	}

done:
	mutex_unlock(&radio->lock);
	retval = copy_to_user(buffer, &buf_fifo[0], bytesused);
	if (retval > 0) {
		FMDERR("%s Failed to copy %d bytes data\n", __func__, retval);
		return -EAGAIN;
	}
	retval = bytesused;
	return retval;
}