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 */