udev-ish replacement for hal-cups-utils?

Kay Sievers kay.sievers at vrfy.org
Mon Jul 20 16:28:08 PDT 2009


On Fri, 2009-07-17 at 12:08 +0100, Tim Waugh wrote:
> On Tue, 2009-07-14 at 18:32 +0200, Martin Pitt wrote:
> > So, one immediate workaround would be to not pass the device ID
> > itself, but the path (%p) and just read that value plus "/ieee1284_id"
> > from the python program. That's a little tricky with identifying the
> > ID at removal time, though (you'd need to remember the quoted one as
> > well, i. e. consider that an abstract identifier for the real device
> > ID).
> 
> Please take a look at the 'udev' branch of system-config-printer:
> 
> http://git.fedorahosted.org/git/?p=system-config-printer.git;a=shortlog;h=refs/heads/udev
> 
> I'm trying to use libudev to read the ieee1284_id attribute but am
> failing.  The devpath I'm given is:
>   /devices/pci0000:00/0000:00:1d.3/usb5/5-1
> 
> I can see that the file I need is:
>   /sys/devices/pci0000:00/0000:00:1d.3/usb5/5-1/5-1:1.0/ieee1284_id
> 
> but I can't see how to get to it.  How do I find out the name "5-1:1.0"?
> (The code is currently trying usb_interface which is obviously wrong.)

I needed to solve the libusb problem which always scans all devices
which we need to avoid in the udev context, and I needed something to
play around.

I played a bit around with the printer, and here is a libudev version
that finds the usblp attribute if available and not asked to unbind
usblp. Maybe you can pick some stuff from here if you still need it.

This will work from all IMPORT, PROGRAM, RUN keys in udev because it
does not use libusb, but the kernel ioctl() interfaces directly.

I works like this with usblp loaded:
  $ extras/printer/printer --devpath=/devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0
  MFG:Brother;CMD:PJL,PCL,PCLXL;MDL:HL-2070N series;CLS:PRINTER;

If asked to get rid of usblp, or usblp is not active at all, it will
unbind the device first, and then ask the raw class interface: 
  $ extras/printer/printer --devpath=/devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0 --unbind
  MFG:Brother;CMD:PJL,PCL,PCLXL;MDL:HL-2070N series;CLS:PRINTER;

Cheers,
Kay


commit a7be5b0a6d8e5b1a177caa9b10817f2fe34d3e25
Author: Kay Sievers <kay.sievers at vrfy.org>
Date:   Tue Jul 21 01:08:14 2009 +0200

    extras: printer query callout

