Run a script using udev when display driver is loaded in Linux - linux

I need to run a script when my frambe buffer (/dev/fb?) device is loaded. So, for testing, I used a udev rule (called 98-framebuffer.rules) like that:
KERNEL=="fb0", RUN+="/bin/touch /tmp/test"
The file is not being created when the system starts. What have I done wrong?

udev rules are loaded during the boot process. Check dmesg out after rebooting. Your rule is being executed after your mount.

Related

How to automatically run 'sudo modprobe -r ftdi_sio' whenever the device is plugged into my computer

I have a USB device that I'm using and I'm developing an application using WebUSB with Google Chrome.
The thing is whenever I plug the USB device into my Linux computer, I have to manually run sudo modprobe -r ftdi_sio to unload it.
I want it to be unloaded automatically whenever I plug that device into my computer instead of having to type it manually every single time.
Any ideas on how this could be implemented ? Help would be much appreciated
One option would be to "blacklist" the ftdi_sio module to stop it being loaded automatically. To do that create the following file:
/etc/modprobe.d/ftdi_sio-blacklist.conf
# This is a comment. Change it if you want.
blacklist ftdi_sio
Put your command in /etc/rc.local and restart. See if it works. Or you can find how other .ko are configured to automatically load during system startup. Follow the same to make your module load automatically.
The proper way is to create a udev rule that is triggered when the specific USB device is attached.
Create a file /etc/udev/rules.d/99-usb-load.rules, and replace the "7523" and "1a86" with the Product ID and Vendor ID of your USB device.
# For debugging if the rule is working
ACTION=="add", ENV{ID_MODEL_ID}=="7523", ENV{ID_VENDOR}=="1a86", RUN+="/bin/sh -c '/bin/echo inserted device >> /tmp/udev_file'"
ACTION=="remove", ENV{ID_MODEL_ID}=="7523", ENV{ID_VENDOR}=="1a86", RUN+="/bin/sh -c '/bin/echo removed device >> /tmp/udev_file'"
# Actual rules
ACTION=="add", ENV{ID_MODEL_ID}=="7523", ENV{ID_VENDOR}=="1a86", RUN+="/sbin/rmmod ftdi_sio"
ACTION=="remove", ENV{ID_MODEL_ID}=="7523", ENV{ID_VENDOR}=="1a86", RUN+=""
Restart the udev daemon
sudo /etc/init.d/udev restart
The add rule will be executed whenever the USB device with matching PID/VID is attached and it will unload the module ftdi_sio. The first two rules are for debugging purposes which write a line into /tmp/udev_file and can be used to verify if the rules has been triggered.
Looks like USB device is new and there are no existing drivers to handle as soon as it is plugged in. You need an interrupt line and a USB driver code for your requirement. You need to register your device to that driver and driver to the USB bus. Also need to write appropriate interrupt routines to be called as soon as your device is plugged in. This will make it work as you want !!
If you already have a .rules file for the USB device then append the following to the pre-existing file in the /etc/udev/rules.d/ directory. Otherwise, create a file in the /etc/udev/rules.d/ directory with the following content:
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ACTION=="add", RUN+="/sbin/rmmod ftdi_sio"
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ACTION=="remove", RUN+=""
This means that when the device with vendorID 0403 and product ID 6010 is plugged in it runs /sbin/rmmod ftdi_sio which removes the ftdi_sio module. The second rule means nothing will be run when unplugged. See [writing udev rules] for more info on how to name the .rules file (e.g. 99-mydevice.rules)
You'll have to replace 0403 and 6010 with your device's vendor ID and prodcut ID. The vendor ID and product ID can be found by running lsusb on the command line after plugging in the USB device. It will have the format:
Bus xxx Device xxx: ID idVendor:idProduct ManufacturerName
After creating or editing the .rules file in /etc/udev/rules.d/ directory be sure to reload the .rules file with the following command:
sudo udevadm control --reload
Some further references on udev rules:
debian wiki
arch wiki
writing udev rules

enable linux kernel driver dev_dbg debug messages

