I ended part 1 with a description of my struggles to display trace statements inserted into libusb. One spot where I needed to add a trace was
if ((fd = open(busnode, O_RDWR)) < 0) {
if (errno != ENOENT && errno != ENXIO)
usbi_err(ctx, "could not open %s", busnode);
continue;
}
Notice that the code here keeps a rather important detail (errno) to itself. I changed the code to
if ((fd = open(busnode, O_RDWR)) < 0) {
if (errno != ENOENT && errno != ENXIO) {
usbi_err(ctx, "could not open %s", busnode);
fprintf(stderr, "errno: %d", errno);
}
continue;
}
and once the output started flowing I found out that errno was 13 (EACCESS). A classic file permissions problem, it's just that it wasn't very well reported. It should have been apparent back when I saw the backend work without problems when run directly.
Rather than figuring out which user's permissions are in effect when CUPS calls the backend, I simply turned on global read-write permissions for /dev/ugen* to see if it would help. It didn't.
After another bit of "fun" detective work, I found the reason buried in the libusb port. For those unfamiliar with OpenBSD ports, a port is basically a recipe for turning an external piece of software into an OpenBSD package. It contains instructions for fetching and unpacking the source, patching it for OpenBSD, building it, packaging the result in a neat .tgz file and even installing an unistalling it.
I noticed that the patch for openbsd_usb.c was rather big - almost 18K. On closer look, it was a substantial rewrite of the whole file which was kind of unexpected since the original code was already supposed to be OpenBSD-specific. One thing the rewrite changed was that it was no longer iterating over /dev/ugen but rather over /dev/usb. I failed to notice it when inserting trace statements - the pattern had been extracted into constants at the start of the file.
Armed with new wisdom, I turned on global read-write permissions for /dev/usb*. Progress! CUPS finally found my printer. I clicked on "Print test page". As you may have guessed, nothing happened. Continued in part 3.