How can you take ownership of a hid device? - linux

What I would like to take ownership of a hid device that may already have been plugged in, consume it's output, while preventing others(X11 or terminal) from consuming it.
If I can help it, I don't want to pretend to be a terminal, but rather to monopolize a particular hid or character device. The idea is that some hid devices may be recognized as mice/keyboards by x/terminal, but a second mouse or keyboard could be used for something else, but to do that you need to make sure they aren't sending spurious input into an open terminal.
Does anyone have any insight as to how this might be done?

I have done this - my specific application was a daemon that read events from a USB HID barcode reader (which presents as a USB HID keyboard device).
To do this I used the event device interface, opening the /dev/input/event* device corresponding to the device I was after. You can then issue the EVIOCGRAB ioctl on the device, which grabs it for exclusive use, and read events (which represent keypresses, mouse movements etc) from the device as they become available.
(When the device is grabbed for exclusive use, only your application will see events from it).

Related

Linux: access i2c device within board_init function

(iMX6 SOC running Linux 3.0)
I need to run a few I2C transactions in my board_init function. I tried calling i2c_get_adapter, then i2c_transfer, those being available in kernel mode, but i2c_get_adapter returns NULL. It's already called imx6q_add_imx_i2c, which is a wrapper around platform_device_register_full, but that isn't enough.
I can manipulate GPIO in board_init by calling gpio_request to obtain access, and gpio_free at the end. Is there something analogous to those functions for i2c?
--- added details ---
I've got a LAN9500A USB 100Base-T Ethernet MAC connected to a LAN9303 3-port switch with a virtual PHY. The MAC has a GPIO reset line that has to be turned off before it will spring to life and enumerate on the USB. That's done in board_init because it's completely nonstandard, so we don't want to patch the stock driver to manipulate some GPIO that's not part of the device.
The problem I'm having is that even though the MAC is permanently attached to the VPHY, it's not noticing it's connected, and an "ip link show eth1" command shows NO-CARRIER. I found I can kickstart it by unmasking the VPHY's Device Ready interrupt via I2C, but I also have to mask it immediately, or I get infinite interrupts. That's not the right solution, but Microchip has been no help in showing me a better way. But we don't want to patch the MAC driver with code to fiddle with the PHY.
There is no PHY driver for this part, and the MII interface to the VPHY doesn't include any interrupt-related registers, so it must be done through I2C. Writing a PHY driver just to flip a bit on and off once seems a lot of trouble, especially for a newbie like me who's never written a driver before.
I can do it in Python in a startup script, but that, too, seems like a heavyweight solution to a lightweight problem.
That's a wrong approach. Board file supposed to register device drivers and pass important information to them, rather than act as a device driver itself. I'm not sure if what you're trying to do is even possible.
If you really need to extract something from your I2C device on a very early stage - do that in the bootloader and pass the data to kernel via cmdline (U-boot, by the way, has I2C support for a quite some time). Then later, kernel might do appropriate actions depending on what you have passed to it.

write mouse data to USB driver, replacing mouse virtually

I am looking to supply a USB driver with the data it would receive from a physically moving mouse. Essentially replacing a physical mouse. But since the data is delivered directly to the usb driver, it thinks there is a real mouse. I am not looking for an application which makes the mouse move in some other programmatic/emulated way. I want to deliver data to the usb driver that it would regularly receive from physical mouse.
Here is something that looks promising (looking for Unix but windows might work too)
http://manpages.ubuntu.com/manpages/vivid/man4/mousedrv.4.html
Can anyone assist me on this?

Disabling specific USB devices

