2

Due to a broken udev setup on a machine from which I'm trying to rescue data (see this post of mine) I'm trying to write to a "character special" device corresponding to a USB flash drive, but am encountering difficulty.

What I would expect is that (with root permissions) I could do this:

echo "test 123" > /dev/bus/usb/001/031

But I get

bash: echo: write error: Invalid argument

What's going on? How can I write to a character device?

P.S.: this is of interest specifically because the block devices I would normally expect (/dev/sdb, stuff in /dev/block) aren't being created for some reason. Yet I noticed that a character device does get created when I insert a USB drive (and removed when I remove it). If I could find some way to write to that device I could save myself a lot of trouble transferring data slowly over audio cables (which is my current best approach).

5

Those are "raw USB" devices. Using them requires several USB-specific ioctl() functions: just writing raw data into them from the shell is unlikely to accomplish much at all. The data would have to be formatted into valid USB packets first, and the ioctl() functions used to establish connection to the right USB endpoint within that device.

And since we're talking about a USB storage device, the procedure would be even more complicated: withing those USB packets, there should be one of six possible storage command sets. In practice, the overwhelmingly most common command set is the "SCSI transparent" command set - a SCSI protocol wrapped into USB.

As a result, you would first have to learn how to write onto a disk device using /dev/sg* devices, by crafting your own SCSI command packets. Once you achieved that, you could add USB-specific wrappers onto that procedure, and only then you might be able to write raw blocks onto a USB storage device using those /dev/bus/usb/<busnum>/<devnum> devices.

In most cases, using raw USB ioctl()s is extremely tedious unless you need something very specific: most programmers needing raw USB access will use libusb or some other library (like libftdi for hardware-developer-level access to FTDI USB-to-serial converter chips) to handle the base mechanics of USB for them. In short, you would have to already be a pretty well established USB I/O programmer to successfully use raw USB storage device in a rescue situation such as yours.

Having said that, your other post looks like you've had to pull off a truly epic data rescue operation. For that, I respect your achievement... but I also hope you've learned something about the importance of backups.

  • Followup question: were I able to create the block device file for a USB drive, could I write directly to that? Or does that still require special handling like this character device? – Josh Hansen Dec 9 '17 at 7:55
  • If the usb-storage kernel module was loaded and the problem was just a failure of udev to create the device node, then yes; you could use the mknod command to create the device node and then write to it with dd or perhaps even mount it. The usb-storage module will normally do all the "special handling" required for you. But if the module cannot be loaded, then creating the device file would do nothing at all: any attempts to write into that device would just result in an "unknown device" error message. – telcoM Dec 9 '17 at 8:09
  • It appears that the usb-storage module is not loaded, and I get an I/O error when I try to load it. No luck. – Josh Hansen Dec 9 '17 at 17:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.