libudev monitor, filtering on KERNEL - c

in real-time I want to print out hot-plugging events on Harddisks only. My code does print out all events for the correct "devtype"("disk") and "subsystem"("block"). However this includes devices I don`t care about such as loop devices, cdrom devices etc I only care about raw disks (e.g /dev/sda and not partitions like /dev/sda1). Is there a ways to filter from within libudev on something like that? in udev rule speak this is called "KERNEL". In essence I want to show all new devices that would match a udev rule like this:
KERNEL=="sd*", ENV{DEVTYPE}=="disk"
this would only match raw disks. like /dev/sda.
Now my program can match against devtype and and subsystem by using the
udev_monitor_filter_add_match_subsystem_devtype(mon, "block", "disk");
libudev call.
now this however still prints out changes to devices such as /dev/loop* or /dev/sr* which I don`t want.
is there a way to filter on KERNEL?
edit:

Related

Embedded Firmware Architecture

I’ve been writing increasingly complex firmware and am starting to notice that my knowledge of design patterns and architecture is a bit lacking. I’m trying to work on developing these skills and am hoping for some input. Note: this is for embedded c for microcontrollers.
I’m working with a concept for a new project as an exercise right now that goes something like this:
We have a battery management module with user I/O
The main controller is responsible for I/O (button, LCD, UART debug), detecting things like the charger being plugged in/unplugged, and managing high level operations.
The sub controller is a battery management controller (pretty much a custom PMIC) capable of monitoring battery levels, running charging/discharging firmware etc.
The PMIC interfaces with a fuel gauge IC that it uses to read battery information from
The interface between the two controllers, fuel gauge and the LCD are all I2C
Here is a rough system diagram:
Now what I’m trying to do is to come up with a good firmware architecture that will allow for expandability (adding multiple batteries, adding more sensors, changing the LCD (or other) interface from I2C to SPI, etc), and for testing (simulate button presses via UART, replace battery readings with simulated values to test PMIC charge firmware, etc).
What I would normally do is write a custom driver for each peripheral, and a firmware module for each block. I would implement a flagging module as well with a globally available get/set that would be used throughout the system. For example my timers would set 100Hz, 5Hz, 1Hz, flags, which the main loop would handle and call the individual modules at their desired rate. Then the modules themselves could set flags for the main loop to handle for events like I2C transaction complete, transaction timed out, temperature exceeded, etc.
What I am hoping to get from this is a few suggestions on a better way to architect the system to achieve my goals of scalability, encapsulation and abstraction. It seems like what I’m doing is sort of a pseudo event-driven system but one that’s been hacked together.
In any case here’s my attempt at an architecture diagram:
The concept of an "event bus" is over-complicated. In many cases, the simplest approach is to minimize the number of things that need to happen asynchronously, but instead have a "main poll" routine which runs on an "as often as convenient" basis and calls polling routines for each subsystem. It may be helpful to have such routine in a compilation by itself, so that the essence of that file would simply be a list of all polling functions used by other subsystems, rather than anything with semantics of its own. If one has a "get button push" routine, one can have a loop within that routine which calls the main poll routine until a button is pushed, there's a keyboard timeout, or something else happens that the caller needs to deal with. That would then allow the main UI to be implemented using code like:
void maybe_do_something_fun(void)
{
while(1)
{
show_message("Do something fun?");
wait_for_button();
if (button_hit(YES_BUTTON))
{
... do something fun
return;
}
else if (button_hit(NO_BUTTON))
{
... do something boring
return;
}
} while(1);
}
This is often much more convenient than trying to have a giant state machine and say that if the code is the STATE_MAYBE_DO_SOMETHING_FUN state and the yes or no button is pushed, it will need to advance to the STATE_START_DOING_SOMETHING_FUN or STATE_START_DOING_SOMETHING_BORING state.
Note that if one uses this approach, one will need to ensure that the worst-case time between calls to main_poll will always satisfy the timeliness requirements of the polling operations handled through main_poll, but in cases where that requirement can be met, this approach can be far more convenient and efficient than doing everything necessary to preemptively-scheduled multi-threaded code along with the locks and other guards needed to make it work reliably.

Implementation of linux char driver with multiple parameters to access

