|
@ -86,6 +86,36 @@ typedef struct __attribute__ (( packed )) { |
|
|
} features; |
|
|
} features; |
|
|
} detailed_timing_descriptor_t; |
|
|
} detailed_timing_descriptor_t; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct __attribute__ (( packed )) { |
|
|
|
|
|
uint16_t display_descriptor; |
|
|
|
|
|
uint8_t reserved; |
|
|
|
|
|
uint8_t display_range_limits_descriptor; |
|
|
|
|
|
struct __attribute__ (( packed )) { |
|
|
|
|
|
uint8_t vertical :2; |
|
|
|
|
|
uint8_t horizontal :2; |
|
|
|
|
|
uint8_t reserved :4; |
|
|
|
|
|
} rate_offsets; |
|
|
|
|
|
struct __attribute__ (( packed )) { |
|
|
|
|
|
uint8_t minimum; |
|
|
|
|
|
uint8_t maximum; |
|
|
|
|
|
} vertical_field_rate; |
|
|
|
|
|
struct __attribute__ (( packed )) { |
|
|
|
|
|
uint8_t minimum; |
|
|
|
|
|
uint8_t maximum; |
|
|
|
|
|
} horizontal_line_rate; |
|
|
|
|
|
uint8_t maximum_pixel_clock_mhz; // In 10 MHz units
|
|
|
|
|
|
uint8_t extended_timing_information_type; |
|
|
|
|
|
uint8_t video_timing_params[7]; |
|
|
|
|
|
} range_limits_descriptor_t; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct __attribute__ (( packed )) { |
|
|
|
|
|
uint16_t display_descriptor; |
|
|
|
|
|
uint8_t reserved0; |
|
|
|
|
|
uint8_t descriptor_type; |
|
|
|
|
|
uint8_t reserved1; |
|
|
|
|
|
uint8_t descriptor_data[13]; |
|
|
|
|
|
} display_descriptor_t; |
|
|
|
|
|
|
|
|
typedef struct __attribute__ (( packed )) { |
|
|
typedef struct __attribute__ (( packed )) { |
|
|
/*! Header information, 20 bytes */ |
|
|
/*! Header information, 20 bytes */ |
|
|
struct __attribute__ (( packed )) { |
|
|
struct __attribute__ (( packed )) { |
|
@ -178,13 +208,10 @@ typedef struct __attribute__ (( packed )) { |
|
|
/*! Standard timing information. Up to 8 2-byte fields describing standard
|
|
|
/*! Standard timing information. Up to 8 2-byte fields describing standard
|
|
|
display modes. Unused fields are filled with 01 01 hex. 16 bytes */ |
|
|
display modes. Unused fields are filled with 01 01 hex. 16 bytes */ |
|
|
standard_timing_information_t timings[8]; |
|
|
standard_timing_information_t timings[8]; |
|
|
/* uint8_t descriptor_1[18];
|
|
|
|
|
|
uint8_t descriptor_2[18]; |
|
|
|
|
|
uint8_t descriptor_3[18]; |
|
|
|
|
|
uint8_t descriptor_4[18]; |
|
|
|
|
|
*/ |
|
|
|
|
|
detailed_timing_descriptor_t detailed_timing_descriptor; |
|
|
detailed_timing_descriptor_t detailed_timing_descriptor; |
|
|
detailed_timing_descriptor_t descriptors[3]; |
|
|
range_limits_descriptor_t range_limits_descriptor; |
|
|
|
|
|
display_descriptor_t display_name_descriptor; |
|
|
|
|
|
display_descriptor_t display_serial_number_descriptor; |
|
|
uint8_t number_extensions; |
|
|
uint8_t number_extensions; |
|
|
uint8_t checksum; |
|
|
uint8_t checksum; |
|
|
} edid_t; |
|
|
} edid_t; |
|
@ -791,8 +818,6 @@ static int generate_detailed_timing_descriptor( |
|
|
&multi_use_int); |
|
|
&multi_use_int); |
|
|
edid->detailed_timing_descriptor |
|
|
edid->detailed_timing_descriptor |
|
|
.vertical_border_lines = 0xFF & multi_use_int; |
|
|
.vertical_border_lines = 0xFF & multi_use_int; |
|
|
#define PETER |
|
|
|
|
|
#ifdef PETER |
|
|
|
|
|
// Sync features bitmap
|
|
|
// Sync features bitmap
|
|
|
json_scanf( json_str, json_len, |
|
|
json_scanf( json_str, json_len, |
|
|
"{detailed_timing_descriptor: {stereo_mode: %Q}}", |
|
|
"{detailed_timing_descriptor: {stereo_mode: %Q}}", |
|
@ -847,7 +872,122 @@ static int generate_detailed_timing_descriptor( |
|
|
features in detailed timing descriptor.\n"); |
|
|
features in detailed timing descriptor.\n"); |
|
|
return 1; |
|
|
return 1; |
|
|
} |
|
|
} |
|
|
#endif |
|
|
} else { |
|
|
|
|
|
printf("Error: One of either edid or json_str is NULL.\n"); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int generate_range_limit_descriptor( |
|
|
|
|
|
edid_t* edid, |
|
|
|
|
|
unsigned char* json_str, |
|
|
|
|
|
size_t json_len) |
|
|
|
|
|
{ |
|
|
|
|
|
char* multi_use_str; |
|
|
|
|
|
unsigned multi_use_int; |
|
|
|
|
|
|
|
|
|
|
|
if (edid && json_str) { |
|
|
|
|
|
edid->range_limits_descriptor.display_descriptor = 0; |
|
|
|
|
|
edid->range_limits_descriptor.reserved = 0; |
|
|
|
|
|
edid->range_limits_descriptor.display_range_limits_descriptor = 0xFD; |
|
|
|
|
|
// Range offsets
|
|
|
|
|
|
int n = json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {rate_offsets: {vertical: %Q}}}", |
|
|
|
|
|
&multi_use_str); |
|
|
|
|
|
printf("n>%d\n", n); |
|
|
|
|
|
if (strcmp(multi_use_str, "none") == 0) { |
|
|
|
|
|
edid->range_limits_descriptor.rate_offsets.vertical = 0; |
|
|
|
|
|
} else { |
|
|
|
|
|
printf("Error: Range limit offset other than none is not yet implemented.\n"); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
free(multi_use_str); |
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {rate_offsets: {horizontal: %Q}}}", |
|
|
|
|
|
&multi_use_str); |
|
|
|
|
|
if (strcmp(multi_use_str, "none") == 0) { |
|
|
|
|
|
edid->range_limits_descriptor.rate_offsets.horizontal = 0; |
|
|
|
|
|
} else { |
|
|
|
|
|
printf("Error: Range limit offset other than none is not yet implemented.\n"); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
free(multi_use_str); |
|
|
|
|
|
// Vertical and horizontal lines
|
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {rates: {vertical: {minimum_hz: %d}}}}", |
|
|
|
|
|
&multi_use_int); |
|
|
|
|
|
edid->range_limits_descriptor.vertical_field_rate.minimum = 0xFF & multi_use_int; |
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {rates: {vertical: {maximum_hz: %d}}}}", |
|
|
|
|
|
&multi_use_int); |
|
|
|
|
|
edid->range_limits_descriptor.vertical_field_rate.maximum = 0xFF & multi_use_int; |
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {rates: {horizontal: {minimum_khz: %d}}}}", |
|
|
|
|
|
&multi_use_int); |
|
|
|
|
|
edid->range_limits_descriptor.horizontal_line_rate.minimum = 0xFF & multi_use_int; |
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {rates: {horizontal: {maximum_khz: %d}}}}", |
|
|
|
|
|
&multi_use_int); |
|
|
|
|
|
edid->range_limits_descriptor.horizontal_line_rate.maximum = 0xFF & multi_use_int; |
|
|
|
|
|
// Maximum pixel clock rate
|
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {maximum_pixel_clock_mhz: %d}}", |
|
|
|
|
|
&multi_use_int); |
|
|
|
|
|
// Multiples of 10 MHz
|
|
|
|
|
|
edid->range_limits_descriptor.maximum_pixel_clock_mhz = 0xFF & (multi_use_int/10); |
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{range_limits_descriptor: {extended_timing_information_type: %Q}}", |
|
|
|
|
|
&multi_use_str); |
|
|
|
|
|
if (strcmp(multi_use_str, "default_gtf") == 0) { |
|
|
|
|
|
edid->range_limits_descriptor.extended_timing_information_type = 0; |
|
|
|
|
|
// Apply padding for video timing parameters
|
|
|
|
|
|
edid->range_limits_descriptor.video_timing_params[0] = 0x0A; |
|
|
|
|
|
memset(edid->range_limits_descriptor.video_timing_params + 1, 0x20, 6); |
|
|
|
|
|
} else { |
|
|
|
|
|
printf("Error: Any other timing information type than default_gtf is currently not implemented.\n"); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
free(multi_use_str); |
|
|
|
|
|
} else { |
|
|
|
|
|
printf("Error: One of either edid or json_str is NULL.\n"); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int generate_display_name_descriptor( |
|
|
|
|
|
edid_t* edid, |
|
|
|
|
|
unsigned char* json_str, |
|
|
|
|
|
size_t json_len) |
|
|
|
|
|
{ |
|
|
|
|
|
char* display_name = NULL; |
|
|
|
|
|
|
|
|
|
|
|
if (edid && json_str) { |
|
|
|
|
|
edid->display_name_descriptor.display_descriptor = 0; |
|
|
|
|
|
edid->display_name_descriptor.reserved0 = 0; |
|
|
|
|
|
edid->display_name_descriptor.descriptor_type = 0xFC; |
|
|
|
|
|
edid->display_name_descriptor.reserved1 = 0; |
|
|
|
|
|
json_scanf( json_str, json_len, |
|
|
|
|
|
"{display_name_descriptor: {name: %Q}}", |
|
|
|
|
|
&display_name); |
|
|
|
|
|
if (display_name != NULL) { |
|
|
|
|
|
if (strlen(display_name) <= 13) { |
|
|
|
|
|
memcpy(edid->display_name_descriptor.descriptor_data, display_name, strlen(display_name)); |
|
|
|
|
|
if (strlen(display_name) < 13) { |
|
|
|
|
|
memset( edid->display_name_descriptor.descriptor_data |
|
|
|
|
|
+ strlen(display_name), 0x0A, 1); |
|
|
|
|
|
memset( edid->display_name_descriptor.descriptor_data |
|
|
|
|
|
+ strlen(display_name) + 1, 0x20, 13-strlen(display_name)-1); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
printf("Error: Display name is too long.\n"); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
printf("Error: Could not parse JSON file somewhere around display_name_descriptor.\n"); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
printf("Error: One of either edid or json_str is NULL.\n"); |
|
|
printf("Error: One of either edid or json_str is NULL.\n"); |
|
|
return 1; |
|
|
return 1; |
|
@ -874,6 +1014,8 @@ int main(void) |
|
|
generate_common_timing_modes(&edith, mystr, len); |
|
|
generate_common_timing_modes(&edith, mystr, len); |
|
|
generate_timings(&edith, mystr, len); |
|
|
generate_timings(&edith, mystr, len); |
|
|
generate_detailed_timing_descriptor(&edith, mystr, len); |
|
|
generate_detailed_timing_descriptor(&edith, mystr, len); |
|
|
|
|
|
generate_range_limit_descriptor(&edith, mystr, len); |
|
|
|
|
|
generate_display_name_descriptor(&edith, mystr, len); |
|
|
disp_buf((uint8_t*)&edith, EDID_LENGTH); |
|
|
disp_buf((uint8_t*)&edith, EDID_LENGTH); |
|
|
free(mystr); |
|
|
free(mystr); |
|
|
return 0; |
|
|
return 0; |
|
|