linux-kernel-mentees.lists.linuxfoundation.org archive mirror
 help / color / mirror / Atom feed
* [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support
@ 2019-10-14  4:17 c0d1n61at3
  2019-10-14  4:17 ` Jiunn Chang
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


This patch series will add digital tuner support to cec-compliance.
cec-follower support for the following digital broadcast systems:

  - ARIB-BS
  - ARIB-T
  - ATSC-SAT
  - ATSC-T
  - DVB-S2
  - DVB-T

has been added for 18 digital plus 81 analog for a total of 98 channels.
Tuner step features have been implemented to cycle through all available
channels with digital proceeding analog.  Channels will wrap on both ends.
Tuner testing will cycle through all channels and check status with tuner
select service following after.

---

Jiunn Chang (8):
  cec-follower: fix analog tuner device info update
  cec-follower: rename freq_idx to service_idx
  cec-follower: create digital ARIB channels
  cec-follower: create digital ATSC channels
  cec-follower: create digital DVB channels
  cec-follower: add tuner digital service emulation
  cec-follower: fix tuner step increment/decrement
  cec-compliance: add digital tuner control testing

 utils/cec-compliance/cec-test.cpp   |  50 +++-
 utils/cec-follower/cec-follower.cpp |   2 +-
 utils/cec-follower/cec-follower.h   |   4 +-
 utils/cec-follower/cec-tuner.cpp    | 375 ++++++++++++++++++++++++++--
 4 files changed, 400 insertions(+), 31 deletions(-)

-- 
2.23.0

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
@ 2019-10-14  4:17 ` Jiunn Chang
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 1/8] cec-follower: fix analog tuner device info update c0d1n61at3
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


This patch series will add digital tuner support to cec-compliance.
cec-follower support for the following digital broadcast systems:

  - ARIB-BS
  - ARIB-T
  - ATSC-SAT
  - ATSC-T
  - DVB-S2
  - DVB-T

has been added for 18 digital plus 81 analog for a total of 98 channels.
Tuner step features have been implemented to cycle through all available
channels with digital proceeding analog.  Channels will wrap on both ends.
Tuner testing will cycle through all channels and check status with tuner
select service following after.

---

Jiunn Chang (8):
  cec-follower: fix analog tuner device info update
  cec-follower: rename freq_idx to service_idx
  cec-follower: create digital ARIB channels
  cec-follower: create digital ATSC channels
  cec-follower: create digital DVB channels
  cec-follower: add tuner digital service emulation
  cec-follower: fix tuner step increment/decrement
  cec-compliance: add digital tuner control testing

 utils/cec-compliance/cec-test.cpp   |  50 +++-
 utils/cec-follower/cec-follower.cpp |   2 +-
 utils/cec-follower/cec-follower.h   |   4 +-
 utils/cec-follower/cec-tuner.cpp    | 375 ++++++++++++++++++++++++++--
 4 files changed, 400 insertions(+), 31 deletions(-)

-- 
2.23.0

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 1/8] cec-follower: fix analog tuner device info update
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
  2019-10-14  4:17 ` Jiunn Chang
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 2/8] cec-follower: rename freq_idx to service_idx c0d1n61at3
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


With the addition of digital tuner control support, analog update
needs to set is_analog and tuner_display_info.

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 46acccf4..b3b20b89 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -131,6 +131,8 @@ static void analog_update_tuner_dev_info(struct node *node, unsigned int idx)
 	unsigned int freq_khz;
 
 	node->state.freq_idx = idx;
+	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE;
+	info->is_analog = true;
 	info->analog.ana_bcast_type = node->state.freq_idx / tot_freqs;
 	info->analog.bcast_system =
 		(node->state.freq_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 1/8] cec-follower: fix analog tuner device info update
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 1/8] cec-follower: fix analog tuner device info update c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  0 siblings, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


With the addition of digital tuner control support, analog update
needs to set is_analog and tuner_display_info.

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 46acccf4..b3b20b89 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -131,6 +131,8 @@ static void analog_update_tuner_dev_info(struct node *node, unsigned int idx)
 	unsigned int freq_khz;
 
 	node->state.freq_idx = idx;
+	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE;
+	info->is_analog = true;
 	info->analog.ana_bcast_type = node->state.freq_idx / tot_freqs;
 	info->analog.bcast_system =
 		(node->state.freq_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 2/8] cec-follower: rename freq_idx to service_idx
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
  2019-10-14  4:17 ` Jiunn Chang
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 1/8] cec-follower: fix analog tuner device info update c0d1n61at3
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels c0d1n61at3
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


The implementation of digital support in tuner control requires the
renaming of freq_idx to service_idx as analog and digital channels
are referred to collectively as services.  The index will now represent
the current state of both analog and digital.  Tuner step features will
cycle through both analog and digital with digital preceeding analog.

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-follower.h |  2 +-
 utils/cec-follower/cec-tuner.cpp  | 32 +++++++++++++++----------------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/utils/cec-follower/cec-follower.h b/utils/cec-follower/cec-follower.h
index fc335b14..2a9e397a 100644
--- a/utils/cec-follower/cec-follower.h
+++ b/utils/cec-follower/cec-follower.h
@@ -53,7 +53,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;
+	unsigned int service_idx;
 };
 
 struct node {
diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index b3b20b89..3a71a890 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -96,7 +96,7 @@ 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;
+	state->service_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;
@@ -106,8 +106,8 @@ void analog_tuner_init(struct state *state)
 	info->analog.ana_freq = (freq_khz * 10) / 625;
 }
 
-static unsigned int analog_get_nearest_freq_idx(__u8 ana_bcast_type, __u8 ana_bcast_system,
-						int ana_freq_khz)
+static unsigned int analog_get_nearest_service_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;
@@ -130,13 +130,13 @@ static void analog_update_tuner_dev_info(struct node *node, unsigned int idx)
 	unsigned int offset;
 	unsigned int freq_khz;
 
-	node->state.freq_idx = idx;
+	node->state.service_idx = idx;
 	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE;
 	info->is_analog = true;
-	info->analog.ana_bcast_type = node->state.freq_idx / tot_freqs;
+	info->analog.ana_bcast_type = node->state.service_idx / tot_freqs;
 	info->analog.bcast_system =
-		(node->state.freq_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
-	offset = node->state.freq_idx % NUM_ANALOG_FREQS;
+		(node->state.service_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
+	offset = node->state.service_idx % NUM_ANALOG_FREQS;
 	freq_khz = analog_freqs_khz[info->analog.ana_bcast_type][info->analog.bcast_system][offset];
 	info->analog.ana_freq = (freq_khz * 10) / 625;
 }
@@ -152,7 +152,7 @@ static bool analog_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
 	if (type < 3 && system < 9) {
 		int freq_khz = (freq * 625) / 10;
 
-		idx = analog_get_nearest_freq_idx(type, system, freq_khz);
+		idx = analog_get_nearest_service_idx(type, system, freq_khz);
 		analog_update_tuner_dev_info(node, idx);
 		return true;
 	}
@@ -206,11 +206,11 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
 
-		if (node->state.freq_idx == 0)
-			node->state.freq_idx = TOT_ANALOG_FREQS - 1;
+		if (node->state.service_idx == 0)
+			node->state.service_idx = TOT_ANALOG_FREQS - 1;
 		else
-			node->state.freq_idx--;
-		analog_update_tuner_dev_info(node, node->state.freq_idx);
+			node->state.service_idx--;
+		analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
@@ -218,11 +218,11 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
 
-		if (node->state.freq_idx == TOT_ANALOG_FREQS - 1)
-			node->state.freq_idx = 0;
+		if (node->state.service_idx == TOT_ANALOG_FREQS - 1)
+			node->state.service_idx = 0;
 		else
-			node->state.freq_idx++;
-		analog_update_tuner_dev_info(node, node->state.freq_idx);
+			node->state.service_idx++;
+		analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 2/8] cec-follower: rename freq_idx to service_idx
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 2/8] cec-follower: rename freq_idx to service_idx c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  0 siblings, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


The implementation of digital support in tuner control requires the
renaming of freq_idx to service_idx as analog and digital channels
are referred to collectively as services.  The index will now represent
the current state of both analog and digital.  Tuner step features will
cycle through both analog and digital with digital preceeding analog.

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-follower.h |  2 +-
 utils/cec-follower/cec-tuner.cpp  | 32 +++++++++++++++----------------
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/utils/cec-follower/cec-follower.h b/utils/cec-follower/cec-follower.h
index fc335b14..2a9e397a 100644
--- a/utils/cec-follower/cec-follower.h
+++ b/utils/cec-follower/cec-follower.h
@@ -53,7 +53,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;
+	unsigned int service_idx;
 };
 
 struct node {
diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index b3b20b89..3a71a890 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -96,7 +96,7 @@ 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;
+	state->service_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;
@@ -106,8 +106,8 @@ void analog_tuner_init(struct state *state)
 	info->analog.ana_freq = (freq_khz * 10) / 625;
 }
 
-static unsigned int analog_get_nearest_freq_idx(__u8 ana_bcast_type, __u8 ana_bcast_system,
-						int ana_freq_khz)
+static unsigned int analog_get_nearest_service_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;
@@ -130,13 +130,13 @@ static void analog_update_tuner_dev_info(struct node *node, unsigned int idx)
 	unsigned int offset;
 	unsigned int freq_khz;
 
-	node->state.freq_idx = idx;
+	node->state.service_idx = idx;
 	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE;
 	info->is_analog = true;
-	info->analog.ana_bcast_type = node->state.freq_idx / tot_freqs;
+	info->analog.ana_bcast_type = node->state.service_idx / tot_freqs;
 	info->analog.bcast_system =
