aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-08-19 01:27:30 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-08-22 23:10:17 +0200
commit64b19e4986f1f2233fd16d1252dc19a2014a1116 (patch)
tree312cf383f1f128ed7552769253ffe6845abf0aa3
parent4a33434d40bb9b3d4d36fb65c80f36dfa492daf6 (diff)
monitors: speakers and SADs
Signed-off-by: Burt P <pburt0@gmail.com>
-rw-r--r--deps/sysobj_early/include/util_edid.h34
-rw-r--r--deps/sysobj_early/src/util_edid.c185
-rw-r--r--modules/devices/monitors.c21
3 files changed, 147 insertions, 93 deletions
diff --git a/deps/sysobj_early/include/util_edid.h b/deps/sysobj_early/include/util_edid.h
index 4efee6b3..b50dcb33 100644
--- a/deps/sysobj_early/include/util_edid.h
+++ b/deps/sysobj_early/include/util_edid.h
@@ -54,30 +54,21 @@ struct edid_svd {
edid_output out;
};
-struct edid_cea_header {
- uint8_t *ptr;
- int type, len;
-};
-
-struct edid_cea_block {
- struct edid_cea_header header;
- int reserved[8];
-};
-
-struct edid_cea_audio {
- struct edid_cea_header header;
+struct edid_sad {
+ uint8_t v[3];
int format, channels, freq_bits;
int depth_bits; /* format 1 */
int max_kbps; /* formats 2-8 */
};
-struct edid_cea_vendor_spec {
- struct edid_cea_header header;
+struct edid_cea_header {
+ uint8_t *ptr;
+ int type, len;
};
-struct edid_cea_speaker {
+struct edid_cea_block {
struct edid_cea_header header;
- int alloc_bits;
+ int reserved[8];
};
typedef struct {
@@ -109,11 +100,14 @@ typedef struct {
int dtd_count;
struct edid_dtd *dtds;
+ int cea_block_count;
+ struct edid_cea_block *cea_blocks;
+
int svd_count;
struct edid_svd *svds;
- int cea_block_count;
- struct edid_cea_block *cea_blocks;
+ int sad_count;
+ struct edid_sad *sads;
char ven[4];
int d_type[4];
@@ -132,6 +126,8 @@ typedef struct {
int week, year;
edid_output img;
edid_output img_max;
+ int speaker_alloc_bits;
+
} edid;
edid *edid_new(const char *data, unsigned int len);
edid *edid_new_from_hex(const char *hex_string);
@@ -149,6 +145,8 @@ const char *edid_cea_audio_type(int type);
char *edid_output_describe(edid_output *out);
char *edid_dtd_describe(struct edid_dtd *dtd, int dump_bytes);
char *edid_cea_block_describe(struct edid_cea_block *blk);
+char *edid_cea_audio_describe(struct edid_sad *sad);
+char *edid_cea_speaker_allocation_describe(int bitfield, int short_version);
char *edid_dump2(edid *e);
diff --git a/deps/sysobj_early/src/util_edid.c b/deps/sysobj_early/src/util_edid.c
index 936744e0..7c9f9a05 100644
--- a/deps/sysobj_early/src/util_edid.c
+++ b/deps/sysobj_early/src/util_edid.c
@@ -53,28 +53,37 @@ char *hex_bytes(uint8_t *bytes, int count) {
return buffer;
}
-static void cea_block_decode(struct edid_cea_block *blk) {
- struct edid_cea_audio *blk_audio = (void*)blk;
- struct edid_cea_speaker *blk_speaker = (void*)blk;
- //struct edid_cea_vendor_spec *blk_vendor_spec = (void*)blk;
+static void cea_block_decode(struct edid_cea_block *blk, edid *e) {
+ int i;
if (blk) {
switch(blk->header.type) {
- case 0x1:
- blk_audio->format = (blk->header.ptr[1] & 0x78) >> 3;
- blk_audio->channels = 1 + blk->header.ptr[1] & 0x7;
- blk_audio->freq_bits = blk->header.ptr[2];
- if (blk_audio->format == 1) {
- blk_audio->depth_bits = blk->header.ptr[3];
- } else if (blk_audio->format >= 2
- && blk_audio->format <= 8) {
- blk_audio->max_kbps = blk->header.ptr[3] * 8;
+ case 0x1: /* SADS */
+ for(i = 1; i <= blk->header.len; i+=3) {
+ struct edid_sad *sad = &e->sads[e->sad_count];
+ sad->v[0] = blk->header.ptr[i];
+ sad->v[1] = blk->header.ptr[i+1];
+ sad->v[2] = blk->header.ptr[i+2];
+ sad->format = (sad->v[0] & 0x78) >> 3;
+ sad->channels = 1 + sad->v[0] & 0x7;
+ sad->freq_bits = sad->v[1];
+ if (sad->format == 1) {
+ sad->depth_bits = sad->v[2];
+ } else if (sad->format >= 2
+ && sad->format <= 8) {
+ sad->max_kbps = 8 * sad->v[2];
+ }
+ e->sad_count++;
}
break;
- case 0x4:
- blk_speaker->alloc_bits = blk->header.ptr[1];
+ case 0x4: /* Speaker allocation */
+ e->speaker_alloc_bits = blk->header.ptr[1];
+ break;
+ case 0x2: /* SVDs */
+ for(i = 1; i <= blk->header.len; i++)
+ e->svds[e->svd_count++].v = blk->header.ptr[i];
break;
- case 0x3:
- case 0x2: /* SVD list is handled elsewhere */
+ case 0x3: /* Vendor-specific */
+ // TODO:
default:
break;
}
@@ -154,9 +163,11 @@ edid *edid_new(const char *data, unsigned int len) {
e->dtds = malloc(sizeof(struct edid_dtd) * 1000);
e->cea_blocks = malloc(sizeof(struct edid_cea_block) * 1000);
e->svds = malloc(sizeof(struct edid_svd) * 1000);
+ e->sads = malloc(sizeof(struct edid_sad) * 1000);
memset(e->dtds, 0, sizeof(struct edid_dtd) * 1000);
memset(e->cea_blocks, 0, sizeof(struct edid_cea_block) * 1000);
memset(e->svds, 0, sizeof(struct edid_svd) * 1000);
+ memset(e->sads, 0, sizeof(struct edid_sad) * 1000);
uint16_t vid = be16toh(e->u16[4]); /* bytes 8-9 */
e->ven[2] = 64 + (vid & 0x1f);
@@ -305,11 +316,7 @@ edid *edid_new(const char *data, unsigned int len) {
e->cea_blocks[e->cea_block_count].header.ptr = &u8[b];
e->cea_blocks[e->cea_block_count].header.type = db_type;
e->cea_blocks[e->cea_block_count].header.len = db_size;
- if (db_type == 0x2) {
- for(i = 1; i <= db_size; i++)
- e->svds[e->svd_count++].v = u8[b+i];
- } else
- cea_block_decode(&e->cea_blocks[e->cea_block_count]);
+ cea_block_decode(&e->cea_blocks[e->cea_block_count], e);
e->cea_block_count++;
b += db_size + 1;
}
@@ -442,6 +449,13 @@ edid *edid_new(const char *data, unsigned int len) {
} else {
e->svds = realloc(e->svds, sizeof(struct edid_svd) * e->svd_count);
}
+ if (!e->sad_count) {
+ if (e->sads)
+ free(e->sads);
+ e->sads = NULL;
+ } else {
+ e->sads = realloc(e->sads, sizeof(struct edid_sad) * e->sad_count);
+ }
return e;
}
@@ -635,72 +649,81 @@ const char *edid_descriptor_type(int type) {
return N_("detailed timing descriptor");
}
+char *edid_cea_audio_describe(struct edid_sad *sad) {
+ if (!sad) return NULL;
+
+ if (!sad->format)
+ return g_strdup_printf("format:([%x] %s)",
+ sad->format, _(edid_cea_audio_type(sad->format)) );
+
+ gchar *ret = NULL;
+ gchar *tmp[3] = {};
+#define appfreq(b, f) if (sad->freq_bits & (1 << b)) tmp[0] = appf(tmp[0], ", ", "%d", f);
+#define appdepth(b, d) if (sad->depth_bits & (1 << b)) tmp[1] = appf(tmp[1], ", ", "%d%s", d, _("-bit"));
+ appfreq(0, 32);
+ appfreq(1, 44);
+ appfreq(2, 48);
+ appfreq(3, 88);
+ appfreq(4, 96);
+ appfreq(5, 176);
+ appfreq(6, 192);
+
+ if (sad->format == 1) {
+ appdepth(0, 16);
+ appdepth(1, 20);
+ appdepth(2, 24);
+ tmp[2] = g_strdup_printf("depths: %s", tmp[1]);
+ } else if (sad->format >= 2
+ && sad->format <= 8 ) {
+ tmp[2] = g_strdup_printf("max_bitrate: %d %s", sad->max_kbps, _("kbps"));
+ } else
+ tmp[2] = g_strdup("");
+
+ ret = g_strdup_printf("format:([%x] %s) channels:%d rates:%s %s %s",
+ sad->format, _(edid_cea_audio_type(sad->format)),
+ sad->channels, tmp[0], _("kHz"),
+ tmp[2]);
+ g_free(tmp[0]);
+ g_free(tmp[1]);
+ g_free(tmp[2]);
+ return ret;
+}
+
+char *edid_cea_speaker_allocation_describe(int bitfield, int short_version) {
+ gchar *spk_list = NULL;
+#define appspk(b, sv, fv) if (bitfield & (1 << b)) \
+ spk_list = appf(spk_list, short_version ? ", " : "\n", "%s", short_version ? sv : fv);
+
+ appspk(0, "FL+FR", _("Front left and right"));
+ appspk(1, "LFE", _("Low-frequency effects"));
+ appspk(2, "FC", _("Front center"));
+ appspk(3, "RL+RR", _("Rear left and right"));
+ appspk(4, "RC", _("Rear center"));
+ appspk(5, "???", _(""));
+ appspk(6, "???", _(""));
+
+ return spk_list;
+}
+
char *edid_cea_block_describe(struct edid_cea_block *blk) {
gchar *ret = NULL;
gchar *tmp[3] = {};
- struct edid_cea_audio *blk_audio = (void*)blk;
- struct edid_cea_speaker *blk_speaker = (void*)blk;
- //struct edid_cea_vendor_spec *blk_vendor_spec = (void*)blk;
if (blk) {
char *hb = hex_bytes(blk->header.ptr, blk->header.len+1);
switch(blk->header.type) {
- case 0x1:
-
-#define appfreq(b, f) if (blk_audio->freq_bits & (1 << b)) tmp[0] = appf(tmp[0], ", ", "%d", f);
-#define appdepth(b, d) if (blk_audio->depth_bits & (1 << b)) tmp[1] = appf(tmp[1], ", ", "%d%s", d, _("-bit"));
- appfreq(0, 32);
- appfreq(1, 44);
- appfreq(2, 48);
- appfreq(3, 88);
- appfreq(4, 96);
- appfreq(5, 176);
- appfreq(6, 192);
-
- if (blk_audio->format == 1) {
- appdepth(0, 16);
- appdepth(1, 20);
- appdepth(2, 24);
- tmp[2] = g_strdup_printf("depths: %s", tmp[1]);
- } else if (blk_audio->format >= 2
- && blk_audio->format <= 8 ) {
- tmp[2] = g_strdup_printf("max_bitrate: %d %s", blk_audio->max_kbps, _("kbps"));
- } else
- tmp[2] = g_strdup("");
-
- ret = g_strdup_printf("([%x] %s) len:%d format:([%x] %s) channels:%d rates:%s %s %s -- %s",
- blk->header.type, _(edid_cea_block_type(blk->header.type)),
- blk->header.len,
- blk_audio->format, _(edid_cea_audio_type(blk_audio->format)),
- blk_audio->channels, tmp[0], _("kHz"),
- tmp[2],
- hb);
- g_free(tmp[0]);
- g_free(tmp[1]);
- g_free(tmp[2]);
- break;
- case 0x4:
-#define appspk(b, s) if (blk_speaker->alloc_bits & (1 << b)) tmp[0] = appf(tmp[0], ", ", "%s", s);
- appspk(0, _("LF+LR: Front left and right"));
- appspk(1, _("LFE: Low-frequency effects"));
- appspk(2, _("FC: Front center"));
- appspk(3, _("LR+LR: Rear left and right"));
- appspk(4, _("RC: Rear center"));
- appspk(5, _("???"));
- appspk(6, _("???"));
- ret = g_strdup_printf("([%x] %s) len:%d %s -- %s",
+ case 0x1: /* SAD list */
+ ret = g_strdup_printf("([%x] %s) sads:%d",
blk->header.type, _(edid_cea_block_type(blk->header.type)),
- blk->header.len,
- tmp[0],
- hb);
- g_free(tmp[0]);
+ blk->header.len/3);
break;
- case 0x2:
+ case 0x2: /* SVD list */
ret = g_strdup_printf("([%x] %s) svds:%d",
blk->header.type, _(edid_cea_block_type(blk->header.type)),
blk->header.len);
break;
case 0x3: //TODO
+ case 0x4:
default:
ret = g_strdup_printf("([%x] %s) len:%d -- %s",
blk->header.type, _(edid_cea_block_type(blk->header.type)),
@@ -772,6 +795,12 @@ char *edid_dump2(edid *e) {
g_free(desc);
g_free(desc_max);
+ if (e->speaker_alloc_bits) {
+ char *desc = edid_cea_speaker_allocation_describe(e->speaker_alloc_bits, 1);
+ ret = appfnl(ret, "speakers: %s", desc);
+ g_free(desc);
+ }
+
for(i = 0; i < e->etb_count; i++) {
char *desc = edid_output_describe(&e->etbs[i]);
ret = appfnl(ret, "etb[%d]: %s", i, desc);
@@ -817,6 +846,14 @@ char *edid_dump2(edid *e) {
free(desc);
}
+ for(i = 0; i < e->sad_count; i++) {
+ char *desc = edid_cea_audio_describe(&e->sads[i]);
+ ret = appfnl(ret, "sad[%d] [%02x%02x%02x] %s", i,
+ e->sads[i].v[0], e->sads[i].v[1], e->sads[i].v[2],
+ desc);
+ free(desc);
+ }
+
return ret;
}
diff --git a/modules/devices/monitors.c b/modules/devices/monitors.c
index 37093b31..f7ec6b00 100644
--- a/modules/devices/monitors.c
+++ b/modules/devices/monitors.c
@@ -179,7 +179,7 @@ static gchar *make_edid_section(monitor *m) {
const gchar *iface = e->interface ? _(edid_interface(e->interface)) : _("(Unspecified)");
gchar *d_list, *ext_list, *dtd_list, *cea_list,
- *etb_list, *std_list, *svd_list;
+ *etb_list, *std_list, *svd_list, *sad_list;
etb_list = NULL;
for(i = 0; i < e->etb_count; i++) {
@@ -236,6 +236,20 @@ static gchar *make_edid_section(monitor *m) {
}
if (!svd_list) svd_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+ sad_list = NULL;
+ for(i = 0; i < e->sad_count; i++) {
+ char *desc = edid_cea_audio_describe(&e->sads[i]);
+ sad_list = appfnl(sad_list, "sad%d=%s", i, desc);
+ g_free(desc);
+ }
+ if (!sad_list) sad_list = g_strdup_printf("%s=\n", _("(Empty List)"));
+
+ gchar *speakers = NULL;
+ if (e->speaker_alloc_bits)
+ speakers = edid_cea_speaker_allocation_describe(e->speaker_alloc_bits, 0);
+ else
+ speakers = g_strdup(_("(Unspecified)"));
+
gchar *hex = edid_dump_hex(e, 0, 1);
gchar *hex_esc = gg_key_file_parse_string_as_value(hex, '|');
g_free(hex);
@@ -250,6 +264,7 @@ static gchar *make_edid_section(monitor *m) {
"%s=%s\n" /* sig type */
"%s=[%x] %s\n" /* interface */
"%s=%s\n" /* bpcc */
+ "%s=%s\n" /* speakers */
"[%s]\n"
"%s=%s\n" /* base out */
"%s=%s\n" /* ext out */
@@ -272,11 +287,13 @@ static gchar *make_edid_section(monitor *m) {
"[%s]\n%s\n"
"[%s]\n%s\n"
"[%s]\n%s\n"
+ "[%s]\n%s\n"
"[%s]\n%s=%s\n"
,
_("Signal Type"), e->a_or_d ? _("Digital") : _("Analog"),
_("Interface"), e->interface, iface,
_("Bits per Color Channel"), UNSPECIFNULL2(bpcc),
+ _("Speaker Allocation"), speakers,
_("Output (Max)"),
edid_output_src(e->img.src), edid_output_describe(&e->img),
edid_output_src(e->img_max.src), edid_output_describe(&e->img_max),
@@ -298,6 +315,7 @@ static gchar *make_edid_section(monitor *m) {
_("Standard Timings (STD)"), std_list,
_("E-EDID Extension Blocks"), ext_list,
_("EIA/CEA-861 Data Blocks"), cea_list,
+ _("EIA/CEA-861 Short Audio Descriptors"), sad_list,
_("EIA/CEA-861 Short Video Descriptors"), svd_list,
_("Hex Dump"), _("Data"), hex
);
@@ -310,6 +328,7 @@ static gchar *make_edid_section(monitor *m) {
g_free(std_list);
g_free(dtd_list);
g_free(cea_list);
+ g_free(sad_list);
g_free(svd_list);
g_free(hex);
//printf("ret: %s\n", ret);