I am writing a simple char driver which accesses a PCI card. It is registered to sysfs with the help of a new class and accessible under /dev/foodev. Using standard file operations I can perform simple read and write operations to the device.
My problem: I have multiple parameters stored at different addresses on the card (version, status, control, ...) which I would like access independently. Currently having only one read and one write function I therefore have to change the address every time again in the driver code.
Obviously there is a more convenient way to implement this. I stumbled about the two following approaches and was wondering which is the better one in terms of sustainability and user accessibility:
Using ioctl commands setting the address/parameter before an
access.
Having the device already nicely set up in udev using multiple attributes
(device_create_file()) of which the user than just can write/read from
different "files":
/dev/foodev
../version
../status
../control
I think you should take a look at the PCI framework to implement your driver.
Don't (mis)use ioctls; you'll have race conditions. Use the attributes as files. That scheme is already used in sysfs. E.G. look at GPIO LEDs and keys. – sawdust

Enumerating capture ALSA devices and capture from them

I am writing a C program where I would like to enumerate all the capture devices in my system (in practice, I know I have three webcams plus the "integrated" microphone), recognize them and start capturing from them all at the same time.
I has some success using snd_device_name_hint() to enumerate all PCM devices and then snd_device_name_get_hint() to determine the "IOID" to see if they support capture. But now, how do I open the related device with snd_pcm_open() so that I can capture? I would like to use the "hw" interface as I do not want to overload the system with many conversion rates, so I would also like to see if there is a method to report the HW supported sampling frequencies.
Thank you!
snd_device_name_hint() can return multiple device names for the same hardware device (e.g., plughw and hw).
It can also returns devices that do not correspond to a single hardware device (such as null, or PulseAudio/Jack/Bluetooth devices).
To enumerate hardware devices, call snd_card_next() and snd_ctl_pcm_next_device() (see the aplay source code for an example).
To check whether a sample rate is supported, call snd_pcm_hw_params_test_rate().

Get node name given to a USB by ACM Driver

I have two usb devices that are recognized by the ACM driver and I’m developing a program in C to communicate with them. As the command for each one are different, I need to know the name given for each one (usb/acm/X).
How can I get this name given the vendorId and productId? I have tried parsing dmesg text but in some cases I may have the two lines “ttyACMX: USB ACM device” one after the other.
I could parse the order each device shows its name in dmesg and take the same number in the “ttyACMX” but this force me to parse also the disconnections messages and all becomes a bit dirty.
I’ve seen that the information I need is in the structure tty_driver created for each device and I’m sure I can have this information easier than parsing dmesg.
Can someone point me out int the right direction?
libudev (C) might be a solution, also have a look at the source of ModemManager daemon (C, glib based)
Use libudev or some higher-level library like gudev (GLib-based libudev). Don't use ModemManager unless your devices are really mobile broadband (2G/3G/4G) modems.
I found this thread to be helpful: http://forum.pololu.com/viewtopic.php?f=16&t=6741
You can make a udev rule file in /etc/udev/rules.d that has a rule like this:
KERNEL=="ttyACM0", SUBSYSTEM=="tty", SUBSYSTEMS=="usb",
ATTRS{idVendor}=="1ffb", ATTRS{idProduct}=="008c",
ATTRS{serial}=="00053419", MODE="0666", SYMLINK+="TTYS_002"
I think this will make a device named /dev/TTYS_002 when you plug in a CDC ACM device that has the specified vendor ID, product ID, and serial number.

Reliable method for detecting when a USB HID device is emulating a keyboard

I'm working on an embedded system, and I need to determine if the user has connected an HID device emulating a keyboard (i.e. a barcode scanner) or an actual keyboard.
I can inspect the iManufacturer, iProduct, iSerialNumber, and iInterface string descriptors to gain some clues. For example, "reader" or "scanner" has been observed to appear in the iProduct string when a barcode reader has been connected. Likewise, "emulation" has been seen in the iInterface string. However, I'm a bit reluctant to rely solely on these strings (string case is easy enough to handle, but handling things like abbreviations in key words/phrases quickly becomes onerous.)
I've reviewed the USB 1.10 and 1.11 specs and found that the Report descriptor offers some cues, as well. For example, the Global Usage item should be something like 0x0501 for Generic Desktop, and the Local Usage item should be 0x0906 (Keyboard). Is there anything else in the Report descriptor that might assist in detecting the difference?
I would like to avoid relying on the Vendor ID and Product ID lists since this is an embedded system with limited resources. Suggestions? Is there something I've missed?
There is no absolutely reliable method to do this. There cannot be, because there is no absolute definition of what is or is not a keyboard -- nor of what the difference is between "emulating a keyboard" and "being a keyboard". The boundary gets particularly fuzzy around assistive devices and things like chording keyboards, but even beyond that, you have the fundamental problem that the way to emulate a keyboard is to communicate across the USB cable in exactly the way that a keyboard communicates.
The methods you've suggested are reasonable heuristics for identifying a number of things that are clearly non-keyboards (with a faint risk of false positives in some cases), but heuristics that look for hints are the best solution that's going to be possible.

Resources