edid-decode: fix spurious warning about string termination
Fixes bug https://bugs.freedesktop.org/show_bug.cgi?id=93777:
The Monitor Name description string can be exactly 13 bytes, which
case there is no newline at the end. Yet this was considered an
error.
Simplify the code by relying on extract_string to do the checking.
The extract_string function also checks for trailing spaces and
warns about that.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Hans Verkuil
5 years ago
50 | 50 | static int nonconformant_extension = 0; |
51 | 51 | static int did_detailed_timing = 0; |
52 | 52 | static int has_name_descriptor = 0; |
53 | static int name_descriptor_terminated = 0; | |
53 | static int has_serial_string = 0; | |
54 | static int has_ascii_string = 0; | |
54 | 55 | static int has_range_descriptor = 0; |
55 | 56 | static int has_preferred_timing = 0; |
56 | 57 | static int has_valid_checksum = 1; |
60 | 61 | static int has_valid_dummy_block = 1; |
61 | 62 | static int has_valid_serial_number = 0; |
62 | 63 | static int has_valid_serial_string = 0; |
64 | static int has_valid_ascii_string = 0; | |
65 | static int has_valid_name_descriptor = 0; | |
63 | 66 | static int has_valid_week = 0; |
64 | 67 | static int has_valid_year = 0; |
65 | 68 | static int has_valid_detailed_blocks = 0; |
68 | 71 | static int has_valid_range_descriptor = 1; |
69 | 72 | static int has_valid_max_dotclock = 1; |
70 | 73 | static int has_valid_string_termination = 1; |
74 | static int empty_string = 0; | |
75 | static int trailing_space = 0; | |
71 | 76 | static int has_cta861 = 0; |
72 | 77 | static int has_640x480p60_est_timing = 0; |
73 | 78 | static int has_cta861_vic_1 = 0; |
404 | 409 | } |
405 | 410 | |
406 | 411 | /* extract a string from a detailed subblock, checking for termination */ |
407 | static char *extract_string(unsigned char *x, int *valid_termination, int len) | |
412 | static char *extract_string(unsigned char *x, int *valid, int len) | |
408 | 413 | { |
409 | 414 | static char ret[EDID_PAGE_SIZE]; |
410 | 415 | int i, seen_newline = 0; |
411 | 416 | |
412 | 417 | memset(ret, 0, sizeof(ret)); |
418 | *valid = 1; | |
413 | 419 | |
414 | 420 | for (i = 0; i < len; i++) { |
415 | 421 | if (isgraph(x[i])) { |
417 | 423 | } else if (!seen_newline) { |
418 | 424 | if (x[i] == 0x0a) { |
419 | 425 | seen_newline = 1; |
426 | if (!i) { | |
427 | empty_string = 1; | |
428 | *valid = 0; | |
429 | } else if (ret[i - 1] == 0x20) { | |
430 | trailing_space = 1; | |
431 | *valid = 0; | |
432 | } | |
420 | 433 | } else if (x[i] == 0x20) { |
421 | 434 | ret[i] = x[i]; |
422 | 435 | } else { |
423 | *valid_termination = 0; | |
436 | has_valid_string_termination = 0; | |
437 | *valid = 0; | |
424 | 438 | return ret; |
425 | 439 | } |
426 | } else { | |
427 | if (x[i] != 0x20) { | |
428 | *valid_termination = 0; | |
429 | return ret; | |
430 | } | |
431 | } | |
440 | } else if (x[i] != 0x20) { | |
441 | has_valid_string_termination = 0; | |
442 | *valid = 0; | |
443 | return ret; | |
444 | } | |
445 | } | |
446 | /* Does the string end with a space? */ | |
447 | if (!seen_newline && ret[len - 1] == 0x20) { | |
448 | trailing_space = 1; | |
449 | *valid = 0; | |
432 | 450 | } |
433 | 451 | |
434 | 452 | return ret; |
604 | 622 | /* 1 means valid data */ |
605 | 623 | static int detailed_block(unsigned char *x, int in_extension) |
606 | 624 | { |
607 | static unsigned char name[53]; | |
608 | 625 | int ha, hbl, hso, hspw, hborder, va, vbl, vso, vspw, vborder; |
609 | 626 | int refresh, pixclk_khz; |
610 | 627 | int i; |
725 | 742 | return 1; |
726 | 743 | } |
727 | 744 | case 0xFC: |
728 | /* XXX should check for spaces after the \n */ | |
729 | /* XXX check: terminated with 0x0A, padded with 0x20 */ | |
730 | 745 | has_name_descriptor = 1; |
731 | if (strchr((char *)name, '\n')) return 1; | |
732 | strncat((char *)name, (char *)x + 5, 13); | |
733 | if (strchr((char *)name, '\n')) { | |
734 | name_descriptor_terminated = 1; | |
735 | printf("Monitor name: %s\n", | |
736 | extract_string(name, &has_valid_string_termination, | |
737 | strlen((char *)name))); | |
738 | } | |
746 | printf("Monitor name: %s\n", | |
747 | extract_string(x + 5, &has_valid_name_descriptor, 13)); | |
739 | 748 | return 1; |
740 | 749 | case 0xFD: { |
741 | 750 | int h_max_offset = 0, h_min_offset = 0; |
892 | 901 | * TODO: Two of these in a row, in the third and fourth slots, |
893 | 902 | * seems to be specified by SPWG: http://www.spwg.org/ |
894 | 903 | */ |
904 | has_ascii_string = 1; | |
895 | 905 | printf("ASCII string: %s\n", |
896 | extract_string(x + 5, &has_valid_string_termination, 13)); | |
906 | extract_string(x + 5, &has_valid_ascii_string, 13)); | |
897 | 907 | return 1; |
898 | 908 | case 0xFF: |
909 | has_serial_string = 1; | |
899 | 910 | printf("Serial number: %s\n", |
900 | extract_string(x + 5, &has_valid_string_termination, 13)); | |
901 | has_valid_serial_string = 1; | |
911 | extract_string(x + 5, &has_valid_serial_string, 13)); | |
902 | 912 | return 1; |
903 | 913 | default: |
904 | 914 | printf("Unknown monitor description type %d\n", x[3]); |
2934 | 2944 | !has_valid_string_termination || |
2935 | 2945 | !has_valid_descriptor_pad || |
2936 | 2946 | !has_name_descriptor || |
2937 | !name_descriptor_terminated || | |
2938 | 2947 | !has_preferred_timing || |
2939 | 2948 | (!claims_one_point_four && !has_range_descriptor)) |
2940 | 2949 | conformant = 0; |
2956 | 2965 | printf("\tHDMI Forum VSDB Max TMDS rate is > 0 and <= 340 or > 600\n"); |
2957 | 2966 | if (!has_name_descriptor) |
2958 | 2967 | printf("\tMissing name descriptor\n"); |
2959 | else if (!name_descriptor_terminated) | |
2960 | printf("\tName descriptor not terminated with a newline\n"); | |
2961 | 2968 | if (!has_preferred_timing) |
2962 | 2969 | printf("\tMissing preferred timing\n"); |
2963 | 2970 | if (!has_range_descriptor) |
2967 | 2974 | if (!has_valid_string_termination) /* Likewise */ |
2968 | 2975 | printf("\tDetailed block string not properly terminated\n"); |
2969 | 2976 | } else if (claims_one_point_two) { |
2970 | if (nonconformant_digital_display || | |
2971 | (has_name_descriptor && !name_descriptor_terminated)) | |
2977 | if (nonconformant_digital_display) | |
2972 | 2978 | conformant = 0; |
2973 | 2979 | if (!conformant) |
2974 | 2980 | printf("EDID block does NOT conform to EDID 1.2!\n"); |
2975 | 2981 | if (nonconformant_digital_display) |
2976 | 2982 | printf("\tDigital display field contains garbage: %x\n", |
2977 | 2983 | nonconformant_digital_display); |
2978 | if (has_name_descriptor && !name_descriptor_terminated) | |
2979 | printf("\tName descriptor not terminated with a newline\n"); | |
2980 | 2984 | } else if (claims_one_point_oh) { |
2981 | 2985 | if (seen_non_detailed_descriptor) |
2982 | 2986 | conformant = 0; |
3016 | 3020 | !has_valid_dummy_block || |
3017 | 3021 | !has_valid_descriptor_ordering || |
3018 | 3022 | !has_valid_range_descriptor || |
3019 | !manufacturer_name_well_formed) { | |
3023 | !manufacturer_name_well_formed || | |
3024 | (has_name_descriptor && !has_valid_name_descriptor) || | |
3025 | (has_serial_string && !has_valid_serial_string) || | |
3026 | (has_ascii_string && !has_valid_ascii_string) || | |
3027 | empty_string || | |
3028 | trailing_space) { | |
3020 | 3029 | conformant = 0; |
3021 | 3030 | printf("EDID block does not conform at all!\n"); |
3022 | 3031 | if (nonconformant_extension) |
3044 | 3053 | printf("\tRange descriptor contains garbage\n"); |
3045 | 3054 | if (!has_valid_max_dotclock) |
3046 | 3055 | printf("\tEDID 1.4 block does not set max dotclock\n"); |
3056 | if (has_name_descriptor && !has_valid_name_descriptor) | |
3057 | printf("\tInvalid Monitor Name descriptor\n"); | |
3058 | if (has_ascii_string && !has_valid_ascii_string) | |
3059 | printf("\tInvalid ASCII string\n"); | |
3060 | if (has_serial_string && !has_valid_serial_string) | |
3061 | printf("\tInvalid serial string\n"); | |
3062 | if (trailing_space) | |
3063 | printf("\tString contains one or more trailing spaces\n"); | |
3064 | if (empty_string) | |
3065 | printf("\tString is empty\n"); | |
3047 | 3066 | } |
3048 | 3067 | |
3049 | 3068 | if (!has_valid_cta_checksum) { |