I need to write a program in linux (debian, to be exact) that disables a USB device if it doesn't pass specific filters. For example, the program might be set to disallow webcams, usb sticks and keyboards, enable mice and printer (through usb). The filters may change in runtime. For example, the program might receive a message to enable usb sticks and it should respond without rebooting the system. The program is written in python but embedding c code (or others) is also acceptable.
What I have tried
I have tried many methods but some of them aren't about programming.
First, I tried to mess with udev. I can monitor the activities when a device is plugged and write filters. There used to be an option "ignore_device" that ignored the filtered devices. For example, to ignore all the devices that are a member of usb subsystem, I would write this as a udev rule:
ACTION=="add", SUBSYSTEM=="usb", OPTIONS+="ignore_device"
But this option is released in this release of udev. What I get so far is that udev can currently be used mainly for monitoring. Sure, I can write additional rules for the rule above that runs a script, but I have to do the disabling elsewhere.
Second, I tried ioctl to send a DISCONNECT signal to device handle. I'm testing this with a USB mouse. This is the python code for that: (I have also tried this in C, nothing changed)
import fcntl
import sys
USBDEVFS_RESET = ord('U') << (4*2) | 20
USBDEVFS_DISCONNECT = ord('U') << (4*2) | 22
raw_name = "/dev/bus/usb/{:03d}/{:03d}"
filename = raw_name.format(1,2)
fd = open(filename, "wb")
fcntl.ioctl(fd, USBDEVFS_DISCONNECT, 0)
Here, if I would send USBDEVFS_RESET, it works, the mouse input is ignored for a second or two. But disconnect signal raises an error:
IOError: [Errno 25] Inappropriate ioctl for device
What I get from here is, I cannot send disconnect signal to a mouse. Maybe a usb stick or printer or some other devices would work, I haven't tried. I want to develop the program as generic as possible so as to prevent writing additional device-specific code, so this approach seems useless for me. And another point here is that when I manually disconnect/connect my mouse, I see events in udev monitor. But when I send reset signal, no event is sent.
The udev monitor says that the mouse was mounted to this path: /sys/bus/usb/devices/1-3 (which is a symlink for /sys/devices/pci0000:00/0000:00:14.0/usb1/1-3). Some documents told me that this folder contains the device's settings and setting /power/level to "off" or "suspended" would turn the device power off. But I cannot manipulate any files in /power. Come to think about it, it might not be a good idea after all.
The Question
So, the question is, what is the best way to achieve such task? I have an idea but I'm not sure whether it will work and even if it does, it might be overkill. My idea is writing a "wrapper driver" that identifies itself to linux kernel as driver for all usb devices. The "wrapper driver" reads the device information and if the device is good to go, it acts as a wrapper for real drivers in the kernel, calling their functions. If not, the "wrapper driver" just ignores the device.
I'm not sure it can even be done, I'm not experienced in kernel or driver programming.
Another way is, -somehow- getting the handle of the device programatically and telling it to power off (or making it busy forever, whatever works). I have also done some little research but couldn't find a proper-easy way. They say all devices are considered as "files" but I cannot reach those files at all.
Note:
The question is mostly about linux internals but it also involves kernel programming. I read a lot about usb manipulation/monitoring programs, I read manual pages of udevadm. But these approaches do not help me at all. I think I need to alter either kernel or device internals programatically.
I have also tried manipulating authorized file that resides in /sys/devices/pci0000:00/0000:00:14.0/usb1/1-4 (for a keyboard). It's default value is 1. Changing it to 0 successfully disabled the bus (NOT device, but the physical usb port. The same device can still be used when plugged in another port). But making it 0 also stopped udev events from this usb port. So, I can disable the port if the user plugs in a forbidden device but I cannot decide when to enable it since I cannot listen to remove events in udev. Would it make sense if I delve deeper to lower levels of code (possibly kernel) and listen to usb events in some other way?
I think the simplest way to solve your problem is balcklisting all usb device drivers excepting mouse, keyboard etc.
The cleanest way is whitlisting mouse etc. with udev using usb device id's
Writing a wrapper driver is an absolute overkill never chose that way.
One possible solution could be tying usb access to user permissions. here is a related link you may find handy
http://robots.mobilerobots.com/wiki/Linux_udev_USB_Device_Permissions_Configuration

Is there a USB device descriptor to determine if a device is HID or keyboard emulation?

Does anyone know how to determine from the USB device descriptor or other USB descriptors if a USB device is HID or keyboard emulation? I'm looking to interface to a family of magtek magcard swipe readers and they can be configured to operate as HID or keyboard emulation. The magtek PID will tell me but what happens if someone plugs in a different manufacture? I'm looking for a univseral way of determining this. I'm using the libudev library to interface to my USB.
Also, does Linux have a universal routine to decode keyboard emulation scan codes. I've got my own look-up table which works fine but I was just wondering.
Steve
The only way you can tell what a device is, is by using the PID/VID of the USB device (and the Class, but I believe both modes are declared as HID-class devices anyway).
So, if you plug in a new manufacturer, you'll have to manually add support for it. From my experience (I did not use a magtek reader, but a tmsr33), no reader behave the same way in both HID or emulation mode. Generally speaking, I'd say it is better to use HID mode, as bytes exposed will need less conversion.
AFAICT, I went into the same trouble and I basically copy pasted the keycodes/keylayout from the kernel sources to my own code. If you prefer, you can link directly to the kernel's source code to get the tables.
https://github.com/MicahCarrick/magtek-pyusb
https://github.com/guyzmo/tmsr33-pyusb‎
HTH

Detect if an open file/device has been replaced/deleted

Assume the following situation under Linux:
A process is continuously reading from an USB-serial converter device (/dev/ttyUSB0). That device is suddenly unplugged and plugged in again (or is resetting itself for some reason). The process continues to have a valid file handle for /dev/ttyUSB0 but won't receive any data from the device unless the process re-opens the device (because udev has deleted and re-created the device node).
Is there a direct way to detect such a situation (ie. not indirectly by detecting a timeout in data flow) so that the process knows it has to re-open the device? Would it be reliable to monitor the modification time of /dev/ttyUSB0 using stat()?
Additional details:
The process opens the device file by using the standard open() function.
/dev is a tmpfs controlled by udev.
Note: I do not want to use any udev rules for this and prefer a solution implemented directly in the process.
If a USB device is hot-unplugged, operations on the device will begin failing with -EIO; you can detect this and take appropriate action.
If the device node is actually being removed and re-created (which I believe it is if you have udev), then you should be able to use the inode number to tell when this happens.
Just call fstat() on your open file descriptor, stat() on /dev/ttyUSB0, and compare the st_ino fields of the two struct stats.
And let me know if it actually works. :-)
I think FAM or gamin will detect these events.

Resources