diff --git a/configure.ac b/configure.ac
index 69c115d..d6a4380 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([udev], [145], [linux-hotplug at vger.kernel.org])
+AC_INIT([udev], [146], [linux-hotplug at vger.kernel.org])
 AC_PREREQ(2.60)
 AM_INIT_AUTOMAKE([check-news foreign 1.9 dist-bzip2])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -110,6 +110,7 @@ AC_CONFIG_FILES([
 	udev/udev.pc
 	rules/Makefile
 	extras/Makefile
+	extras/usb/Makefile
 	extras/ata_id/Makefile
 	extras/cdrom_id/Makefile
 	extras/edd_id/Makefile
@@ -125,6 +126,7 @@ AC_CONFIG_FILES([
 	extras/hid2hci/Makefile
 	extras/udev-acl/Makefile
 	extras/usb-db/Makefile
+	extras/printer/Makefile
 	extras/gudev/Makefile
 	extras/gudev/gudev-1.0.pc
 	extras/gudev/docs/Makefile
diff --git a/extras/Makefile.am b/extras/Makefile.am
index b7c9fe8..47e038a 100644
--- a/extras/Makefile.am
+++ b/extras/Makefile.am
@@ -1,6 +1,7 @@
 include $(top_srcdir)/Makefile.am.inc
 
 SUBDIRS = \
+	usb \
 	ata_id \
 	cdrom_id \
 	edd_id \
@@ -12,7 +13,8 @@ SUBDIRS = \
 	rule_generator \
 	scsi_id \
 	usb_id \
-	v4l_id
+	v4l_id \
+	printer
 
 if ENABLE_EXTRAS
 SUBDIRS += \
diff --git a/extras/printer/.gitignore b/extras/printer/.gitignore
new file mode 100644
index 0000000..24b8a4f
--- /dev/null
+++ b/extras/printer/.gitignore
@@ -0,0 +1 @@
+printer
diff --git a/extras/printer/Makefile.am b/extras/printer/Makefile.am
new file mode 100644
index 0000000..c0728e0
--- /dev/null
+++ b/extras/printer/Makefile.am
@@ -0,0 +1,15 @@
+include $(top_srcdir)/Makefile.am.inc
+
+libexec_PROGRAMS = \
+	printer
+
+printer_SOURCES = \
+	printer.c \
+	../usb/usb.h \
+	../usb/usb.c \
+	../../libudev/libudev.h \
+	../../libudev/libudev.c \
+	../../libudev/libudev-list.c \
+	../../libudev/libudev-util.c \
+	../../libudev/libudev-device.c \
+	../../libudev/libudev-enumerate.c
diff --git a/extras/printer/printer.c b/extras/printer/printer.c
new file mode 100644
index 0000000..20d520e
--- /dev/null
+++ b/extras/printer/printer.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2009 Kay Sievers <kay.sievers at vrfy.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+
+#include "libudev.h"
+#include "libudev-private.h"
+#include "../usb/usb.h"
+
+static int ieee1284_id(struct usb_dev_handle *dev, int config, int
intf,
+		       char *devid, size_t size)
+{
+	char id[1024];
+	size_t len;
+	int ret;
+
+	ret = usb_control_msg(dev,
+		USB_TYPE_CLASS|USB_DIR_IN|USB_RECIP_INTERFACE, 0,
+		config, intf, id, size, 5000);
+	if (ret < 0)
+		return ret;
+
+	len = ((unsigned char)id[0] << 8) + ((unsigned char)id[1]);
+	if (len >= size)
+		return -EINVAL;
+	id[len] = '\0';
+	memcpy(devid, &id[2], len+1);
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	static const struct option options[] = {
+		{ "devpath", required_argument, NULL, 'p' },
+		{ "device", required_argument, NULL, 'n' },
+		{ "unbind", no_argument, NULL, 'u' },
+		{ "help", no_argument, NULL, 'h' },
+		{}
+	};
+	struct udev *udev;
+	char syspath[UTIL_PATH_SIZE];
+	char *devpath = NULL;
+	const char *device = NULL;
+	bool unbind = false;
+	struct udev_device *usb_if = NULL;
+	struct udev_device *usb_dev;
+	struct usb_dev_handle *usb_handle = NULL;
+	const char *str;
+	int if_num, conf_num;
+	char id[1024];
+	int rc = 1;
+
+	while (1) {
+		int option;
+
+		option = getopt_long(argc, argv, "p:n:uh", options, NULL);
+		if (option == -1)
+			break;
+
+		switch (option) {
+		case 'p':
+			devpath = optarg;
+			break;
+		case 'n':
+			device = optarg;
+			break;
+		case 'u':
+			unbind = true;
+			break;
+		case 'h':
+			printf("Usage: printer --devpath=<sys device> [--device=<device
file>] [--help]\n\n");
+			return 0;
+		default:
+			return 1;
+		}
+	}
+
+	udev = udev_new();
+	if (udev == NULL)
+		goto exit;
+
+	util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev),
devpath, NULL);
+	usb_if = udev_device_new_from_syspath(udev, syspath);
+	if (usb_if == NULL)
+		goto exit;
+	str = udev_device_get_devtype(usb_if);
+	if (str == NULL || strcmp(str, "usb_interface") != 0)
+		goto exit;
+
+	/* check for usblp id */
+	if (!unbind) {
+		str = udev_device_get_sysattr_value(usb_if, "ieee1284_id");
+		if (str != NULL) {
+			printf("%s\n", str);
+			rc = 0;
+			goto exit;
+		}
+	}
+
+	str = udev_device_get_sysattr_value(usb_if, "bInterfaceNumber");
+	if (str == NULL)
+		goto exit;
+	if_num = strtoul(str, NULL, 16);
+
+	/* get usb_device */
+	usb_dev = udev_device_get_parent_with_subsystem_devtype(usb_if, "usb",
"usb_device");
+	if (usb_dev == NULL)
+		goto exit;
+	str = udev_device_get_sysattr_value(usb_dev, "bConfigurationValue");
+	if (str == NULL)
+		goto exit;
+	conf_num = strtoul(str, NULL, 16);
+
+	/* open the device */
+	if (device == NULL)
+		device = udev_device_get_devnode(usb_dev);
+	if (device == NULL)
+		goto exit;
+	usb_handle = usb_open_from_devnode(device);
+	if (usb_handle == NULL)
+		goto exit;
+
+	/* unbind kernel driver */
+	if (unbind)
+		usb_detach_kernel_driver_np(usb_handle, if_num);
+
+	/* query printer class interface */
+	if (ieee1284_id(usb_handle, conf_num, if_num, id, sizeof(id)) < 0)
+		goto exit;
+	printf("%s\n", id);
+	rc = 0;
+exit:
+	usb_close(usb_handle);
+	udev_device_unref(usb_if);
+	udev_unref(udev);
+	return rc;
+}
diff --git a/extras/usb/Makefile.am b/extras/usb/Makefile.am
new file mode 100644
index 0000000..3ea07f6
--- /dev/null
+++ b/extras/usb/Makefile.am
@@ -0,0 +1,5 @@
+include $(top_srcdir)/Makefile.am.inc
+
+usb_SOURCES = \
+	usb.h \
+	usb.c
diff --git a/extras/usb/usb.c b/extras/usb/usb.c
new file mode 100644
index 0000000..8c04fba
--- /dev/null
+++ b/extras/usb/usb.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009 Kay Sievers <kay.sievers at vrfy.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/usbdevice_fs.h>
+#include <linux/usb/ch9.h>
+
+#include "usb.h"
+
+struct usb_dev_handle {
+	int fd;
+	int intf;
+};
+
+struct usb_dev_handle *usb_open_from_devnode(const char *filename)
+{
+	struct usb_dev_handle *handle;
+
+	handle = calloc(1, sizeof(struct usb_dev_handle));
+	if (handle == NULL)
+		return NULL;
+
+	handle->fd = open(filename, O_RDWR);
+	if (handle->fd < 0) {
+		free(handle);
+		return NULL;
+	}
+	return handle;
+}
+
+int usb_close(struct usb_dev_handle *dev)
+{
+	if (dev == NULL)
+		return 0;
+	close(dev->fd);
+	free(dev);
+	return 0;
+}
+
+int usb_claim_interface(struct usb_dev_handle *dev, int interface)
+{
+	int ret;
+
+	ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
+	if (ret < 0)
+		return ret;
+	dev->intf = interface;
+	return 0;
+}
+
+int usb_control_msg(struct usb_dev_handle *dev, int requesttype, int
request,
+		    int value, int idx, char *bytes, int size, int timeout)
+{
+	struct usbdevfs_ctrltransfer ctrl = {
+		.bRequestType = requesttype,
+		.bRequest = request,
+		.wValue = value,
+		.wIndex = idx,
+		.wLength = size,
+		.data = bytes,
+		.timeout = timeout,
+	};
+	return ioctl(dev->fd, USBDEVFS_CONTROL, &ctrl);
+}
+
+int usb_detach_kernel_driver_np(struct usb_dev_handle *dev, int
interface)
+{
+	struct usbdevfs_ioctl command = {
+		.ifno = interface,
+		.ioctl_code = USBDEVFS_DISCONNECT,
+	};
+	return ioctl(dev->fd, USBDEVFS_IOCTL, &command);
+}
diff --git a/extras/usb/usb.h b/extras/usb/usb.h
new file mode 100644
index 0000000..03f65cb
--- /dev/null
+++ b/extras/usb/usb.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 Kay Sievers <kay.sievers at vrfy.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details:
+ */
+
+#ifndef _USB_H_
+#define _USB_H_
+
+#include <linux/usbdevice_fs.h>
+#include <linux/usb/ch9.h>
+
+struct usb_dev_handle;
+struct usb_dev_handle *usb_open_from_devnode(const char *filename);
+int usb_close(struct usb_dev_handle *dev);
+int usb_control_msg(struct usb_dev_handle *dev, int requesttype, int
request,
+		    int value, int idx, char *bytes, int size, int timeout);
+int usb_claim_interface(struct usb_dev_handle *dev, int interface);
+int usb_detach_kernel_driver_np(struct usb_dev_handle *dev, int
interface);
+
+#endif




More information about the devkit-devel mailing list