File hplip-support-prolific-2305.patch of Package hplip

--- hplip-3.25.8/io/hpmud/musb.c.orig	2025-11-13 13:27:26.000000000 +0200
+++ hplip-3.25.8/io/hpmud/musb.c	2026-02-06 09:16:46.378183754 +0200
@@ -582,110 +582,232 @@
     return i;
 }
 
-/* See if this usb device and URI match. */
-static int is_uri(libusb_device *dev, const char *uri)
+static int min(int a, int b)
 {
-    libusb_device_handle *hd=NULL;
-    struct libusb_device_descriptor devdesc;
-    char sz[128], uriModel[128], uriSerial[128], gen[128];
-    int r, stat=0;
+	if (a < b) return a;
+	if (a > b) return b;
+	return a;
+}
+
+static int is_prolific_(struct libusb_device_descriptor *devdesc) {
+  return devdesc->idVendor == 0x67b && devdesc->idProduct == 0x2305;
+}
+
+static int is_prolific(libusb_device *dev) {
+  struct libusb_device_descriptor devdesc;
+  libusb_get_device_descriptor(dev, &devdesc);
+  return is_prolific_(&devdesc);
+}
+
+static int is_us(libusb_device *dev) {
+  struct libusb_device_descriptor devdesc;
+  libusb_get_device_descriptor(dev, &devdesc);
+  return devdesc.idVendor == 0x3f0 || is_prolific_(&devdesc);
+}
+
+static int device_id(int fd, unsigned char *buffer, int size)
+{
+    libusb_device_handle *hd;
+    int config,interface,alt;
+    int len=0, rlen, maxSize;
+
+    hd = fd_table[fd].hd;
+    config = fd_table[fd].config;
+    interface = fd_table[fd].interface;
+    alt = fd_table[fd].alt_setting;
 
-    libusb_open(dev, &hd);
     if (hd == NULL)
     {
-        BUG("invalid usb_open: %m\n");
+        BUG("invalid device_id state\n");
         goto bugout;
     }
 
-    libusb_get_device_descriptor(dev, &devdesc);
-    if (devdesc.idVendor != 0x3f0)
-        goto bugout;
+    maxSize = (size > 1024) ? 1024 : size;   /* RH8 has a size limit for device id (usb) */
 
-    if ((r=get_string_descriptor(hd, devdesc.iProduct, sz, sizeof(sz))) < 0)
+    rlen = libusb_control_transfer(hd,
+            LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, /* bmRequestType */
+            LIBUSB_REQUEST_GET_STATUS,        /* bRequest */
+            config,        /* wValue */
+            interface, /* wIndex */    /* note firmware does not follow the USB Printer Class specification for wIndex */
+            buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT);
+
+    if (rlen < 0)
     {
-        BUG("invalid product id string ret=%d\n", r);
+        BUG("invalid deviceid ret=%d: %m\n", rlen);
         goto bugout;
     }
 
-    generalize_model(sz, gen, sizeof(gen));
+    len = ntohs(*(short *)buffer);
+    if (len > (size-1))
+        len = size-1;   /* leave byte for zero termination */
+    if (len > 2)
+        len -= 2;
+    memcpy(buffer, buffer+2, len);    /* remove length */
+    buffer[len]=0;
+    DBG("read actual device_id successfully fd=%d len=%d\n", fd, len);
+
+bugout:
+    return len; /* length does not include zero termination */
+}
 
