Tizen 2.1 base
[platform/upstream/hplip.git] / io / hpmud / musb.c
1 /*****************************************************************************\
2
3   musb.c - USB support for multi-point transport driver 
4  
5   (c) 2010 Copyright Hewlett-Packard Development Company, LP
6
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:
13
14   The above copyright notice and this permission notice shall be included in all
15   copies or substantial portions of the Software.
16
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):
24
25   Author: Naga Samrat Chowdary Narla, Sarbeswar Meher
26 \*****************************************************************************/
27
28 #include "hpmud.h"
29 #include "hpmudi.h"
30
31 mud_device_vf __attribute__ ((visibility ("hidden"))) musb_mud_device_vf = 
32 {
33    .read = musb_read,
34    .write = musb_write,
35    .open = musb_open,
36    .close = musb_close,
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
43 };
44
45 static mud_channel_vf musb_raw_channel_vf =
46 {
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
51 };
52
53 static mud_channel_vf musb_comp_channel_vf =
54 {
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
59 };
60
61 static mud_channel_vf musb_mlc_channel_vf =
62 {
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
67 };
68
69 static mud_channel_vf musb_dot4_channel_vf =
70 {
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
75 };
76
77 /*
78  * The folloing fd arrays must match "enum FD_ID" definition.
79  */
80
81 static char *fd_name[MAX_FD] =
82 {
83    "na",
84    "7/1/2",
85    "7/1/3",
86    "ff/1/1",
87    "ff/2/1",
88    "ff/3/1",
89    "ff/ff/ff",
90    "ff/d4/0",
91    "ff/4/1",
92    "ff/1/0",
93    "ff/cc/0",
94    "ff/2/10",
95 };
96
97 static int fd_class[MAX_FD] =
98 {
99    0,0x7,0x7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
100 };
101
102 static int fd_subclass[MAX_FD] =
103 {
104    0,0x1,0x1,0x1,0x2,0x3,0xff,0xd4,0x4,0x1,0xcc,0x2,
105 };
106
107 static int fd_protocol[MAX_FD] =
108 {
109    0,0x2,0x3,0x1,0x1,0x1,0xff,0,0x1,0,0,0x10,
110 };
111
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' };
114
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 */
118
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)
121 {
122    char tbuf[255];       /* Some devices choke on size > 255 */
123    int ret, si, di, cnt=5;
124
125    while (cnt--)
126    {
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);
129       if (ret==0)
130       {
131          /* This retry is necessary for lj1000 and lj1005. des 12/12/07 */
132          BUG("get_string_descriptor zero result, retrying...");
133          continue;
134       }
135       break;
136    }
137
138    if (ret < 0)
139    {
140       BUG("unable get_string_descriptor %d: %m\n", ret); 
141       return ret;
142    }
143
144    if (tbuf[1] != USB_DT_STRING)
145    {
146       BUG("invalid get_string_descriptor tag act=%d exp=%d\n", tbuf[1], USB_DT_STRING); 
147       return -EIO;
148    }
149
150    if (tbuf[0] > ret)
151    {
152       BUG("invalid get_string_descriptor size act=%d exp=%d\n", tbuf[0], ret); 
153       return -EFBIG;
154    }
155
156    for (di = 0, si = 2; si < tbuf[0]; si += 2)
157    {
158       if (di >= (buflen - 1))
159          break;
160
161       if (tbuf[si + 1])   /* high byte */
162          buf[di++] = '0';
163       else
164          buf[di++] = tbuf[si];
165    }
166
167    buf[di] = 0;
168
169    return di;
170 }
171
172 /* Check for USB interface descriptor with specified class. */
173 static int is_interface(struct usb_device *dev, int dclass)
174 {
175    struct usb_interface_descriptor *pi;
176    int i, j, k;
177
178    for (i=0; i<dev->descriptor.bNumConfigurations; i++)
179    {
180       for (j=0; j<dev->config[i].bNumInterfaces; j++)
181       {
182          for (k=0; k<dev->config[i].interface[j].num_altsetting; k++)
183          {
184             pi = &dev->config[i].interface[j].altsetting[k];
185             if (pi->bInterfaceClass == dclass)
186             {
187                return 1;            /* found interface */
188             }
189          }
190       }
191    }
192    return 0;    /* no interface found */
193 }
194
195 /* Write HP vendor-specific ECP channel message. */
196 static int write_ecp_channel(file_descriptor *pfd, int value)
197 {
198    usb_dev_handle *hd;
199    int interface = pfd->interface;
200    int len, stat=1;
201    char byte;
202
203    if (pfd->hd == NULL)
204    {
205       BUG("invalid write_ecp_channel state\n");
206       goto bugout;
207    }
208
209    hd = pfd->hd;
210
211    len = usb_control_msg(hd, 
212              USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, /* bmRequestType */
213              USB_REQ_GET_STATUS,        /* bRequest */
214              value,        /* wValue */
215              interface, /* wIndex */
216              &byte, 1, LIBUSB_CONTROL_REQ_TIMEOUT);
217
218    if (len != 1)
219    {
220       BUG("invalid write_ecp_channel: %m\n");
221       goto bugout;
222    }
223
224    stat = 0;
225
226 bugout:
227    return stat;
228 }
229
230 /* Set Cypress USS-725 Bridge Chip to 1284.4 mode. */
231 static int bridge_chip_up(file_descriptor *pfd)
232 {
233    usb_dev_handle *hd;
234    int len, stat=1;
235    char buf[9];
236    char nullByte=0;
237
238    if (pfd->hd == NULL)
239    {
240       BUG("invalid bridge_chip_up state\n");
241       goto bugout;
242    }
243
244    hd = pfd->hd;
245
246    memset(buf, 0, sizeof(buf));
247
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 */
252              0,        /* wValue */
253              0, /* wIndex */
254              buf, sizeof(buf), LIBUSB_CONTROL_REQ_TIMEOUT);
255    if (len < 0)
256    {
257       BUG("invalid write_bridge_up: %m\n");
258       goto bugout;
259    }
260
261    /* Check for auto ECP mode. */
262    if (buf[ECRR] != 0x43)
263    {
264       /* Place 725 chip in register mode. */
265       len = usb_control_msg(hd, 
266              USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
267              0x04,        /* bRequest */
268              0x0758,        /* wValue */
269              0, /* wIndex */
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 */
274              0x04,        /* bRequest */
275              0x0a1d,        /* wValue */
276              0, /* wIndex */
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 */
281              0x04,        /* bRequest */
282              0x0759,        /* wValue */
283              0, /* wIndex */
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 */
288              0x04,        /* bRequest */
289              0x0817,        /* wValue */
290              0, /* wIndex */
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 */
296              0,        /* wValue */
297              0, /* wIndex */
298              buf, sizeof(buf), LIBUSB_CONTROL_REQ_TIMEOUT);
299       if (buf[ECRR] != 0x43)
300       {
301          BUG("invalid auto ecp mode mode=%d\n", buf[ECRR]);
302       }
303    }
304
305    /* Reset to ECP channel 0. */
306    len = usb_control_msg(hd, 
307              USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
308              0x04,        /* bRequest */
309              0x05ce,        /* wValue */
310              0, /* wIndex */
311              NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
312    musb_write(pfd->fd, &nullByte, 1, HPMUD_EXCEPTION_TIMEOUT);
313
314    /* Switch to ECP channel 77. */
315    len = usb_control_msg(hd, 
316              USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
317              0x04,        /* bRequest */
318              0x05cd,        /* wValue */
319              0, /* wIndex */
320              NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
321
322    stat = 0;
323
324 bugout:
325    return stat;
326 }
327
328 /* Set Cypress USS-725 Bridge Chip to compatibility mode. */
329 static int bridge_chip_down(file_descriptor *pfd)
330 {
331    usb_dev_handle *hd;
332    int len, stat=1;
333
334    if (pfd->hd == NULL)
335    {
336       BUG("invalid bridge_chip_down state\n");
337       goto bugout;
338    }
339
340    hd = pfd->hd;
341
342    len = usb_control_msg(hd, 
343              USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, /* bmRequestType */
344              0x04,        /* bRequest */
345              0x080f,        /* wValue */
346              0, /* wIndex */
347              NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
348    if (len < 0)
349    {
350       BUG("invalid write_bridge_up: %m\n");
351       goto bugout;
352    }
353
354    stat = 0;
355
356 bugout:
357    return stat;
358 }
359
360 /* Write HP vendor-specific Setup command. */
361 static int write_phoenix_setup(file_descriptor *pfd)
362 {
363    usb_dev_handle *hd;
364    int len, stat=1;
365
366    if (pfd->hd == NULL)
367    {
368       BUG("invalid write_phoenix_setup state\n");
369       goto bugout;
370    }
371
372    hd = pfd->hd;
373
374    len = usb_control_msg(hd, 
375              USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, /* bmRequestType */
376              0x02,        /* bRequest */
377              0,        /* wValue */
378              0, /* wIndex */
379              NULL, 0, LIBUSB_CONTROL_REQ_TIMEOUT);
380
381    if (len < 0)
382    {
383       BUG("invalid write_phoenix_setup: %m\n");
384       goto bugout;
385    }
386
387    stat = 0;
388
389 bugout:
390    return stat;
391 }
392
393 /* Detach any kernel module that may have claimed specified inteface. */
394 static int detach(usb_dev_handle *hd, int interface)
395 {
396    char driver[32];
397
398    driver[0] = 0;
399
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))
404    {
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);
408    }
409 #endif
410
411    return 0;
412 }
413
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)
416 {
417    struct usb_interface_descriptor *pi;
418    int i, j, k;
419
420    for (i=0; i<dev->descriptor.bNumConfigurations; i++)
421    {
422       if (dev->config == NULL)
423          goto bugout; 
424
425       for (j=0; j<dev->config[i].bNumInterfaces; j++)
426       {
427          if (dev->config[i].interface == NULL)
428             goto bugout; 
429
430          for (k=0; k<dev->config[i].interface[j].num_altsetting; k++)
431          {
432             if (dev->config[i].interface[j].altsetting == NULL)
433                goto bugout; 
434
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])
437             {
438                pfd->config=i;            /* found interface */
439                pfd->interface=j;
440                pfd->alt_setting=k;
441                pfd->fd=index;
442                return 0;
443             }
444          }
445       }
446    }
447
448 bugout:
449    return 1;    /* no interface found */
450 }
451
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)
454 {
455    struct usb_interface_descriptor *pi;
456    int i;
457
458    if (dev->config == NULL || dev->config[config].interface == NULL || dev->config[config].interface[interface].altsetting == NULL)
459       goto bugout;
460
461    pi = &dev->config[config].interface[interface].altsetting[altset];
462    for (i=0; i<pi->bNumEndpoints; i++)
463    {
464       if (pi->endpoint == NULL)
465          goto bugout;   
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;
469       }
470    }
471
472 bugout:
473    DBG("get_out_ep: ERROR! returning -1\n");
474    return -1; /* no endpoint found */
475 }
476
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)
479 {
480    struct usb_interface_descriptor *pi;
481    int i;
482
483    if (dev->config == NULL || dev->config[config].interface == NULL || dev->config[config].interface[interface].altsetting == NULL)
484       goto bugout;
485
486    pi = &dev->config[config].interface[interface].altsetting[altset];
487    for (i=0; i<pi->bNumEndpoints; i++)
488    {
489       if (pi->endpoint == NULL)
490          goto bugout;   
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;
494       }
495    }
496
497 bugout:
498    DBG("get_in_ep: ERROR! returning -1\n");
499    return -1;  /* no endpoint found */
500 }
501
502 static int claim_interface(struct usb_device *dev, file_descriptor *pfd)
503 {
504    int stat=1;
505
506    if (pfd->hd != NULL)
507       return 0;  /* interface is already claimed */
508
509    if ((pfd->hd = usb_open(dev)) == NULL)
510    {
511       BUG("invalid usb_open: %m\n");
512       goto bugout;
513    }
514
515    detach(pfd->hd, pfd->interface);
516
517 #if 0   /* hp devices only have one configuration, so far ... */
518    if (usb_set_configuration(FD[fd].pHD, dev->config[config].bConfigurationValue))
519       goto bugout;
520 #endif
521
522    if (usb_claim_interface(pfd->hd, pfd->interface))
523    {
524       usb_close(pfd->hd);
525       pfd->hd = NULL;
526       DBG("invalid claim_interface %s: %m\n", fd_name[pfd->fd]);
527       goto bugout;
528    }
529
530    if (usb_set_altinterface(pfd->hd, pfd->alt_setting))
531    {
532       usb_release_interface(pfd->hd, pfd->interface);
533       usb_close(pfd->hd);
534       pfd->hd = NULL;
535       BUG("invalid set_altinterface %s altset=%d: %m\n", fd_name[pfd->fd], pfd->alt_setting);
536       goto bugout;
537    }
538
539    pfd->write_active=0;
540    pthread_mutex_init(&pfd->mutex, NULL);
541    pthread_cond_init(&pfd->write_done_cond, NULL);
542
543    DBG("claimed %s interface\n", fd_name[pfd->fd]);
544
545    stat=0;
546
547 bugout:
548    return stat;   
549 }
550
551 static int release_interface(file_descriptor *pfd)
552 {
553    if (pfd->hd == NULL)
554       return 0;
555
556    if (pfd->write_active)
557    {
558       BUG("aborting outstanding %s write\n", fd_name[pfd->fd]);
559       pthread_cancel(pfd->tid);    /* kill outstanding write */
560       pfd->write_active = 0;
561    }
562
563    usb_release_interface(pfd->hd, pfd->interface);
564    usb_close(pfd->hd);
565    pfd->hd = NULL;
566    pthread_mutex_destroy(&pfd->mutex);
567    pthread_cond_destroy(&pfd->write_done_cond);
568
569    DBG("released %s interface\n", fd_name[pfd->fd]);
570
571    return 0;
572 }
573
574 /* Claim any open interface which is valid for device_id and device status. */
575 static int claim_id_interface(struct usb_device *dev)
576 {
577    enum FD_ID i;
578
579    for (i=FD_7_1_2; i!=MAX_FD; i++)
580    {
581       if (get_interface(dev, i, &fd_table[i]) == 0)
582       {
583          if (claim_interface(libusb_device, &fd_table[i]))
584             continue;  /* interface is busy, try next interface */
585          break;  /* done */
586       }
587    }
588
589    return i;
590 }
591
592 /* See if this usb device and URI match. */
593 static int is_uri(struct usb_device *dev, const char *uri)
594 {
595    usb_dev_handle *hd=NULL;
596    char sz[128];
597    char uriModel[128];
598    char uriSerial[128];
599    char gen[128];
600    int r, stat=0;
601
602    if ((hd = usb_open(dev)) == NULL)
603    {
604       BUG("invalid usb_open: %m\n");
605       goto bugout;
606    }
607
608    if (dev->descriptor.idVendor != 0x3f0)
609       goto bugout;
610
611    if ((r=get_string_descriptor(hd, dev->descriptor.iProduct, sz, sizeof(sz))) < 0)
612    {
613       BUG("invalid product id string ret=%d\n", r);
614       goto bugout;
615    }
616
617    generalize_model(sz, gen, sizeof(gen));
618
619    hpmud_get_uri_model(uri, uriModel, sizeof(uriModel));
620    if (strcasecmp(uriModel, gen) != 0)
621       goto bugout;
622
623    if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, sz, sizeof(sz))) < 0)
624    {
625       BUG("invalid serial id string ret=%d\n", r);
626       goto bugout;
627    }
628
629    if (sz[0])
630       generalize_serial(sz, gen, sizeof(gen));
631    else
632       strcpy(gen, "0");
633
634    get_uri_serial(uri, uriSerial, sizeof(uriSerial));
635    if (strcmp(uriSerial, gen) != 0)
636       goto bugout;
637
638    stat = 1;    /* found usb device that matches uri */
639      
640 bugout:
641    if (hd != NULL)
642       usb_close(hd);
643
644    return stat;
645 }
646
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)
649 {
650    usb_dev_handle *hd=NULL;
651    char sz[128];
652    char gen[128];
653    int r, stat=0;
654
655    if ((hd = usb_open(dev)) == NULL)
656    {
657       BUG("invalid usb_open: %m\n");
658       goto bugout;
659    }
660
661    if (dev->descriptor.idVendor != 0x3f0)
662       goto bugout;      /* not a HP product */
663
664    if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, sz, sizeof(sz))) < 0)
665    {
666       BUG("invalid serial id string ret=%d\n", r);
667       goto bugout;
668    }
669    if (sz[0])
670       generalize_serial(sz, gen, sizeof(gen));
671    else
672       strcpy(gen, "0");
673
674    if (strncmp(sn, gen, sizeof(gen)) != 0)
675       goto bugout;  /* match failed */
676
677    if ((r=get_string_descriptor(hd, dev->descriptor.iProduct, sz, sizeof(sz))) < 0)
678    {
679       BUG("invalid product id string ret=%d\n", r);
680       goto bugout;
681    }
682    generalize_model(sz, model, model_size);
683
684    stat = 1;    /* found usb device that matches sn */
685      
686 bugout:
687    if (hd != NULL)
688       usb_close(hd);
689
690    return stat;
691 }
692
693 static struct usb_device *get_libusb_device(const char *uri)
694 {
695    struct usb_bus *bus;
696    struct usb_device *dev;
697
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 */
703
704    return NULL;
705 }
706
707 static int device_id(int fd, char *buffer, int size)
708 {
709    usb_dev_handle *hd;
710    int config,interface,alt;
711    int len=0, rlen, maxSize;
712
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;
717
718    if (hd == NULL)
719    {
720       BUG("invalid device_id state\n");
721       goto bugout;
722    }
723
724    maxSize = (size > 1024) ? 1024 : size;   /* RH8 has a size limit for device id (usb) */
725
726    rlen = usb_control_msg(hd, 
727              USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, /* bmRequestType */
728              USB_REQ_GET_STATUS,        /* bRequest */
729              config,        /* wValue */
730              interface, /* wIndex */    /* note firmware does not follow the USB Printer Class specification for wIndex */
731              buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT);
732
733    if (rlen < 0)
734    {
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 */
741              config,        /* wValue */
742              interface << 8, /* wIndex */ 
743              buffer, maxSize, LIBUSB_CONTROL_REQ_TIMEOUT);
744       if (rlen < 0)
745       {
746          BUG("invalid deviceid retry ret=%d: %m\n", rlen);
747          goto bugout;
748       }
749 #endif
750       BUG("invalid deviceid ret=%d: %m\n", rlen);
751       goto bugout;
752    }
753
754    len = ntohs(*(short *)buffer);
755    if (len > (size-1))
756       len = size-1;   /* leave byte for zero termination */
757    if (len > 2)
758       len -= 2;
759    memcpy(buffer, buffer+2, len);    /* remove length */
760    buffer[len]=0;
761    DBG("read actual device_id successfully fd=%d len=%d\n", fd, len);
762
763 bugout:
764    return len; /* length does not include zero termination */
765 }
766
767 static int device_status(int fd, unsigned int *status)
768 {
769    usb_dev_handle *hd;
770    int interface;
771    int len, stat=1;
772    char byte;
773
774    hd = fd_table[fd].hd;
775    interface = fd_table[fd].interface;
776
777    if (hd == NULL)
778    {
779       BUG("invalid device_status state\n");
780       goto bugout;
781    }
782
783    len = usb_control_msg(hd, 
784              USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, /* bmRequestType */
785              USB_REQ_CLEAR_FEATURE,        /* bRequest */
786              0,        /* wValue */
787              interface, /* wIndex */
788              &byte, 1, LIBUSB_CONTROL_REQ_TIMEOUT);
789
790    if (len < 0)
791    {
792       BUG("invalid device_status: %m\n");
793       goto bugout;
794    }
795
796    *status = (unsigned int)byte;
797    stat = 0;
798    DBG("read actual device_status successfully fd=%d\n", fd);
799
800 bugout:
801    return stat; 
802 }
803
804 /* Get VStatus from S-field. */
805 static int sfield_printer_state(const char *id)
806 {
807    char *pSf;
808    int vstatus=0, ver;
809
810    if ((pSf = strstr(id, ";S:")) == NULL)
811    {
812       BUG("invalid S-field\n");
813       return vstatus;
814    }
815
816    /* Valid S-field, get version number. */
817    pSf+=3;
818    ver = 0; 
819    HEX2INT(*pSf, ver);
820    pSf++;
821    ver = ver << 4;
822    HEX2INT(*pSf, ver);
823    pSf++;
824
825    /* Position pointer to printer state subfield. */
826    switch (ver)
827    {
828       case 0:
829       case 1:
830       case 2:
831          pSf+=12;
832          break;
833       case 3:
834          pSf+=14;
835          break;
836       case 4:
837          pSf+=18;
838          break;
839       default:
840          BUG("unknown S-field version=%d\n", ver);
841          pSf+=12;
842          break;            
843    }
844
845    /* Extract VStatus.*/
846    vstatus = 0; 
847    HEX2INT(*pSf, vstatus);
848    pSf++;
849    vstatus = vstatus << 4;
850    HEX2INT(*pSf, vstatus);
851
852    return vstatus;
853 }
854
855 /*
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.
858  */
859 int __attribute__ ((visibility ("hidden"))) power_up(mud_device *pd, int fd)
860 {
861    const char *pSf;
862
863    if ((pSf = strstr(pd->id, "CMD:LDL")) != NULL)
864      return 0;   /* crossbow don't do power-up */
865
866    if ((pSf = strstr(pd->id, ";S:")) != NULL)
867    {
868       if (sfield_printer_state(pd->id) != 3)
869          return 0;     /* already powered up */
870    }
871    else if ((pSf = strstr(pd->id, "VSTATUS:")) != NULL)
872    {
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 */
876    }
877    else
878       return 0;  /* must be laserjet, don't do power-up */
879
880    (pd->vf.write)(fd, venice_power_on, sizeof(venice_power_on), HPMUD_EXCEPTION_TIMEOUT);   
881    sleep(2);
882
883    return 0;
884 }
885
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)
888 {
889    int stat=1;
890
891    /* Check for existing name service already open. */
892    if (pd->channel[index].client_cnt)
893    {
894 #if 0
895       if (index == HPMUD_EWS_CHANNEL)
896       {
897          pd->channel[index].client_cnt++;  /* allow multiple clients for separate USB interfaces only */
898          stat = 0;
899          DBG("reused %s channel=%d clientCnt=%d channelCnt=%d\n", sn, index, pd->channel[index].client_cnt, pd->channel_cnt);
900       }
901       else
902 #endif
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);
904       goto bugout; 
905    }
906
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;
912    } 
913    else if (pd->io_mode == HPMUD_RAW_MODE || pd->io_mode == HPMUD_UNI_MODE) {
914       pd->channel[index].vf = musb_raw_channel_vf;
915    }
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;
918    }
919    else {
920       pd->channel[index].vf = musb_dot4_channel_vf;
921    }
922
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);
930    pd->channel_cnt++;
931
932    stat = 0;
933    DBG("new %s channel=%d clientCnt=%d channelCnt=%d\n", sn, index, pd->channel[index].client_cnt, pd->channel_cnt);
934
935 bugout:
936    return stat;
937 }
938
939 /* Remove channel object given the channel decriptor. */
940 static int del_channel(mud_device *pd, mud_channel *pc)
941 {
942    pc->client_cnt--;
943
944    if (pc->client_cnt <= 0)
945    {
946       pd->channel_cnt--;
947    }
948    DBG("removed %s channel=%d clientCnt=%d channelCnt=%d\n", pc->sn, pc->index, pc->client_cnt, pd->channel_cnt);
949    return 0;
950 }
951
952 static void write_thread(file_descriptor *pfd)
953 {
954    int ep;
955
956    pthread_detach(pthread_self());
957
958    if ((ep = get_out_ep(libusb_device, pfd->config, pfd->interface, pfd->alt_setting, USB_ENDPOINT_TYPE_BULK)) < 0)
959    {
960       BUG("invalid bulk out endpoint\n");
961       goto bugout;
962    }
963
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);  
966
967 bugout:
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);
972
973    return;
974 }
975
976 /*********************************************************************************************************************************
977  * USB mud_device functions.
978  */
979
980 int __attribute__ ((visibility ("hidden"))) musb_write(int fd, const void *buf, int size, int usec)
981 {
982    int len=-EIO;
983
984    if (fd_table[fd].hd == NULL)
985    {
986       BUG("invalid musb_write state\n");
987       goto bugout;
988    }
989
990 #if 1
991    struct timeval now;
992    struct timespec timeout;
993    int ret;
994    /* If write is still active, probably OOP condition, don't kick off a new write. */
995    if (!fd_table[fd].write_active)
996    {
997       fd_table[fd].write_active = 1;
998       fd_table[fd].write_buf = buf;
999       fd_table[fd].write_size = size;
1000
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)
1003       {
1004          BUG("unable to creat write_thread: %m\n");
1005          goto bugout; /* bail */
1006       } 
1007    }
1008
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;
1017    ret = 0;
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);
1021
1022    if (ret == ETIMEDOUT)
1023    {
1024       len = -ETIMEDOUT;     /* write timeout, let client know */
1025       goto bugout;
1026    }
1027
1028    fd_table[fd].write_active = 0;
1029
1030    len = fd_table[fd].write_return;
1031 #else
1032    int ep;
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)
1034    {
1035       BUG("invalid bulk out endpoint\n");
1036       goto bugout;
1037    }
1038
1039    len = usb_bulk_write(fd_table[fd].hd, ep, (char *)buf, size, usec);
1040 #endif
1041
1042    if (len < 0)
1043    {
1044       BUG("bulk_write failed buf=%p size=%d len=%d: %m\n", buf, size, len);
1045       goto bugout;
1046    }
1047
1048    DBG("write fd=%d len=%d size=%d usec=%d\n", fd, len, size, usec);
1049    DBG_DUMP(buf, len < 512 ? len : 512);
1050
1051 bugout:
1052    return len;
1053 }
1054
1055 int __attribute__ ((visibility ("hidden"))) musb_read(int fd, void *buf, int size, int usec)
1056 {
1057    struct timeval t1, t2;
1058    int total_usec, tmo_usec=usec;
1059    int len=-EIO, ep;
1060
1061    if (fd_table[fd].hd == NULL)
1062    {
1063       BUG("invalid musb_read state\n");
1064       goto bugout;
1065    }
1066
1067    gettimeofday (&t1, NULL);     /* get start time */
1068
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)
1070    {
1071       BUG("invalid bulk in endpoint\n");
1072       goto bugout;
1073    }
1074
1075    while (1)
1076    {
1077       len = usb_bulk_read(fd_table[fd].hd, ep, (char *)buf, size, tmo_usec/1000);
1078
1079       if (len == -ETIMEDOUT)
1080          goto bugout;
1081
1082       if (len < 0)
1083       {
1084          BUG("bulk_read failed: %m\n");
1085          goto bugout;
1086       }
1087
1088       if (len == 0)
1089       {
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 */
1092
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)
1096          {
1097             len = -ETIMEDOUT;   /* timeout */
1098             goto bugout;
1099          }
1100          tmo_usec = usec - total_usec;    /* decrease timeout */
1101          continue;
1102       }
1103
1104       break;
1105    }
1106
1107    DBG("read fd=%d len=%d size=%d usec=%d\n", fd, len, size, usec);
1108    DBG_DUMP(buf, len < 32 ? len : 32);
1109
1110 bugout:
1111    return len;
1112 }
1113
1114 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_open(mud_device *pd)
1115 {
1116    int len=0, fd=0;
1117    enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1118
1119    usb_init();
1120    usb_find_busses();
1121    usb_find_devices();
1122
1123    /* Find usb device for specified uri. */
1124    if ((libusb_device = get_libusb_device(pd->uri)) == NULL)
1125    {
1126       BUG("unable to open %s\n", pd->uri);
1127       goto bugout;
1128    }
1129
1130    pthread_mutex_lock(&pd->mutex);
1131
1132    if (pd->id[0] == 0)
1133    {
1134       /* First client. */
1135
1136       if ((fd = claim_id_interface(libusb_device)) == MAX_FD)
1137       {
1138          stat = HPMUD_R_DEVICE_BUSY;
1139          goto blackout;
1140       }
1141
1142       len = device_id(fd, pd->id, sizeof(pd->id));  /* get new copy and cache it  */ 
1143
1144       if (len > 0 && is_hp(pd->id))
1145          power_up(pd, fd);
1146
1147       release_interface(&fd_table[fd]);
1148
1149       if (len == 0)
1150          goto blackout;
1151
1152       pd->open_fd = fd;
1153    }
1154
1155    stat = HPMUD_R_OK;
1156
1157 blackout:
1158    pthread_mutex_unlock(&pd->mutex);
1159
1160 bugout:
1161    return stat;
1162 }
1163
1164 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_close(mud_device *pd)
1165 {
1166    int i;
1167    enum HPMUD_RESULT stat = HPMUD_R_OK;
1168
1169    pthread_mutex_lock(&pd->mutex);
1170
1171    for (i=1; i<MAX_FD; i++)
1172    {
1173       if (fd_table[i].hd != NULL)
1174          release_interface(&fd_table[i]);
1175    }
1176
1177    pd->id[0] = 0;
1178
1179    pthread_mutex_unlock(&pd->mutex);
1180
1181    return stat;
1182 }
1183
1184 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_get_device_id(mud_device *pd, char *buf, int size, int *len)
1185 {
1186    int i, fd=FD_NA;
1187    enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1188    
1189    *len=0;
1190
1191    pthread_mutex_lock(&pd->mutex);
1192
1193    if (pd->io_mode == HPMUD_DOT4_BRIDGE_MODE || pd->io_mode == HPMUD_UNI_MODE)
1194    {
1195       *len = strlen(pd->id);  /* usb/parallel bridge chip, use cached copy */
1196    }
1197    else
1198    {
1199       /* See if any interface is already claimed. */
1200       for (i=1; i<MAX_FD; i++)
1201       {
1202          if (fd_table[i].hd != NULL)
1203          {
1204             fd = i;
1205             break;
1206          }
1207       }
1208       
1209       if (fd == FD_NA)
1210       {
1211          /* Device not in use. Claim interface, but release for other processes. */
1212          if ((fd = claim_id_interface(libusb_device)) != MAX_FD)
1213          {
1214             *len = device_id(fd, pd->id, sizeof(pd->id));  /* get new copy and cache it  */ 
1215             release_interface(&fd_table[fd]);
1216          }
1217          else
1218          {
1219             /* Device is in use by another process, return cache copy. */
1220             *len = strlen(pd->id);
1221          }
1222       }
1223       else
1224       {
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  */ 
1227       }
1228    }
1229
1230    if (*len)
1231    {
1232       memcpy(buf, pd->id, *len > size ? size : *len); 
1233       stat = HPMUD_R_OK;
1234    }
1235
1236    pthread_mutex_unlock(&pd->mutex);
1237    return stat;
1238 }
1239
1240 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_get_device_status(mud_device *pd, unsigned int *status)
1241 {
1242    int i, fd=FD_NA;
1243    enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1244    int r=1;
1245
1246    pthread_mutex_lock(&pd->mutex);
1247
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 */
1250    else
1251    {
1252       /* See if any interface is already claimed. */
1253       for (i=1; i<MAX_FD; i++)
1254       {
1255          if (fd_table[i].hd != NULL)
1256          {
1257             fd = i;
1258             break;
1259          }
1260       }
1261
1262       if (fd == FD_NA)
1263       {
1264          /* Device not in use. Claim interface, but release for other processes. */
1265          if ((fd = claim_id_interface(libusb_device)) != MAX_FD)
1266          {
1267             r = device_status(fd, status);
1268             release_interface(&fd_table[fd]);
1269          }
1270       }
1271       else
1272       {
1273          /* Device in use by current process, leave interface up. Other processes are blocked. */
1274          r = device_status(fd, status);
1275       }
1276    }
1277
1278    pthread_mutex_unlock(&pd->mutex);
1279
1280    if (r != 0)
1281       goto bugout;
1282     
1283    stat = HPMUD_R_OK;
1284
1285 bugout:
1286    return stat;
1287 }
1288
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)
1290 {   
1291    enum HPMUD_RESULT stat;
1292
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);
1296    return stat;
1297 }
1298
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)
1300 {   
1301    enum HPMUD_RESULT stat;
1302
1303    if (pd->io_mode == HPMUD_UNI_MODE)
1304    {
1305       stat = HPMUD_R_INVALID_STATE;
1306       BUG("invalid channel_read io_mode=%d\n", pd->io_mode);
1307       goto bugout;
1308    }
1309  
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);
1313
1314 bugout:
1315    return stat;
1316 }
1317
1318 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_channel_open(mud_device *pd, const char *sn, HPMUD_CHANNEL *cd)
1319 {
1320    int index;
1321    enum HPMUD_RESULT stat;
1322
1323    /* Check for valid service requests. */
1324    if ((stat = service_to_channel(pd, sn, &index)) != HPMUD_R_OK)
1325       goto bugout;
1326
1327    pthread_mutex_lock(&pd->mutex);
1328
1329    if (new_channel(pd, index, sn))
1330    {
1331       stat = HPMUD_R_DEVICE_BUSY;
1332    }
1333    else
1334    {
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 */
1337       else
1338          *cd = index;
1339    }
1340
1341    pthread_mutex_unlock(&pd->mutex);
1342
1343 bugout:
1344    return stat;
1345 }
1346
1347 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_channel_close(mud_device *pd, mud_channel *pc)
1348 {
1349    enum HPMUD_RESULT stat = HPMUD_R_OK;
1350
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);
1355
1356    return stat;
1357 }
1358
1359 /*******************************************************************************************************************************
1360  * USB raw_channel functions.
1361  */
1362
1363 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_raw_channel_open(mud_channel *pc)
1364 {
1365    int fd = FD_7_1_2;
1366    enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1367
1368    get_interface(libusb_device, fd, &fd_table[fd]);
1369
1370    if (claim_interface(libusb_device, &fd_table[fd]))
1371       goto bugout;
1372
1373    pc->fd = fd;
1374
1375    stat = HPMUD_R_OK;
1376
1377 bugout:
1378    return stat;
1379 }
1380
1381 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_raw_channel_close(mud_channel *pc)
1382 {
1383    int fd = pc->fd;
1384
1385    // For New laserjet devices like Tsunami, end point was getting stall or halted, hence clearing it
1386    int ep = -1;
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)
1388    {
1389        usb_clear_halt(fd_table[fd].hd,  ep);
1390    }
1391
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)
1393    {
1394        usb_clear_halt(fd_table[fd].hd,  ep);
1395    }
1396
1397    release_interface(&fd_table[fd]);
1398
1399    pc->fd = 0;
1400
1401    return HPMUD_R_OK;
1402 }
1403
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)
1405 {
1406    int len, size, total=0;
1407    enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1408
1409    *bytes_wrote=0;
1410    size = length;
1411
1412    while (size > 0)
1413    {
1414       len = (msp->device[pc->dindex].vf.write)(pc->fd, buf+total, size, sec_timeout*1000000);
1415       if (len < 0)
1416       {
1417          if (len == -ETIMEDOUT)
1418          {
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);
1422          }
1423          else
1424             BUG("unable to write data %s: %m\n", msp->device[pc->dindex].uri);
1425          goto bugout;
1426       }
1427       size-=len;
1428       total+=len;
1429       *bytes_wrote+=len;
1430    }
1431    
1432    stat = HPMUD_R_OK;
1433
1434 bugout:
1435    return stat;
1436 }
1437
1438 /*
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".
1441  */
1442 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_raw_channel_read(mud_channel *pc, void *buf, int length, int sec_timeout, int *bytes_read)
1443 {
1444    int len=0, usec;
1445    enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1446
1447    *bytes_read = 0;
1448
1449    if (sec_timeout==0)
1450       usec = 1000;       /* minmum timeout is 1ms for libusb 0.1.12, hangs forever with zero */
1451    else
1452       usec = sec_timeout*1000000;
1453
1454    len = (msp->device[pc->dindex].vf.read)(pc->fd, buf, length, usec);
1455    if (len < 0)
1456    {
1457       if (len == -ETIMEDOUT)
1458       {
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);
1462       }
1463       else
1464          BUG("unable to read data %s: %m\n", msp->device[pc->dindex].uri);
1465       goto bugout;
1466    }
1467
1468    *bytes_read = len;
1469    stat = HPMUD_R_OK;
1470
1471 bugout:
1472    return stat;
1473 }
1474
1475 /*******************************************************************************************************************************
1476  * USB comp_channel functions.
1477  */
1478
1479 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_comp_channel_open(mud_channel *pc)
1480 {
1481    int fd;
1482    enum HPMUD_RESULT stat = HPMUD_R_DEVICE_BUSY;
1483
1484    /* Get requested composite interface. */
1485    switch (pc->index)
1486    {
1487       case HPMUD_EWS_CHANNEL:
1488          fd = FD_ff_1_1;   
1489          break;
1490       case HPMUD_EWS_LEDM_CHANNEL:
1491          fd = FD_ff_4_1;
1492          break;
1493       case HPMUD_SOAPSCAN_CHANNEL:
1494          fd = FD_ff_2_1;
1495          break;
1496       case HPMUD_SOAPFAX_CHANNEL:
1497          fd = FD_ff_3_1;
1498          break;
1499       case HPMUD_MARVELL_SCAN_CHANNEL:
1500          fd = FD_ff_ff_ff;
1501          break;
1502       case HPMUD_MARVELL_FAX_CHANNEL:  //using vendor specific C/S/P codes for fax too
1503          fd = FD_ff_1_0;
1504          break;
1505       case HPMUD_LEDM_SCAN_CHANNEL:  //using vendor specific C/S/P codes for fax too
1506          fd = FD_ff_cc_0;
1507          break;
1508       default:
1509          stat = HPMUD_R_INVALID_SN;
1510          BUG("invalid %s channel=%d\n", pc->sn, pc->index);
1511          goto bugout;
1512          break;
1513    }
1514
1515    if (get_interface(libusb_device, fd, &fd_table[fd]))
1516    {
1517       stat = HPMUD_R_INVALID_SN;
1518       BUG("invalid %s channel=%d\n", pc->sn, pc->index);
1519       goto bugout;
1520    }
1521
1522    if (claim_interface(libusb_device, &fd_table[fd]))
1523       goto bugout;
1524
1525    pc->fd = fd;
1526
1527    stat = HPMUD_R_OK;
1528
1529 bugout:
1530    return stat;
1531 }
1532
1533 /*******************************************************************************************************************************
1534  * USB mlc_channel functions.
1535  */
1536
1537 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_mlc_channel_open(mud_channel *pc)
1538 {
1539    mud_device *pd = &msp->device[pc->dindex];
1540    enum FD_ID fd;
1541    enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1542
1543    /* Initialize MLC transport if this is the first MLC channel. */
1544    if (pd->channel_cnt==1)
1545    {
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 */
1554       else
1555       {
1556          stat = HPMUD_R_DEVICE_BUSY;
1557          goto bugout;
1558       }
1559
1560       if (fd == FD_7_1_2)
1561       { 
1562          /* Emulate 7/1/3 on 7/1/2 using vendor-specific ECP channel-77. */
1563          if (write_ecp_channel(&fd_table[fd], 77)) 
1564             goto bugout;
1565       }
1566
1567       unsigned int i;
1568 #if 0
1569 // Removed reverse drain I seen it hang forever on read, one-time with PSC750 (FC5 64-bit). DES 
1570       int len;
1571       unsigned char buf[255];
1572
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 */
1576 #endif
1577
1578       /* MLC initialize */
1579       if (MlcInit(pc, fd) != 0)
1580          goto bugout;
1581     
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));
1585
1586       pd->mlc_fd = fd;
1587       pd->mlc_up=1;
1588
1589    } /* if (pDev->ChannelCnt==1) */
1590  
1591    if (MlcConfigSocket(pc, pd->mlc_fd))
1592       goto bugout;
1593
1594    if (MlcOpenChannel(pc, pd->mlc_fd))
1595       goto bugout;
1596
1597    pc->rcnt = pc->rindex = 0;
1598
1599    stat = HPMUD_R_OK;
1600
1601 bugout:
1602    return stat;  
1603 }
1604
1605 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_mlc_channel_close(mud_channel *pc)
1606 {
1607    mud_device *pd = &msp->device[pc->dindex];
1608    unsigned char nullByte=0;
1609    enum HPMUD_RESULT stat = HPMUD_R_OK;
1610
1611    if (pd->mlc_up)
1612    {
1613       if (MlcCloseChannel(pc, pd->mlc_fd))
1614          stat = HPMUD_R_IO_ERROR;
1615    }
1616
1617    /* Remove MLC transport if this is the last MLC channel. */
1618    if (pd->channel_cnt==1)
1619    {
1620       if (pd->mlc_up)
1621       {
1622          if (MlcExit(pc, pd->mlc_fd))
1623             stat = HPMUD_R_IO_ERROR;
1624       }
1625       pd->mlc_up=0;
1626
1627       if (pd->mlc_fd == FD_7_1_2)
1628       {
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);
1632       }
1633
1634       release_interface(&fd_table[pd->mlc_fd]);
1635
1636       /* Delay for back-to-back scanning using scanimage (OJ 7110, OJ d135). */
1637       sleep(1);
1638    }
1639
1640    return stat;
1641 }
1642
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)
1644 {
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;
1648
1649    *bytes_wrote=0;
1650    size = length;
1651    dlen = pc->ta.h2psize - sizeof(MLCHeader);
1652    while (size > 0)
1653    {
1654       len = (size > dlen) ? dlen : size;
1655
1656       if (pc->ta.h2pcredit == 0 && pd->io_mode == HPMUD_MLC_MISER_MODE)
1657       {
1658          if (MlcCreditRequest(pc, pd->mlc_fd, 1))  /* Miser flow control */
1659          {
1660             BUG("invalid MlcCreditRequest from peripheral\n");
1661             goto bugout;
1662          }
1663       }
1664
1665       if (pc->ta.h2pcredit == 0)
1666       {
1667          ret = MlcReverseCmd(pc, pd->mlc_fd);
1668          if (pc->ta.h2pcredit == 0)
1669          {
1670             if (ret == 0)
1671                continue;  /* Got a reverse command, but no MlcCredit, try again. */ 
1672
1673             if (pd->io_mode != HPMUD_MLC_MISER_MODE)
1674             {
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;
1678                continue;
1679             } 
1680
1681             BUG("invalid MlcCredit from peripheral\n");
1682             goto bugout;
1683          }
1684       }
1685
1686       if (MlcForwardData(pc, pd->mlc_fd, buf+total, len, sec_timeout*1000000))
1687       {
1688          goto bugout;
1689       }
1690
1691       pc->ta.h2pcredit--;
1692       size-=len;
1693       total+=len;
1694       *bytes_wrote+=len;
1695    }
1696
1697    stat = HPMUD_R_OK;
1698
1699 bugout:
1700    return stat;
1701 }
1702
1703 /*
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".
1706  *
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.
1709  *
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.
1712  *
1713  * Note, if a "timeout" occurs one peripheral to host credit is left outstanding. Which means the peripheral
1714  * can send unsolicited data later.
1715  */
1716 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_mlc_channel_read(mud_channel *pc, void *buf, int length, int sec_timeout, int *bytes_read)
1717 {
1718    mud_device *pd = &msp->device[pc->dindex];
1719    enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1720
1721    *bytes_read=0;
1722    if (pc->ta.p2hsize==0)
1723    {
1724       BUG("invalid channel_read state\n");
1725       goto bugout;
1726    }
1727
1728    if (pc->rcnt)
1729    {
1730       stat=HPMUD_R_OK;
1731       *bytes_read = cut_buf(pc, buf, length);
1732       goto bugout;
1733    }
1734
1735    if (pc->ta.p2hcredit == 0)
1736    {
1737       /* Issue enough credit to the peripheral to read one data packet. */ 
1738       if (MlcCredit(pc, pd->mlc_fd, 1))
1739          goto bugout;
1740    }
1741
1742    stat=HPMUD_R_OK;
1743    pc->rcnt = MlcReverseData(pc, pd->mlc_fd, pc->rbuf, sizeof(pc->rbuf), sec_timeout*1000000);
1744    if (pc->rcnt)
1745       pc->ta.p2hcredit--; /* one data packet was read, decrement credit count */
1746  
1747    *bytes_read = cut_buf(pc, buf, length);
1748
1749 bugout:
1750    return stat;
1751 }
1752
1753 /*******************************************************************************************************************************
1754  * USB dot4_channel functions.
1755  */
1756
1757 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_dot4_channel_open(mud_channel *pc)
1758 {
1759    mud_device *pd = &msp->device[pc->dindex];
1760    enum FD_ID fd;
1761    enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1762
1763    /* Initialize MLC transport if this is the first MLC channel. */
1764    if (pd->channel_cnt==1)
1765    {
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 */
1774       else
1775       {
1776          stat = HPMUD_R_DEVICE_BUSY;
1777          goto bugout;
1778       }
1779          
1780       if (fd == FD_7_1_2)
1781       { 
1782          if (pd->io_mode == HPMUD_DOT4_BRIDGE_MODE)
1783          {
1784             /* Emulate 7/1/3 on 7/1/2 using the bridge chip set (ie: CLJ2500). */
1785             if (bridge_chip_up(&fd_table[fd]))
1786                goto bugout;
1787          }
1788          else
1789          {
1790             /* Emulate 7/1/3 on 7/1/2 using vendor-specific ECP channel-77. */
1791             if (write_ecp_channel(&fd_table[fd], 77)) 
1792                goto bugout;
1793          }
1794       }
1795
1796       if (pd->io_mode == HPMUD_DOT4_PHOENIX_MODE)
1797          write_phoenix_setup(&fd_table[fd]);
1798
1799       unsigned int i;
1800 #if 0
1801 //   Removed reverse drain LJ1015 can hang forever on read (FC5 64-bit). DES
1802       unsigned char buf[255];
1803       int len;
1804
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 */
1808 #endif
1809       /* DOT4 initialize */
1810       if (Dot4Init(pc, fd) != 0)
1811          goto bugout;
1812     
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));
1816
1817       pd->mlc_fd = fd;
1818       pd->mlc_up=1;
1819
1820    } /* if (pDev->ChannelCnt==1) */
1821  
1822    if (Dot4GetSocket(pc, pd->mlc_fd))
1823       goto bugout;
1824
1825    if (Dot4OpenChannel(pc, pd->mlc_fd))
1826       goto bugout;
1827
1828    if (pd->io_mode == HPMUD_DOT4_PHOENIX_MODE)
1829    {
1830       /* Issue credit to peripheral. */ 
1831       if (Dot4Credit(pc, pd->mlc_fd, 2))
1832       {
1833          BUG("invalid Dot4Credit to peripheral\n");
1834          goto bugout;
1835       }     
1836    }
1837
1838    pc->rcnt = pc->rindex = 0;
1839
1840    stat = HPMUD_R_OK;
1841
1842 bugout:
1843    return stat;  
1844 }
1845
1846 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_dot4_channel_close(mud_channel *pc)
1847 {
1848    mud_device *pd = &msp->device[pc->dindex];
1849    enum HPMUD_RESULT stat = HPMUD_R_OK;
1850
1851    if (pd->mlc_up)
1852    {
1853       if (Dot4CloseChannel(pc, pd->mlc_fd))
1854          stat = HPMUD_R_IO_ERROR;
1855    }
1856
1857    /* Remove 1284.4 transport if this is the last 1284.4 channel. */
1858    if (pd->channel_cnt==1)
1859    {
1860       if (pd->mlc_up)
1861       {
1862          if (Dot4Exit(pc, pd->mlc_fd))
1863             stat = HPMUD_R_IO_ERROR;
1864       }
1865       pd->mlc_up=0;
1866
1867       if (pd->mlc_fd == FD_7_1_2)
1868       {
1869          if (pd->io_mode == HPMUD_DOT4_BRIDGE_MODE)
1870          {
1871             bridge_chip_down(&fd_table[pd->mlc_fd]);
1872          }
1873          else
1874          {
1875             write_ecp_channel(&fd_table[pd->mlc_fd], 78);
1876             write_ecp_channel(&fd_table[pd->mlc_fd], 0);
1877          }
1878       }
1879
1880       release_interface(&fd_table[pd->mlc_fd]);
1881
1882       /* Delay for back-to-back scanning using scanimage (OJ 7110, OJ d135). */
1883       sleep(1);
1884    }
1885
1886    return stat;
1887 }
1888
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)
1890 {
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;
1894
1895    *bytes_wrote=0;
1896    size = length;
1897    dlen = pc->ta.h2psize - sizeof(DOT4Header);
1898    while (size > 0)
1899    {
1900       len = (size > dlen) ? dlen : size;
1901
1902       if (pc->ta.h2pcredit == 0 && pd->io_mode == HPMUD_DOT4_PHOENIX_MODE)
1903       {
1904          /* Issue credit request to peripheral. */ 
1905          if (Dot4CreditRequest(pc, pd->mlc_fd, 1)) 
1906          {
1907             BUG("invalid Dot4CreditRequest from peripheral\n");
1908             goto bugout;
1909          }
1910          if (pc->ta.h2pcredit == 0)
1911          {
1912             if (cnt++ > HPMUD_EXCEPTION_SEC_TIMEOUT)
1913             {
1914                BUG("invalid Dot4CreditRequest from peripheral\n");
1915                goto bugout;
1916             }
1917             sleep(1);
1918             continue;    /* Got a valid Dot4CreditRequest but no credit from peripheral, try again. */ 
1919          }
1920       }
1921
1922       if (pc->ta.h2pcredit == 0)
1923       {
1924          ret = Dot4ReverseCmd(pc, pd->mlc_fd);
1925          if (pc->ta.h2pcredit == 0)
1926          {
1927             if (ret == 0)
1928                continue;  /* Got a reverse command, but no Dot4Credit, try again. */ 
1929
1930             BUG("invalid Dot4Credit from peripheral\n");
1931             goto bugout;
1932          }
1933       }
1934
1935       if (Dot4ForwardData(pc, pd->mlc_fd, buf+total, len, sec_timeout*1000000))
1936       {
1937          goto bugout;
1938       }
1939
1940       pc->ta.h2pcredit--;
1941       size-=len;
1942       total+=len;
1943       *bytes_wrote+=len;
1944       cnt=0;
1945    }
1946
1947    stat = HPMUD_R_OK;
1948
1949 bugout:
1950    return stat;
1951 }
1952
1953 /*
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".
1956  *
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.
1959  *
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.
1962  *
1963  * Note, if a "timeout" occurs one peripheral to host credit is left outstanding. Which means the peripheral
1964  * can send unsolicited data later.
1965  */
1966 enum HPMUD_RESULT __attribute__ ((visibility ("hidden"))) musb_dot4_channel_read(mud_channel *pc, void *buf, int length, int sec_timeout, int *bytes_read)
1967 {
1968    mud_device *pd = &msp->device[pc->dindex];
1969    enum HPMUD_RESULT stat = HPMUD_R_IO_ERROR;
1970
1971    *bytes_read=0;
1972    if (pc->ta.p2hsize==0)
1973    {
1974       BUG("invalid channel_read state\n");
1975       goto bugout;
1976    }
1977
1978    if (pc->rcnt)
1979    {
1980       stat=HPMUD_R_OK;
1981       *bytes_read = cut_buf(pc, buf, length);
1982       goto bugout;
1983    }
1984
1985    if (pc->ta.p2hcredit == 0)
1986    {
1987       /* Issue enough credit to the peripheral to read one data packet. */ 
1988       if (Dot4Credit(pc, pd->mlc_fd, 1))
1989          goto bugout;
1990    }
1991
1992    stat=HPMUD_R_OK;
1993    pc->rcnt = Dot4ReverseData(pc, pd->mlc_fd, pc->rbuf, sizeof(pc->rbuf), sec_timeout*1000000);
1994    if (pc->rcnt)
1995       pc->ta.p2hcredit--; /* one data packet was read, decrement credit count */
1996  
1997    *bytes_read = cut_buf(pc, buf, length);
1998
1999 bugout:
2000    return stat;
2001 }
2002
2003 /*******************************************************************************************************************************
2004  * USB probe devices, walk the USB bus(s) looking for HP products.
2005  */
2006
2007 int __attribute__ ((visibility ("hidden"))) musb_probe_devices(char *lst, int lst_size, int *cnt)
2008 {
2009    struct usb_bus *bus;
2010    struct usb_device *dev;
2011    usb_dev_handle *hd;
2012    struct hpmud_model_attributes ma;
2013    char rmodel[128];
2014    char rserial[128];
2015    char model[128];
2016    char serial[128];
2017    char mfg[128];
2018    char sz[HPMUD_LINE_SIZE];
2019    int r, size=0;
2020
2021    usb_init();
2022    usb_find_busses();
2023    usb_find_devices();
2024
2025    for (bus=usb_busses; bus; bus=bus->next)
2026    {
2027       for (dev=bus->devices; dev; dev=dev->next)
2028       {
2029
2030          model[0] = serial[0] = rmodel[0] = rserial[0] = sz[0] = mfg[0] = 0;
2031
2032          if (dev->descriptor.idVendor == 0x3f0 && is_interface(dev, 7))
2033          {
2034             if((hd = usb_open(dev)) == NULL)
2035             {
2036                 BUG("Invalid usb_open: %m\n");
2037                 continue;
2038             }
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);
2042             else
2043                generalize_model(rmodel, model, sizeof(model));
2044
2045             if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, rserial, sizeof(rserial))) < 0)
2046                BUG("invalid serial id string ret=%d\n", r);
2047             else
2048                generalize_serial(rserial, serial, sizeof(serial));
2049
2050             if ((r=get_string_descriptor(hd, dev->descriptor.iManufacturer, sz, sizeof(sz))) < 0)
2051                BUG("invalid manufacturer string ret=%d\n", r);
2052             else
2053                generalize_serial(sz, mfg, sizeof(serial));
2054
2055             if (!serial[0])
2056                strcpy(serial, "0"); /* no serial number, make it zero */
2057
2058             if (model[0])
2059             {
2060                snprintf(sz, sizeof(sz), "hp:/usb/%s?serial=%s", model, serial);
2061
2062                /* See if device is supported by hplip. */
2063                hpmud_query_model(sz, &ma); 
2064                if (ma.support != HPMUD_SUPPORT_TYPE_HPLIP)
2065                {
2066                   BUG("ignoring %s support=%d\n", sz, ma.support);
2067                   continue;           /* ignor, not supported */
2068                }
2069
2070                /*
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.
2073                 */
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);
2077                else
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);
2080
2081                *cnt+=1;
2082             }
2083             usb_close(hd);
2084          }
2085       }
2086    }
2087
2088    return size;
2089 }
2090
2091 enum HPMUD_RESULT hpmud_make_usb_uri(const char *busnum, const char *devnum, char *uri, int uri_size, int *bytes_read)
2092 {
2093    struct usb_bus *bus;
2094    struct usb_device *dev, *found_dev=NULL;
2095    usb_dev_handle *hd=NULL;
2096    char model[128];
2097    char serial[128];
2098    char sz[256];
2099    int r;
2100    enum HPMUD_RESULT stat = HPMUD_R_INVALID_DEVICE_NODE;
2101
2102    DBG("[%d] hpmud_make_usb_uri() bus=%s dev=%s\n", getpid(), busnum, devnum);
2103
2104    *bytes_read=0;
2105
2106    usb_init();
2107    usb_find_busses();
2108    usb_find_devices();
2109
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 */
2115
2116    if (found_dev == NULL)
2117    {
2118       BUG("invalid busnum:devnum %s:%s\n", busnum, devnum);
2119       goto bugout;
2120    }
2121
2122    dev = found_dev;
2123    if ((hd = usb_open(dev)) == NULL)
2124    {
2125       BUG("invalid usb_open: %m\n");
2126       goto bugout;
2127    }
2128
2129    model[0] = serial[0] = sz[0] = 0;
2130
2131    if (dev->descriptor.idVendor == 0x3f0)
2132    {
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);
2136       else
2137          generalize_model(sz, model, sizeof(model));
2138
2139       if ((r=get_string_descriptor(hd, dev->descriptor.iSerialNumber, sz, sizeof(sz))) < 0)
2140          BUG("invalid serial id string ret=%d\n", r);
2141       else
2142          generalize_serial(sz, serial, sizeof(serial));
2143
2144       if (!serial[0])
2145          strcpy(serial, "0"); /* no serial number, make it zero */
2146    }
2147    else
2148    {
2149       BUG("invalid vendor id: %d\n", dev->descriptor.idVendor);
2150       goto bugout;
2151    }
2152
2153    if (!model[0] || !serial[0])
2154       goto bugout;
2155    
2156    *bytes_read = snprintf(uri, uri_size, "hp:/usb/%s?serial=%s", model, serial); 
2157    stat = HPMUD_R_OK;
2158
2159 bugout:
2160    if (hd != NULL)
2161       usb_close(hd);
2162
2163    return stat;
2164 }
2165
2166 enum HPMUD_RESULT hpmud_make_usb_serial_uri(const char *sn, char *uri, int uri_size, int *bytes_read)
2167 {
2168    struct usb_bus *bus;
2169    struct usb_device *dev, *found_dev=NULL;
2170    char model[128];
2171    enum HPMUD_RESULT stat = HPMUD_R_INVALID_DEVICE_NODE;
2172
2173    DBG("[%d] hpmud_make_usb_serial_uri() sn=%s\n", getpid(), sn);
2174
2175    *bytes_read=0;
2176
2177    usb_init();
2178    usb_find_busses();
2179    usb_find_devices();
2180
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 */
2185
2186    if (found_dev == NULL)
2187    {
2188       BUG("invalid sn %s\n", sn);
2189       goto bugout;
2190    }
2191  
2192    *bytes_read = snprintf(uri, uri_size, "hp:/usb/%s?serial=%s", model, sn); 
2193    stat = HPMUD_R_OK;
2194
2195 bugout:
2196    return stat;
2197 }