diff --git a/src/common/edidHelper.h b/src/common/edidHelper.h index dc4e4fb3a..44065790a 100644 --- a/src/common/edidHelper.h +++ b/src/common/edidHelper.h @@ -8,6 +8,7 @@ bool ffEdidGetName(const uint8_t edid[128], FFstrbuf* name); void ffEdidGetPreferredResolutionAndRefreshRate(const uint8_t edid[128], uint32_t* width, uint32_t* height, double* refreshRate); void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint32_t* height); void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* height); // in mm -void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week); +void ffEdidGetManufactureDate(const uint8_t edid[128], uint16_t* year, uint16_t* week); +bool ffEdidGetSerial(const uint8_t edid[128], FFstrbuf* result); bool ffEdidGetHdrCompatible(const uint8_t* edid, uint32_t length); bool ffEdidIsValid(const uint8_t edid[128], uint32_t length); diff --git a/src/common/impl/edidHelper.c b/src/common/impl/edidHelper.c index 1e3310e2a..fd7b4035a 100644 --- a/src/common/impl/edidHelper.c +++ b/src/common/impl/edidHelper.c @@ -66,7 +66,7 @@ void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* h } } -void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week) { +void ffEdidGetManufactureDate(const uint8_t edid[128], uint16_t* year, uint16_t* week) { if (edid[17] > 0 && edid[17] < 0xFF) { *year = (uint16_t) (edid[17] + 1990); *week = (uint16_t) edid[16]; @@ -76,8 +76,49 @@ void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial } else { *year = *week = 0; } +} - *serial = *(uint32_t*) &edid[12]; +bool ffEdidGetSerial(const uint8_t edid[128], FFstrbuf* result) { + int descriptor_offsets[4] = {54, 72, 90, 108}; + + for (int i = 0; i < 4; i++) { + int offset = descriptor_offsets[i]; + const uint8_t* desc = edid + offset; + + if (desc[0] == 0x00 && desc[1] == 0x00) { // Monitor Descriptor + uint8_t tag = desc[3]; // Descriptor Type Tag + + if (tag == 0xFF) { // Display Product Serial Number + ffStrbufClear(result); + for (int j = 0; j < 13; j++) { + uint8_t ch = desc[5 + j]; + + if (ch == 0x0A || ch == 0x00) { + break; + } + + ffStrbufAppendC(result, (char) ch); + } + + ffStrbufTrim(result, ' '); + if (result->length > 0) { + return true; + } + } + } + } + + uint32_t int_serial = 0; + int_serial |= (uint32_t)edid[12]; + int_serial |= (uint32_t)edid[13] << 8; + int_serial |= (uint32_t)edid[14] << 16; + int_serial |= (uint32_t)edid[15] << 24; + + if (int_serial != 0 && int_serial != 0xFFFFFFFF) { + ffStrbufSetF(result, "0x%08X", int_serial); + return 0; + } + return false; } bool ffEdidGetHdrCompatible(const uint8_t* edid, uint32_t length) { diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 58c8c8912..e91377109 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -42,7 +42,7 @@ FFDisplayResult* ffdsAppendDisplay( display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; display->manufactureYear = 0; display->manufactureWeek = 0; - display->serial = 0; + ffStrbufInit(&display->serial); display->drrStatus = FF_DISPLAY_DRR_STATUS_UNKNOWN; return display; diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index fd88f370d..53c0de3ea 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -89,7 +89,7 @@ typedef struct FFDisplayResult { FFDisplayHdrStatus hdrStatus; uint16_t manufactureYear; uint16_t manufactureWeek; - uint32_t serial; + FFstrbuf serial; FFDisplayVrrStatus drrStatus; } FFDisplayResult; diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index f92c144f9..5c4f57e63 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -196,7 +196,8 @@ static void detectDisplays(FFDisplayServerResult* ds) { } } if (edid.length > 0) { - ffEdidGetSerialAndManufactureDate(edid.data, &display->serial, &display->manufactureYear, &display->manufactureWeek); + ffEdidGetManufactureDate(edid.data, &display->manufactureYear, &display->manufactureWeek); + ffEdidGetSerial(edid.data, &display->serial); } display->drrStatus = path->flags & DISPLAYCONFIG_PATH_BOOST_REFRESH_RATE ? FF_DISPLAY_DRR_STATUS_ENABLED : FF_DISPLAY_DRR_STATUS_DISABLED; } diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 497c783e8..0cc068cf0 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -96,7 +96,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) { "sysfs-drm"); if (item && edidLength) { item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; - ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetManufactureDate(edidData, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetSerial(edidData, &item->serial); } ffStrbufSubstrBefore(&drmDir, drmDirLength); @@ -327,7 +328,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) { FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); uint16_t myear = 0, mweak = 0; - uint32_t serial = 0; + FF_STRBUF_AUTO_DESTROY serial = ffStrbufCreate(); FFDisplayHdrStatus hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; uint32_t* props = malloc(conn.count_props * sizeof(uint32_t)); @@ -363,7 +364,8 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) { if (ioctl(primaryFd, DRM_IOCTL_MODE_GETPROPBLOB, &blob) >= 0 && ffEdidIsValid(blobData, blob.length)) { ffEdidGetName(blobData, &name); hdrStatus = ffEdidGetHdrCompatible(blobData, blob.length) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; - ffEdidGetSerialAndManufactureDate(blobData, &serial, &myear, &mweak); + ffEdidGetManufactureDate(blobData, &myear, &mweak); + ffEdidGetSerial(blobData, &serial); } } break; @@ -380,7 +382,8 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) { if (edidLength > 0 && edidLength % 128 == 0) { ffEdidGetName(edidData, &name); hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; - ffEdidGetSerialAndManufactureDate(edidData, &serial, &myear, &mweak); + ffEdidGetManufactureDate(edidData, &myear, &mweak); + ffEdidGetSerial(edidData, &serial); } } #endif @@ -416,7 +419,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) { if (item) { item->hdrStatus = hdrStatus; - item->serial = serial; + ffStrbufInitMove(&item->serial, &serial); item->manufactureYear = myear; item->manufactureWeek = mweak; item->bitDepth = bitDepth; diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index 3c49d51e3..b8618d7b3 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -198,7 +198,7 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* item->manufactureYear = display.myear; item->manufactureWeek = display.mweek; - item->serial = display.serial; + ffStrbufInitMove(&item->serial, &display.serial); } ffStrbufDestroy(&display.description); diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index 94be50cab..73f9ac5af 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -95,7 +95,8 @@ static void waylandKdeEdidListener(void* data, FF_A_UNUSED struct kde_output_dev } ffEdidGetName((const uint8_t*) edid.chars, &wldata->edidName); wldata->hdrSupported = ffEdidGetHdrCompatible((const uint8_t*) edid.chars, edid.length); - ffEdidGetSerialAndManufactureDate((const uint8_t*) edid.chars, &wldata->serial, &wldata->myear, &wldata->mweek); + ffEdidGetManufactureDate((const uint8_t*) edid.chars, &wldata->myear, &wldata->mweek); + ffEdidGetSerial((const uint8_t*) edid.chars, &wldata->serial); wldata->hdrInfoAvailable = true; } @@ -259,7 +260,7 @@ static const char* waylandKdeHandleOutput(WaylandData* wldata, struct wl_proxy* item->manufactureYear = display.myear; item->manufactureWeek = display.mweek; - item->serial = display.serial; + ffStrbufInitMove(&item->serial, &display.serial); item->bitDepth = display.bitDepth; } diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index 096eef0ab..f25fd5158 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -130,7 +130,8 @@ static FF_A_UNUSED bool matchDrmConnector(const char* connName, WaylandDisplay* if (edidLength > 0 && ffEdidIsValid(edidData, (uint32_t) edidLength)) { ffEdidGetName(edidData, &wldata->edidName); wldata->hdrSupported = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); - ffEdidGetSerialAndManufactureDate(edidData, &wldata->serial, &wldata->myear, &wldata->mweek); + ffEdidGetManufactureDate((const uint8_t*) edidData, &wldata->myear, &wldata->mweek); + ffEdidGetSerial((const uint8_t*) edidData, &wldata->serial); wldata->hdrInfoAvailable = true; return true; } diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index 90dc8c9d1..e9d4fede8 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -55,7 +55,7 @@ typedef struct WaylandDisplay { bool hdrEnabled; uint16_t myear; uint16_t mweek; - uint32_t serial; + FFstrbuf serial; uint8_t bitDepth; bool primary; } WaylandDisplay; diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 8620d7150..8ad663d17 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -227,7 +227,8 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, if (item) { if (edidData && edidLength >= 128) { item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; - ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetManufactureDate(edidData, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetSerial(edidData, &item->serial); } item->bitDepth = bitDepth; if ((rotation == 90 || rotation == 180) && !randrEmulation) { diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 2beffccab..642a0d2f2 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -161,7 +161,8 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* if (item) { if (edidLength) { item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; - ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetManufactureDate(edidData, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetSerial(edidData, &item->serial); } item->bitDepth = bitDepth; if ((rotation == 90 || rotation == 180) && !randrEmulation) { diff --git a/src/modules/display/display.c b/src/modules/display/display.c index b11a2aabc..be3d66f75 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -166,14 +166,6 @@ bool ffPrintDisplay(FFDisplayOptions* options) { preferredRefreshRate[0] = 0; } - char buf[32]; - if (result->serial) { - const uint8_t* nums = (uint8_t*) &result->serial; - snprintf(buf, ARRAY_SIZE(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); - } else { - buf[0] = '\0'; - } - FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) { FF_ARG(result->width, "width"), FF_ARG(result->height, "height"), @@ -192,7 +184,7 @@ bool ffPrintDisplay(FFDisplayOptions* options) { FF_ARG(hdrEnabled, "hdr-enabled"), FF_ARG(result->manufactureYear, "manufacture-year"), FF_ARG(result->manufactureWeek, "manufacture-week"), - FF_ARG(buf, "serial"), + FF_ARG(result->serial, "serial"), FF_ARG(result->platformApi, "platform-api"), FF_ARG(hdrCompatible, "hdr-compatible"), FF_ARG(scaleFactor, "scale-factor"), @@ -395,8 +387,8 @@ bool ffGenerateDisplayJsonResult(FF_A_UNUSED FFDisplayOptions* options, yyjson_m yyjson_mut_obj_add_null(doc, obj, "manufactureDate"); } - if (item->serial) { - yyjson_mut_obj_add_uint(doc, obj, "serial", item->serial); + if (item->serial.length) { + yyjson_mut_obj_add_strbuf(doc, obj, "serial", &item->serial); } else { yyjson_mut_obj_add_null(doc, obj, "serial"); } diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 105ee67c6..86ff1fcdf 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -51,14 +51,6 @@ bool ffPrintMonitor(FFMonitorOptions* options) { } putchar('\n'); } else { - char buf[32]; - if (display->serial) { - const uint8_t* nums = (uint8_t*) &display->serial; - snprintf(buf, sizeof(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); - } else { - buf[0] = '\0'; - } - FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) { FF_ARG(display->name, "name"), FF_ARG(display->width, "width"), @@ -69,7 +61,7 @@ bool ffPrintMonitor(FFMonitorOptions* options) { FF_ARG(ppi, "ppi"), FF_ARG(display->manufactureYear, "manufacture-year"), FF_ARG(display->manufactureWeek, "manufacture-week"), - FF_ARG(buf, "serial"), + FF_ARG(display->serial, "serial"), FF_ARG(display->refreshRate, "refresh-rate"), FF_ARG(hdrCompatible, "hdr-compatible"), }));