-    hpmud_get_uri_model(uri, uriModel, sizeof(uriModel));
-    if (strcasecmp(uriModel, gen) != 0)
-        goto bugout;
+static int get_generalized(
+	libusb_device *dev,
+	char *mfg, int mfg_size,
+	char *model, int model_size,
+	char *serial, int serial_size)
+{
+	int r;
+	int status = 0;
+	char rmodel[128], rserial[128], rmfg[128];
+	char sz[HPMUD_LINE_SIZE];
+	libusb_device_handle *hd=NULL;
+	struct libusb_device_descriptor devdesc;
 
-    if ((r=get_string_descriptor(hd, devdesc.iSerialNumber, sz, sizeof(sz))) < 0)
-    {
-        BUG("invalid serial id string ret=%d\n", r);
-        goto bugout;
-    }
+	rmodel[0] = rserial[0] = rmfg[0] = 0;
+	model[0] = mfg[0] = serial[0] = 0;
 
-    if (sz[0])
-        generalize_serial(sz, gen, sizeof(gen));
-    else
-        strcpy(gen, "0");
+	/* assumes caller has already verified idProduct and idVendor */
 
-    get_uri_serial(uri, uriSerial, sizeof(uriSerial));
-    if (strcmp(uriSerial, gen) != 0)
-        goto bugout;
+        libusb_get_device_descriptor (dev, &devdesc);
 
-    stat = 1;    /* found usb device that matches uri */
+        if (!devdesc.bNumConfigurations || !devdesc.idVendor || !devdesc.idProduct)
+            return status;
 
-bugout:
-    if (hd != NULL)
-        libusb_close(hd);
+	if (devdesc.idVendor == 0x3f0)
+	{
+		/* this is a "true" HP usb printer, the idVendor will indicate so... */
 
-    return stat;
+		libusb_open(dev, &hd);
+		if (hd == NULL)
+		{
+		    BUG("Invalid usb_open: %m\n");
+		    return status;
+		}
+		/* Found hp device. */
+		if ((r=get_string_descriptor(hd, devdesc.iProduct, rmodel, sizeof(rmodel))) < 0)
+		    BUG("invalid product id string ret=%d\n", r);
+		else
+		    generalize_model(rmodel, model, model_size);
+
+		if ((r=get_string_descriptor(hd, devdesc.iSerialNumber, rserial, sizeof(rserial))) < 0)
+		    BUG("invalid serial id string ret=%d\n", r);
+		else
+		    generalize_serial(rserial, serial, serial_size);
+
+		if ((r=get_string_descriptor(hd, devdesc.iManufacturer, sz, sizeof(sz))) < 0)
+		    BUG("invalid manufacturer string ret=%d\n", r);
+		else
+		    generalize_serial(sz, mfg, mfg_size);
+
+		if (!serial[0])
+		    strcpy(serial, "0"); /* no serial number, make it zero */
+
+		status = model[0];
+
+		libusb_close(hd);
+	}
+	else
+	{
+		/* this may be a prolific usb->parallel thingy - read the actual device's id */
+
+		int fd;
+		int len;
+		if ((fd = claim_id_interface(dev)) != MAX_FD)
+		{
+			char *si;
+			char *sci;
+			len = device_id(fd, (unsigned char *)sz, sizeof(sz));
+
+			si = strstr(sz, "MODEL:");
+			if (si != NULL)
+			{
+				si += strlen("MODEL:");
+				sci = strstr(si, ";");
+				len = min(sci-si, model_size);
+				strncpy(rmodel, si, len);
+				rmodel[len] = '\0';
+				generalize_model(rmodel, model, model_size);
+			}
+
+			si = strstr(sz, "SERIAL:");
+			if (si != NULL)
+			{
+				si += strlen("SERIAL:");
+				sci = strstr(si, ";");
+				len = min(sci-si, model_size);
+				strncpy(rserial, si, len);
+				rserial[len] = '\0';
+				generalize_serial(rserial, serial, serial_size);
+			}
+
+			si = strstr(sz, "MANUFACTURER:");
+			if (si != NULL)
+			{
+				si += strlen("MANUFACTURER:");
+				sci = strstr(si, ";");
+				len = min(sci-si, mfg_size);
+				strncpy(rmfg, si, len);
+				rmfg[len] = '\0';
+				generalize_serial(rmfg, mfg, sizeof(mfg_size));
+			}
+
+			if (!serial[0])
+			    strcpy(serial, "0"); /* no serial number, make it zero */
+
+			status = model[0];
+
+			release_interface(&fd_table[fd]);
+		}
+	}
+
+	return status;
 }
 
