1 /*****************************************************************************\
3 musb.c - USB support for multi-point transport driver
5 (c) 2010 Copyright Hewlett-Packard Development Company, LP
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 of the Software, and to permit persons to whom the Software is furnished to do
12 so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Client/Server generic message format (see messaging-protocol.doc):
25 Author: Naga Samrat Chowdary Narla, Sarbeswar Meher
26 \*****************************************************************************/
31 mud_device_vf __attribute__ ((visibility ("hidden"))) musb_mud_device_vf =
37 .get_device_id = musb_get_device_id,
38 .get_device_status = musb_get_device_status,
39 .channel_open = musb_channel_open,
40 .channel_close = musb_channel_close,
41 .channel_write = musb_channel_write,
42 .channel_read = musb_channel_read
45 static mud_channel_vf musb_raw_channel_vf =
47 .open = musb_raw_channel_open,
48 .close = musb_raw_channel_close,
49 .channel_write = musb_raw_channel_write,
50 .channel_read = musb_raw_channel_read
53 static mud_channel_vf musb_comp_channel_vf =
55 .open = musb_comp_channel_open,
56 .close = musb_raw_channel_close,
57 .channel_write = musb_raw_channel_write,
58 .channel_read = musb_raw_channel_read
61 static mud_channel_vf musb_mlc_channel_vf =
63 .open = musb_mlc_channel_open,
64 .close = musb_mlc_channel_close,
65 .channel_write = musb_mlc_channel_write,
66 .channel_read = musb_mlc_channel_read
69 static mud_channel_vf musb_dot4_channel_vf =
71 .open = musb_dot4_channel_open,
72 .close = musb_dot4_channel_close,
73 .channel_write = musb_dot4_channel_write,
74 .channel_read = musb_dot4_channel_read
78 * The folloing fd arrays must match "enum FD_ID" definition.
81 static char *fd_name[MAX_FD] =
97 static int fd_class[MAX_FD] =
99 0,0x7,0x7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
102 static int fd_subclass[MAX_FD] =
104 0,0x1,0x1,0x1,0x2,0x3,0xff,0xd4,0x4,0x1,0xcc,0x2,
107 static int fd_protocol[MAX_FD] =
109 0,0x2,0x3,0x1,0x1,0x1,0xff,0,0x1,0,0,0x10,
112 static const unsigned char venice_power_on[] = {0x1b, '%','P','u','i','f','p','.','p','o','w','e','r',' ','1',';',
113 'u','d','w','.','q','u','i','t',';',0x1b,'%','-','1','2','3','4','5','X' };
115 static struct usb_device *libusb_device; /* libusb device referenced by URI */
116 //static int open_fd; /* 7/1/2 file descriptor, used by deviceid and status */
117 static file_descriptor fd_table[MAX_FD]; /* usb file descriptors */
119 /* This function is similar to usb_get_string_simple, but it handles zero returns. */
120 static int get_string_descriptor(usb_dev_handle *dev, int index, char *buf, size_t buflen)
122 char tbuf[255]; /* Some devices choke on size > 255 */
123 int ret, si, di, cnt=5;
127 ret = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index,
128 0x409, tbuf, sizeof(tbuf), LIBUSB_CONTROL_REQ_TIMEOUT);
131 /* This retry is necessary for lj1000 and lj1005. des 12/12/07 */
132 BUG("get_string_descriptor zero result, retrying...");
140 BUG("unable get_string_descriptor %d: %m\n", ret);
144 if (tbuf[1] != USB_DT_STRING)
146 BUG("invalid get_string_descriptor tag act=%d exp=%d\n", tbuf[1], USB_DT_STRING);
152 BUG("invalid get_string_descriptor size act=%d exp=%d\n", tbuf[0], ret);
156 for (di = 0, si = 2; si < tbuf[0]; si += 2)
158 if (di >= (buflen - 1))
161 if (tbuf[si + 1]) /* high byte */
164 buf[di++] = tbuf[si];
172 /* Check for USB interface descriptor with specified class. */
173 static int is_interface(struct usb_device *dev, int dclass)
175 struct usb_interface_descriptor *pi;
178 for (i=0; i<dev->descriptor.bNumConfigurations; i++)
180 for (j=0; j<dev->config[i].bNumInterfaces; j++)
182 for (k=0; k<dev->config[i].interface[j].num_altsetting; k++)
184 pi = &dev->config[i].interface[j].altsetting[k];
185 if (pi->bInterfaceClass == dclass)
187 return 1; /* found interface */
192 return 0; /* no interface found */
195 /* Write HP vendor-specific ECP channel message. */
196 static int write_ecp_channel(file_descriptor *pfd, int value)
199 int interface = pfd->interface;
205 BUG("invalid write_ecp_channel state\n");
211 len = usb_control_msg(hd,
212 USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, /* bmRequestType */
213 USB_REQ_GET_STATUS, /* bRequest */
215 interface, /* wIndex */
216 &byte, 1, LIBUSB_CONTROL_REQ_TIMEOUT);
220 BUG("invalid write_ecp_channel: %m\n");
230 /* Set Cypress USS-725 Bridge Chip to 1284.4 mode. */
231 static int bridge_chip_up(file_descriptor *pfd)
240 BUG("invalid bridge_chip_up state\n");
246 memset(buf, 0, sizeof(buf));
248 /* Read register values. */
249 len = usb_control_msg(hd,
250 USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
251 USB_REQ_SET_FEATURE, /* bRequest */
254 buf, sizeof(buf), LIBUSB_CONTROL_REQ_TIMEOUT);
257 BUG("invalid write_bridge_up: %m\n");
261 /* Check for auto ECP mode. */
262 if (buf[ECRR] != 0x43)
264 /* Place 725 chip in register mode. */
265 len = usb_control_msg(hd,
266 USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
270 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
271 /* Turn off RLE in auto ECP mode. */
272 len = usb_control_msg(hd,
273 USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
277 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
278 /* Place 725 chip in auto ECP mode. */
279 len = usb_control_msg(hd,
280 USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
284 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
285 /* Force negotiation. */
286 len = usb_control_msg(hd,
287 USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
291 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
292 /* Read register values. */
293 len = usb_control_msg(hd,
294 USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
295 USB_REQ_SET_FEATURE, /* bRequest */
298 buf, sizeof(buf), LIBUSB_CONTROL_REQ_TIMEOUT);
299 if (buf[ECRR] != 0x43)
301 BUG("invalid auto ecp mode mode=%d\n", buf[ECRR]);
305 /* Reset to ECP channel 0. */
306 len = usb_control_msg(hd,
307 USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
311 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
312 musb_write(pfd->fd, &nullByte, 1, HPMUD_EXCEPTION_TIMEOUT);
314 /* Switch to ECP channel 77. */
315 len = usb_control_msg(hd,
316 USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
320 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
328 /* Set Cypress USS-725 Bridge Chip to compatibility mode. */
329 static int bridge_chip_down(file_descriptor *pfd)
336 BUG("invalid bridge_chip_down state\n");
342 len = usb_control_msg(hd,
343 USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
347 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
350 BUG("invalid write_bridge_up: %m\n");
360 /* Write HP vendor-specific Setup command. */
361 static int write_phoenix_setup(file_descriptor *pfd)
368 BUG("invalid write_phoenix_setup state\n");
374 len = usb_control_msg(hd,
375 USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, /* bmRequestType */
379 NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
383 BUG("invalid write_phoenix_setup: %m\n");
393 /* Detach any kernel module that may have claimed specified inteface. */
394 static int detach(usb_dev_handle *hd, int interface)
400 #ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
401 /* If any kernel module (ie:usblp) has claimed this interface, detach it. */
402 usb_get_driver_np(hd, interface, driver, sizeof(driver));
403 if ((driver[0] != 0) && (strcasecmp(driver, "usbfs") != 0))
405 DBG("removing %s driver interface=%d\n", driver, interface);
406 if (usb_detach_kernel_driver_np(hd, interface) < 0)
407 BUG("could not remove %s driver interface=%d: %m\n", driver, interface);
414 /* Get interface descriptor for specified xx/xx/xx protocol. */
415 static int get_interface(struct usb_device *dev, enum FD_ID index, file_descriptor *pfd)
417 struct usb_interface_descriptor *pi;
420 for (i=0; i<dev->descriptor.bNumConfigurations; i++)
422 if (dev->config == NULL)
425 for (j=0; j<dev->config[i].bNumInterfaces; j++)
427 if (dev->config[i].interface == NULL)
430 for (k=0; k<dev->config[i].interface[j].num_altsetting; k++)
432 if (dev->config[i].interface[j].altsetting == NULL)
435 pi = &dev->config[i].interface[j].altsetting[k];
436 if (pi->bInterfaceClass == fd_class[index] && pi->bInterfaceSubClass == fd_subclass[index] && pi->bInterfaceProtocol == fd_protocol[index])
438 pfd->config=i; /* found interface */
449 return 1; /* no interface found */
452 /* Get out endpoint for specified interface descriptor. */
453 static int get_out_ep(struct usb_device *dev, int config, int interface, int altset, int type)
455 struct usb_interface_descriptor *pi;
458 if (dev->config == NULL || dev->config[config].interface == NULL || dev->config[config].interface[interface].altsetting == NULL)
461 pi = &dev->config[config].interface[interface].altsetting[altset];
462 for (i=0; i<pi->bNumEndpoints; i++)
464 if (pi->endpoint == NULL)
466 if (pi->endpoint[i].bmAttributes == type && !(pi->endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
467 DBG("get_out_ep(type=%d): out=%d\n", type, pi->endpoint[i].bEndpointAddress);
468 return pi->endpoint[i].bEndpointAddress;
473 DBG("get_out_ep: ERROR! returning -1\n");
474 return -1; /* no endpoint found */
477 /* Get in endpoint for specified interface descriptor. */
478 static int get_in_ep(struct usb_device *dev, int config, int interface, int altset, int type)
480 struct usb_interface_descriptor *pi;
483 if (dev->config == NULL || dev->config[config].interface == NULL || dev->config[config].interface[interface].altsetting == NULL)
486 pi = &dev->config[config].interface[interface].altsetting[altset];
487 for (i=0; i<pi->bNumEndpoints; i++)
489 if (pi->endpoint == NULL)
491 if (pi->endpoint[i].bmAttributes == type && (pi->endpoint[i].bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
492 DBG("get_in_ep(type=%d): out=%d\n", type, pi->endpoint[i].bEndpointAddress);
493 return pi->endpoint[i].bEndpointAddress;
498 DBG("get_in_ep: ERROR! returning -1\n");
499 return -1; /* no endpoint found */
502 static int claim_interface(struct usb_device *dev, file_descriptor *pfd)
507 return 0; /* interface is already claimed */
509 if ((pfd->hd = usb_open(dev)) == NULL)
511 BUG("invalid usb_open: %m\n");
515 detach(pfd->hd, pfd->interface);
517 #if 0 /* hp devices only have one configuration, so far ... */
518 if (usb_set_configuration(FD[fd].pHD, dev->config[config].bConfigurationValue))
522 if (usb_claim_interface(pfd->hd, pfd->interface))
526 DBG("invalid claim_interface %s: %m\n", fd_name[pfd->fd]);
530 if (usb_set_altinterface(pfd->hd, pfd->alt_setting))
532 usb_release_interface(pfd->hd, pfd->interface);
535 BUG("invalid set_altinterface %s altset=%d: %m\n", fd_name[pfd->fd], pfd->alt_setting);
540 pthread_mutex_init(&pfd->mutex, NULL);
541 pthread_cond_init(&pfd->write_done_cond, NULL);
543 DBG("claimed %s interface\n", fd_name[pfd->fd]);
551 static int release_interface(file_descriptor *pfd)
556 if (pfd->write_active)
558 BUG("aborting outstanding %s write\n", fd_name[pfd->fd]);
559 pthread_cancel(pfd->tid); /* kill outstanding write */
560 pfd->write_active = 0;
563 usb_release_interface(pfd->hd, pfd->interface);
566 pthread_mutex_destroy(&pfd->mutex);
567 pthread_cond_destroy(&pfd->write_done_cond);
569 DBG("released %s interface\n", fd_name[pfd->fd]);
574 /* Claim any open interface which is valid for device_id and device status. */
575 static int claim_id_interface(struct usb_device *dev)
579 for (i=FD_7_1_2; i!=MAX_FD; i++)
581 if (get_interface(dev, i, &fd_table[i]) == 0)
583 if (claim_interface(libusb_device, &fd_table[i]))
584 continue; /* interface is busy, try next interface */
592 /* See if this usb device and URI match. */
593 static int is_uri(struct usb_device *dev, const char *uri)
595 usb_dev_handle *hd=NULL;
602 if ((hd = usb_open(dev)) == NULL)
604 BUG("invalid usb_open: %m\n");
608 if (dev->descriptor.idVendor != 0x3f0)
611 if ((r=get_string_descriptor(hd, dev->descriptor.iProduct, sz, sizeof(sz))) < 0)
613 BUG("invalid product id string ret=%d\n", r);
617 generalize_model(sz, gen, sizeof(gen));
619 hpmud_get_uri_model(uri, uriModel, sizeof(uriModel));
620 if (strcasecmp(uriModel, gen) != 0)
623 if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, sz, sizeof(sz))) < 0)
625 BUG("invalid serial id string ret=%d\n", r);
630 generalize_serial(sz, gen, sizeof(gen));
634 get_uri_serial(uri, uriSerial, sizeof(uriSerial));
635 if (strcmp(uriSerial, gen) != 0)
638 stat = 1; /* found usb device that matches uri */
647 /* See if this usb device and serial number match. Return model if match. */
648 static int is_serial(struct usb_device *dev, const char *sn, char *model, int model_size)
650 usb_dev_handle *hd=NULL;
655 if ((hd = usb_open(dev)) == NULL)
657 BUG("invalid usb_open: %m\n");
661 if (dev->descriptor.idVendor != 0x3f0)
662 goto bugout; /* not a HP product */
664 if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, sz, sizeof(sz))) < 0)
666 BUG("invalid serial id string ret=%d\n", r);
670 generalize_serial(sz, gen, sizeof(gen));
674 if (strncmp(sn, gen, sizeof(gen)) != 0)
675 goto bugout; /* match failed */
677 if ((r=get_string_descriptor(hd, dev->descriptor.iProduct, sz, sizeof(sz))) < 0)
679 BUG("invalid product id string ret=%d\n", r);
682 generalize_model(sz, model, model_size);
684 stat = 1; /* found usb device that matches sn */
693 static struct usb_device *get_libusb_device(const char *uri)
696 struct usb_device *dev;
698 for (bus=usb_busses; bus; bus=bus->next)
699 for (dev=bus->devices; dev; dev=dev->next)
700 if (dev->descriptor.idVendor == 0x3f0 && is_interface(dev, 7))
701 if (is_uri(dev, uri))
702 return dev; /* found usb device that matches uri */
707 static int device_id(int fd, char *buffer, int size)
710 int config,interface,alt;
711 int len=0, rlen, maxSize;
713 hd = fd_table[fd].hd;
714 config = fd_table[fd].config;
715 interface = fd_table[fd].interface;
716 alt = fd_table[fd].alt_setting;
720 BUG("invalid device_id state\n");
724 maxSize = (size > 1024) ? 1024 : size; /* RH8 has a size limit for device id (usb) */
726 rlen = usb_control_msg(hd,
727 USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, /* bmRequestType */
728 USB_REQ_GET_STATUS, /* bRequest */
730 interface, /* wIndex */ /* note firmware does not follow the USB Printer Class specification for wIndex */
731 buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT);
735 #if 0 /* Removed this PS A420 hack so a valid error is returned after USB reset. DES 10/1/09 */
736 /* Following retry is necessary for a firmware problem with PS A420 products. DES 4/17/07 */
737 BUG("invalid deviceid wIndex=%x, retrying wIndex=%x: %m\n", interface, interface << 8);
738 rlen = usb_control_msg(hd,
739 USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, /* bmRequestType */
740 USB_REQ_GET_STATUS, /* bRequest */
742 interface << 8, /* wIndex */
743 buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT);
746 BUG("invalid deviceid retry ret=%d: %m\n", rlen);
750 BUG("invalid deviceid ret=%d: %m\n", rlen);
754 len = ntohs(*(short *)buffer);
756 len = size-1; /* leave byte for zero termination */
759 memcpy(buffer, buffer+2, len); /* remove length */
761 DBG("read actual device_id successfully fd=%d len=%d\n", fd, len);
764 return len; /* length does not include zero termination */
767 static int device_status(int fd, unsigned int *status)
774 hd = fd_table[fd].hd;
775 interface = fd_table[fd].interface;
779 BUG("invalid device_status state\n");
783 len = usb_control_msg(hd,
784 USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, /* bmRequestType */
785 USB_REQ_CLEAR_FEATURE, /* bRequest */
787 interface, /* wIndex */
788 &byte, 1, LIBUSB_CONTROL_REQ_TIMEOUT);
792 BUG("invalid device_status: %m\n");
796 *status = (unsigned int)byte;
798 DBG("read actual device_status successfully fd=%d\n", fd);
804 /* Get VStatus from S-field. */
805 static int sfield_printer_state(const char *id)
810 if ((pSf = strstr(id, ";S:")) == NULL)
812 BUG("invalid S-field\n");
816 /* Valid S-field, get version number. */
825 /* Position pointer to printer state subfield. */
840 BUG("unknown S-field version=%d\n", ver);
845 /* Extract VStatus.*/
847 HEX2INT(*pSf, vstatus);
849 vstatus = vstatus << 4;
850 HEX2INT(*pSf, vstatus);
856 * Power up printer if necessary. Most all-in-ones have no power down state (ie: OJ K80), so they are already powered up.
857 * Newer single function printers power-up with the print job. May be called by other mud_device.
859 int __attribute__ ((visibility ("hidden"))) power_up(mud_device *pd, int fd)
863 if ((pSf = strstr(pd->id, "CMD:LDL")) != NULL)
864 return 0; /* crossbow don't do power-up */
866 if ((pSf = strstr(pd->id, ";S:")) != NULL)
868 if (sfield_printer_state(pd->id) != 3)
869 return 0; /* already powered up */
871 else if ((pSf = strstr(pd->id, "VSTATUS:")) != NULL)
873 /* DJ895C returns $XB0$XC0 (unknown pens) when powered off. */
874 if (!(strstr(pSf+8, "OFFF") || strstr(pSf+8, "PWDN") || strstr(pSf+8, "$X")))
875 return 0; /* already powered up */
878 return 0; /* must be laserjet, don't do power-up */
880 (pd->vf.write)(fd, venice_power_on, sizeof(venice_power_on), HPMUD_EXCEPTION_TIMEOUT);
886 /* Create channel object given the requested socket id and service name. */
887 static int new_channel(mud_device *pd, int index, const char *sn)
891 /* Check for existing name service already open. */
892 if (pd->channel[index].client_cnt)
895 if (index == HPMUD_EWS_CHANNEL)
897 pd->channel[index].client_cnt++; /* allow multiple clients for separate USB interfaces only */
899 DBG("reused %s channel=%d clientCnt=%d channelCnt=%d\n", sn, index, pd->channel[index].client_cnt, pd->channel_cnt);
903 BUG("%s channel=%d is busy, used by [%d], clientCnt=%d channelCnt=%d\n", sn, index, pd->channel[index].pid, pd->channel[index].client_cnt, pd->channel_cnt);
907 if (index == HPMUD_EWS_CHANNEL || index == HPMUD_EWS_LEDM_CHANNEL ||
908 index == HPMUD_SOAPSCAN_CHANNEL || index == HPMUD_SOAPFAX_CHANNEL ||
909 index == HPMUD_MARVELL_SCAN_CHANNEL || index == HPMUD_MARVELL_FAX_CHANNEL ||
910 index == HPMUD_LEDM_SCAN_CHANNEL) {
911 pd->channel[index].vf = musb_comp_channel_vf;
913 else if (pd->io_mode == HPMUD_RAW_MODE || pd->io_mode == HPMUD_UNI_MODE) {
914 pd->channel[index].vf = musb_raw_channel_vf;
916 else if (pd->io_mode == HPMUD_MLC_GUSHER_MODE || pd->io_mode == HPMUD_MLC_MISER_MODE) {
917 pd->channel[index].vf = musb_mlc_channel_vf;
920 pd->channel[index].vf = musb_dot4_channel_vf;
923 pd->channel[index].index = index;
924 pd->channel[index].client_cnt = 1;
925 pd->channel[index].sockid = index; /* static socket id is valid for MLC but not 1284.4 */
926 pd->channel[index].pid = getpid();
927 pd->channel[index].dindex = pd->index;
928 pd->channel[index].fd = 0;
929 strcpy(pd->channel[index].sn, sn);
933 DBG("new %s channel=%d clientCnt=%d channelCnt=%d\n", sn, index, pd->channel[index].client_cnt, pd->channel_cnt);
939 /* Remove channel object given the channel decriptor. */
940 static int del_channel(mud_device *pd, mud_channel *pc)
944 if (pc->client_cnt <= 0)
948 DBG("removed %s channel=%d clientCnt=%d channelCnt=%d\n", pc->sn, pc->index, pc->client_cnt, pd->channel_cnt);
952 static void write_thread(file_descriptor *pfd)
956 pthread_detach(pthread_self());
958 if ((ep = get_out_ep(libusb_device, pfd->config, pfd->interface, pfd->alt_setting, USB_ENDPOINT_TYPE_BULK)) < 0)
960 BUG("invalid bulk out endpoint\n");
964 /* Wait forever for write to complete (actually 72 hours in ms). */
965 pfd->write_return = usb_bulk_write(pfd->hd, ep, (char *)pfd->write_buf, pfd->write_size, 72*3600*1000);
968 pthread_mutex_lock(&pfd->mutex);
969 pfd->write_buf = NULL;
970 pthread_cond_signal(&pfd->write_done_cond); /* signal write is complete */
971 pthread_mutex_unlock(&pfd->mutex);
976 /*********************************************************************************************************************************
977 * USB mud_device functions.
980 int __attribute__ ((visibility ("hidden"))) musb_write(int fd, const void *buf, int size, int usec)
984 if (fd_table[fd].hd == NULL)
986 BUG("invalid musb_write state\n");
992 struct timespec timeout;
994 /* If write is still active, probably OOP condition, don't kick off a new write. */
995 if (!fd_table[fd].write_active)
997 fd_table[fd].write_active = 1;
998 fd_table[fd].write_buf = buf;
999 fd_table[fd].write_size = size;
1001 /* Create usb_bulk_write thread so we can use our own timeout. Otherwise we cannot handle OOP condition. */
1002 if (pthread_create(&fd_table[fd].tid, NULL, (void *(*)(void*))write_thread, (void *)&fd_table[fd]) != 0)
1004 BUG("unable to creat write_thread: %m\n");
1005 goto bugout; /* bail */
1009 /* Wait for write to complete. */
1010 pthread_mutex_lock(&fd_table[fd].mutex);
1011 gettimeofday(&now, NULL);
1012 now.tv_usec += usec;
1013 now.tv_sec += now.tv_usec / 1000000;
1014 now.tv_usec %= 1000000;
1015 timeout.tv_sec = now.tv_sec;
1016 timeout.tv_nsec = now.tv_usec * 1000;
1018 while (fd_table[fd].write_buf && ret != ETIMEDOUT)
1019 ret = pthread_cond_timedwait(&fd_table[fd].write_done_cond, &fd_table[fd].mutex, &timeout);
1020 pthread_mutex_unlock(&fd_table[fd].mutex);
1022 if (ret == ETIMEDOUT)
1024 len = -ETIMEDOUT; /* write timeout, let client know */
1028 fd_table[fd].write_active = 0;
1030 len = fd_table[fd].write_return;
1033 if ((ep = get_out_ep(libusb_device, fd_table[fd].config, fd_table[fd].interface, fd_table[fd].alt_setting, USB_ENDPOINT_TYPE_BULK)) < 0)
1035 BUG("invalid bulk out endpoint\n");
1039 len = usb_bulk_write(fd_table[fd].hd, ep, (char *)buf, size, usec);
1044 BUG("bulk_write failed buf=%p size=%d len=%d: %m\n", buf, size, len);
1048 DBG("write fd=%d len=%d size=%d usec=%d\n", fd, len, size, usec);
1049 DBG_DUMP(buf, len < 512 ? len : 512);
1055 int __attribute__ ((visibility ("hidden"))) musb_read(int fd, void *buf, int size, int usec)
1057 struct timeval t1, t2;
1058 int total_usec, tmo_usec=usec;
1061 if (fd_table[fd].hd == NULL)
1063 BUG("invalid musb_read state\n");
1067 gettimeofday (&t1, NULL); /* get start time */
1069 if ((ep = get_in_ep(libusb_device, fd_table[fd].config, fd_table[fd].interface, fd_table[fd].alt_setting, USB_ENDPOINT_TYPE_BULK)) < 0)
1071 BUG("invalid bulk in endpoint\n");
1077 len = usb_bulk_read(fd_table[fd].hd, ep, (char *)buf, size, tmo_usec/1000);
1079 if (len == -ETIMEDOUT)
1084 BUG("bulk_read failed: %m\n");
1090 /* Bulk_read has a timeout, but bulk_read can return zero byte packet(s), so we must use our own timeout here. */
1091 gettimeofday(&t2, NULL); /* get current time */
1093 total_usec = (t2.tv_sec - t1.tv_sec)*1000000;
1094 total_usec += (t2.tv_usec > t1.tv_usec) ? t2.tv_usec - t1.tv_usec : t1.tv_usec - t2.tv_usec;
1095 if (total_usec > usec)
1097 len = -ETIMEDOUT; /* timeout */
1100 tmo_usec = usec - total_usec; /* decrease timeout */
1107 DBG("read fd=%d len=%d size=%d usec=%d\n", fd, len, size, usec);
1108 DBG_DUMP(buf, len < 32 ? len : 32);
1114 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_open(mud_device *pd)
1117 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1123 /* Find usb device for specified uri. */
1124 if ((libusb_device = get_libusb_device(pd->uri)) == NULL)
1126 BUG("unable to open %s\n", pd->uri);
1130 pthread_mutex_lock(&pd->mutex);
1136 if ((fd = claim_id_interface(libusb_device)) == MAX_FD)
1138 stat = HPMUD_R_DEVICE_BUSY;
1142 len = device_id(fd, pd->id, sizeof(pd->id)); /* get new copy and cache it */
1144 if (len > 0 && is_hp(pd->id))
1147 release_interface(&fd_table[fd]);
1158 pthread_mutex_unlock(&pd->mutex);
1164 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_close(mud_device *pd)
1167 enum HPMUD_RESULT stat = HPMUD_R_OK;
1169 pthread_mutex_lock(&pd->mutex);
1171 for (i=1; i<MAX_FD; i++)
1173 if (fd_table[i].hd != NULL)
1174 release_interface(&fd_table[i]);
1179 pthread_mutex_unlock(&pd->mutex);
1184 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_get_device_id(mud_device *pd, char *buf, int size, int *len)
1187 enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1191 pthread_mutex_lock(&pd->mutex);
1193 if (pd->io_mode == HPMUD_DOT4_BRIDGE_MODE || pd->io_mode == HPMUD_UNI_MODE)
1195 *len = strlen(pd->id); /* usb/parallel bridge chip, use cached copy */
1199 /* See if any interface is already claimed. */
1200 for (i=1; i<MAX_FD; i++)
1202 if (fd_table[i].hd != NULL)
1211 /* Device not in use. Claim interface, but release for other processes. */
1212 if ((fd = claim_id_interface(libusb_device)) != MAX_FD)
1214 *len = device_id(fd, pd->id, sizeof(pd->id)); /* get new copy and cache it */
1215 release_interface(&fd_table[fd]);
1219 /* Device is in use by another process, return cache copy. */
1220 *len = strlen(pd->id);
1225 /* Device in use by current process, leave interface up. Other processes are blocked. */
1226 *len = device_id(fd, pd->id, sizeof(pd->id)); /* get new copy and cache it */
1232 memcpy(buf, pd->id, *len > size ? size : *len);
1236 pthread_mutex_unlock(&pd->mutex);
1240 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_get_device_status(mud_device *pd, unsigned int *status)
1243 enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1246 pthread_mutex_lock(&pd->mutex);
1248 if (pd->io_mode == HPMUD_DOT4_BRIDGE_MODE || pd->io_mode == HPMUD_UNI_MODE)
1249 *status = NFAULT_BIT; /* usb/parallel bridge chip, fake status */
1252 /* See if any interface is already claimed. */
1253 for (i=1; i<MAX_FD; i++)
1255 if (fd_table[i].hd != NULL)
1264 /* Device not in use. Claim interface, but release for other processes. */
1265 if ((fd = claim_id_interface(libusb_device)) != MAX_FD)
1267 r = device_status(fd, status);
1268 release_interface(&fd_table[fd]);
1273 /* Device in use by current process, leave interface up. Other processes are blocked. */
1274 r = device_status(fd, status);
1278 pthread_mutex_unlock(&pd->mutex);
1289 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_channel_write(mud_device *pd, mud_channel *pc, const void *buf, int length, int sec_timeout, int *bytes_wrote)
1291 enum HPMUD_RESULT stat;
1293 pthread_mutex_lock(&pd->mutex);
1294 stat = (pc->vf.channel_write)(pc, buf, length, sec_timeout, bytes_wrote);
1295 pthread_mutex_unlock(&pd->mutex);
1299 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_channel_read(mud_device *pd, mud_channel *pc, void *buf, int length, int sec_timeout, int *bytes_read)
1301 enum HPMUD_RESULT stat;
1303 if (pd->io_mode == HPMUD_UNI_MODE)
1305 stat = HPMUD_R_INVALID_STATE;
1306 BUG("invalid channel_read io_mode=%d\n", pd->io_mode);
1310 pthread_mutex_lock(&pd->mutex);
1311 stat = (pc->vf.channel_read)(pc, buf, length, sec_timeout, bytes_read);
1312 pthread_mutex_unlock(&pd->mutex);
1318 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_channel_open(mud_device *pd, const char *sn, HPMUD_CHANNEL *cd)
1321 enum HPMUD_RESULT stat;
1323 /* Check for valid service requests. */
1324 if ((stat = service_to_channel(pd, sn, &index)) != HPMUD_R_OK)
1327 pthread_mutex_lock(&pd->mutex);
1329 if (new_channel(pd, index, sn))
1331 stat = HPMUD_R_DEVICE_BUSY;
1335 if ((stat = (pd->channel[index].vf.open)(&pd->channel[index])) != HPMUD_R_OK) /* call transport specific open */
1336 del_channel(pd, &pd->channel[index]); /* open failed, cleanup */
1341 pthread_mutex_unlock(&pd->mutex);
1347 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_channel_close(mud_device *pd, mud_channel *pc)
1349 enum HPMUD_RESULT stat = HPMUD_R_OK;
1351 pthread_mutex_lock(&pd->mutex);
1352 stat = (pc->vf.close)(pc); /* call trasport specific close */
1353 del_channel(pd, pc);
1354 pthread_mutex_unlock(&pd->mutex);
1359 /*******************************************************************************************************************************
1360 * USB raw_channel functions.
1363 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_raw_channel_open(mud_channel *pc)
1366 enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1368 get_interface(libusb_device, fd, &fd_table[fd]);
1370 if (claim_interface(libusb_device, &fd_table[fd]))
1381 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_raw_channel_close(mud_channel *pc)
1385 // For New laserjet devices like Tsunami, end point was getting stall or halted, hence clearing it
1387 if (( ep = get_in_ep(libusb_device, fd_table[fd].config, fd_table[fd].interface, fd_table[fd].alt_setting, USB_ENDPOINT_TYPE_BULK)) >= 0)
1389 usb_clear_halt(fd_table[fd].hd, ep);
1392 if (( ep = get_out_ep(libusb_device, fd_table[fd].config, fd_table[fd].interface, fd_table[fd].alt_setting, USB_ENDPOINT_TYPE_BULK)) >= 0)
1394 usb_clear_halt(fd_table[fd].hd, ep);
1397 release_interface(&fd_table[fd]);
1404 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_raw_channel_write(mud_channel *pc, const void *buf, int length, int sec_timeout, int *bytes_wrote)
1406 int len, size, total=0;
1407 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1414 len = (msp->device[pc->dindex].vf.write)(pc->fd, buf+total, size, sec_timeout*1000000);
1417 if (len == -ETIMEDOUT)
1419 stat = HPMUD_R_IO_TIMEOUT;
1420 if (sec_timeout >= HPMUD_EXCEPTION_SEC_TIMEOUT)
1421 BUG("unable to write data %s: %d second io timeout\n", msp->device[pc->dindex].uri, sec_timeout);
1424 BUG("unable to write data %s: %m\n", msp->device[pc->dindex].uri);
1439 * Channel_read() tries to read "length" bytes from the peripheral. The returned read count may be zero
1440 * (timeout, no data available), less than "length" or equal "length".
1442 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_raw_channel_read(mud_channel *pc, void *buf, int length, int sec_timeout, int *bytes_read)
1445 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1450 usec = 1000; /* minmum timeout is 1ms for libusb 0.1.12, hangs forever with zero */
1452 usec = sec_timeout*1000000;
1454 len = (msp->device[pc->dindex].vf.read)(pc->fd, buf, length, usec);
1457 if (len == -ETIMEDOUT)
1459 stat = HPMUD_R_IO_TIMEOUT;
1460 if (sec_timeout >= HPMUD_EXCEPTION_SEC_TIMEOUT)
1461 BUG("unable to read data %s: %d second io timeout\n", msp->device[pc->dindex].uri, sec_timeout);
1464 BUG("unable to read data %s: %m\n", msp->device[pc->dindex].uri);
1475 /*******************************************************************************************************************************
1476 * USB comp_channel functions.
1479 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_comp_channel_open(mud_channel *pc)
1482 enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1484 /* Get requested composite interface. */
1487 case HPMUD_EWS_CHANNEL:
1490 case HPMUD_EWS_LEDM_CHANNEL:
1493 case HPMUD_SOAPSCAN_CHANNEL:
1496 case HPMUD_SOAPFAX_CHANNEL:
1499 case HPMUD_MARVELL_SCAN_CHANNEL:
1502 case HPMUD_MARVELL_FAX_CHANNEL: //using vendor specific C/S/P codes for fax too
1505 case HPMUD_LEDM_SCAN_CHANNEL: //using vendor specific C/S/P codes for fax too
1509 stat = HPMUD_R_INVALID_SN;
1510 BUG("invalid %s channel=%d\n", pc->sn, pc->index);
1515 if (get_interface(libusb_device, fd, &fd_table[fd]))
1517 stat = HPMUD_R_INVALID_SN;
1518 BUG("invalid %s channel=%d\n", pc->sn, pc->index);
1522 if (claim_interface(libusb_device, &fd_table[fd]))
1533 /*******************************************************************************************************************************
1534 * USB mlc_channel functions.
1537 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_mlc_channel_open(mud_channel *pc)
1539 mud_device *pd = &msp->device[pc->dindex];
1541 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1543 /* Initialize MLC transport if this is the first MLC channel. */
1544 if (pd->channel_cnt==1)
1546 if (get_interface(libusb_device, FD_7_1_3, &fd_table[FD_7_1_3]) == 0 && claim_interface(libusb_device, &fd_table[FD_7_1_3]) == 0)
1547 fd = FD_7_1_3; /* mlc, dot4 */
1548 else if (get_interface(libusb_device, FD_ff_ff_ff, &fd_table[FD_ff_ff_ff]) == 0 && claim_interface(libusb_device, &fd_table[FD_ff_ff_ff]) == 0)
1549 fd = FD_ff_ff_ff; /* mlc, dot4 */
1550 else if (get_interface(libusb_device, FD_ff_d4_0, &fd_table[FD_ff_d4_0]) == 0 && claim_interface(libusb_device, &fd_table[FD_ff_d4_0]) == 0)
1551 fd = FD_ff_d4_0; /* mlc, dot4 */
1552 else if (get_interface(libusb_device, FD_7_1_2, &fd_table[FD_7_1_2]) == 0 && claim_interface(libusb_device, &fd_table[FD_7_1_2]) == 0)
1553 fd = FD_7_1_2; /* raw, mlc, dot4 */
1556 stat = HPMUD_R_DEVICE_BUSY;
1562 /* Emulate 7/1/3 on 7/1/2 using vendor-specific ECP channel-77. */
1563 if (write_ecp_channel(&fd_table[fd], 77))
1569 // Removed reverse drain I seen it hang forever on read, one-time with PSC750 (FC5 64-bit). DES
1571 unsigned char buf[255];
1573 /* Drain any reverse data. */
1574 for (i=0,len=1; len > 0 && i < sizeof(buf); i++)
1575 len = (pd->vf.read)(fd, buf+i, 1, 0); /* no blocking */
1578 /* MLC initialize */
1579 if (MlcInit(pc, fd) != 0)
1582 /* Reset transport attributes for all channels. */
1583 for (i=0; i<HPMUD_CHANNEL_MAX; i++)
1584 memset(&pd->channel[i].ta, 0 , sizeof(transport_attributes));
1589 } /* if (pDev->ChannelCnt==1) */
1591 if (MlcConfigSocket(pc, pd->mlc_fd))
1594 if (MlcOpenChannel(pc, pd->mlc_fd))
1597 pc->rcnt = pc->rindex = 0;
1605 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_mlc_channel_close(mud_channel *pc)
1607 mud_device *pd = &msp->device[pc->dindex];
1608 unsigned char nullByte=0;
1609 enum HPMUD_RESULT stat = HPMUD_R_OK;
1613 if (MlcCloseChannel(pc, pd->mlc_fd))
1614 stat = HPMUD_R_IO_ERROR;
1617 /* Remove MLC transport if this is the last MLC channel. */
1618 if (pd->channel_cnt==1)
1622 if (MlcExit(pc, pd->mlc_fd))
1623 stat = HPMUD_R_IO_ERROR;
1627 if (pd->mlc_fd == FD_7_1_2)
1629 write_ecp_channel(&fd_table[pd->mlc_fd], 78);
1630 (pd->vf.write)(pd->mlc_fd, &nullByte, 1, HPMUD_EXCEPTION_TIMEOUT);
1631 write_ecp_channel(&fd_table[pd->mlc_fd], 0);
1634 release_interface(&fd_table[pd->mlc_fd]);
1636 /* Delay for back-to-back scanning using scanimage (OJ 7110, OJ d135). */
1643 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_mlc_channel_write(mud_channel *pc, const void *buf, int length, int sec_timeout, int *bytes_wrote)
1645 mud_device *pd = &msp->device[pc->dindex];
1646 int ret, len, size, dlen, total=0;
1647 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1651 dlen = pc->ta.h2psize - sizeof(MLCHeader);
1654 len = (size > dlen) ? dlen : size;
1656 if (pc->ta.h2pcredit == 0 && pd->io_mode == HPMUD_MLC_MISER_MODE)
1658 if (MlcCreditRequest(pc, pd->mlc_fd, 1)) /* Miser flow control */
1660 BUG("invalid MlcCreditRequest from peripheral\n");
1665 if (pc->ta.h2pcredit == 0)
1667 ret = MlcReverseCmd(pc, pd->mlc_fd);
1668 if (pc->ta.h2pcredit == 0)
1671 continue; /* Got a reverse command, but no MlcCredit, try again. */
1673 if (pd->io_mode != HPMUD_MLC_MISER_MODE)
1675 /* If miser flow control works for this device, set "miser" in models.dat. */
1676 BUG("invalid MlcCredit from peripheral, trying miser\n");
1677 pd->io_mode = HPMUD_MLC_MISER_MODE;
1681 BUG("invalid MlcCredit from peripheral\n");
1686 if (MlcForwardData(pc, pd->mlc_fd, buf+total, len, sec_timeout*1000000))
1704 * Mlc_channel_read() tries to read "length" bytes from the peripheral. ReadData() reads data in packet size chunks.
1705 * The returned read count may be zero (timeout, no data available), less than "length" or equal "length".
1707 * Mlc_channel_read() may read more the "length" if the data packet is greater than "length". For this case the
1708 * return value will equal "length" and the left over data will be buffered for the next ReadData() call.
1710 * The "timeout" specifies how many seconds to wait for a data packet. Once the read of the data packet has
1711 * started the "timeout" is no longer used.
1713 * Note, if a "timeout" occurs one peripheral to host credit is left outstanding. Which means the peripheral
1714 * can send unsolicited data later.
1716 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_mlc_channel_read(mud_channel *pc, void *buf, int length, int sec_timeout, int *bytes_read)
1718 mud_device *pd = &msp->device[pc->dindex];
1719 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1722 if (pc->ta.p2hsize==0)
1724 BUG("invalid channel_read state\n");
1731 *bytes_read = cut_buf(pc, buf, length);
1735 if (pc->ta.p2hcredit == 0)
1737 /* Issue enough credit to the peripheral to read one data packet. */
1738 if (MlcCredit(pc, pd->mlc_fd, 1))
1743 pc->rcnt = MlcReverseData(pc, pd->mlc_fd, pc->rbuf, sizeof(pc->rbuf), sec_timeout*1000000);
1745 pc->ta.p2hcredit--; /* one data packet was read, decrement credit count */
1747 *bytes_read = cut_buf(pc, buf, length);
1753 /*******************************************************************************************************************************
1754 * USB dot4_channel functions.
1757 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_dot4_channel_open(mud_channel *pc)
1759 mud_device *pd = &msp->device[pc->dindex];
1761 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1763 /* Initialize MLC transport if this is the first MLC channel. */
1764 if (pd->channel_cnt==1)
1766 if (get_interface(libusb_device, FD_7_1_3, &fd_table[FD_7_1_3]) == 0 && claim_interface(libusb_device, &fd_table[FD_7_1_3]) == 0)
1767 fd = FD_7_1_3; /* mlc, dot4 */
1768 else if (get_interface(libusb_device, FD_ff_ff_ff, &fd_table[FD_ff_ff_ff]) == 0 && claim_interface(libusb_device, &fd_table[FD_ff_ff_ff]) == 0)
1769 fd = FD_ff_ff_ff; /* mlc, dot4 */
1770 else if (get_interface(libusb_device, FD_ff_d4_0, &fd_table[FD_ff_d4_0]) == 0 && claim_interface(libusb_device, &fd_table[FD_ff_d4_0]) == 0)
1771 fd = FD_ff_d4_0; /* mlc, dot4 */
1772 else if (get_interface(libusb_device, FD_7_1_2, &fd_table[FD_7_1_2]) == 0 && claim_interface(libusb_device, &fd_table[FD_7_1_2]) == 0)
1773 fd = FD_7_1_2; /* raw, mlc, dot4 */
1776 stat = HPMUD_R_DEVICE_BUSY;
1782 if (pd->io_mode == HPMUD_DOT4_BRIDGE_MODE)
1784 /* Emulate 7/1/3 on 7/1/2 using the bridge chip set (ie: CLJ2500). */
1785 if (bridge_chip_up(&fd_table[fd]))
1790 /* Emulate 7/1/3 on 7/1/2 using vendor-specific ECP channel-77. */
1791 if (write_ecp_channel(&fd_table[fd], 77))
1796 if (pd->io_mode == HPMUD_DOT4_PHOENIX_MODE)
1797 write_phoenix_setup(&fd_table[fd]);
1801 // Removed reverse drain LJ1015 can hang forever on read (FC5 64-bit). DES
1802 unsigned char buf[255];
1805 /* Drain any reverse data. */
1806 for (i=0,len=1; len > 0 && i < sizeof(buf); i++)
1807 len = (pd->vf.read)(fd, buf+i, 1, 0); /* no blocking */
1809 /* DOT4 initialize */
1810 if (Dot4Init(pc, fd) != 0)
1813 /* Reset transport attributes for all channels. */
1814 for (i=0; i<HPMUD_CHANNEL_MAX; i++)
1815 memset(&pd->channel[i].ta, 0 , sizeof(transport_attributes));
1820 } /* if (pDev->ChannelCnt==1) */
1822 if (Dot4GetSocket(pc, pd->mlc_fd))
1825 if (Dot4OpenChannel(pc, pd->mlc_fd))
1828 if (pd->io_mode == HPMUD_DOT4_PHOENIX_MODE)
1830 /* Issue credit to peripheral. */
1831 if (Dot4Credit(pc, pd->mlc_fd, 2))
1833 BUG("invalid Dot4Credit to peripheral\n");
1838 pc->rcnt = pc->rindex = 0;
1846 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_dot4_channel_close(mud_channel *pc)
1848 mud_device *pd = &msp->device[pc->dindex];
1849 enum HPMUD_RESULT stat = HPMUD_R_OK;
1853 if (Dot4CloseChannel(pc, pd->mlc_fd))
1854 stat = HPMUD_R_IO_ERROR;
1857 /* Remove 1284.4 transport if this is the last 1284.4 channel. */
1858 if (pd->channel_cnt==1)
1862 if (Dot4Exit(pc, pd->mlc_fd))
1863 stat = HPMUD_R_IO_ERROR;
1867 if (pd->mlc_fd == FD_7_1_2)
1869 if (pd->io_mode == HPMUD_DOT4_BRIDGE_MODE)
1871 bridge_chip_down(&fd_table[pd->mlc_fd]);
1875 write_ecp_channel(&fd_table[pd->mlc_fd], 78);
1876 write_ecp_channel(&fd_table[pd->mlc_fd], 0);
1880 release_interface(&fd_table[pd->mlc_fd]);
1882 /* Delay for back-to-back scanning using scanimage (OJ 7110, OJ d135). */
1889 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_dot4_channel_write(mud_channel *pc, const void *buf, int length, int sec_timeout, int *bytes_wrote)
1891 mud_device *pd = &msp->device[pc->dindex];
1892 int ret, len, size, dlen, total=0, cnt=0;
1893 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1897 dlen = pc->ta.h2psize - sizeof(DOT4Header);
1900 len = (size > dlen) ? dlen : size;
1902 if (pc->ta.h2pcredit == 0 && pd->io_mode == HPMUD_DOT4_PHOENIX_MODE)
1904 /* Issue credit request to peripheral. */
1905 if (Dot4CreditRequest(pc, pd->mlc_fd, 1))
1907 BUG("invalid Dot4CreditRequest from peripheral\n");
1910 if (pc->ta.h2pcredit == 0)
1912 if (cnt++ > HPMUD_EXCEPTION_SEC_TIMEOUT)
1914 BUG("invalid Dot4CreditRequest from peripheral\n");
1918 continue; /* Got a valid Dot4CreditRequest but no credit from peripheral, try again. */
1922 if (pc->ta.h2pcredit == 0)
1924 ret = Dot4ReverseCmd(pc, pd->mlc_fd);
1925 if (pc->ta.h2pcredit == 0)
1928 continue; /* Got a reverse command, but no Dot4Credit, try again. */
1930 BUG("invalid Dot4Credit from peripheral\n");
1935 if (Dot4ForwardData(pc, pd->mlc_fd, buf+total, len, sec_timeout*1000000))
1954 * dot4_read_data() tries to read "length" bytes from the peripheral. Read_data() reads data in packet size chunks.
1955 * The returned read count may be zero (timeout, no data available), less than "length" or equal "length".
1957 * dot4_read_data() may read more the "length" if the data packet is greater than "length". For this case the
1958 * return value will equal "length" and the left over data will be buffered for the next read_data() call.
1960 * The "timeout" specifies how many seconds to wait for a data packet. Once the read of the data packet has
1961 * started the "timeout" is no longer used.
1963 * Note, if a "timeout" occurs one peripheral to host credit is left outstanding. Which means the peripheral
1964 * can send unsolicited data later.
1966 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_dot4_channel_read(mud_channel *pc, void *buf, int length, int sec_timeout, int *bytes_read)
1968 mud_device *pd = &msp->device[pc->dindex];
1969 enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1972 if (pc->ta.p2hsize==0)
1974 BUG("invalid channel_read state\n");
1981 *bytes_read = cut_buf(pc, buf, length);
1985 if (pc->ta.p2hcredit == 0)
1987 /* Issue enough credit to the peripheral to read one data packet. */
1988 if (Dot4Credit(pc, pd->mlc_fd, 1))
1993 pc->rcnt = Dot4ReverseData(pc, pd->mlc_fd, pc->rbuf, sizeof(pc->rbuf), sec_timeout*1000000);
1995 pc->ta.p2hcredit--; /* one data packet was read, decrement credit count */
1997 *bytes_read = cut_buf(pc, buf, length);
2003 /*******************************************************************************************************************************
2004 * USB probe devices, walk the USB bus(s) looking for HP products.
2007 int __attribute__ ((visibility ("hidden"))) musb_probe_devices(char *lst, int lst_size, int *cnt)
2009 struct usb_bus *bus;
2010 struct usb_device *dev;
2012 struct hpmud_model_attributes ma;
2018 char sz[HPMUD_LINE_SIZE];
2025 for (bus=usb_busses; bus; bus=bus->next)
2027 for (dev=bus->devices; dev; dev=dev->next)
2030 model[0] = serial[0] = rmodel[0] = rserial[0] = sz[0] = mfg[0] = 0;
2032 if (dev->descriptor.idVendor == 0x3f0 && is_interface(dev, 7))
2034 if((hd = usb_open(dev)) == NULL)
2036 BUG("Invalid usb_open: %m\n");
2039 /* Found hp device. */
2040 if ((r=get_string_descriptor(hd, dev->descriptor.iProduct, rmodel, sizeof(rmodel))) < 0)
2041 BUG("invalid product id string ret=%d\n", r);
2043 generalize_model(rmodel, model, sizeof(model));
2045 if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, rserial, sizeof(rserial))) < 0)
2046 BUG("invalid serial id string ret=%d\n", r);
2048 generalize_serial(rserial, serial, sizeof(serial));
2050 if ((r=get_string_descriptor(hd, dev->descriptor.iManufacturer, sz, sizeof(sz))) < 0)
2051 BUG("invalid manufacturer string ret=%d\n", r);
2053 generalize_serial(sz, mfg, sizeof(serial));
2056 strcpy(serial, "0"); /* no serial number, make it zero */
2060 snprintf(sz, sizeof(sz), "hp:/usb/%s?serial=%s", model, serial);
2062 /* See if device is supported by hplip. */
2063 hpmud_query_model(sz, &ma);
2064 if (ma.support != HPMUD_SUPPORT_TYPE_HPLIP)
2066 BUG("ignoring %s support=%d\n", sz, ma.support);
2067 continue; /* ignor, not supported */
2071 * For Cups 1.2 we append a dummy deviceid. A valid deviceid would require us to claim the USB interface, thus removing usblp.
2072 * This will allow us to do discovery and not disable other CUPS backend(s) who use /dev/usb/lpx instead of libusb.
2074 if (strncasecmp(rmodel, "hp ", 3) == 0)
2075 size += snprintf(lst+size, lst_size-size, "direct %s \"HP %s\" \"HP %s USB %s HPLIP\" \"MFG:%s;MDL:%s;CLS:PRINTER;DES:%s;SN:%s;\"\n",
2076 sz, &rmodel[3], &rmodel[3], serial, mfg, rmodel, rmodel, rserial);
2078 size += snprintf(lst+size, lst_size-size, "direct %s \"HP %s\" \"HP %s USB %s HPLIP\" \"MFG:%s;MDL:%s;CLS:PRINTER;DES:%s;SN:%s;\"\n",
2079 sz, rmodel, rmodel, serial, mfg, rmodel, rmodel, rserial);
2091 enum HPMUD_RESULT hpmud_make_usb_uri(const char *busnum, const char *devnum, char *uri, int uri_size, int *bytes_read)
2093 struct usb_bus *bus;
2094 struct usb_device *dev, *found_dev=NULL;
2095 usb_dev_handle *hd=NULL;
2100 enum HPMUD_RESULT stat = HPMUD_R_INVALID_DEVICE_NODE;
2102 DBG("[%d] hpmud_make_usb_uri() bus=%s dev=%s\n", getpid(), busnum, devnum);
2110 for (bus=usb_busses; bus && !found_dev; bus=bus->next)
2111 if (strcmp(bus->dirname, busnum) == 0)
2112 for (dev=bus->devices; dev && !found_dev; dev=dev->next)
2113 if (strcmp(dev->filename, devnum) == 0)
2114 found_dev = dev; /* found usb device that matches bus:device */
2116 if (found_dev == NULL)
2118 BUG("invalid busnum:devnum %s:%s\n", busnum, devnum);
2123 if ((hd = usb_open(dev)) == NULL)
2125 BUG("invalid usb_open: %m\n");
2129 model[0] = serial[0] = sz[0] = 0;
2131 if (dev->descriptor.idVendor == 0x3f0)
2133 /* Found hp device. */
2134 if ((r=get_string_descriptor(hd, dev->descriptor.iProduct, sz, sizeof(sz))) < 0)
2135 BUG("invalid product id string ret=%d\n", r);
2137 generalize_model(sz, model, sizeof(model));
2139 if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, sz, sizeof(sz))) < 0)
2140 BUG("invalid serial id string ret=%d\n", r);
2142 generalize_serial(sz, serial, sizeof(serial));
2145 strcpy(serial, "0"); /* no serial number, make it zero */
2149 BUG("invalid vendor id: %d\n", dev->descriptor.idVendor);
2153 if (!model[0] || !serial[0])
2156 *bytes_read = snprintf(uri, uri_size, "hp:/usb/%s?serial=%s", model, serial);
2166 enum HPMUD_RESULT hpmud_make_usb_serial_uri(const char *sn, char *uri, int uri_size, int *bytes_read)
2168 struct usb_bus *bus;
2169 struct usb_device *dev, *found_dev=NULL;
2171 enum HPMUD_RESULT stat = HPMUD_R_INVALID_DEVICE_NODE;
2173 DBG("[%d] hpmud_make_usb_serial_uri() sn=%s\n", getpid(), sn);
2181 for (bus=usb_busses; bus && !found_dev; bus=bus->next)
2182 for (dev=bus->devices; dev && !found_dev; dev=dev->next)
2183 if (is_serial(dev, sn, model, sizeof(model)))
2184 found_dev = dev; /* found usb device that matches serial number */
2186 if (found_dev == NULL)
2188 BUG("invalid sn %s\n", sn);
2192 *bytes_read = snprintf(uri, uri_size, "hp:/usb/%s?serial=%s", model, sn);