Supporting scanners on multi function devices

Steinar Hamre steinarh at pvv.ntnu.no
Thu Feb 1 15:11:26 UTC 2007


On Thu, Feb 01, 2007 at 08:33:33AM +0100, Alexander Leidinger wrote:
> Quoting Steinar Hamre <steinarh at pvv.ntnu.no> (from Thu, 1 Feb 2007  
> 
> >Did the device work without my patch?
> 
> I never tried, I don't have a driver for this scanner (Brother has  
> binary only drivers for sane on linux only).

Can you verify that the same crash occurs if you add your device
to uscanner.c without my patch?

If so, the problem might indeed be that the scanner is not the
first device. I have attached a small program to list the interfaces
of an ugen device.

Making a ugen device of a multi function device is a bit tricky.
If you kldunload all modules using the device (usbdevs -d),
kldload ugen and then powercycle the device, that should do
the trick. Alternativly, compile a kernel without the relevant
devices and reboot.
(A way to get this information from a non-ugen device would
be appreciated.)

Then run
./ugeninfo /dev/ugen0

On my printer/scanner/memorycardreader this looks like:

4:4: EPSON(0x04b8) USB2.0 MFP(Hi-Speed)(0x082b): class 0:0:0 config 1, 3 ifs
        0: class 255:255:255, 2 eps
        1: class 7:1:2, 2 eps
        2: class 8:6:80, 2 eps

0 is the scanner. (UICLASS_VENDOR)
1 is UICLASS_PRINTER and 2 is UICLASS_MASS

	Steinar
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <dev/usb/usb.h>
#include <sys/ioctl.h>

int
print_device(char *path) {
  struct usb_device_info di; 
  struct usb_config_desc cd; 
  struct usb_interface_desc id; 
  int r, i, f;

  f=open(path, O_RDONLY);
  if (!f) {
    perror(path);
    return 0;
  }

  //di.udi_addr = a;
  r = ioctl(f, USB_GET_DEVICEINFO, &di);
  if (r<0) {
    perror("USB_GET_DEVICEINFO");
    return 0;
  }

  cd.ucd_config_index=USB_CURRENT_CONFIG_INDEX;
  r = ioctl(f, USB_GET_CONFIG_DESC, &cd);
  if (r<0) {
    perror("USB_GET_CONFIG_DESC");
    return 0;
  }
  
  printf("%d:%d: %s(0x%04x) %s(0x%04x): class %d:%d:%d config %d, %d ifs\n",
	 di.udi_bus, di.udi_addr,
	 di.udi_vendor, di.udi_vendorNo,
	 di.udi_product, di.udi_productNo,
	 di.udi_class, di.udi_subclass, di.udi_protocol,
	 cd.ucd_desc.bConfigurationValue,
	 cd.ucd_desc.bNumInterface);
  for (i = 0; i < cd.ucd_desc.bNumInterface; i++) {
    id.uid_config_index=USB_CURRENT_CONFIG_INDEX;
    id.uid_interface_index=i;
    id.uid_alt_index=USB_CURRENT_ALT_INDEX;
    r = ioctl(f, USB_GET_INTERFACE_DESC, &id);
    if (r<0) {
      perror("USB_GET_INTERFACE_DESC");
      continue;
    }
    printf("\t%d: class %d:%d:%d, %d eps\n",
	   i, id.uid_desc.bInterfaceClass,
	   id.uid_desc.bInterfaceSubClass, id.uid_desc.bInterfaceProtocol,
	   id.uid_desc.bNumEndpoints);
  }
  return 1;
}

int
main(int argc, char *argv[]) {
  print_device(argv[1]);
}



More information about the freebsd-usb mailing list