-/* See if this usb device and serial number match. Return model if match. */
-static int is_serial(libusb_device *dev, const char *sn, char *model, int model_size)
+/* See if this usb device and URI match. */
+static int is_uri(libusb_device *dev, const char *uri)
 {
     libusb_device_handle *hd=NULL;
     struct libusb_device_descriptor devdesc;
-    char sz[128];
-    char gen[128];
+    char sz[128], uriModel[128], uriSerial[128], gen[128];
+    char model[128], serial[128], mfg[128];
     int r, stat=0;
 
-    libusb_open(dev, &hd);
-    if (hd == NULL)
-    {
-        BUG("invalid usb_open: %m\n");
+    if (get_generalized(dev, mfg, sizeof(mfg), model, sizeof(model), serial,
+                        sizeof(serial))) {
+      hpmud_get_uri_model(uri, uriModel, sizeof(uriModel));
+      if (strcasecmp(uriModel, model) != 0)
         goto bugout;
-    }
-
-    libusb_get_device_descriptor(dev, &devdesc);
-    if (devdesc.idVendor != 0x3f0)
-        goto bugout;      /* not a HP product */
-
-    if ((r=get_string_descriptor(hd, devdesc.iSerialNumber, sz, sizeof(sz))) < 0)
-    {
-        BUG("invalid serial id string ret=%d\n", r);
+      if (!serial[0])
+        strcpy(serial, "0");
+      get_uri_serial(uri, uriSerial, sizeof(uriSerial));
+      if (strcmp(uriSerial, serial) != 0)
         goto bugout;
+      stat = 1;
     }
-    if (sz[0])
-        generalize_serial(sz, gen, sizeof(gen));
-    else
-        strcpy(gen, "0");
-
-    if (strncmp(sn, gen, sizeof(gen)) != 0)
-        goto bugout;  /* match failed */
-
-    if ((r=get_string_descriptor(hd, devdesc.iProduct, sz, sizeof(sz))) < 0)
-    {
-        BUG("invalid product id string ret=%d\n", r);
-        goto bugout;
-    }
-    generalize_model(sz, model, model_size);
-
-    stat = 1;    /* found usb device that matches sn */
-
 bugout:
-    if (hd != NULL)
-        libusb_close(hd);
+  return stat;
+}
 
-    return stat;
+/* See if this usb device and serial number match. Return model if match. */
+static int is_serial(libusb_device *dev, const char *sn, char *model, int model_size)
+{
+  char serial[128], mfg[128];
+  char sz[128];
+  int r, stat = 0;
+
+  if (get_generalized(dev, mfg, sizeof(mfg), model, sizeof(model), serial,
+                      sizeof(serial))) {
+    if (!serial[0])
+      strcpy(serial, "0");
+    if (strncmp(sn, serial, sizeof(serial)) != 0)
+      goto bugout;
+    stat = 1;
+  }
+bugout:
+  return stat;
 }
 
+
 static libusb_device *get_libusb_device(const char *uri)
 {
     libusb_device *dev = NULL; /* Current device */
@@ -707,13 +829,17 @@
         if (!devdesc.bNumConfigurations || !devdesc.idVendor || !devdesc.idProduct)
             continue;
 
-        if (devdesc.idVendor != 0x3f0) /*Not a HP device*/
-            continue;
+        if (!is_us(dev)) {
+          DBG("get_libusb_device: not us=\n");
+          continue;
+	}
 
         for (conf = 0; conf < devdesc.bNumConfigurations; conf++)
         {
-            if (libusb_get_config_descriptor (dev, conf, &confptr) < 0)
-                continue;
+          if (libusb_get_config_descriptor(dev, conf, &confptr) < 0) {
+	    DBG("can't get usb config descriptor\n");
+            continue;
+	  }
             for (iface = 0, ifaceptr = confptr->interface; iface < confptr->bNumInterfaces; iface ++, ifaceptr ++)
             {
                 for (altset = 0, altptr = ifaceptr->altsetting; altset < ifaceptr->num_altsetting; altset++, altptr++)
@@ -726,7 +852,7 @@
                             libusb_free_config_descriptor(confptr);
                             return dev;  /* found usb device that matches uri */
                         }
-                    }
+                    } else DBG("not the right class/subclass: %x %x\n", altptr->bInterfaceClass, altptr->bInterfaceSubClass);
                 }
             }
             libusb_free_config_descriptor(confptr); confptr = NULL;
