#include #include #include #include #include #include "edid.h" #include "info.h" #include "log.h" #include "memory-stream.h" /* Generated file pnp-id-table.c: */ const char * pnp_id_table(const char *key); struct di_info * di_info_parse_edid(const void *data, size_t size) { struct memory_stream failure_msg; struct di_edid *edid; struct di_info *info; char *failure_msg_str = NULL; if (!memory_stream_open(&failure_msg)) return NULL; edid = _di_edid_parse(data, size, failure_msg.fp); if (!edid) goto err_failure_msg_file; info = calloc(1, sizeof(*info)); if (!info) goto err_edid; info->edid = edid; failure_msg_str = memory_stream_close(&failure_msg); if (failure_msg_str && failure_msg_str[0] != '\0') info->failure_msg = failure_msg_str; else free(failure_msg_str); return info; err_edid: _di_edid_destroy(edid); err_failure_msg_file: memory_stream_cleanup(&failure_msg); return NULL; } void di_info_destroy(struct di_info *info) { _di_edid_destroy(info->edid); free(info->failure_msg); free(info); } const struct di_edid * di_info_get_edid(const struct di_info *info) { return info->edid; } const char * di_info_get_failure_msg(const struct di_info *info) { return info->failure_msg; } static void encode_ascii_byte(FILE *out, char ch) { uint8_t c = (uint8_t)ch; /* * Replace ASCII control codes and non-7-bit codes * with an escape string. The result is guaranteed to be valid * UTF-8. */ if (c < 0x20 || c >= 0x7f) fprintf(out, "\\x%02x", c); else fputc(c, out); } static void encode_ascii_string(FILE *out, const char *str) { size_t len = strlen(str); size_t i; for (i = 0; i < len; i++) encode_ascii_byte(out, str[i]); } char * di_info_get_make(const struct di_info *info) { const struct di_edid_vendor_product *evp; char pnp_id[(sizeof(evp->manufacturer)) + 1] = { 0, }; const char *manuf; struct memory_stream m; if (!info->edid) return NULL; if (!memory_stream_open(&m)) return NULL; evp = di_edid_get_vendor_product(info->edid); memcpy(pnp_id, evp->manufacturer, sizeof(evp->manufacturer)); manuf = pnp_id_table(pnp_id); if (manuf) { encode_ascii_string(m.fp, manuf); return memory_stream_close(&m); } fputs("PNP(", m.fp); encode_ascii_string(m.fp, pnp_id); fputs(")", m.fp); return memory_stream_close(&m); } char * di_info_get_model(const struct di_info *info) { const struct di_edid_vendor_product *evp; const struct di_edid_display_descriptor *const *desc; struct memory_stream m; size_t i; enum di_edid_display_descriptor_tag tag; const char *str; if (!info->edid) return NULL; if (!memory_stream_open(&m)) return NULL; desc = di_edid_get_display_descriptors(info->edid); for (i = 0; desc[i]; i++) { tag = di_edid_display_descriptor_get_tag(desc[i]); if (tag != DI_EDID_DISPLAY_DESCRIPTOR_PRODUCT_NAME) continue; str = di_edid_display_descriptor_get_string(desc[i]); if (str[0] == '\0') continue; encode_ascii_string(m.fp, str); return memory_stream_close(&m); } evp = di_edid_get_vendor_product(info->edid); fprintf(m.fp, "0x%04" PRIX16, evp->product); return memory_stream_close(&m); } char * di_info_get_serial(const struct di_info *info) { const struct di_edid_display_descriptor *const *desc; const struct di_edid_vendor_product *evp; struct memory_stream m; size_t i; enum di_edid_display_descriptor_tag tag; const char *str; if (!info->edid) return NULL; if (!memory_stream_open(&m)) return NULL; desc = di_edid_get_display_descriptors(info->edid); for (i = 0; desc[i]; i++) { tag = di_edid_display_descriptor_get_tag(desc[i]); if (tag != DI_EDID_DISPLAY_DESCRIPTOR_PRODUCT_SERIAL) continue; str = di_edid_display_descriptor_get_string(desc[i]); if (str[0] == '\0') continue; encode_ascii_string(m.fp, str); return memory_stream_close(&m); } evp = di_edid_get_vendor_product(info->edid); if (evp->serial != 0) { fprintf(m.fp, "0x%08" PRIX32, evp->serial); return memory_stream_close(&m); } memory_stream_cleanup(&m); return NULL; }