is there a simplest possible way to enable linux kernel driver dev_dbg debug messages (actually it's a trace style messages) hopefully without messing up with the kernel patching/recompiling or the driver implementing something extra like debugfs? perhaps there is a way to enable something SIMPLE in the kernel (like one flag?) triggering particular driver or all drivers dev_dbg (it can be filtered with the `dmesg|grep "driverName") output?
the kernel version is 4.14.
there is NO syslog/daemonlog/system log running at all. there is NO network interface and only single serial port is available. the target system is very slow and is very compact so there is NO WAY to add syslog/etc, there is nothing but dmesg where exactly would be good to see the output of the lines like:
dev_dbg(&client->dev, "bla bla bla\n");
some posts already suggested to add debug keyword for the bootargs kernel parameters unfortunately wasn't enough.
the outputs like dev_info are getting into the dmesg with no issue so it's definitely something close. thanks
the simplest way to receive dev_dbg messages without installing/configuring syslog/etc, appeared necessary to do following steps:
provide debug key into bootargs kernel parameters
append #define DEBUG at the first line of the driver file - if the driver is a single file and is using a common Makefile, or append -DDEBUG inside the CC build options if the driver contains of multiple source files and as usually has it's own Makefile
upon the kernel booted and the prompt appear to enable debug level messages by executing either dmesg -n 8 or echo 8 > /proc/sys/kernel/printk
load the driver if the module with the command either insmod <driver name> or modprobe <driver name> or if the driver is integrated into the kernel the insertion commands may vary.
example on how to assign the kernel integrated driver for the i2c bus subsystem:
echo <driver name> <i2c bus address> > /sys/bus/i2c/devices/i2c-0/new_device
side notes:
if the DTS will have a driver record assignment, manually repeated driver assignment will cause the error - in case of i2c subsystem - error EBUSY (-16), the driver will be assigned way before the command prompt and the dmesg messages will be limited to the default level (usually dev_info only)
in case if the driver has been already assigned by DTS and there is no way to exclude it temporary from the tree source - it's useful to detach and reattach it once again after the debug (trace) level messages activated
for the i2c subsystem it would require to execute a command:
echo <driver name> > /sys/bus/i2c/drivers/<drivername>/unbind
then
echo <driver name> > /sys/bus/i2c/drivers/<drivername>/bind
warning:
the kernel drivers trace mechanism will not help on debugging internal driver improper configured or missing service structures. i.e. if the driver is loaded but remain silent with no trace messages means the probe has never been executed because of some kernel expected service structures information were missing or faulty
You need to follow below three steps.
1. Make sure that your kernel is complied with CONFIG_DYNAMIC_DEBUG=y
cat /proc/config.gz | gunzip | grep CONFIG_DYNAMIC_DEBUG
If not then recompile your kernel with CONFIG_DYNAMIC_DEBUG=y
2) After boot up check that debugfs is mounted somewhere or not.
mount | grep debugfs
mostly it get mounted in /sys/kernel/debug if not then you can manually mount it anywhere like below
mount -t debugfs none /sys/kernel/debug
3) Now enable the file name for which you need dev_dbg() logs.
echo 'file <driverfilename.c> +p'>/sys/kernel/debug/dynamic_debug/control
some more commands to play with dynamic_debug/control are at https://www.kernel.org/doc/html/v4.11/admin-guide/dynamic-debug-howto.html
now you should get your debug.
If you still do not see your message then enable prink level
echo "8 4 1 7" > /proc/sys/kernel/printk
If the CONFIG_DYNAMIC_DEBUG option is not set, then dev_dbg/pr_debug can be turned into normal printk() statements with KERN_DEBUG level.
But for that you need to add #define DEBUG at beginning of file.
or add -DDEBUG while compiling
or Enable CONFIG_[SUBSYSTEM]_DEBUG=y
I used below command to turn on the Kernel log for Android. I think for Linux to it should work:
echo 'file <driverfilename.c> +p'>/sys/kernel/debug/dynamic_debug/control
You can see the driver logs in "dmesg"
Thanks
MJ
Adding "debug" to the kernel parameters will lift the kernel events log level to the KERN_DEBUG (level 7) that will pollute the kmsg buffer with debug messages for the entire kernel code and it's not usually what we want while debugging our kernel module. The same is right when we change the current kernel log level via /proc/sys/kernel/printk.
To gain fine-grained control of all log levels above the KERN_ERR for your kernel module only without messing with global kernel log level configuration just add the following lines at the beginning of your module code:
#undef dev_dbg
#undef dev_info
#undef dev_warn
#undef dev_notice
#define dev_dbg dev_err
#define dev_info dev_err
#define dev_warn dev_err
#define dev_notice dev_err
You can mount the debug filesystem manually by executing the following command:
mount -t debugfs none /sys/kernel/debug
Once done, do:
ls /sys/kernel/debug
All debug information and message would be stored there without having to re-compile.
Also, you can add the this under your /etc/fstab to make the mount go automatic when you reboot.
... If you are re-compiling your kernel anyway, then you could enable " [*] Debug File System" under "Kernel Hacking"
Good luck, I hope all goes well.
It's likely that the driver you're interested in has exported the Kconfig option to enable the debug messages. In such case, you can enable debug output from just one driver by setting the DEBUG_YOUR_DRIVER=y or YOUR_DRIVER_DEBUG=y in menuconfig and rebuilding the kernel. Search for the driver name and you will see if this is available.
For example, for NXP/Freescale i.MX pinctrl driver, I just changed DEBUG_PINCTRL to y and looked into dmesg to get the debug logs from that driver.
This was the fastest approach for me.

Creating boot.scr for u-boot

