How to see raw USB events on Linux via usbmon
Suppose, not entirely hypothetically,
that you're wondering if your USB keyboard actually does anything for certain
key presses, such as its Fn button plus a normal letter key like
's'. One way to try to find out is just to type the key combination
while sitting at your shell prompt or in your editor or the like,
and see what happens. A more elaborate method is to fire up
see what it says about X events, since there are a number of things
that can happen between the level of X events and what your shell
sees. Of course this starts to hint at the broad problem, which is
that a modern graphical Linux environment has all sorts of layers
that may swallow or distort raw events, so not seeing anything in
the shell or in
xev only means that things didn't make it that
(This is useful knowledge, of course, especially if your ultimate
goal is getting characters to your shell or to an X program that
should recognize them. And hitting that key produces some event,
xev will tell you what it's been turned into.)
Usefully, the Linux kernel gives us a way to bypass all of the
(potential) layers of input processing and see the raw USB events
being generated (or not generated, as the case may be). Looking at
the presence or absence of raw events is pretty definite. If the
keyboard is not generating any USB events when you press some keys,
well, that's it. How you do this is with the kernel's usbmon system,
as covered in the kernel's
Ubuntu's page on debugging USB. For quick checks,
the text interface in
/sys/kernel/debug/usb/usbmon is your most
convenient option, but Linux distributions seem to vary as to whether
you need to load a
usbmon kernel module or not to get it.
(On my Fedora 25 machines, everything is ready to go out of the
box, with no kernel modules needing to be loaded; the Fedora kernels
are apparently built with
CONFIG_USB_MON=y. On a relatively
stock Ubuntu 16.04 server, there's a
usbmon module and it's not
loaded by default.)
Wireshark can capture and interpret USB bus traffic, per here, and in theory should be a good way to see the details of USB events in a more user-friendly format than the kernel's text dump. In practice I can't seem to persuade the Fedora 25 version to give me useful information here. I find it more helpful to read the output from the text interface, which at least lets me distinguish one sort of event from another (for example, the mouse scrollwheel going in one direction versus the other direction). Possibly I'm missing some magic Wireshark options, especially since I don't use Wireshark very often. Alternately, I'd need to know a non-casual amount about USB message formats and the details of the USB protocol in order to understand what Wireshark is showing me and extract the things I'm interested in.
(There also may be an issue that apparently Wireshark may only do a good job decoding things if it sees you plug in the USB device. This is perhaps sensible behavior for Wireshark, or even necessary, but it's not very useful for checking the details of what my (only) keyboard or mouse generate. I'm not really enthused about unplugging and then replugging them; it has somewhat annoying side effects.)
As a side note, since you can only monitor an entire USB buss (or
all busses at once), it's not necessarily very important to be
detailed about identifying what USB device is where. For instance,
on my home machine, the only USB bus that reports
any non-hub devices is bus 2, so even if a plain '
clearly identify the specific USB device that's my keyboard or
mouse, it's a pretty good bet that they're on bus 2. '
can also give strong hints; on my home machine, all '
Interface Device' USB devices are on bus 2 even if
tell me exactly what their (product) names are.
(I started writing this entry just to have some information about the usbmon feature recorded for my later use, and wound up learning useful things about Wireshark's USB stuff.)
PS: Because Wireshark is actually using libpcap to get the USB
traffic from the kernel, you can also use
tcpdump to capture USB
traces, for example '
tcpdump -i usbmon2 -s 0 -w /tmp/usbmon.pcap'.
This may be handy if you have a server seeing USB oddities; at least
around here, we're far more likely to have basic
on random machines than we are to put Wireshark on them. As usual,
you can use
tcpdump to capture the packet trace, transfer it to
your workstation, and run Wireshark on the capture to decode and
analyze it and so on.
(This is also how I avoid running Wireshark as
root even if I'm
capturing the traffic on my own machine.)