Tuner step increment/decrement will select the next highest or next
lowest service frequency.  There are a total of three possible
frequencies given a broadcast type and system for a total of 81 analog
channels.

Opcodes implemented:
  - <Tuner Step Increment>
  - <Tuner Step Decrement>

Signed-off-by: Jiunn Chang <c0d1n61...@gmail.com>
---
 utils/cec-follower/cec-follower.cpp |  2 +-
 utils/cec-follower/cec-follower.h   |  3 +-
 utils/cec-follower/cec-tuner.cpp    | 65 ++++++++++++++++++++++-------
 3 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/utils/cec-follower/cec-follower.cpp 
b/utils/cec-follower/cec-follower.cpp
index 4243fdd9..8375404e 100644
--- a/utils/cec-follower/cec-follower.cpp
+++ b/utils/cec-follower/cec-follower.cpp
@@ -298,7 +298,7 @@ void state_init(struct node &node)
        node.state.sac_active = false;
        node.state.volume = 50;
        node.state.mute = false;
-       analog_tuner_init(&node.state.tuner_dev_info);
+       analog_tuner_init(&node.state);
 }
 
 int main(int argc, char **argv)
diff --git a/utils/cec-follower/cec-follower.h 
b/utils/cec-follower/cec-follower.h
index a53c16fe..d8ac4e77 100644
--- a/utils/cec-follower/cec-follower.h
+++ b/utils/cec-follower/cec-follower.h
@@ -52,6 +52,7 @@ struct state {
        unsigned rc_press_hold_count;
        unsigned rc_duration_sum;
        struct cec_op_tuner_device_info tuner_dev_info;
+       unsigned int freq_idx;
 };
 
 struct node {
@@ -221,7 +222,7 @@ std::string opcode2s(const struct cec_msg *msg);
 void sad_encode(const struct short_audio_desc *sad, __u32 *descriptor);
 
 // cec-tuner.cpp
-void analog_tuner_init(struct cec_op_tuner_device_info *tuner_dev_info);
+void analog_tuner_init(struct state *state);
 void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, 
unsigned me);
 
 // CEC processing
diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index d74981b2..6f14b059 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -9,6 +9,8 @@
 #include "cec-follower.h"
 
 #define NUM_ANALOG_FREQS       3
+#define ARRAY_SIZE_ANA_FREQS(x) \
+       ARRAY_SIZE(x) * ARRAY_SIZE(*x) * ARRAY_SIZE(**x)
 
 /*
  * This table contains analog television channel frequencies in KHz.  There are
@@ -90,10 +92,12 @@ static unsigned int 
analog_freqs_khz[3][9][NUM_ANALOG_FREQS] =
        }
 };
 
-void analog_tuner_init(struct cec_op_tuner_device_info *info)
+void analog_tuner_init(struct state *state)
 {
+       struct cec_op_tuner_device_info *info = &state->tuner_dev_info;
        unsigned int freq_khz;
 
+       state->freq_idx = 0;
        info->rec_flag = CEC_OP_REC_FLAG_NOT_USED;
        info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE;
        info->is_analog = true;
@@ -103,23 +107,41 @@ void analog_tuner_init(struct cec_op_tuner_device_info 
*info)
        info->analog.ana_freq = (freq_khz * 10) / 625;
 }
 
-static unsigned int analog_get_nearest_freq(__u8 ana_bcast_type, __u8 
ana_bcast_system,
-                                            int ana_freq_khz)
+static unsigned int analog_get_nearest_freq_idx(__u8 ana_bcast_type, __u8 
ana_bcast_system,
+                                               int ana_freq_khz)
 {
        int nearest = analog_freqs_khz[ana_bcast_type][ana_bcast_system][0];
+       unsigned int offset = 0;
 
        for (int i = 0; i < NUM_ANALOG_FREQS; i++) {
                int freq = 
analog_freqs_khz[ana_bcast_type][ana_bcast_system][i];
 
-               if (abs(ana_freq_khz - freq) < abs(ana_freq_khz - nearest))
+               if (abs(ana_freq_khz - freq) < abs(ana_freq_khz - nearest)) {
                        nearest = freq;
+                       offset++;
+               }
        }
-       return nearest;
+       return NUM_ANALOG_FREQS * ((ana_bcast_type * 9) + ana_bcast_system) + 
offset;
 }
 
-static bool analog_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
+static void analog_get_type_system_idx(struct node *node)
 {
        struct cec_op_tuner_device_info *info = &node->state.tuner_dev_info;
+       unsigned int tot_freqs = NUM_ANALOG_FREQS * 9;
+       unsigned int freq_idx = node->state.freq_idx;
+       unsigned int freq_khz;
+       unsigned int idx;
+
+       info->analog.ana_bcast_type = freq_idx / tot_freqs;
+       info->analog.bcast_system =
+               (freq_idx - (tot_freqs * info->analog.ana_bcast_type)) / 
NUM_ANALOG_FREQS;
+       idx = freq_idx % NUM_ANALOG_FREQS;
+       freq_khz = 
analog_freqs_khz[info->analog.ana_bcast_type][info->analog.bcast_system][idx];
+       info->analog.ana_freq = (freq_khz * 10) / 625;
+}
+
+static bool analog_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
+{
        __u8 type;
        __u16 freq;
        __u8 system;
@@ -127,11 +149,9 @@ static bool analog_set_tuner_dev_info(struct node *node, 
struct cec_msg *msg)
        cec_ops_select_analogue_service(msg, &type, &freq, &system);
        if (type < 3 && system < 9) {
                int freq_khz = (freq * 625) / 10;
-               unsigned int nearest = analog_get_nearest_freq(type, system,
-                                                              freq_khz);
-               info->analog.ana_bcast_type = type;
-               info->analog.ana_freq = (nearest * 10) / 625;
-               info->analog.bcast_system = system;
+
+               node->state.freq_idx = analog_get_nearest_freq_idx(type, 
system, freq_khz);
+               analog_get_type_system_idx(node);
                return true;
        }
        return false;
@@ -180,12 +200,29 @@ void process_tuner_record_timer_msgs(struct node *node, 
struct cec_msg &msg, uns
                return;
 
        case CEC_MSG_SELECT_DIGITAL_SERVICE:
-       case CEC_MSG_TUNER_STEP_DECREMENT:
-       case CEC_MSG_TUNER_STEP_INCREMENT:
-               if (!cec_has_tuner(1 << me))
+       case CEC_MSG_TUNER_STEP_DECREMENT: {
+               if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
                        break;
+
+               if (node->state.freq_idx == 0)
+                       node->state.freq_idx = 
ARRAY_SIZE_ANA_FREQS(analog_freqs_khz) - 1;
+               else
+                       node->state.freq_idx--;
+               analog_get_type_system_idx(node);
                return;
+       }
 
+       case CEC_MSG_TUNER_STEP_INCREMENT: {
+               if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
+                       break;
+
+               if (node->state.freq_idx == 
ARRAY_SIZE_ANA_FREQS(analog_freqs_khz) - 1)
+                       node->state.freq_idx = 0;
+               else
+                       node->state.freq_idx++;
+               analog_get_type_system_idx(node);
+               return;
+       }
 
                /*
                  One Touch Record
-- 
2.23.0

Reply via email to