I generate image for a Freescale i.mx6 sabresd using Yocto.
When booting, to activate the hdmi I have to modify u-boot by editing the bootargs. I use the following command :
setenv mmcargs 'setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk2p2 rootwait rw video=mxcfb0:dev=hdmi, 1920x1080M#60, if=RGB24'
I can use saveenv to not enter it at every boot, but I'd like to automatize it to make the deployment easier. So I have made a boot.scr. Here is the boot.txt :
setenv mmcargs 'setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk2p2 rootwait rw video=mxcfb0:dev=hdmi, 1920x1080M#60, if=RGB24'
boot
And I create the boot.scr using mkimage -A arm -T script -O linux -d boot.txt boot.scr. But, when booting, it makes a loop (boot make uboot reload the configuration, where it reads boot so it begin again). Without boot... no boot. I've tried a lot of possibilities : boot 0x120000000, bootm, bootz, with a lot of options, nothing works.
Most likely, your boot fails because you never load a kernel from which you could boot from.
In most cases, if bootcmd loads a boot.scr, then it is up to your boot.scr script to load the kernel (and also a device tree assuming you are using a recent iMX6 kernel). Then your script may boot with this kernel or allow bootcmd to carry on with its boot sequence using the loaded kernel. The load commands would look something like:
loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
loaduimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${uimage}
And the boot command should look something like:
run loaduimage; run loadfdt; bootm ${loadaddr} - ${fdt_addr}
You may already have an mmcboot command defined which already takes care of these.
I would remove the "boot" line from your script and instead load the kernel and device tree and then run bootm (or mmcboot) - basically try adding the above three lines to your script after setting mmcarg - you'll need to ensure all referenced variables are properly set (ie. mmcdev, mmpart, etc).
Using the answer from shibley, I've found a simpler way :
run loadimage
run mmcboot
He was right, mmcboot takes care of the booting of the kernel. But I have to run loadimage (not loaduimage) before.

Run command after mount/unmout usb pen drive

I have Raspberry Pi (with Raspbian) and using it as DLNA/UPnP server and renderer. I run minidlna as DLNA server and i have some media files on USB.
I would like to automaticaly rebuild DLNA DB when drive is mounted and unmounted. This is done by command:
sudo service minidlna force-reload
Is threre any way how to autorun this command?
BTW I use "USBmount" package for automount USB drives.
Thanx
You can do this using the tool usbmount.
It has the possibility to add scripts that will be run on mount/umount events in /etc/usbmount/mount.d/ and /etc/usbmount/umount.d/.
Start by finding your device in lsusb. Note the ID (eg 12f5:a91a)
Create a new udev rules file in /etc/udev/rules.d/ eg /etc/udev/rules.d/100-my-mount.rules and write a new rule in there like this:
ACTION=="add", ATTRS{idVendor}=="12f5", ATTRS{idProduct}=="a91a", RUN+="/home/your_username/bin/my-mount-script.sh"
For unmounted device use ACTION=="remove" in rule and another script.

Run something when USB device is plugged in doesn't work

I made a script in /etc/udev/rules.d/local.rules
SUBSYSTEM=="usb", SYSFS{idVendor=="b58e"}, SYSFS{idProduct=="9e84"}, ACTION=="add", RUN+="notify-send USB"
I then reload udev with
sudo udevadm control --reload-rules
I've tried to remove everything but subsystem and run. I've tried the run '=' instead of '+=', I've tired ATTR instead of SYSFS. I tried "sudo service udev restart" and "sudo reload udev". I unplug the device, then plug it in again and it does not run the action. I tried renaming it 70-local.rules and changing permissions to a+x. I've tried changing 'subsystem' to 'bus'. I've tried setting run to be "/path/test.sh" which has the same command.
I'm not an expert and this isn't an answer, but I've found the following steps useful in identifying the appropriate attributes to trigger on:
Locate the device path using udevadm, lsusb, or usb-devices. I normally just use lsusb and let tab completion in my shell guide me. In my case, the path is /dev/bus/usb/003/007.
Use udevadm to identify the device attributes for rule writing. In my case, I used udevadm info -a --attribute-walk --root --name=/dev/bus/usb/003/007.
Write the rule and check that it's triggering. In my case, I'm just changing the device owner to user "stephen" and it's very easy for me to check if it's working by using ls -l /dev/bus/usb/003/007. My rule for this case looks like: SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", OWNER="stephen". I have a similar rule that puzzled me for a little while because the subsystem was expecting ATTRS not ATTR, which is why I recommend walking the attributes. The rule in this latter case became: `SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", OWNER="stephen".
And, of course, man udev is always helpful. As you said, you should struggle to identify that your rule is triggering properly and may be best off just doing a quick ownership change on the device as I did for a first step. You can run into trouble with bad attributes or symbolic links sometimes and it's
it does not run the action
No, it runs the action. The problem is that it doesn't know where to send the notification, since there's no notification framework running when udev starts. You will need to send a DBus message across the system bus and have a user daemon catch the message and post a notification instead.

Resources