-		(node->state.freq_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
-	offset = node->state.freq_idx % NUM_ANALOG_FREQS;
+		(node->state.service_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
+	offset = node->state.service_idx % NUM_ANALOG_FREQS;
 	freq_khz = analog_freqs_khz[info->analog.ana_bcast_type][info->analog.bcast_system][offset];
 	info->analog.ana_freq = (freq_khz * 10) / 625;
 }
@@ -152,7 +152,7 @@ static bool analog_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
 	if (type < 3 && system < 9) {
 		int freq_khz = (freq * 625) / 10;
 
-		idx = analog_get_nearest_freq_idx(type, system, freq_khz);
+		idx = analog_get_nearest_service_idx(type, system, freq_khz);
 		analog_update_tuner_dev_info(node, idx);
 		return true;
 	}
@@ -206,11 +206,11 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
 
-		if (node->state.freq_idx == 0)
-			node->state.freq_idx = TOT_ANALOG_FREQS - 1;
+		if (node->state.service_idx == 0)
+			node->state.service_idx = TOT_ANALOG_FREQS - 1;
 		else
-			node->state.freq_idx--;
-		analog_update_tuner_dev_info(node, node->state.freq_idx);
+			node->state.service_idx--;
+		analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
@@ -218,11 +218,11 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
 
-		if (node->state.freq_idx == TOT_ANALOG_FREQS - 1)
-			node->state.freq_idx = 0;
+		if (node->state.service_idx == TOT_ANALOG_FREQS - 1)
+			node->state.service_idx = 0;
 		else
-			node->state.freq_idx++;
-		analog_update_tuner_dev_info(node, node->state.freq_idx);
+			node->state.service_idx++;
+		analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
                   ` (2 preceding siblings ...)
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 2/8] cec-follower: rename freq_idx to service_idx c0d1n61at3
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  2019-10-14  9:19   ` hverkuil
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 4/8] cec-follower: create digital ATSC channels c0d1n61at3
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


This table will allow proper testing of digital tuner control features.
There are three channels per TSID/ONID/SID combination along with channel
data for the following digital ARIB broadcast systems:
  - ARIB-BS
  - ARIB-T

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 52 ++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 3a71a890..4fd65876 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -9,8 +9,60 @@
 #include "cec-follower.h"
 
 #define NUM_ANALOG_FREQS 3
+#define NUM_DIGITAL_CHANS 3
 #define TOT_ANALOG_FREQS (sizeof(analog_freqs_khz) / sizeof(analog_freqs_khz[0][0][0]))
 
