+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+
+#include <linux/videodev2.h>
+
+#include <sqlite3.h>
+
+#include "rds.h"
+#include "tmc.h"
+
+sqlite3 *lcl_db;
+int OutputFlags;
+
+unsigned char pi_received = 0;
+unsigned char sid_received = 0;
+
+void test_rds_PI_cb(unsigned short PI, unsigned char ccode, unsigned char ptype, unsigned char pref, void *udata)
+{
+ printf("New PI=%d ccode=%X ptype=%X '%s' '%s' pref=%d\n", PI, ccode, ptype, ptype_stext[ptype], ptype_ltext[ptype], pref);
+ pi_received = 1;
+}
+
+void test_rds_sname_cb(char *sname, void *udata)
+{
+ printf("RDS sname='%s'\n", sname);
+ sid_received = 1;
+}
+
+
+void station_scan(int fd)
+{
+int ret;
+struct v4l2_frequency v4lfreq;
+struct v4l2_tuner v4ltuner;
+unsigned short rdsgroup[4];
+
+ v4ltuner.index = 0;
+ ret = ioctl(fd, VIDIOC_G_TUNER, &v4ltuner);
+ if (ret < 0)
+ return;
+ printf("tuner=%d\n", v4ltuner.index);
+ if (v4ltuner.type == V4L2_TUNER_RADIO)
+ printf(" is a radio tuner\n");
+ printf("name='%s'\n", v4ltuner.name);
+
+ v4lfreq.tuner = v4ltuner.index;
+ memset(&v4lfreq.reserved, 0, 32);
+ ret = ioctl(fd, VIDIOC_G_FREQUENCY, &v4lfreq);
+ if (ret < 0)
+ return;
+
+ v4lfreq.frequency = v4ltuner.rangelow;
+ while (v4lfreq.frequency <= v4ltuner.rangehigh) {
+ ret = ioctl(fd, VIDIOC_S_FREQUENCY, &v4lfreq);
+ if (ret < 0)
+ break;
+ ret = ioctl(fd, VIDIOC_G_FREQUENCY, &v4lfreq);
+ if (ret < 0)
+ break;
+ ret = ioctl(fd, VIDIOC_G_TUNER, &v4ltuner);
+ if (ret < 0)
+ break;
+ printf("%lf %d %d %s %s\n", (double)v4lfreq.frequency * 62.5 / 1000000,
+ v4lfreq.frequency,
+ v4ltuner.signal,
+ v4ltuner.rxsubchans & V4L2_TUNER_SUB_STEREO ? "stereo" : "mono",
+ v4ltuner.rxsubchans & V4L2_TUNER_SUB_RDS ? "RDS" : "noRDS");
+
+ if (v4ltuner.signal > 30000) {
+ /* seems to be a strong signal, so try RDS */
+ pi_received = 0;
+ sid_received = 0;
+ rds_radio_retuned();
+ while (pi_received == 0 || sid_received == 0) {
+ if (rds_receive_group(fd, rdsgroup)) {
+ /* group complete, start decode */
+ rds_decode_group(rdsgroup);
+ }
+ }
+ }
+
+ v4lfreq.frequency += 1600; /* 1600 for .1MHz steps, 800 for 0.05MHz */
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+int fd, ret;
+struct v4l2_capability v4lcap;
+struct v4l2_frequency v4lfreq;
+struct v4l2_tuner v4ltuner;
+
+ fd = open ("/dev/radio0", O_RDONLY);
+ if (fd < 0) {
+ printf("error opening fd\n");
+ perror("open");
+ return 1;
+ }
+
+ ret = ioctl(fd, VIDIOC_QUERYCAP, &v4lcap);
+ if (ret < 0)
+ return 1;
+
+ printf("driver = '%s'\n", v4lcap.driver);
+ printf("card = '%s'\n", v4lcap.card);
+ printf("bus_info = '%s'\n", v4lcap.bus_info);
+ printf("cap && RADIO = %s\n", (v4lcap.capabilities & V4L2_CAP_RADIO) ? "yes" : "no");
+ printf("cap && TUNER = %s\n", (v4lcap.capabilities & V4L2_CAP_TUNER) ? "yes" : "no");
+ printf("cap && RDS = %s\n", (v4lcap.capabilities & V4L2_CAP_RDS_CAPTURE) ? "yes" : "no");
+
+ v4ltuner.index = 0;
+ ret = ioctl(fd, VIDIOC_G_TUNER, &v4ltuner);
+ if (ret < 0)
+ return 1;
+ printf("tuner=%d\n", v4ltuner.index);
+ if (v4ltuner.type == V4L2_TUNER_RADIO)
+ printf(" is a radio tuner\n");
+ printf("name='%s'\n", v4ltuner.name);
+
+ v4lfreq.tuner = v4ltuner.index;
+ memset(&v4lfreq.reserved, 0, 32);
+ ret = ioctl(fd, VIDIOC_G_FREQUENCY, &v4lfreq);
+
+ if (ret >= 0) {
+ if (v4ltuner.capability & V4L2_TUNER_CAP_LOW) {
+ printf("range %3.2lf MHz - %3.2lf MHz\n", (double)v4ltuner.rangelow * 62.5 / 1000000, (double)v4ltuner.rangehigh * 62.5 / 1000000);
+ printf("freq = %3.2lf MHz\n", (double)v4lfreq.frequency * 62.5 / 1000000);
+ } else
+ printf("freq = %lf kHz\n", (double)v4lfreq.frequency * 62.5);
+ }
+ printf("signal: %d %s\n", v4ltuner.signal, v4ltuner.rxsubchans & V4L2_TUNER_SUB_STEREO ? "stereo" : "mono");
+ printf("RDS signal present: %s\n", v4ltuner.rxsubchans & V4L2_TUNER_SUB_RDS ? "yes" : "no");
+
+ if (argc > 1 && strcmp(argv[1], "-s")==0) {
+ rds_init();
+ tmc_init();
+ rds_set_sname_cb(test_rds_sname_cb, NULL);
+ rds_set_PI_cb(test_rds_PI_cb, NULL);
+ station_scan(fd);
+ }
+
+ close(fd);
+
+return 0;
+}