Here is a patch which implements the outline below. A new structure
is added to usbdevice_fs.h and a new ioctl function is added to be passed
along to the device driver. An implementation of the ioctl for the
USB printer.c module is also here. There are not many changes because
the infrastructure is largely in place but it does introduce a dependency
of the printer module on the USB device filesystem.
Attached is a very simple program to exercise the new ioctl. I tested it
in an /etc/hotplug/usb/printer script to configure the user space drivers
for an HP OfficeJet.
Thanks,
Allen
diff -u -B -r orig/include/linux/usbdevice_fs.h linux/include/linux/usbdevice_fs.h
--- orig/include/linux/usbdevice_fs.h Wed Feb 21 19:11:49 2001
+++ linux/include/linux/usbdevice_fs.h Tue Apr 3 16:38:18 2001
@@ -124,6 +124,13 @@
char port [127]; /* e.g. port 3 connects to device 27 */
};
+/* Ask a driver about its device node; useful for hotplug scripts */
+struct usbdevfs_driver_devinfo {
+ int type; /* S_IFCHR or S_IFBLK from <sys/stat.h> */
+ int major; /* device node number */
+ int minor;
+};
+
#define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
#define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
@@ -142,6 +149,7 @@
#define USBDEVFS_HUB_PORTINFO _IOR('U', 19, struct usbdevfs_hub_portinfo)
#define USBDEVFS_RESET _IO('U', 20)
#define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int)
+#define USBDEVFS_DRIVER_DEVINFO _IOR('U', 22, struct usbdevfs_driver_devinfo)
/* --------------------------------------------------------------------- */
diff -u -B -r orig/drivers/usb/printer.c linux/drivers/usb/printer.c
--- orig/drivers/usb/printer.c Tue Feb 13 19:40:24 2001
+++ linux/drivers/usb/printer.c Tue Apr 3 16:33:50 2001
@@ -47,6 +47,7 @@
#include <linux/lp.h>
#undef DEBUG
#include <linux/usb.h>
+#include <linux/usbdevice_fs.h>
#define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024
@@ -604,6 +604,24 @@
kfree(usblp);
}
+static int usblp_usbdevfs_ioctl(struct usb_device *dev, unsigned int code, void* buf)
+{
+ struct usbdevfs_driver_devinfo* devinfo;
+ switch (code) {
+
+ case USBDEVFS_DRIVER_DEVINFO:
+ devinfo = (struct usbdevfs_driver_devinfo *)buf;
+ devinfo->type = S_IFCHR;
+ devinfo->major = USB_MAJOR;
+ devinfo->minor = ((struct usblp
+*)(dev->actconfig->interface->private_data))->minor;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static struct file_operations usblp_fops = {
owner: THIS_MODULE,
read: usblp_read,
@@ -630,6 +648,7 @@
fops: &usblp_fops,
minor: USBLP_MINOR_BASE,
id_table: usblp_ids,
+ ioctl: usblp_usbdevfs_ioctl,
};
static int __init usblp_init(void)
------------------------------- END OF PATCH --------------------------
David Brownell wrote:
>
> > Would it be possible (or reasonable) to add an ioctl to usbdevfs which
> > can ask for this information via the /proc/bus/usb/###/### interface? Or
> > should the printer.o module execute a user-space helper app to do this
> > configuration itself?
>
> IMHO, either of those would be reasonable 2.4 solutions. I'd likely
> want to see the ioctl, since scenarios have wanted this feature before.
> But that wouldn't work with non-USB printers; "printer hotplug" should
> IMHO happen at some point, too.
>
> That is, perhaps adding something like this to <linux/usbdevice_fs.h>
>
> struct usbdevfs_driver_devinfo {
> int type; /* S_IFCHR or S_IFBLK from <sys/stat.h> */
> dev_t dev; /* major/minor */
> }
> #define USBDEVFS_DRIVER_DEVINFO \
> _IOR('U',22, struct usbdevfs_driver_devinfo)
>
> and the driver (printer.c) would get updated
>
> static int printer_ioctl (
> struct usb_device *dev,
> unsigned int ioctl_code,
> void *user_data
> ) {
> switch (ioctl_code) {
> case USBDEVFS_DRIVER_DEVINFO:
> ... user_data is a struct usbdevfs_driver_devinfo
> ... fill it out and return
> default:
> return -ENOSYS;
> }
> }
>
> static struct usb_driver
> ...
> ioctl: printer_ioctl;
> }
>
> Then userspace would call it using the USBDEVFS_IOCTL mechanism.
> Printer would be the first to start reporting useful info with it.
>
> - Dave
/*
* Test out new IOCTL for the USB printer device number
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/usbdevice_fs.h>
static const char* USAGE = "usage: %s usbdevfs_file\n";
static struct usbdevfs_driver_devinfo devinfo;
static struct usbdevfs_ioctl driver_devinfo_ioctl = {
0,
USBDEVFS_DRIVER_DEVINFO,
&devinfo
};
int main (int argc, char* argv[])
{
int fd;
if ( argc != 2 ) {
fprintf( stderr, USAGE, argv[0] );
return 1;
}
fd = open( argv[1], O_RDWR );
if ( fd == -1 ) {
perror( argv[1] );
return 1;
}
if ( ioctl( fd, USBDEVFS_IOCTL, &driver_devinfo_ioctl ) == -1 )
perror( "error: ioctl request" );
else
printf( "DEVICETYPE=%c DEVICEMAJOR=%d DEVICEMINOR=%d\n",
devinfo.type == S_IFCHR ? 'C' : 'B',
devinfo.major,
devinfo.minor );
close( fd );
return 0;
}