+struct service_info {
+	unsigned tsid;
+	unsigned onid;
+	unsigned sid;
+	unsigned fmt;
+	unsigned major;
+	unsigned minor;
+};
+
+/*
+ * This table contains the digital television channels for ARIB (ISDB).  There
+ * are a total of three channels that are identified by digital IDs or by
+ * channel.
+ *
+ * CEC 17 of the 1.4 specification lists the available digital identification
+ * methods, IDs, and channel data.
+ *
+ * Digital channel data for ARIB-BS is from:
+ *
+ * https://sichbopvr.com/frequency-tables/19-20E
+ *
+ * No public data was found for ARIB-BS so data is just copied.
+ *
+ * Digital channel data for ARIB-T is from:
+ *
+ * https://sichbopvr.com/frequency-tables/Brazil/Rio%20de%20Janeiro/Rio%20De%20Janeiro
+ */
+static const struct service_info digital_arib_data[2][1][NUM_DIGITAL_CHANS] =
+{
+	// satellite
+	{
+		// arib-bs
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1032, 1, 30203, 1, 0, 30203 },
+			{ 1046, 1, 30505, 1, 0, 30505 },
+			{ 1060, 1, 30609, 1, 0, 30609 }
+		}
+	},
+	// terrestrial
+	{
+		// arib-t
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1519, 1519, 48608, 1, 0, 48608 },
+			{ 1624, 1624, 51992, 1, 0, 51992 },
+			{ 1905, 1905, 60960, 1, 0, 60960 }
+		}
+	}
+};
+
 /*
  * This table contains analog television channel frequencies in KHz.  There are
  * a total of three frequencies per analog broadcast type and broadcast system.
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  2019-10-14  9:19   ` hverkuil
  1 sibling, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


This table will allow proper testing of digital tuner control features.
There are three channels per TSID/ONID/SID combination along with channel
data for the following digital ARIB broadcast systems:
  - ARIB-BS
  - ARIB-T

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 52 ++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 3a71a890..4fd65876 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -9,8 +9,60 @@
 #include "cec-follower.h"
 
 #define NUM_ANALOG_FREQS 3
+#define NUM_DIGITAL_CHANS 3
 #define TOT_ANALOG_FREQS (sizeof(analog_freqs_khz) / sizeof(analog_freqs_khz[0][0][0]))
 
+struct service_info {
+	unsigned tsid;
+	unsigned onid;
+	unsigned sid;
+	unsigned fmt;
+	unsigned major;
+	unsigned minor;
+};
+
+/*
+ * This table contains the digital television channels for ARIB (ISDB).  There
+ * are a total of three channels that are identified by digital IDs or by
+ * channel.
+ *
+ * CEC 17 of the 1.4 specification lists the available digital identification
+ * methods, IDs, and channel data.
+ *
+ * Digital channel data for ARIB-BS is from:
+ *
+ * https://sichbopvr.com/frequency-tables/19-20E
+ *
+ * No public data was found for ARIB-BS so data is just copied.
+ *
+ * Digital channel data for ARIB-T is from:
+ *
+ * https://sichbopvr.com/frequency-tables/Brazil/Rio%20de%20Janeiro/Rio%20De%20Janeiro
+ */
+static const struct service_info digital_arib_data[2][1][NUM_DIGITAL_CHANS] =
+{
+	// satellite
+	{
+		// arib-bs
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1032, 1, 30203, 1, 0, 30203 },
+			{ 1046, 1, 30505, 1, 0, 30505 },
+			{ 1060, 1, 30609, 1, 0, 30609 }
+		}
+	},
+	// terrestrial
+	{
+		// arib-t
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1519, 1519, 48608, 1, 0, 48608 },
+			{ 1624, 1624, 51992, 1, 0, 51992 },
+			{ 1905, 1905, 60960, 1, 0, 60960 }
+		}
+	}
+};
+
 /*
  * This table contains analog television channel frequencies in KHz.  There are
  * a total of three frequencies per analog broadcast type and broadcast system.
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 4/8] cec-follower: create digital ATSC channels
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
                   ` (3 preceding siblings ...)
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels c0d1n61at3
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 5/8] cec-follower: create digital DVB channels c0d1n61at3
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


This table will allow proper testing of digital tuner control features.
There are three channels per TSID/program number combination along with
channel data for the following digital ATSC broadcast systems:
  - ATSC-SAT
  - ATSC-T

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 45 ++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 4fd65876..4a4d2c7f 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -63,6 +63,51 @@ static const struct service_info digital_arib_data[2][1][NUM_DIGITAL_CHANS] =
 	}
 };
 
+/*
+ * This table contains the digital television channels for ATSC.  There
+ * are a total of three channels that are identified by digital IDs or by
+ * channel.
+ *
+ * CEC 17 of the 1.4 specification lists the available digital identification
+ * methods, IDs, and channel data.
+ *
+ * Digital channel data for atsc-sat is from:
+ *
+ * https://sichbopvr.com/frequency-tables/28-50E
+ *
+ * No public data was found for atsc-sat so data is just copied.
+ *
+ * Digital channel data for atsc-t is from:
+ *
+ * https://sichbopvr.com/frequency-tables/United%20States/Illinois/Caseyville
+ *
+ * ATSC does not use ONIDs and SID will be used as the program number.  All ATSC
+ * channel number formats are 2 part.
+ */
+static const struct service_info digital_atsc_data[2][1][NUM_DIGITAL_CHANS] =
+{
+	// satellite
+	{
+		// atsc-sat
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 2065, 0, 50316, 2, 3, 50316 },
+			{ 2090, 0, 50882, 2, 3, 50882 },
+			{ 2122, 0, 55295, 2, 3, 55295 }
+		}
+	},
+	// terrestrial
+	{
+		// atsc-t
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1675, 0, 1, 2, 4, 1 },
+			{ 1675, 0, 2, 2, 4, 2 },
+			{ 1675, 0, 3, 2, 4, 3 }
+		}
+	}
+};
+
 /*
  * This table contains analog television channel frequencies in KHz.  There are
  * a total of three frequencies per analog broadcast type and broadcast system.
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 4/8] cec-follower: create digital ATSC channels
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 4/8] cec-follower: create digital ATSC channels c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  0 siblings, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


This table will allow proper testing of digital tuner control features.
There are three channels per TSID/program number combination along with
channel data for the following digital ATSC broadcast systems:
  - ATSC-SAT
  - ATSC-T

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 45 ++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 4fd65876..4a4d2c7f 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -63,6 +63,51 @@ static const struct service_info digital_arib_data[2][1][NUM_DIGITAL_CHANS] =
 	}
 };
 
+/*
+ * This table contains the digital television channels for ATSC.  There
+ * are a total of three channels that are identified by digital IDs or by
+ * channel.
+ *
+ * CEC 17 of the 1.4 specification lists the available digital identification
+ * methods, IDs, and channel data.
+ *
+ * Digital channel data for atsc-sat is from:
+ *
+ * https://sichbopvr.com/frequency-tables/28-50E
+ *
+ * No public data was found for atsc-sat so data is just copied.
+ *
+ * Digital channel data for atsc-t is from:
+ *
+ * https://sichbopvr.com/frequency-tables/United%20States/Illinois/Caseyville
+ *
+ * ATSC does not use ONIDs and SID will be used as the program number.  All ATSC
+ * channel number formats are 2 part.
+ */
+static const struct service_info digital_atsc_data[2][1][NUM_DIGITAL_CHANS] =
+{
+	// satellite
+	{
+		// atsc-sat
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 2065, 0, 50316, 2, 3, 50316 },
+			{ 2090, 0, 50882, 2, 3, 50882 },
+			{ 2122, 0, 55295, 2, 3, 55295 }
+		}
+	},
+	// terrestrial
+	{
+		// atsc-t
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1675, 0, 1, 2, 4, 1 },
+			{ 1675, 0, 2, 2, 4, 2 },
+			{ 1675, 0, 3, 2, 4, 3 }
+		}
+	}
+};
+
 /*
  * This table contains analog television channel frequencies in KHz.  There are
  * a total of three frequencies per analog broadcast type and broadcast system.
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 5/8] cec-follower: create digital DVB channels
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
                   ` (4 preceding siblings ...)
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 4/8] cec-follower: create digital ATSC channels c0d1n61at3
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation c0d1n61at3
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


This table will allow proper testing of digital tuner control features.
There are three channels per TSID/ONID/SID combination along with channel
data for the following digital DVB broadcast systems:
  - DVB-S2
  - DVB-T

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 41 ++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 4a4d2c7f..04e7e4c3 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -108,6 +108,47 @@ static const struct service_info digital_atsc_data[2][1][NUM_DIGITAL_CHANS] =
 	}
 };
 
+/*
+ * This table contains the digital television channels for DVB.  There are a
+ * total of three channels that are identified by digital IDs or by channel.
+ *
+ * CEC 17 of the 1.4 specification lists the available digital identification
+ * methods, IDs, and channel data.
+ *
+ * Digital channel data for DVB-S2 is from:
+ *
+ * https://www.satellite-calculations.com/DVB/getchannellist.php?1west/Swedish_Nordig_Channel_List.htm
+ *
+ * Digital channel data for DVB-T is from:
+ *
+ * https://sichbopvr.com/frequency-tables/Denmark/Hovedstaden/Copenhagen
+ * https://sichbopvr.com/frequency-tables/Sweden/Skane%20Lan/Malm%c3%b6
+ *
+ */
+static const struct service_info digital_dvb_data[2][1][NUM_DIGITAL_CHANS] =
+{
+	// satellite
+	{
+		// dvb-s2
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 61, 70, 7193, 1, 0, 24 },
+			{ 65, 70, 7040, 1, 0, 72 },
+			{ 28, 70, 7012, 1, 0, 101 }
+		}
+	},
+	// terrestrial
+	{
+		// dvb-t
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1002, 8400, 2025, 1, 0, 21 },
+			{ 1004, 8400, 84, 1, 0, 31 },
+			{ 1004, 8945, 1040, 1, 0, 1040 }
+		}
+	}
+};
+
 /*
  * This table contains analog television channel frequencies in KHz.  There are
  * a total of three frequencies per analog broadcast type and broadcast system.
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 5/8] cec-follower: create digital DVB channels
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 5/8] cec-follower: create digital DVB channels c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  0 siblings, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


This table will allow proper testing of digital tuner control features.
There are three channels per TSID/ONID/SID combination along with channel
data for the following digital DVB broadcast systems:
  - DVB-S2
  - DVB-T

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 41 ++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 4a4d2c7f..04e7e4c3 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -108,6 +108,47 @@ static const struct service_info digital_atsc_data[2][1][NUM_DIGITAL_CHANS] =
 	}
 };
 
+/*
+ * This table contains the digital television channels for DVB.  There are a
+ * total of three channels that are identified by digital IDs or by channel.
+ *
+ * CEC 17 of the 1.4 specification lists the available digital identification
+ * methods, IDs, and channel data.
+ *
+ * Digital channel data for DVB-S2 is from:
+ *
+ * https://www.satellite-calculations.com/DVB/getchannellist.php?1west/Swedish_Nordig_Channel_List.htm
+ *
+ * Digital channel data for DVB-T is from:
+ *
+ * https://sichbopvr.com/frequency-tables/Denmark/Hovedstaden/Copenhagen
+ * https://sichbopvr.com/frequency-tables/Sweden/Skane%20Lan/Malm%c3%b6
+ *
+ */
+static const struct service_info digital_dvb_data[2][1][NUM_DIGITAL_CHANS] =
+{
+	// satellite
+	{
+		// dvb-s2
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 61, 70, 7193, 1, 0, 24 },
+			{ 65, 70, 7040, 1, 0, 72 },
+			{ 28, 70, 7012, 1, 0, 101 }
+		}
+	},
+	// terrestrial
+	{
+		// dvb-t
+		{
+			// tsid, onid, sid, fmt, major, minor
+			{ 1002, 8400, 2025, 1, 0, 21 },
+			{ 1004, 8400, 84, 1, 0, 31 },
+			{ 1004, 8945, 1040, 1, 0, 1040 }
+		}
+	}
+};
+
 /*
  * This table contains analog television channel frequencies in KHz.  There are
  * a total of three frequencies per analog broadcast type and broadcast system.
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
                   ` (5 preceding siblings ...)
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 5/8] cec-follower: create digital DVB channels c0d1n61at3
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  2019-10-14 10:03   ` hverkuil
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 7/8] cec-follower: fix tuner step increment/decrement c0d1n61at3
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 8/8] cec-compliance: add digital tuner control testing c0d1n61at3
  8 siblings, 2 replies; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


The cec-follower will now emulate a digital service.  This allows an
initiator device can directly select a digital service by choosing a
digital service ID method and broadcast system along with the proper
digital IDs or channel data.  After a digital service is selected,
the cec-follower will also provide the tuner device status upon
request.

Opcodes implemented:
  - <Select Digital Service>

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 169 +++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 04e7e4c3..760eed2a 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -244,6 +244,162 @@ void analog_tuner_init(struct state *state)
 	info->analog.ana_freq = (freq_khz * 10) / 625;
 }
 
+static int digital_get_service_offset(struct cec_op_digital_service_id *digital)
+{
+	__u8 method = digital->service_id_method;
+	struct cec_op_dvb_data *dvb = &digital->dvb;
+	struct cec_op_atsc_data *atsc = &digital->atsc;
+	struct cec_op_channel_data *channel = &digital->channel;
+	unsigned int sys =
+		(digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T ||
+		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T ||
+		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T) ? 1 : 0;
+
+	for (int i = 0; i < NUM_DIGITAL_CHANS; i++) {
+		switch (method) {
+		case CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID:
+			if (dvb->transport_id == digital_arib_data[sys][0][i].tsid &&
+			    dvb->service_id == digital_arib_data[sys][0][i].sid &&
+			    dvb->orig_network_id == digital_arib_data[sys][0][i].onid) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (atsc->transport_id == digital_atsc_data[sys][0][i].tsid &&
+			    atsc->program_number == digital_atsc_data[sys][0][i].sid) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (dvb->transport_id == digital_dvb_data[sys][0][i].tsid &&
+			    dvb->service_id == digital_dvb_data[sys][0][i].sid &&
+			    dvb->orig_network_id == digital_dvb_data[sys][0][i].onid) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			break;
+		case CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL:
+			if (channel->minor == digital_arib_data[sys][0][i].minor) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (channel->major == digital_atsc_data[sys][0][i].major &&
+			    channel->minor == digital_atsc_data[sys][0][i].minor) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (channel->minor == digital_dvb_data[sys][0][i].minor) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	return -1;
+}
+
+static int digital_get_service_idx(struct cec_op_digital_service_id *digital)
+{
+	__u8 system = digital->dig_bcast_system;
+	int offset = digital_get_service_offset(digital);
+
+	switch (system) {
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
+		return offset;
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: {
+		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 2 + offset;
+	}
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T: {
+		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 4 + offset;
+	}
+	default:
+		break;
+	}
+	return -1;
+}
+
+static void digital_update_tuner_dev_info(struct node *node, unsigned int idx,
+					  __u8 method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID)
+{
+	struct cec_op_tuner_device_info *info = &node->state.tuner_dev_info;
+	struct cec_op_digital_service_id *digital = &info->digital;
+	struct cec_op_dvb_data *dvb = &digital->dvb;
+	struct cec_op_atsc_data *atsc = &digital->atsc;
+	struct cec_op_channel_data *channel = &digital->channel;
+	unsigned int tbl = idx / (NUM_DIGITAL_CHANS * 2);
+	unsigned int sys = (idx % (NUM_DIGITAL_CHANS * 2)) / NUM_DIGITAL_CHANS;
+	unsigned int offset = idx % NUM_DIGITAL_CHANS;
+
+	node->state.service_idx = idx;
+	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_DIGITAL;
+	info->is_analog = false;
+	digital->service_id_method = method;
+	switch (tbl) {
+	case 0: {
+		if (sys)
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T;
+		else
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
+		if (digital->service_id_method) {
+			channel->channel_number_fmt = digital_arib_data[sys][0][offset].fmt;
+			channel->major = digital_arib_data[sys][0][offset].major;
+			channel->minor = digital_arib_data[sys][0][offset].minor;
+		} else {
+			dvb->transport_id = digital_arib_data[sys][0][offset].tsid;
+			dvb->orig_network_id = digital_arib_data[sys][0][offset].onid;
+			dvb->service_id = digital_arib_data[sys][0][offset].sid;
+		}
+		break;
+	}
+	case 1: {
+		if (sys)
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T;
+		else
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT;
+		if (digital->service_id_method) {
+			channel->channel_number_fmt = digital_atsc_data[sys][0][offset].fmt;
+			channel->major = digital_atsc_data[sys][0][offset].major;
+			channel->minor = digital_atsc_data[sys][0][offset].minor;
+		} else {
+			atsc->transport_id = digital_atsc_data[sys][0][offset].tsid;
+			atsc->program_number = digital_atsc_data[sys][0][offset].sid;
+		}
+		break;
+	}
+	case 2: {
+		if (sys)
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T;
+		else
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2;
+		if (digital->service_id_method) {
+			channel->channel_number_fmt = digital_dvb_data[sys][0][offset].fmt;
+			channel->major = digital_dvb_data[sys][0][offset].major;
+			channel->minor = digital_dvb_data[sys][0][offset].minor;
+		} else {
+			dvb->transport_id = digital_dvb_data[sys][0][offset].tsid;
+			dvb->orig_network_id = digital_dvb_data[sys][0][offset].onid;
+			dvb->service_id = digital_dvb_data[sys][0][offset].sid;
+		}
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+static bool digital_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
+{
+	struct cec_op_digital_service_id digital = {};
+	__u8 method;
+	int idx;
+
+	cec_ops_select_digital_service(msg, &digital);
+	method = digital.service_id_method;
+	idx = digital_get_service_idx(&digital);
+	if (idx > -1) {
+		digital_update_tuner_dev_info(node, idx, method);
+		return true;
+	}
+	return false;
+}
+
 static unsigned int analog_get_nearest_service_idx(__u8 ana_bcast_type, __u8 ana_bcast_system,
 						   int ana_freq_khz)
 {
@@ -340,6 +496,19 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		return;
 
 	case CEC_MSG_SELECT_DIGITAL_SERVICE:
+		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
+			break;
+
+		if (node->state.tuner_dev_info.rec_flag == CEC_OP_REC_FLAG_USED) {
+			reply_feature_abort(node, &msg, CEC_OP_ABORT_REFUSED);
+			return;
+		}
+		if (!digital_set_tuner_dev_info(node, &msg)) {
+			reply_feature_abort(node, &msg, CEC_OP_ABORT_INVALID_OP);
+			return;
+		}
+		return;
+
 	case CEC_MSG_TUNER_STEP_DECREMENT: {
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  2019-10-14 10:03   ` hverkuil
  1 sibling, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


The cec-follower will now emulate a digital service.  This allows an
initiator device can directly select a digital service by choosing a
digital service ID method and broadcast system along with the proper
digital IDs or channel data.  After a digital service is selected,
the cec-follower will also provide the tuner device status upon
request.

Opcodes implemented:
  - <Select Digital Service>

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-tuner.cpp | 169 +++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
index 04e7e4c3..760eed2a 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -244,6 +244,162 @@ void analog_tuner_init(struct state *state)
 	info->analog.ana_freq = (freq_khz * 10) / 625;
 }
 
+static int digital_get_service_offset(struct cec_op_digital_service_id *digital)
+{
+	__u8 method = digital->service_id_method;
+	struct cec_op_dvb_data *dvb = &digital->dvb;
+	struct cec_op_atsc_data *atsc = &digital->atsc;
+	struct cec_op_channel_data *channel = &digital->channel;
+	unsigned int sys =
+		(digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T ||
+		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T ||
+		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T) ? 1 : 0;
+
+	for (int i = 0; i < NUM_DIGITAL_CHANS; i++) {
+		switch (method) {
+		case CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID:
+			if (dvb->transport_id == digital_arib_data[sys][0][i].tsid &&
+			    dvb->service_id == digital_arib_data[sys][0][i].sid &&
+			    dvb->orig_network_id == digital_arib_data[sys][0][i].onid) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (atsc->transport_id == digital_atsc_data[sys][0][i].tsid &&
+			    atsc->program_number == digital_atsc_data[sys][0][i].sid) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (dvb->transport_id == digital_dvb_data[sys][0][i].tsid &&
+			    dvb->service_id == digital_dvb_data[sys][0][i].sid &&
+			    dvb->orig_network_id == digital_dvb_data[sys][0][i].onid) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			break;
+		case CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL:
+			if (channel->minor == digital_arib_data[sys][0][i].minor) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (channel->major == digital_atsc_data[sys][0][i].major &&
+			    channel->minor == digital_atsc_data[sys][0][i].minor) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			if (channel->minor == digital_dvb_data[sys][0][i].minor) {
+				return (sys * NUM_DIGITAL_CHANS) + i;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	return -1;
+}
+
+static int digital_get_service_idx(struct cec_op_digital_service_id *digital)
+{
+	__u8 system = digital->dig_bcast_system;
+	int offset = digital_get_service_offset(digital);
+
+	switch (system) {
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
+		return offset;
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: {
+		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 2 + offset;
+	}
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
+	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T: {
+		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 4 + offset;
+	}
+	default:
+		break;
+	}
+	return -1;
+}
+
+static void digital_update_tuner_dev_info(struct node *node, unsigned int idx,
+					  __u8 method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID)
+{
+	struct cec_op_tuner_device_info *info = &node->state.tuner_dev_info;
+	struct cec_op_digital_service_id *digital = &info->digital;
+	struct cec_op_dvb_data *dvb = &digital->dvb;
+	struct cec_op_atsc_data *atsc = &digital->atsc;
+	struct cec_op_channel_data *channel = &digital->channel;
+	unsigned int tbl = idx / (NUM_DIGITAL_CHANS * 2);
+	unsigned int sys = (idx % (NUM_DIGITAL_CHANS * 2)) / NUM_DIGITAL_CHANS;
+	unsigned int offset = idx % NUM_DIGITAL_CHANS;
+
+	node->state.service_idx = idx;
+	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_DIGITAL;
+	info->is_analog = false;
+	digital->service_id_method = method;
+	switch (tbl) {
+	case 0: {
+		if (sys)
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T;
+		else
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
+		if (digital->service_id_method) {
+			channel->channel_number_fmt = digital_arib_data[sys][0][offset].fmt;
+			channel->major = digital_arib_data[sys][0][offset].major;
+			channel->minor = digital_arib_data[sys][0][offset].minor;
+		} else {
+			dvb->transport_id = digital_arib_data[sys][0][offset].tsid;
+			dvb->orig_network_id = digital_arib_data[sys][0][offset].onid;
+			dvb->service_id = digital_arib_data[sys][0][offset].sid;
+		}
+		break;
+	}
+	case 1: {
+		if (sys)
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T;
+		else
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT;
+		if (digital->service_id_method) {
+			channel->channel_number_fmt = digital_atsc_data[sys][0][offset].fmt;
+			channel->major = digital_atsc_data[sys][0][offset].major;
+			channel->minor = digital_atsc_data[sys][0][offset].minor;
+		} else {
+			atsc->transport_id = digital_atsc_data[sys][0][offset].tsid;
+			atsc->program_number = digital_atsc_data[sys][0][offset].sid;
+		}
+		break;
+	}
+	case 2: {
+		if (sys)
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T;
+		else
+			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2;
+		if (digital->service_id_method) {
+			channel->channel_number_fmt = digital_dvb_data[sys][0][offset].fmt;
+			channel->major = digital_dvb_data[sys][0][offset].major;
+			channel->minor = digital_dvb_data[sys][0][offset].minor;
+		} else {
+			dvb->transport_id = digital_dvb_data[sys][0][offset].tsid;
+			dvb->orig_network_id = digital_dvb_data[sys][0][offset].onid;
+			dvb->service_id = digital_dvb_data[sys][0][offset].sid;
+		}
+		break;
+	}
+	default:
+		break;
+	}
+}
+
+static bool digital_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
+{
+	struct cec_op_digital_service_id digital = {};
+	__u8 method;
+	int idx;
+
+	cec_ops_select_digital_service(msg, &digital);
+	method = digital.service_id_method;
+	idx = digital_get_service_idx(&digital);
+	if (idx > -1) {
+		digital_update_tuner_dev_info(node, idx, method);
+		return true;
+	}
+	return false;
+}
+
 static unsigned int analog_get_nearest_service_idx(__u8 ana_bcast_type, __u8 ana_bcast_system,
 						   int ana_freq_khz)
 {
@@ -340,6 +496,19 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		return;
 
 	case CEC_MSG_SELECT_DIGITAL_SERVICE:
+		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
+			break;
+
+		if (node->state.tuner_dev_info.rec_flag == CEC_OP_REC_FLAG_USED) {
+			reply_feature_abort(node, &msg, CEC_OP_ABORT_REFUSED);
+			return;
+		}
+		if (!digital_set_tuner_dev_info(node, &msg)) {
+			reply_feature_abort(node, &msg, CEC_OP_ABORT_INVALID_OP);
+			return;
+		}
+		return;
+
 	case CEC_MSG_TUNER_STEP_DECREMENT: {
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 7/8] cec-follower: fix tuner step increment/decrement
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
                   ` (6 preceding siblings ...)
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation c0d1n61at3
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 8/8] cec-compliance: add digital tuner control testing c0d1n61at3
  8 siblings, 1 reply; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


Tuner step feature will select the next highest or lowest service
There are a total of 98 channels, 18 digital and 81 analog with
digital preceeding analog.  Analog channels defined by broadcast
type and system.  Digital channels defined by service ID method
and broadcast system along with digital IDs and channel data.

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

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-follower.cpp |  2 +-
 utils/cec-follower/cec-follower.h   |  2 +-
 utils/cec-follower/cec-tuner.cpp    | 46 +++++++++++++++++++----------
 3 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/utils/cec-follower/cec-follower.cpp b/utils/cec-follower/cec-follower.cpp
index 00783d15..2488d2e8 100644
--- a/utils/cec-follower/cec-follower.cpp
+++ b/utils/cec-follower/cec-follower.cpp
@@ -296,7 +296,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_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 2a9e397a..01357dc2 100644
--- a/utils/cec-follower/cec-follower.h
+++ b/utils/cec-follower/cec-follower.h
@@ -223,7 +223,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 state *state);
+void tuner_dev_info_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 760eed2a..8a75f0f5 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -11,6 +11,9 @@
 #define NUM_ANALOG_FREQS 3
 #define NUM_DIGITAL_CHANS 3
 #define TOT_ANALOG_FREQS (sizeof(analog_freqs_khz) / sizeof(analog_freqs_khz[0][0][0]))
+#define TOT_DIGITAL_CHANS ((sizeof(digital_arib_data) / sizeof(digital_arib_data[0][0][0])) + \
+			   (sizeof(digital_atsc_data) / sizeof(digital_atsc_data[0][0][0])) + \
+			   (sizeof(digital_dvb_data) / sizeof(digital_dvb_data[0][0][0])))
 
 struct service_info {
 	unsigned tsid;
@@ -229,19 +232,20 @@ static unsigned int analog_freqs_khz[3][9][NUM_ANALOG_FREQS] =
 	}
 };
 
-void analog_tuner_init(struct state *state)
+void tuner_dev_info_init(struct state *state)
 {
 	struct cec_op_tuner_device_info *info = &state->tuner_dev_info;
-	unsigned int freq_khz;
+	struct cec_op_digital_service_id *digital = &info->digital;
 
 	state->service_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;
-	info->analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_CABLE;
-	info->analog.bcast_system = CEC_OP_BCAST_SYSTEM_PAL_BG;
-	freq_khz = analog_freqs_khz[info->analog.ana_bcast_type][info->analog.bcast_system][0];
-	info->analog.ana_freq = (freq_khz * 10) / 625;
+	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_DIGITAL;
+	info->is_analog = false;
+	digital->service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID;
+	digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
+	digital->arib.transport_id = digital_arib_data[0][0][0].tsid;
+	digital->arib.service_id = digital_arib_data[0][0][0].sid;
+	digital->arib.orig_network_id = digital_arib_data[0][0][0].onid;
 }
 
 static int digital_get_service_offset(struct cec_op_digital_service_id *digital)
@@ -414,22 +418,24 @@ static unsigned int analog_get_nearest_service_idx(__u8 ana_bcast_type, __u8 ana
 			offset = i;
 		}
 	}
-	return NUM_ANALOG_FREQS * ((ana_bcast_type * 9) + ana_bcast_system) + offset;
+	return NUM_ANALOG_FREQS * ((ana_bcast_type * 9) + ana_bcast_system) +
+		offset + TOT_DIGITAL_CHANS;
 }
 
 static void analog_update_tuner_dev_info(struct node *node, unsigned int idx)
 {
 	struct cec_op_tuner_device_info *info = &node->state.tuner_dev_info;
-	unsigned int tot_freqs = NUM_ANALOG_FREQS * 9;
+	unsigned int sys_freqs = NUM_ANALOG_FREQS * 9;
 	unsigned int offset;
 	unsigned int freq_khz;
 
 	node->state.service_idx = idx;
 	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE;
 	info->is_analog = true;
-	info->analog.ana_bcast_type = node->state.service_idx / tot_freqs;
+	info->analog.ana_bcast_type = (node->state.service_idx - TOT_DIGITAL_CHANS) / sys_freqs;
 	info->analog.bcast_system =
-		(node->state.service_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
+		(node->state.service_idx -
+		 (sys_freqs * info->analog.ana_bcast_type + TOT_DIGITAL_CHANS)) / NUM_ANALOG_FREQS;
 	offset = node->state.service_idx % NUM_ANALOG_FREQS;
 	freq_khz = analog_freqs_khz[info->analog.ana_bcast_type][info->analog.bcast_system][offset];
 	info->analog.ana_freq = (freq_khz * 10) / 625;
@@ -514,10 +520,14 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 			break;
 
 		if (node->state.service_idx == 0)
-			node->state.service_idx = TOT_ANALOG_FREQS - 1;
+			node->state.service_idx =
+				TOT_DIGITAL_CHANS + TOT_ANALOG_FREQS - 1;
 		else
 			node->state.service_idx--;
-		analog_update_tuner_dev_info(node, node->state.service_idx);
+		if (node->state.service_idx < TOT_DIGITAL_CHANS)
+			digital_update_tuner_dev_info(node, node->state.service_idx);
+		else
+			analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
@@ -525,11 +535,15 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
 
-		if (node->state.service_idx == TOT_ANALOG_FREQS - 1)
+		if (node->state.service_idx ==
+				TOT_DIGITAL_CHANS + TOT_ANALOG_FREQS - 1)
 			node->state.service_idx = 0;
 		else
 			node->state.service_idx++;
-		analog_update_tuner_dev_info(node, node->state.service_idx);
+		if (node->state.service_idx < TOT_DIGITAL_CHANS)
+			digital_update_tuner_dev_info(node, node->state.service_idx);
+		else
+			analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 7/8] cec-follower: fix tuner step increment/decrement
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 7/8] cec-follower: fix tuner step increment/decrement c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  0 siblings, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


Tuner step feature will select the next highest or lowest service
There are a total of 98 channels, 18 digital and 81 analog with
digital preceeding analog.  Analog channels defined by broadcast
type and system.  Digital channels defined by service ID method
and broadcast system along with digital IDs and channel data.

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

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-follower/cec-follower.cpp |  2 +-
 utils/cec-follower/cec-follower.h   |  2 +-
 utils/cec-follower/cec-tuner.cpp    | 46 +++++++++++++++++++----------
 3 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/utils/cec-follower/cec-follower.cpp b/utils/cec-follower/cec-follower.cpp
index 00783d15..2488d2e8 100644
--- a/utils/cec-follower/cec-follower.cpp
+++ b/utils/cec-follower/cec-follower.cpp
@@ -296,7 +296,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_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 2a9e397a..01357dc2 100644
--- a/utils/cec-follower/cec-follower.h
+++ b/utils/cec-follower/cec-follower.h
@@ -223,7 +223,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 state *state);
+void tuner_dev_info_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 760eed2a..8a75f0f5 100644
--- a/utils/cec-follower/cec-tuner.cpp
+++ b/utils/cec-follower/cec-tuner.cpp
@@ -11,6 +11,9 @@
 #define NUM_ANALOG_FREQS 3
 #define NUM_DIGITAL_CHANS 3
 #define TOT_ANALOG_FREQS (sizeof(analog_freqs_khz) / sizeof(analog_freqs_khz[0][0][0]))
+#define TOT_DIGITAL_CHANS ((sizeof(digital_arib_data) / sizeof(digital_arib_data[0][0][0])) + \
+			   (sizeof(digital_atsc_data) / sizeof(digital_atsc_data[0][0][0])) + \
+			   (sizeof(digital_dvb_data) / sizeof(digital_dvb_data[0][0][0])))
 
 struct service_info {
 	unsigned tsid;
@@ -229,19 +232,20 @@ static unsigned int analog_freqs_khz[3][9][NUM_ANALOG_FREQS] =
 	}
 };
 
-void analog_tuner_init(struct state *state)
+void tuner_dev_info_init(struct state *state)
 {
 	struct cec_op_tuner_device_info *info = &state->tuner_dev_info;
-	unsigned int freq_khz;
+	struct cec_op_digital_service_id *digital = &info->digital;
 
 	state->service_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;
-	info->analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_CABLE;
-	info->analog.bcast_system = CEC_OP_BCAST_SYSTEM_PAL_BG;
-	freq_khz = analog_freqs_khz[info->analog.ana_bcast_type][info->analog.bcast_system][0];
-	info->analog.ana_freq = (freq_khz * 10) / 625;
+	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_DIGITAL;
+	info->is_analog = false;
+	digital->service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID;
+	digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
+	digital->arib.transport_id = digital_arib_data[0][0][0].tsid;
+	digital->arib.service_id = digital_arib_data[0][0][0].sid;
+	digital->arib.orig_network_id = digital_arib_data[0][0][0].onid;
 }
 
 static int digital_get_service_offset(struct cec_op_digital_service_id *digital)
@@ -414,22 +418,24 @@ static unsigned int analog_get_nearest_service_idx(__u8 ana_bcast_type, __u8 ana
 			offset = i;
 		}
 	}
-	return NUM_ANALOG_FREQS * ((ana_bcast_type * 9) + ana_bcast_system) + offset;
+	return NUM_ANALOG_FREQS * ((ana_bcast_type * 9) + ana_bcast_system) +
+		offset + TOT_DIGITAL_CHANS;
 }
 
 static void analog_update_tuner_dev_info(struct node *node, unsigned int idx)
 {
 	struct cec_op_tuner_device_info *info = &node->state.tuner_dev_info;
-	unsigned int tot_freqs = NUM_ANALOG_FREQS * 9;
+	unsigned int sys_freqs = NUM_ANALOG_FREQS * 9;
 	unsigned int offset;
 	unsigned int freq_khz;
 
 	node->state.service_idx = idx;
 	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_ANALOGUE;
 	info->is_analog = true;
-	info->analog.ana_bcast_type = node->state.service_idx / tot_freqs;
+	info->analog.ana_bcast_type = (node->state.service_idx - TOT_DIGITAL_CHANS) / sys_freqs;
 	info->analog.bcast_system =
-		(node->state.service_idx - (tot_freqs * info->analog.ana_bcast_type)) / NUM_ANALOG_FREQS;
+		(node->state.service_idx -
+		 (sys_freqs * info->analog.ana_bcast_type + TOT_DIGITAL_CHANS)) / NUM_ANALOG_FREQS;
 	offset = node->state.service_idx % NUM_ANALOG_FREQS;
 	freq_khz = analog_freqs_khz[info->analog.ana_bcast_type][info->analog.bcast_system][offset];
 	info->analog.ana_freq = (freq_khz * 10) / 625;
@@ -514,10 +520,14 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 			break;
 
 		if (node->state.service_idx == 0)
-			node->state.service_idx = TOT_ANALOG_FREQS - 1;
+			node->state.service_idx =
+				TOT_DIGITAL_CHANS + TOT_ANALOG_FREQS - 1;
 		else
 			node->state.service_idx--;
-		analog_update_tuner_dev_info(node, node->state.service_idx);
+		if (node->state.service_idx < TOT_DIGITAL_CHANS)
+			digital_update_tuner_dev_info(node, node->state.service_idx);
+		else
+			analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
@@ -525,11 +535,15 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
 		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
 			break;
 
-		if (node->state.service_idx == TOT_ANALOG_FREQS - 1)
+		if (node->state.service_idx ==
+				TOT_DIGITAL_CHANS + TOT_ANALOG_FREQS - 1)
 			node->state.service_idx = 0;
 		else
 			node->state.service_idx++;
-		analog_update_tuner_dev_info(node, node->state.service_idx);
+		if (node->state.service_idx < TOT_DIGITAL_CHANS)
+			digital_update_tuner_dev_info(node, node->state.service_idx);
+		else
+			analog_update_tuner_dev_info(node, node->state.service_idx);
 		return;
 	}
 
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 8/8] cec-compliance: add digital tuner control testing
  2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
                   ` (7 preceding siblings ...)
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 7/8] cec-follower: fix tuner step increment/decrement c0d1n61at3
@ 2019-10-14  4:17 ` c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
  8 siblings, 1 reply; 22+ messages in thread
From: c0d1n61at3 @ 2019-10-14  4:17 UTC (permalink / raw)


tuner_ctl_test() will now test both digital and analog services.  There
are a total of 98 channels, 18 digital and 81 analog with digital
proceeding analog.

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-compliance/cec-test.cpp | 50 +++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/utils/cec-compliance/cec-test.cpp b/utils/cec-compliance/cec-test.cpp
index 1fd0ea92..bc89c317 100644
--- a/utils/cec-compliance/cec-test.cpp
+++ b/utils/cec-compliance/cec-test.cpp
@@ -769,8 +769,11 @@ static int tuner_ctl_test(struct node *node, unsigned me, unsigned la, bool inte
 	for (std::vector<struct cec_op_tuner_device_info>::iterator iter = info_vec.begin();
 			iter != info_vec.end(); iter++) {
 		cec_msg_init(&msg, me, la);
-		cec_msg_select_analogue_service(&msg, iter->analog.ana_bcast_type,
-			iter->analog.ana_freq, iter->analog.bcast_system);
+		if (iter->is_analog)
+			cec_msg_select_analogue_service(&msg, iter->analog.ana_bcast_type,
+				iter->analog.ana_freq, iter->analog.bcast_system);
+		else
+			cec_msg_select_digital_service(&msg, &iter->digital);
 		fail_on_test(!transmit_timeout(node, &msg));
 		fail_on_test(cec_msg_status_is_abort(&msg));
 		cec_msg_init(&msg, me, la);
@@ -784,6 +787,39 @@ static int tuner_ctl_test(struct node *node, unsigned me, unsigned la, bool inte
 			double freq_mhz = (iter->analog.ana_freq * 625) / 10000.0;
 
 			info("Analog channel freq: %.2f MHz\n", freq_mhz);
+		} else {
+			__u8 system = iter->digital.dig_bcast_system;
+
+			switch (system) {
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T: {
+				__u16 tsid = iter->digital.arib.transport_id;
+				__u16 sid = iter->digital.arib.service_id;
+				__u16 onid = iter->digital.arib.orig_network_id;
+
+				info("ARIB digital channel TSID: %u, SID: %u, ONID: %u", tsid, sid, onid);
+				break;
+			}
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: {
+				__u16 tsid = iter->digital.atsc.transport_id;
+				__u16 pn = iter->digital.atsc.program_number;
+
+				info("ATSC digital channel TSID: %u, Program Number: %u", tsid, pn);
+				break;
+			}
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T: {
+				__u16 tsid = iter->digital.dvb.transport_id;
+				__u16 sid = iter->digital.dvb.service_id;
+				__u16 onid = iter->digital.dvb.orig_network_id;
+
+				info("DVB digital channel TSID: %u, SID: %u, ONID: %u", tsid, sid, onid);
+				break;
+			}
+			default:
+				break;
+			}
 		}
 	}
 
@@ -792,6 +828,16 @@ static int tuner_ctl_test(struct node *node, unsigned me, unsigned la, bool inte
 	fail_on_test(!transmit_timeout(node, &msg));
 	fail_on_test(!cec_msg_status_is_abort(&msg));
 	fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
+	cec_msg_init(&msg, me, la);
+	info.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID;
+	info.digital.dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2;
+	info.digital.dvb.transport_id = 0;
+	info.digital.dvb.service_id = 0;
+	info.digital.dvb.orig_network_id = 0;
+	cec_msg_select_digital_service(&msg, &info.digital);
+	fail_on_test(!transmit_timeout(node, &msg));
+	fail_on_test(!cec_msg_status_is_abort(&msg));
+	fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
 
 	return 0;
 }
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 8/8] cec-compliance: add digital tuner control testing
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 8/8] cec-compliance: add digital tuner control testing c0d1n61at3
@ 2019-10-14  4:17   ` Jiunn Chang
  0 siblings, 0 replies; 22+ messages in thread
From: Jiunn Chang @ 2019-10-14  4:17 UTC (permalink / raw)


tuner_ctl_test() will now test both digital and analog services.  There
are a total of 98 channels, 18 digital and 81 analog with digital
proceeding analog.

Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
---
 utils/cec-compliance/cec-test.cpp | 50 +++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/utils/cec-compliance/cec-test.cpp b/utils/cec-compliance/cec-test.cpp
index 1fd0ea92..bc89c317 100644
--- a/utils/cec-compliance/cec-test.cpp
+++ b/utils/cec-compliance/cec-test.cpp
@@ -769,8 +769,11 @@ static int tuner_ctl_test(struct node *node, unsigned me, unsigned la, bool inte
 	for (std::vector<struct cec_op_tuner_device_info>::iterator iter = info_vec.begin();
 			iter != info_vec.end(); iter++) {
 		cec_msg_init(&msg, me, la);
-		cec_msg_select_analogue_service(&msg, iter->analog.ana_bcast_type,
-			iter->analog.ana_freq, iter->analog.bcast_system);
+		if (iter->is_analog)
+			cec_msg_select_analogue_service(&msg, iter->analog.ana_bcast_type,
+				iter->analog.ana_freq, iter->analog.bcast_system);
+		else
+			cec_msg_select_digital_service(&msg, &iter->digital);
 		fail_on_test(!transmit_timeout(node, &msg));
 		fail_on_test(cec_msg_status_is_abort(&msg));
 		cec_msg_init(&msg, me, la);
@@ -784,6 +787,39 @@ static int tuner_ctl_test(struct node *node, unsigned me, unsigned la, bool inte
 			double freq_mhz = (iter->analog.ana_freq * 625) / 10000.0;
 
 			info("Analog channel freq: %.2f MHz\n", freq_mhz);
+		} else {
+			__u8 system = iter->digital.dig_bcast_system;
+
+			switch (system) {
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T: {
+				__u16 tsid = iter->digital.arib.transport_id;
+				__u16 sid = iter->digital.arib.service_id;
+				__u16 onid = iter->digital.arib.orig_network_id;
+
+				info("ARIB digital channel TSID: %u, SID: %u, ONID: %u", tsid, sid, onid);
+				break;
+			}
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: {
+				__u16 tsid = iter->digital.atsc.transport_id;
+				__u16 pn = iter->digital.atsc.program_number;
+
+				info("ATSC digital channel TSID: %u, Program Number: %u", tsid, pn);
+				break;
+			}
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
+			case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T: {
+				__u16 tsid = iter->digital.dvb.transport_id;
+				__u16 sid = iter->digital.dvb.service_id;
+				__u16 onid = iter->digital.dvb.orig_network_id;
+
+				info("DVB digital channel TSID: %u, SID: %u, ONID: %u", tsid, sid, onid);
+				break;
+			}
+			default:
+				break;
+			}
 		}
 	}
 
@@ -792,6 +828,16 @@ static int tuner_ctl_test(struct node *node, unsigned me, unsigned la, bool inte
 	fail_on_test(!transmit_timeout(node, &msg));
 	fail_on_test(!cec_msg_status_is_abort(&msg));
 	fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
+	cec_msg_init(&msg, me, la);
+	info.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID;
+	info.digital.dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2;
+	info.digital.dvb.transport_id = 0;
+	info.digital.dvb.service_id = 0;
+	info.digital.dvb.orig_network_id = 0;
+	cec_msg_select_digital_service(&msg, &info.digital);
+	fail_on_test(!transmit_timeout(node, &msg));
+	fail_on_test(!cec_msg_status_is_abort(&msg));
+	fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
 
 	return 0;
 }
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
@ 2019-10-14  9:19   ` hverkuil
  2019-10-14  9:19     ` Hans Verkuil
  1 sibling, 1 reply; 22+ messages in thread
From: hverkuil @ 2019-10-14  9:19 UTC (permalink / raw)


On 10/14/19 6:17 AM, Jiunn Chang wrote:
> This table will allow proper testing of digital tuner control features.
> There are three channels per TSID/ONID/SID combination along with channel
> data for the following digital ARIB broadcast systems:
>   - ARIB-BS
>   - ARIB-T
> 
> Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
> ---
>  utils/cec-follower/cec-tuner.cpp | 52 ++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
> index 3a71a890..4fd65876 100644
> --- a/utils/cec-follower/cec-tuner.cpp
> +++ b/utils/cec-follower/cec-tuner.cpp
> @@ -9,8 +9,60 @@
>  #include "cec-follower.h"
>  
>  #define NUM_ANALOG_FREQS 3
> +#define NUM_DIGITAL_CHANS 3
>  #define TOT_ANALOG_FREQS (sizeof(analog_freqs_khz) / sizeof(analog_freqs_khz[0][0][0]))
>  
> +struct service_info {
> +	unsigned tsid;
> +	unsigned onid;
> +	unsigned sid;
> +	unsigned fmt;
> +	unsigned major;
> +	unsigned minor;
> +};
> +
> +/*
> + * This table contains the digital television channels for ARIB (ISDB).  There
> + * are a total of three channels that are identified by digital IDs or by
> + * channel.
> + *
> + * CEC 17 of the 1.4 specification lists the available digital identification
> + * methods, IDs, and channel data.
> + *
> + * Digital channel data for ARIB-BS is from:
> + *
> + * https://sichbopvr.com/frequency-tables/19-20E
> + *
> + * No public data was found for ARIB-BS so data is just copied.
> + *
> + * Digital channel data for ARIB-T is from:
> + *
> + * https://sichbopvr.com/frequency-tables/Brazil/Rio%20de%20Janeiro/Rio%20De%20Janeiro
> + */
> +static const struct service_info digital_arib_data[2][1][NUM_DIGITAL_CHANS] =