@@ -739,50 +865,6 @@
     return NULL;
 }
 
-static int device_id(int fd, unsigned char *buffer, int size)
-{
-    libusb_device_handle *hd;
-    int config,interface,alt;
-    int len=0, rlen, maxSize;
-
-    hd = fd_table[fd].hd;
-    config = fd_table[fd].config;
-    interface = fd_table[fd].interface;
-    alt = fd_table[fd].alt_setting;
-
-    if (hd == NULL)
-    {
-        BUG("invalid device_id state\n");
-        goto bugout;
-    }
-
-    maxSize = (size > 1024) ? 1024 : size;   /* RH8 has a size limit for device id (usb) */
-
-    rlen = libusb_control_transfer(hd,
-            LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, /* bmRequestType */
-            LIBUSB_REQUEST_GET_STATUS,        /* bRequest */
-            config,        /* wValue */
-            interface, /* wIndex */    /* note firmware does not follow the USB Printer Class specification for wIndex */
-            buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT);
-
-    if (rlen < 0)
-    {
-        BUG("invalid deviceid ret=%d: %m\n", rlen);
-        goto bugout;
-    }
-
-    len = ntohs(*(short *)buffer);
-    if (len > (size-1))
-        len = size-1;   /* leave byte for zero termination */
-    if (len > 2)
-        len -= 2;
-    memcpy(buffer, buffer+2, len);    /* remove length */
-    buffer[len]=0;
-    DBG("read actual device_id successfully fd=%d len=%d\n", fd, len);
-
-bugout:
-    return len; /* length does not include zero termination */
-}
 
 static int device_status(int fd, unsigned int *status)
 {
@@ -1421,12 +1503,14 @@
 
     if (( ep = get_in_ep(libusb_dev, fd_table[fd].config, fd_table[fd].interface, fd_table[fd].alt_setting, LIBUSB_TRANSFER_TYPE_BULK)) >= 0)
     {
-		//libusb_clear_halt(fd_table[fd].hd,  ep);
+      if (is_prolific(libusb_dev))
+	libusb_clear_halt(fd_table[fd].hd, ep);
     }
 
     if (( ep = get_out_ep(libusb_dev, fd_table[fd].config, fd_table[fd].interface, fd_table[fd].alt_setting, LIBUSB_TRANSFER_TYPE_BULK)) >= 0)
     {
-		//libusb_clear_halt(fd_table[fd].hd,  ep);
+      if (is_prolific(libusb_dev))
+	libusb_clear_halt(fd_table[fd].hd, ep);
     }
     release_interface(&fd_table[fd]);
 
@@ -2053,6 +2137,7 @@
     struct hpmud_model_attributes ma;
     char rmodel[128], rserial[128], model[128];
     char serial[128], mfg[128], sz[HPMUD_LINE_SIZE];
+    char rmfg[128];
     int r, size=0;
 
     libusb_init(&ctx);
@@ -2061,7 +2146,7 @@
     if (numdevs <= 0)
         goto bugout1;
 
-    model[0] = serial[0] = rmodel[0] = rserial[0] = sz[0] = mfg[0] = 0;
+    model[0] = serial[0] = rmodel[0] = rserial[0] = sz[0] = mfg[0] = rmfg[0] = 0;
 
     for (i = 0; i < numdevs; i++)
     {
@@ -2075,8 +2160,8 @@
         if (!devdesc.bNumConfigurations || !devdesc.idVendor || !devdesc.idProduct)
             continue;
 
-        if(devdesc.idVendor != 0x3f0) /*Not a HP device */
-            continue;
+        if (!is_us(dev))
+	  continue;
 
         for (conf = 0; (dev_already_counted == 0 && conf < devdesc.bNumConfigurations); conf++)
         {
@@ -2093,35 +2178,12 @@
                         {
                             continue; /*Check for only print interface (7/1/2) */
                         }
-                        
-                        libusb_open(dev, &hd);
-                        if (hd == NULL)
-                        {
-                            BUG("Invalid usb_open: %m\n");
-                            continue;
-                        }
-                        /* Found hp device. */
-                        if ((r=get_string_descriptor(hd, devdesc.iProduct, rmodel, sizeof(rmodel))) < 0)
-                            BUG("invalid product id string ret=%d\n", r);
-                        else
-                            generalize_model(rmodel, model, sizeof(model));
-
-                        if ((r=get_string_descriptor(hd, devdesc.iSerialNumber, rserial, sizeof(rserial))) < 0)
-                            BUG("invalid serial id string ret=%d\n", r);
-                        else
-                            generalize_serial(rserial, serial, sizeof(serial));
-
-                        if ((r=get_string_descriptor(hd, devdesc.iManufacturer, sz, sizeof(sz))) < 0)
-                            BUG("invalid manufacturer string ret=%d\n", r);
-                        else
-                            generalize_serial(sz, mfg, sizeof(serial));
+                        if (get_generalized(dev, mfg, sizeof(mfg), model,
+                                           sizeof(model), serial,
+                                           sizeof(serial))) {
 
-                        if (!serial[0])
-                            strcpy(serial, "0"); /* no serial number, make it zero */
-
-                        if (model[0])
-                        {
-                            snprintf(sz, sizeof(sz), "hp:/usb/%s?serial=%s", model, serial);
+			  if (model[0])
+			    snprintf(sz, sizeof(sz), "hp:/usb/%s?serial=%s", model, serial);
 
                             /* See if device is supported by hplip. */
                             hpmud_query_model(sz, &ma);
@@ -2144,7 +2206,6 @@
 
                             *cnt+=1;
                         }
-                        libusb_close(hd); hd = NULL;
                         dev_already_counted = 1;
                         break;
                     }
@@ -2156,8 +2217,6 @@
     }//end for loop
 
 bugout:
-    if (!hd)
-        libusb_close(hd);
     if (confptr)
         libusb_free_config_descriptor(confptr);
     libusb_free_device_list(list, 1);
@@ -2177,7 +2236,7 @@
     struct libusb_config_descriptor *confptr = NULL; /* Pointer to current configuration */
     const struct libusb_interface *ifaceptr = NULL; /* Pointer to current interface */
     const struct libusb_interface_descriptor *altptr = NULL; /* Pointer to current alternate setting */
-    char model[128], serial[128], sz[256];
+    char mfg[128], model[128], serial[128], sz[256];
     int r, numdevs, i;
     int conf, iface, altset ;
     int bus_num, dev_num;
@@ -2215,31 +2274,13 @@
     }
 
     dev = found_dev;
-    libusb_open(dev, &hd);
 
-    if (hd == NULL)
-    {
-        BUG("invalid libusb_open: %m\n");
-        goto bugout;
-    }
-
-    model[0] = serial[0] = sz[0] = 0;
+    mfg[0] = model[0] = serial[0] = sz[0] = 0;
 
     libusb_get_device_descriptor (dev, &devdesc);
 
-    if (devdesc.idVendor == 0x3f0)
+    if (is_us(dev) && get_generalized(dev, mfg, sizeof(mfg), model, sizeof(model), serial, sizeof(serial)))
     {
-        /* Found hp device. */
-        if ((r=get_string_descriptor(hd, devdesc.iProduct, sz, sizeof(sz))) < 0)
-            BUG("invalid product id string ret=%d\n", r);
-        else
-            generalize_model(sz, model, sizeof(model));
-
-        if ((r=get_string_descriptor(hd, devdesc.iSerialNumber, sz, sizeof(sz))) < 0)
-            BUG("invalid serial id string ret=%d\n", r);
-        else
-            generalize_serial(sz, serial, sizeof(serial));
-
         if (!serial[0])
             strcpy(serial, "0"); /* no serial number, make it zero */
 
openSUSE Build Service is sponsored by