diff options
Diffstat (limited to 'drivers/media/radio/si470x/radio-si470x-common.c')
-rw-r--r-- | drivers/media/radio/si470x/radio-si470x-common.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index f33315f2c543..4da0f150c6e2 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c | |||
@@ -426,6 +426,104 @@ int si470x_rds_on(struct si470x_device *radio) | |||
426 | 426 | ||
427 | 427 | ||
428 | /************************************************************************** | 428 | /************************************************************************** |
429 | * File Operations Interface | ||
430 | **************************************************************************/ | ||
431 | |||
432 | /* | ||
433 | * si470x_fops_read - read RDS data | ||
434 | */ | ||
435 | static ssize_t si470x_fops_read(struct file *file, char __user *buf, | ||
436 | size_t count, loff_t *ppos) | ||
437 | { | ||
438 | struct si470x_device *radio = video_drvdata(file); | ||
439 | int retval = 0; | ||
440 | unsigned int block_count = 0; | ||
441 | |||
442 | /* switch on rds reception */ | ||
443 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | ||
444 | si470x_rds_on(radio); | ||
445 | |||
446 | /* block if no new data available */ | ||
447 | while (radio->wr_index == radio->rd_index) { | ||
448 | if (file->f_flags & O_NONBLOCK) { | ||
449 | retval = -EWOULDBLOCK; | ||
450 | goto done; | ||
451 | } | ||
452 | if (wait_event_interruptible(radio->read_queue, | ||
453 | radio->wr_index != radio->rd_index) < 0) { | ||
454 | retval = -EINTR; | ||
455 | goto done; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* calculate block count from byte count */ | ||
460 | count /= 3; | ||
461 | |||
462 | /* copy RDS block out of internal buffer and to user buffer */ | ||
463 | mutex_lock(&radio->lock); | ||
464 | while (block_count < count) { | ||
465 | if (radio->rd_index == radio->wr_index) | ||
466 | break; | ||
467 | |||
468 | /* always transfer rds complete blocks */ | ||
469 | if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) | ||
470 | /* retval = -EFAULT; */ | ||
471 | break; | ||
472 | |||
473 | /* increment and wrap read pointer */ | ||
474 | radio->rd_index += 3; | ||
475 | if (radio->rd_index >= radio->buf_size) | ||
476 | radio->rd_index = 0; | ||
477 | |||
478 | /* increment counters */ | ||
479 | block_count++; | ||
480 | buf += 3; | ||
481 | retval += 3; | ||
482 | } | ||
483 | mutex_unlock(&radio->lock); | ||
484 | |||
485 | done: | ||
486 | return retval; | ||
487 | } | ||
488 | |||
489 | |||
490 | /* | ||
491 | * si470x_fops_poll - poll RDS data | ||
492 | */ | ||
493 | static unsigned int si470x_fops_poll(struct file *file, | ||
494 | struct poll_table_struct *pts) | ||
495 | { | ||
496 | struct si470x_device *radio = video_drvdata(file); | ||
497 | int retval = 0; | ||
498 | |||
499 | /* switch on rds reception */ | ||
500 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | ||
501 | si470x_rds_on(radio); | ||
502 | |||
503 | poll_wait(file, &radio->read_queue, pts); | ||
504 | |||
505 | if (radio->rd_index != radio->wr_index) | ||
506 | retval = POLLIN | POLLRDNORM; | ||
507 | |||
508 | return retval; | ||
509 | } | ||
510 | |||
511 | |||
512 | /* | ||
513 | * si470x_fops - file operations interface | ||
514 | */ | ||
515 | static const struct v4l2_file_operations si470x_fops = { | ||
516 | .owner = THIS_MODULE, | ||
517 | .read = si470x_fops_read, | ||
518 | .poll = si470x_fops_poll, | ||
519 | .ioctl = video_ioctl2, | ||
520 | .open = si470x_fops_open, | ||
521 | .release = si470x_fops_release, | ||
522 | }; | ||
523 | |||
524 | |||
525 | |||
526 | /************************************************************************** | ||
429 | * Video4Linux Interface | 527 | * Video4Linux Interface |
430 | **************************************************************************/ | 528 | **************************************************************************/ |
431 | 529 | ||