-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
colormgr get-devices is empty when two identical monitor models are plugged in #164
Comments
The monitors are supposed to have different serial numbers. I'm afraid you might have to dig into the code to find a workaround we can apply upstream. |
I checked the serial numbers on the back of my monitors. It turns out that the serial number is truncated. It uses the first eight letters of the serial number: T78EE004 ... and the last 4 digits "8521" which apparently match. The other 8 hex digits in-between are entirely different. Do you know why there are different md5 hashes then? When I |
Found my missing serial number digits. They are not encoded in hexadecimal but in decimal. However, they match the numbers on the back of my monitors:
It appears to be the only difference between both
I don't know about the internals of the edid file format. It seems that both serial numbers need to be concatenated when creating the device id. Any other monitor examples where this is similar? I guess one could fallback to the current scheme if the "Serial Number" field does not exist. |
I checked the EDID file format with the information on Wikipedia and it turns out that the missing numbers are supposed to be the "real" serial numbers. They can be directly read from the edid file at bytes 12-15 (32 bits, little endian, index starts at 0). The other "Display Product Serial Number" seems to be an "display/monitor descriptor" (max 18 bytes), which is not necessarily unique. I am not sure which source for the serial number colord uses, as I could not directly find a way to get this information with The check implemented in file What do you think? |
Found the problem in First hint at ll. 545ff: /* maybe there isn't a ASCII serial number descriptor, so use this instead */
serial = (guint32) data[CD_EDID_OFFSET_SERIAL+0];
serial += (guint32) data[CD_EDID_OFFSET_SERIAL+1] * 0x100;
serial += (guint32) data[CD_EDID_OFFSET_SERIAL+2] * 0x10000;
serial += (guint32) data[CD_EDID_OFFSET_SERIAL+3] * 0x1000000;
if (serial > 0)
priv->serial_number = g_strdup_printf ("%" G_GUINT32_FORMAT, serial); This indicates that it is assumed that the serial number is the same as the display product serial number, but they are not. After line 603, the serial number is then overwritten with the display product serial number: [...]
} else if (data[i+3] == CD_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
tmp = cd_edid_parse_string (&data[i+5]);
if (tmp != NULL) {
g_free (priv->serial_number);
priv->serial_number = tmp;
}
}
[...] Which is then used in static gchar *
cd_main_get_display_id (CdEdid *edid)
{
GString *device_id;
device_id = g_string_new ("xrandr");
if (cd_edid_get_vendor_name (edid) != NULL)
g_string_append_printf (device_id, "-%s", cd_edid_get_vendor_name (edid));
if (cd_edid_get_monitor_name (edid) != NULL)
g_string_append_printf (device_id, "-%s", cd_edid_get_monitor_name (edid));
if (cd_edid_get_serial_number (edid) != NULL)
g_string_append_printf (device_id, "-%s", cd_edid_get_serial_number (edid));
return g_string_free (device_id, FALSE);
} Which is not correct, in my opinion. My suggestion would be to keep both separate and change the construction of the device id. I.e., in typedef struct
{
CdColorYxy *red;
CdColorYxy *green;
CdColorYxy *blue;
CdColorYxy *white;
gchar *checksum;
gchar *eisa_id;
gchar *monitor_name;
gchar *pnp_id;
gchar *serial_number;
/* the line below is added */
gchar *display_product_serial_number;
gchar *vendor_name;
gdouble gamma;
guint height;
guint width;
} CdEdidPrivate; Then assign the display product serial number to that separate field at ll. 603ff instead of replacing the serial number: } else if (data[i+3] == CD_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
priv->display_product_serial_number = cd_edid_parse_string (&data[i+5]);
/*
// delete these commented lines
if (tmp != NULL) {
g_free (priv->serial_number);
priv->serial_number = tmp;
}
*/
} Make sure to update void
cd_edid_reset (CdEdid *edid)
{
CdEdidPrivate *priv = GET_PRIVATE (edid);
g_return_if_fail (CD_IS_EDID (edid));
/* free old data */
g_free (priv->monitor_name);
g_free (priv->vendor_name);
g_free (priv->serial_number);
/* add the line below */
g_free (priv->display_product_serial_number);
g_free (priv->eisa_id);
g_free (priv->checksum);
/* do not deallocate, just blank */
priv->pnp_id[0] = '\0';
/* set to default values */
priv->monitor_name = NULL;
priv->vendor_name = NULL;
priv->serial_number = NULL;
/* add the line below */
priv->display_product_serial_number = NULL;
priv->eisa_id = NULL;
priv->checksum = NULL;
priv->width = 0;
priv->height = 0;
priv->gamma = 0.0f;
}
static void
cd_edid_finalize (GObject *object)
{
CdEdid *edid = CD_EDID (object);
CdEdidPrivate *priv = GET_PRIVATE (edid);
g_free (priv->monitor_name);
g_free (priv->vendor_name);
g_free (priv->serial_number);
/* add this line */
g_free (priv->display_product_serial_number);
g_free (priv->eisa_id);
g_free (priv->checksum);
g_free (priv->pnp_id);
cd_color_yxy_free (priv->white);
cd_color_yxy_free (priv->red);
cd_color_yxy_free (priv->green);
cd_color_yxy_free (priv->blue);
G_OBJECT_CLASS (cd_edid_parent_class)->finalize (object);
} Add a new function to access it: const gchar *
cd_edid_get_display_product_serial_number (CdEdid *edid)
{
CdEdidPrivate *priv = GET_PRIVATE (edid);
g_return_val_if_fail (CD_IS_EDID (edid), NULL);
return priv->display_product_serial_number;
} Update static gchar *
cd_main_get_display_id (CdEdid *edid)
{
GString *device_id;
device_id = g_string_new ("xrandr");
if (cd_edid_get_vendor_name (edid) != NULL)
g_string_append_printf (device_id, "-%s", cd_edid_get_vendor_name (edid));
if (cd_edid_get_monitor_name (edid) != NULL)
g_string_append_printf (device_id, "-%s", cd_edid_get_monitor_name (edid));
if (cd_edid_get_display_product_serial_number (edid) != NULL)
g_string_append_printf (device_id, "-%s", cd_edid_get_display_product_serial_number (edid));
if (cd_edid_get_serial_number (edid) != NULL)
g_string_append_printf (device_id, "-%s", cd_edid_get_serial_number (edid));
return g_string_free (device_id, FALSE);
} However, I am not sure how the new naming scheme would affect existing installations. |
I think it would break all the profile mappings! :) I think what's supposed to happen is that the CD_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER is only used when the serial "number" contains non-numeric chars. Maybe you can add a quirk for that specific EDID model so that the CD_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER gets ignored completely? |
I am really struggling to get this sorted. First, I implemented the changes I proposed, but it turns out that changing this only affects the debug message and not anything else in the code. Hence, commenting out the code that overwrites the serial number with the display product serial number did not change anything either. Next thing I did was setting I am tempted to give up and accept that I can't have my color-calibrated ICC profiles with colord installed. All I want is to somehow overwrite the default serial number. Where is the serial number data read from? It's not read from the |
The desktop client reads the EDID and creates the device with colord using DBus. You'll need to install the library before it'll be used by the session. |
Thank you for the reply. Can you specify what you mean by desktop client? I see that Do you mean that I would need to fully overwrite the default installation of colord with a custom one? I suppose killing colord and starting the custom compiled colord executable is not enough then? |
Well, in GNOME it's gnome-settings-daemon for instance.
At least the colord shared library. |
I tried an installation yesterday without success. I am not entirely sure whether However, your comment got me thinking that maybe GNOME itself is the issue here. I installed KDE today and both displays showed up in the settings out of the box. Although I could not assign profiles via the GUI, I was able to assign them via KDE uses a different naming scheme that includes the connecting monitor port at the end of the name. This seems to be similar to the I will keep using KDE, because it solved my color profile problem. So for me, the case is closed. I'd still suggest to enhance colord by exposing the "other EDID serial number" somehow. Probably best to do so via a separate function in the Alternatively (?) or additionally, one might extend the "duplicate edid" check with a "duplicate device id" check to change usage of device ids in the same manner. I.e., switch to xrandr device id naming scheme if two device ids will be the same. I think that using the xrandr naming scheme, should have actually solved my problem, as this is what I can observe when using KDE. Thanks for your help! You can close the issue if you want or keep it open as a reference. |
I'm having the same issue on GNOME. |
Update: I'm still having this issue and I couldn't find any solution for it. Since this issue is causing the night light feature from GNOME to not be applied on my two identical external monitors, I was practically forced to move to KDE or get my eyes burnt while using my PC. I also tried using X11 + Redshift but X11 is EXTREMELY laggy and unusable for me nowadays. |
Do you pay for a Red Hat subscription? If so I could look at this in "work time" so to speak. |
Nope, I don't think I do. |
No idea, sorry. |
To throw in another data point here, I have what seems like a similar situation but caused by the same monitor being attached to both integrated and discrete graphics outputs. If I physically disconnect either output (or attach both to one GPU), the monitor appears in If multiple GPU connect to the same monitor, that monitor doesn't appear. Also Wayland/Gnome. |
Same issue here. If I compare the edid information from my two displays with
it doesn't find any differences. When checking the hash of the two files, it shows that they are completely identical in my case:
If I understand @voidptr127 correctly, these files contain the I'm on Gnome by the way. And I don't plan on swapping to KDE because of this. If I recall correctly this worked fine with my old computer and my old OS which was Ubuntu 20.04 I believe. Since then (when I upgraded my pc) I kept the boot drive and upgraded it to Ubuntu 24.04 because of missing firmware for my new GPU. My monitors stayed the same tough. I don't remember if I was already using Wayland back then, but I am now. Is there any way to hardcode/overwrite the serial number in a config file? Since the computer is stationary and always connected to the same displays, this would totally be acceptable. Thanks @voidptr127 for the research. |
@voidptr127 do you know why this code isn't working?
i.e. we check for duplicate EDIDs -- or is the check too strict and the EDIDs are not actually 100% the same, but do have the same model and serial number? I suspect cd_main_check_duplicate_edids() needs love if that's the case. |
I think the issue is not in I have a suggestion though. Would it maybe be worth returning earlier from the function, if // Old
if (old_output != NULL) {
g_debug ("output %s has duplicate EDID", fn);
use_xrandr_mode = TRUE;
}
// New
if (old_output != NULL) {
g_debug ("output %s has duplicate EDID", fn);
use_xrandr_mode = TRUE;
return use_xrandr_mode;
} |
System: Fedora 39 (Workstation), GNOME: 45.3, Kernel 6.6.12-200
I can't assign ICC profiles to my monitors because
colormgr get-devices
returns nothing when two identical monitor models are plugged in. This also affects the gnome-color-manager where neither monitor is shown when both are plugged in.First, I checked system logs and got the following:
Next, I unplugged both displayport cables, then only plugged one monitor back in. In this case, everything works as expected:
Note that at this stage, I could also assign the ICC profile. However, it only works for the monitor that was plugged in. As soon as I plug in the second monitor,
colormgr get-devices
returns nothing and the default ICC profile for the other monitor is used. I also compared both outputs ofcolormgr get-devices
. Both return exactly the same model and serial number.Here is two times the output from colord with the
--verbose
flag set:The first output shows what colord prints when I did stop colord and unplugged both monitors. Then I hit enter (blindly) to start colord, and plugged both monitors in, one after another. The second output is printed when I killed the previous process and started it afterwards while both monitors were already plugged in.
Particularly interesting might be these lines from the second file:
I am not entirely sure about the expected behavior, but I suspect that the names should differ to avoid the confusion.
The text was updated successfully, but these errors were encountered: