From 837a1f8d7d2f4701afaab41991e627e0ef206263 Mon Sep 17 00:00:00 2001 From: Iskren Chernev Date: Sun, 25 Oct 2020 14:03:03 +0200 Subject: [PATCH] pixma: Fix device enumeration for open devices If sane_get_devices is called while a device is already open, read_serial_number tries to open the usb device to read it, but fails (possibly because it's already open), so the returned device ends up lacking a serial. For example `pixma:04A91913_401D8C` gets returned as `pixma:04a91913`. This in turn might promp frontend applications to close existing connection and open a new one to new device, which now fails, because once the device is closed enumeration returns full name again. To fix this, after getting a device name via usb enumeration, check if one of the device names is a substring of an already open device. If it is, just return the full name from the open device. --- backend/pixma/pixma.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/backend/pixma/pixma.c b/backend/pixma/pixma.c index 19e82614a..0b9c33e59 100644 --- a/backend/pixma/pixma.c +++ b/backend/pixma/pixma.c @@ -243,6 +243,30 @@ cleanup_device_list (void) dev_list = NULL; } +static SANE_Bool +pixma_fixup_serial(SANE_Device *sdev) +{ + struct pixma_sane_t * ss; + size_t cdev_len; + const char *open_dev_id; + + cdev_len = strlen(sdev->name); + for (ss = first_scanner; ss; ss = ss->next) + { + open_dev_id = pixma_get_string (ss->s, PIXMA_STRING_ID); + if (strlen(open_dev_id) > cdev_len && + strncmp(open_dev_id, sdev->name, cdev_len) == 0) + { + PDBG (pixma_dbg (3, "pixma_fixup_serial() change name from %s to %s\n", + sdev->name, open_dev_id)); + free_block ((const void *) sdev->name); + sdev->name = strdup (open_dev_id); + return SANE_TRUE; + } + } + return SANE_FALSE; +} + static void find_scanners (SANE_Bool local_only) { @@ -274,8 +298,10 @@ find_scanners (SANE_Bool local_only) sdev->model = model; sdev->vendor = vendor_str; sdev->type = type_str; + pixma_fixup_serial (sdev); dev_list[i] = sdev; } + /* dev_list is already NULL terminated by calloc(). */ return;