Just drop the [1] here and in the next two patches. For all bcast systems you just
have one satellite and one terrestrial system, since we decided not to have two
satellite bcast systems.

So we can just cut out the [1] bit since it doesn't really make sense anymore.

Regards,

	Hans

> +{
> +	// satellite
> +	{
> +		// arib-bs
> +		{
> +			// tsid, onid, sid, fmt, major, minor
> +			{ 1032, 1, 30203, 1, 0, 30203 },
> +			{ 1046, 1, 30505, 1, 0, 30505 },
> +			{ 1060, 1, 30609, 1, 0, 30609 }
> +		}
> +	},
> +	// terrestrial
> +	{
> +		// arib-t
> +		{
> +			// tsid, onid, sid, fmt, major, minor
> +			{ 1519, 1519, 48608, 1, 0, 48608 },
> +			{ 1624, 1624, 51992, 1, 0, 51992 },
> +			{ 1905, 1905, 60960, 1, 0, 60960 }
> +		}
> +	}
> +};
> +
>  /*
>   * This table contains analog television channel frequencies in KHz.  There are
>   * a total of three frequencies per analog broadcast type and broadcast system.
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels
  2019-10-14  9:19   ` hverkuil
@ 2019-10-14  9:19     ` Hans Verkuil
  0 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2019-10-14  9:19 UTC (permalink / raw)


On 10/14/19 6:17 AM, Jiunn Chang wrote:
> This table will allow proper testing of digital tuner control features.
> There are three channels per TSID/ONID/SID combination along with channel
> data for the following digital ARIB broadcast systems:
>   - ARIB-BS
>   - ARIB-T
> 
> Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
> ---
>  utils/cec-follower/cec-tuner.cpp | 52 ++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
> index 3a71a890..4fd65876 100644
> --- a/utils/cec-follower/cec-tuner.cpp
> +++ b/utils/cec-follower/cec-tuner.cpp
> @@ -9,8 +9,60 @@
>  #include "cec-follower.h"
>  
>  #define NUM_ANALOG_FREQS 3
> +#define NUM_DIGITAL_CHANS 3
>  #define TOT_ANALOG_FREQS (sizeof(analog_freqs_khz) / sizeof(analog_freqs_khz[0][0][0]))
>  
> +struct service_info {
> +	unsigned tsid;
> +	unsigned onid;
> +	unsigned sid;
> +	unsigned fmt;
> +	unsigned major;
> +	unsigned minor;
> +};
> +
> +/*
> + * This table contains the digital television channels for ARIB (ISDB).  There
> + * are a total of three channels that are identified by digital IDs or by
> + * channel.
> + *
> + * CEC 17 of the 1.4 specification lists the available digital identification
> + * methods, IDs, and channel data.
> + *
> + * Digital channel data for ARIB-BS is from:
> + *
> + * https://sichbopvr.com/frequency-tables/19-20E
> + *
> + * No public data was found for ARIB-BS so data is just copied.
> + *
> + * Digital channel data for ARIB-T is from:
> + *
> + * https://sichbopvr.com/frequency-tables/Brazil/Rio%20de%20Janeiro/Rio%20De%20Janeiro
> + */
> +static const struct service_info digital_arib_data[2][1][NUM_DIGITAL_CHANS] =

Just drop the [1] here and in the next two patches. For all bcast systems you just
have one satellite and one terrestrial system, since we decided not to have two
satellite bcast systems.

So we can just cut out the [1] bit since it doesn't really make sense anymore.

Regards,

	Hans

> +{
> +	// satellite
> +	{
> +		// arib-bs
> +		{
> +			// tsid, onid, sid, fmt, major, minor
> +			{ 1032, 1, 30203, 1, 0, 30203 },
> +			{ 1046, 1, 30505, 1, 0, 30505 },
> +			{ 1060, 1, 30609, 1, 0, 30609 }
> +		}
> +	},
> +	// terrestrial
> +	{
> +		// arib-t
> +		{
> +			// tsid, onid, sid, fmt, major, minor
> +			{ 1519, 1519, 48608, 1, 0, 48608 },
> +			{ 1624, 1624, 51992, 1, 0, 51992 },
> +			{ 1905, 1905, 60960, 1, 0, 60960 }
> +		}
> +	}
> +};
> +
>  /*
>   * This table contains analog television channel frequencies in KHz.  There are
>   * a total of three frequencies per analog broadcast type and broadcast system.
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation
  2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation c0d1n61at3
  2019-10-14  4:17   ` Jiunn Chang
@ 2019-10-14 10:03   ` hverkuil
  2019-10-14 10:03     ` Hans Verkuil
  1 sibling, 1 reply; 22+ messages in thread
From: hverkuil @ 2019-10-14 10:03 UTC (permalink / raw)


On 10/14/19 6:17 AM, Jiunn Chang wrote:
> The cec-follower will now emulate a digital service.  This allows an
> initiator device can directly select a digital service by choosing a
> digital service ID method and broadcast system along with the proper
> digital IDs or channel data.  After a digital service is selected,
> the cec-follower will also provide the tuner device status upon
> request.
> 
> Opcodes implemented:
>   - <Select Digital Service>
> 
> Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
> ---
>  utils/cec-follower/cec-tuner.cpp | 169 +++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
> 
> diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
> index 04e7e4c3..760eed2a 100644
> --- a/utils/cec-follower/cec-tuner.cpp
> +++ b/utils/cec-follower/cec-tuner.cpp
> @@ -244,6 +244,162 @@ void analog_tuner_init(struct state *state)
>  	info->analog.ana_freq = (freq_khz * 10) / 625;
>  }
>  
> +static int digital_get_service_offset(struct cec_op_digital_service_id *digital)
> +{
> +	__u8 method = digital->service_id_method;
> +	struct cec_op_dvb_data *dvb = &digital->dvb;
> +	struct cec_op_atsc_data *atsc = &digital->atsc;
> +	struct cec_op_channel_data *channel = &digital->channel;
> +	unsigned int sys =
> +		(digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T ||
> +		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T ||
> +		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T) ? 1 : 0;
> +
> +	for (int i = 0; i < NUM_DIGITAL_CHANS; i++) {
> +		switch (method) {
> +		case CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID:
> +			if (dvb->transport_id == digital_arib_data[sys][0][i].tsid &&
> +			    dvb->service_id == digital_arib_data[sys][0][i].sid &&
> +			    dvb->orig_network_id == digital_arib_data[sys][0][i].onid) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (atsc->transport_id == digital_atsc_data[sys][0][i].tsid &&
> +			    atsc->program_number == digital_atsc_data[sys][0][i].sid) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (dvb->transport_id == digital_dvb_data[sys][0][i].tsid &&
> +			    dvb->service_id == digital_dvb_data[sys][0][i].sid &&
> +			    dvb->orig_network_id == digital_dvb_data[sys][0][i].onid) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			break;
> +		case CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL:
> +			if (channel->minor == digital_arib_data[sys][0][i].minor) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (channel->major == digital_atsc_data[sys][0][i].major &&
> +			    channel->minor == digital_atsc_data[sys][0][i].minor) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (channel->minor == digital_dvb_data[sys][0][i].minor) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +	return -1;
> +}
> +
> +static int digital_get_service_idx(struct cec_op_digital_service_id *digital)
> +{
> +	__u8 system = digital->dig_bcast_system;
> +	int offset = digital_get_service_offset(digital);
> +
> +	switch (system) {
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
> +		return offset;
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: {
> +		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 2 + offset;
> +	}
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T: {
> +		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 4 + offset;
> +	}
> +	default:
> +		break;
> +	}
> +	return -1;
> +}

This makes no sense: how can you get the offset without first checking which
bcast system to use? You might get a match for e.g. ARIB when the given
bcast system is DVB.

This can be done much easier by something like this:

static int digital_get_service_idx(struct cec_op_digital_service_id *digital)
{
	struct service_info *info;
	bool is_terrestrial = false;
	unsigned offset, idx;

	switch (digital->dig_bcast_system) {
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
		is_terrestrial = true;
		/* fall through */
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
		info = &digital_arib_data[is_terrestrial][0];
		offset = is_terrestrial * NUM_DIGITAL_CHANS;
		break;
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
		is_terrestrial = true;
		/* fall through */
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
		info = &digital_atsc_data[is_terrestrial][0];
		offset = (2 + is_terrestrial) * NUM_DIGITAL_CHANS;
		break;
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T:
		is_terrestrial = true;
		/* fall through */
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
		info = &digital_dvb_data[is_terrestrial][0];
		offset = (4 + is_terrestrial) * NUM_DIGITAL_CHANS;
		break;
	default:
		return -1;
	}
	idx = digital_get_service_offset(info, digital);
	return idx >= 0 ? idx + offset : -1;
}

And digital_get_service_offset() checks the NUM_DIGITAL_CHANS
entries of the info pointer for a possible match and returns 0-2
as index.

> +
> +static void digital_update_tuner_dev_info(struct node *node, unsigned int idx,
> +					  __u8 method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID)

Why add ' = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID'? This function is always called with this
third argument, so there is no need for specifying a default value for method.

> +{
> +	struct cec_op_tuner_device_info *info = &node->state.tuner_dev_info;
> +	struct cec_op_digital_service_id *digital = &info->digital;
> +	struct cec_op_dvb_data *dvb = &digital->dvb;
> +	struct cec_op_atsc_data *atsc = &digital->atsc;

Also add a cec_op_arib_data *arib here.

> +	struct cec_op_channel_data *channel = &digital->channel;
> +	unsigned int tbl = idx / (NUM_DIGITAL_CHANS * 2);
> +	unsigned int sys = (idx % (NUM_DIGITAL_CHANS * 2)) / NUM_DIGITAL_CHANS;
> +	unsigned int offset = idx % NUM_DIGITAL_CHANS;
> +
> +	node->state.service_idx = idx;
> +	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_DIGITAL;
> +	info->is_analog = false;
> +	digital->service_id_method = method;

Ah, this is interesting, I hadn't thought about that.

When you ask a tuner device what the current service it, it will either use
the channel method or the digital ID method, but not both.

This means that the service ID method has to be something that needs to be specified
with an option to cec-follower.

This also leads to another question: if a tuner uses channels, can you still select
a digital service using the digital ID method, or vice versa? In my opinion I would
say that it is one or the other, but that you cannot mix them.

> +	switch (tbl) {
> +	case 0: {
> +		if (sys)
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T;
> +		else
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
> +		if (digital->service_id_method) {
> +			channel->channel_number_fmt = digital_arib_data[sys][0][offset].fmt;
> +			channel->major = digital_arib_data[sys][0][offset].major;
> +			channel->minor = digital_arib_data[sys][0][offset].minor;
> +		} else {
> +			dvb->transport_id = digital_arib_data[sys][0][offset].tsid;
> +			dvb->orig_network_id = digital_arib_data[sys][0][offset].onid;
> +			dvb->service_id = digital_arib_data[sys][0][offset].sid;

Use arib pointer.

> +		}
> +		break;
> +	}
> +	case 1: {
> +		if (sys)
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T;
> +		else
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT;
> +		if (digital->service_id_method) {
> +			channel->channel_number_fmt = digital_atsc_data[sys][0][offset].fmt;
> +			channel->major = digital_atsc_data[sys][0][offset].major;
> +			channel->minor = digital_atsc_data[sys][0][offset].minor;
> +		} else {
> +			atsc->transport_id = digital_atsc_data[sys][0][offset].tsid;
> +			atsc->program_number = digital_atsc_data[sys][0][offset].sid;
> +		}
> +		break;
> +	}
> +	case 2: {
> +		if (sys)
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T;
> +		else
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2;
> +		if (digital->service_id_method) {
> +			channel->channel_number_fmt = digital_dvb_data[sys][0][offset].fmt;
> +			channel->major = digital_dvb_data[sys][0][offset].major;
> +			channel->minor = digital_dvb_data[sys][0][offset].minor;
> +		} else {
> +			dvb->transport_id = digital_dvb_data[sys][0][offset].tsid;
> +			dvb->orig_network_id = digital_dvb_data[sys][0][offset].onid;
> +			dvb->service_id = digital_dvb_data[sys][0][offset].sid;
> +		}
> +		break;
> +	}
> +	default:
> +		break;
> +	}
> +}
> +
> +static bool digital_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
> +{
> +	struct cec_op_digital_service_id digital = {};
> +	__u8 method;
> +	int idx;
> +
> +	cec_ops_select_digital_service(msg, &digital);
> +	method = digital.service_id_method;
> +	idx = digital_get_service_idx(&digital);
> +	if (idx > -1) {
> +		digital_update_tuner_dev_info(node, idx, method);
> +		return true;
> +	}
> +	return false;
> +}
> +
>  static unsigned int analog_get_nearest_service_idx(__u8 ana_bcast_type, __u8 ana_bcast_system,
>  						   int ana_freq_khz)
>  {
> @@ -340,6 +496,19 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
>  		return;
>  
>  	case CEC_MSG_SELECT_DIGITAL_SERVICE:
> +		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
> +			break;
> +
> +		if (node->state.tuner_dev_info.rec_flag == CEC_OP_REC_FLAG_USED) {
> +			reply_feature_abort(node, &msg, CEC_OP_ABORT_REFUSED);
> +			return;
> +		}
> +		if (!digital_set_tuner_dev_info(node, &msg)) {
> +			reply_feature_abort(node, &msg, CEC_OP_ABORT_INVALID_OP);
> +			return;
> +		}
> +		return;
> +
>  	case CEC_MSG_TUNER_STEP_DECREMENT: {
>  		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
>  			break;
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation
  2019-10-14 10:03   ` hverkuil
@ 2019-10-14 10:03     ` Hans Verkuil
  0 siblings, 0 replies; 22+ messages in thread
From: Hans Verkuil @ 2019-10-14 10:03 UTC (permalink / raw)


On 10/14/19 6:17 AM, Jiunn Chang wrote:
> The cec-follower will now emulate a digital service.  This allows an
> initiator device can directly select a digital service by choosing a
> digital service ID method and broadcast system along with the proper
> digital IDs or channel data.  After a digital service is selected,
> the cec-follower will also provide the tuner device status upon
> request.
> 
> Opcodes implemented:
>   - <Select Digital Service>
> 
> Signed-off-by: Jiunn Chang <c0d1n61at3 at gmail.com>
> ---
>  utils/cec-follower/cec-tuner.cpp | 169 +++++++++++++++++++++++++++++++
>  1 file changed, 169 insertions(+)
> 
> diff --git a/utils/cec-follower/cec-tuner.cpp b/utils/cec-follower/cec-tuner.cpp
> index 04e7e4c3..760eed2a 100644
> --- a/utils/cec-follower/cec-tuner.cpp
> +++ b/utils/cec-follower/cec-tuner.cpp
> @@ -244,6 +244,162 @@ void analog_tuner_init(struct state *state)
>  	info->analog.ana_freq = (freq_khz * 10) / 625;
>  }
>  
> +static int digital_get_service_offset(struct cec_op_digital_service_id *digital)
> +{
> +	__u8 method = digital->service_id_method;
> +	struct cec_op_dvb_data *dvb = &digital->dvb;
> +	struct cec_op_atsc_data *atsc = &digital->atsc;
> +	struct cec_op_channel_data *channel = &digital->channel;
> +	unsigned int sys =
> +		(digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T ||
> +		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T ||
> +		 digital->dig_bcast_system == CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T) ? 1 : 0;
> +
> +	for (int i = 0; i < NUM_DIGITAL_CHANS; i++) {
> +		switch (method) {
> +		case CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID:
> +			if (dvb->transport_id == digital_arib_data[sys][0][i].tsid &&
> +			    dvb->service_id == digital_arib_data[sys][0][i].sid &&
> +			    dvb->orig_network_id == digital_arib_data[sys][0][i].onid) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (atsc->transport_id == digital_atsc_data[sys][0][i].tsid &&
> +			    atsc->program_number == digital_atsc_data[sys][0][i].sid) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (dvb->transport_id == digital_dvb_data[sys][0][i].tsid &&
> +			    dvb->service_id == digital_dvb_data[sys][0][i].sid &&
> +			    dvb->orig_network_id == digital_dvb_data[sys][0][i].onid) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			break;
> +		case CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL:
> +			if (channel->minor == digital_arib_data[sys][0][i].minor) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (channel->major == digital_atsc_data[sys][0][i].major &&
> +			    channel->minor == digital_atsc_data[sys][0][i].minor) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			if (channel->minor == digital_dvb_data[sys][0][i].minor) {
> +				return (sys * NUM_DIGITAL_CHANS) + i;
> +			}
> +			break;
> +		default:
> +			break;
> +		}
> +	}
> +	return -1;
> +}
> +
> +static int digital_get_service_idx(struct cec_op_digital_service_id *digital)
> +{
> +	__u8 system = digital->dig_bcast_system;
> +	int offset = digital_get_service_offset(digital);
> +
> +	switch (system) {
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
> +		return offset;
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: {
> +		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 2 + offset;
> +	}
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
> +	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T: {
> +		return offset == -1 ? offset : NUM_DIGITAL_CHANS * 4 + offset;
> +	}
> +	default:
> +		break;
> +	}
> +	return -1;
> +}

This makes no sense: how can you get the offset without first checking which
bcast system to use? You might get a match for e.g. ARIB when the given
bcast system is DVB.

This can be done much easier by something like this:

static int digital_get_service_idx(struct cec_op_digital_service_id *digital)
{
	struct service_info *info;
	bool is_terrestrial = false;
	unsigned offset, idx;

	switch (digital->dig_bcast_system) {
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
		is_terrestrial = true;
		/* fall through */
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
		info = &digital_arib_data[is_terrestrial][0];
		offset = is_terrestrial * NUM_DIGITAL_CHANS;
		break;
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
		is_terrestrial = true;
		/* fall through */
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
		info = &digital_atsc_data[is_terrestrial][0];
		offset = (2 + is_terrestrial) * NUM_DIGITAL_CHANS;
		break;
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T:
		is_terrestrial = true;
		/* fall through */
	case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
		info = &digital_dvb_data[is_terrestrial][0];
		offset = (4 + is_terrestrial) * NUM_DIGITAL_CHANS;
		break;
	default:
		return -1;
	}
	idx = digital_get_service_offset(info, digital);
	return idx >= 0 ? idx + offset : -1;
}

And digital_get_service_offset() checks the NUM_DIGITAL_CHANS
entries of the info pointer for a possible match and returns 0-2
as index.

> +
> +static void digital_update_tuner_dev_info(struct node *node, unsigned int idx,
> +					  __u8 method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID)

Why add ' = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID'? This function is always called with this
third argument, so there is no need for specifying a default value for method.

> +{
> +	struct cec_op_tuner_device_info *info = &node->state.tuner_dev_info;
> +	struct cec_op_digital_service_id *digital = &info->digital;
> +	struct cec_op_dvb_data *dvb = &digital->dvb;
> +	struct cec_op_atsc_data *atsc = &digital->atsc;

Also add a cec_op_arib_data *arib here.

> +	struct cec_op_channel_data *channel = &digital->channel;
> +	unsigned int tbl = idx / (NUM_DIGITAL_CHANS * 2);
> +	unsigned int sys = (idx % (NUM_DIGITAL_CHANS * 2)) / NUM_DIGITAL_CHANS;
> +	unsigned int offset = idx % NUM_DIGITAL_CHANS;
> +
> +	node->state.service_idx = idx;
> +	info->tuner_display_info = CEC_OP_TUNER_DISPLAY_INFO_DIGITAL;
> +	info->is_analog = false;
> +	digital->service_id_method = method;

Ah, this is interesting, I hadn't thought about that.

When you ask a tuner device what the current service it, it will either use
the channel method or the digital ID method, but not both.

This means that the service ID method has to be something that needs to be specified
with an option to cec-follower.

This also leads to another question: if a tuner uses channels, can you still select
a digital service using the digital ID method, or vice versa? In my opinion I would
say that it is one or the other, but that you cannot mix them.

> +	switch (tbl) {
> +	case 0: {
> +		if (sys)
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T;
> +		else
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
> +		if (digital->service_id_method) {
> +			channel->channel_number_fmt = digital_arib_data[sys][0][offset].fmt;
> +			channel->major = digital_arib_data[sys][0][offset].major;
> +			channel->minor = digital_arib_data[sys][0][offset].minor;
> +		} else {
> +			dvb->transport_id = digital_arib_data[sys][0][offset].tsid;
> +			dvb->orig_network_id = digital_arib_data[sys][0][offset].onid;
> +			dvb->service_id = digital_arib_data[sys][0][offset].sid;

Use arib pointer.

> +		}
> +		break;
> +	}
> +	case 1: {
> +		if (sys)
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T;
> +		else
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT;
> +		if (digital->service_id_method) {
> +			channel->channel_number_fmt = digital_atsc_data[sys][0][offset].fmt;
> +			channel->major = digital_atsc_data[sys][0][offset].major;
> +			channel->minor = digital_atsc_data[sys][0][offset].minor;
> +		} else {
> +			atsc->transport_id = digital_atsc_data[sys][0][offset].tsid;
> +			atsc->program_number = digital_atsc_data[sys][0][offset].sid;
> +		}
> +		break;
> +	}
> +	case 2: {
> +		if (sys)
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T;
> +		else
> +			digital->dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2;
> +		if (digital->service_id_method) {
> +			channel->channel_number_fmt = digital_dvb_data[sys][0][offset].fmt;
> +			channel->major = digital_dvb_data[sys][0][offset].major;
> +			channel->minor = digital_dvb_data[sys][0][offset].minor;
> +		} else {
> +			dvb->transport_id = digital_dvb_data[sys][0][offset].tsid;
> +			dvb->orig_network_id = digital_dvb_data[sys][0][offset].onid;
> +			dvb->service_id = digital_dvb_data[sys][0][offset].sid;
> +		}
> +		break;
> +	}
> +	default:
> +		break;
> +	}
> +}
> +
> +static bool digital_set_tuner_dev_info(struct node *node, struct cec_msg *msg)
> +{
> +	struct cec_op_digital_service_id digital = {};
> +	__u8 method;
> +	int idx;
> +
> +	cec_ops_select_digital_service(msg, &digital);
> +	method = digital.service_id_method;
> +	idx = digital_get_service_idx(&digital);
> +	if (idx > -1) {
> +		digital_update_tuner_dev_info(node, idx, method);
> +		return true;
> +	}
> +	return false;
> +}
> +
>  static unsigned int analog_get_nearest_service_idx(__u8 ana_bcast_type, __u8 ana_bcast_system,
>  						   int ana_freq_khz)
>  {
> @@ -340,6 +496,19 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
>  		return;
>  
>  	case CEC_MSG_SELECT_DIGITAL_SERVICE:
> +		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
> +			break;
> +
> +		if (node->state.tuner_dev_info.rec_flag == CEC_OP_REC_FLAG_USED) {
> +			reply_feature_abort(node, &msg, CEC_OP_ABORT_REFUSED);
> +			return;
> +		}
> +		if (!digital_set_tuner_dev_info(node, &msg)) {
> +			reply_feature_abort(node, &msg, CEC_OP_ABORT_INVALID_OP);
> +			return;
> +		}
> +		return;
> +
>  	case CEC_MSG_TUNER_STEP_DECREMENT: {
>  		if (!cec_has_tuner(1 << me) && !cec_has_tv(1 << me))
>  			break;
> 

Regards,

	Hans

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2019-10-14 10:03 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-14  4:17 [Linux-kernel-mentees] [PATCH 0/8] cec-compliance: add digital tuner support c0d1n61at3
2019-10-14  4:17 ` Jiunn Chang
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 1/8] cec-follower: fix analog tuner device info update c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 2/8] cec-follower: rename freq_idx to service_idx c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 3/8] cec-follower: create digital ARIB channels c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang
2019-10-14  9:19   ` hverkuil
2019-10-14  9:19     ` Hans Verkuil
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 4/8] cec-follower: create digital ATSC channels c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 5/8] cec-follower: create digital DVB channels c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 6/8] cec-follower: add tuner digital service emulation c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang
2019-10-14 10:03   ` hverkuil
2019-10-14 10:03     ` Hans Verkuil
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 7/8] cec-follower: fix tuner step increment/decrement c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang
2019-10-14  4:17 ` [Linux-kernel-mentees] [PATCH 8/8] cec-compliance: add digital tuner control testing c0d1n61at3
2019-10-14  4:17   ` Jiunn Chang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).