How do I suspend an i2c device in Linux from userspace? - c

I am attempting to put a particular device into suspended mode, and have been unable to find a way to do this.
I see in the kernel that a suspend command can be defined, but what is the user space analog to it, if there is one?
In this case, it is to allow me to mask an interrupt in a touchscreen controller before its power is removed.
edited to add additional info:
Additional information: This is for an embedded device, using linux kernel 2.6

the typical sequence is to send a command to the device to put it into 'suspend' mode, then close the open file descriptor to that device.

Related

How to switch between the g_printer and g_serial USB driver without rebooting the whole Linux system?

I'm developing a project on an embedded Linux device in C, which uses those two USB drivers on the same USB cable:
g_printer(Linux USB Printer Gadget Driver)
g_serial(Linux Gadget Serial Driver)
When the user selects USB Virtual COM Mode, the program will:
Check whether the device file /dev/g_printer0 is opened, if yes, close the opened file descriptor.
Check whether the g_printer is installed by using system("lsmod | grep g_printer > /dev/null");, if yes, use system("rmmod g_printer); to uninstall it.
Check whether the usb_f_printer is installed by using system("lsmod | grep usb_f_printer > /dev/null");, if yes, use system("rmmod usb_f_printer); to uninstall it.
Install the g_serial by using system(modprobe g_serial);
Open device file /dev/ttyGS0
When the user selects USB Printer Mode, the program will do almost the same steps as above, but uninstall g_serial first and then install g_printer(also the closed and opened device files are different).
But the whole Linux system crashed at step 3 when it switches from USB Printer Mode to USB Virtual COM Mode, the log shows:
rmmod: can't unload module 'usb_f_printer': Resource temporarily unavailable
In addition, this Linux kernel is customized, after the system boots, the g_printer is automatically installed by the kernel, but the /dev/g_printer0 is not opened yet, so at this time, if I switch to USB Virtual COM Mode by using the steps above, it works with no errors(and the system won't crash of course), so it means I have another weird way to let the user switch between those two modes, that is when user wants to switch the mode, the system won't switch it immediately but save this selection in the configuration file, then it reboots the system, after the reboot, the program will check the configuration file to decide whether switches to USB Virtual COM Mode or just open /dev/g_printer0 to be ready for use. But this is too weird :(.
I can't kill this process because this is the only process running in this device, and also I can't exec another process to do this USB communication stuff because it's kind of wasting memory and computing resources.
So I have two questions:
Is there any way for the user to switch those two modes without rebooting the Linux system?
Does it means, once a process opens the /dev/g_printer0 device file, this driver can't be uninstalled but only reboot the system or kill the process? (even if I have already closed the opened device file)

Writing a FreeBSD kernel module that handles arbitrary interrupt and output to device

I would like to write a FreeBSD kernel module that could accept some arbitrary interrupts and upon receiving these interrupt, output some data to an arbitrary device. Currently, I'm facing several issues:
How would I acquire interrupts through a specific IRQ? On Linux there is the request_irq() call but it seems there's no similar API for FreeBSD... Say, I want to be able to detect all the keyboard interrupt through my kernel module (the keyboard is on irq1), how would I do that? (On Linux it is possible through calling free_irq(1, NULL) and request_irq(1, ...), correct me if I'm wrong though).
Is it possible at all to write to a device file under /dev through a kernel module? I've read the question Example for reading text files in FreeBSD kernel module; following this example I was able to do read/write on regular files, but not a device file under /dev (the "device" was a pseudo "echo device", the classical one used in char device examples). I was able to open the file though.
I do understand that it is considered as a bad practice to do file I/O's in kernel, but I could not think any other way... If anyone has a better solution please tell me. (i.e. write to a device through its device_t node?)
The reason I was doing this in a kernel is that I really need all interrupts to be hit, and running it in the user space has the risk of missing interrupts due to kernel threads preempting user threads (the interrupts could come very frequent).
I would also appreciate if anyone could provide me with some other ideas on how to implement this program (basically, the idea is a kernel module that could do the job of a microcontroller...)
You can register an IRQ handler with bus_setup_intr.
Normally, what one would do in this situation is to have a driver collect the interrupts and any other useful data, and export it through a device, and then a (real-time maybe?) process in user-space can read from one device, do whatever it needs to do, and write to the other device.

Reading from and writing to registers of an IMU via UART

I have an IMU that has a UART interface. The manufacturer has provided a Windows based program that get all the data from the IMU and displays it in real time. (The device is connected to the PC via the USB). I need to write my own software that does this in order to integrate it into my project.
The datasheet/manual for the IMU gives all details about which registers have to be written to and read from (issue commands and read responses) in order to get the IMU data. My question is, how do I implement this in C under Linux?
The closest information I found out was this one but when compiling it it seems I need Linux kernel headers since that program uses #include <linux/module.h> so I'm not sure if I am on the right track.
You need not any kernel headers to talk over a serial port with any device connected to that serial port.
You would get a 'connection' to your device by simply opening a file /dev/ttyUSB0 with open() call (the actual name could be found by looking into dmesg for relevant device messages or by looking what device node appears under /dev when you plug your device into usb port).
Then you would need to set the baud rate and the word format (number of bits, parity and number of stop bits). To achieve that from the user-space process you would use a set of ioctls. For details read man ioctl and man ioctl_list

How does Linux kernel interrupt the application?

First of all, I am a device driver guy. This is my first time to handle an user mode program.
I used to have an interrupt service routine to response a hardware interrupt.
In other word, the hardware uses interrupt service routine to notify the driver to service.
I use ioctl to be a channel to communicate between the application and device driver now and poll it to wait the response.
Are there other ways that a device driver can notify an application when it finishes some task?
Any comments are welcome.
Thanks,
There are several mechanisms for this. First approach: user-space application makes poll() or select() system call, waiting for some event from kernel. Second approach is to use Netlink sockets. There are also others like mmap() or signals. Google by kernel user-space IPC and you will see the whole list.
As for your case (drivers development), I'd say go with next approach. Create sysfs file in your driver, and do sysfs_notify() (and maybe wait_for_completion_interruptible_timeout() or something like that). In user-space do select() system call for your driver sysfs file. See how line discipline installed from user-space for example.
Typically, the kernel never notifies an application unless the application requests the notification and is waiting for the notification. On unix systems, this will typically be done using the select or similar routines. One supplies select with a set of file descriptors and select will then wait until there is activity on one of the file descriptors at which time it returns.
Given that on unix all devices are files, you should be able to make use of this mechanism to wake an application when an interrupt comes in on some hardware device.
There are plenty of kernel-userspace communication interfaces in addition to ioctl (signals, sockets, etc). Please, refer to Kernel Space - User Space Interfaces tutorial for detailed explanation.

Detect certain connected USB device

I'm working with a USB device in Linux and have written a library to control this device.
Without going in to TOO many details, the device uses a standard UART protocol, so all I have to do is open a serial connection with open, configure the relevant parameters like baud rate, stop bit, parity, etc, etc, and start bit-banging registers.
The library works fine, however, it its hard coded to assume that this device is /dev/ttyUSB0. That is, this is what I pass to open. If open fails, I exit.
What I would like to do is detect that this device is present, regardless if it's /dev/ttyUSB0, /dev/ttyUSB1, etc. And even detect if there are multiple of these devices connected.
I can write code to poll certain registers on the device that will return serial number, product ID, etc, so I can detect that what is on the other end of the USB is indeed my device... but how can I find a list of connected USB devices, again, in native C?
OR is there a more elegant way of doing this, such as interfacing with it's kernel module, or something? I can provide the USB driver it actually uses, but I'm sort of lost when looking through the code.
Thanks for any insight.
The elegant method is to use udev to create a descriptive symlink for your device when it is connected. Add a line something like this to /etc/udev/rules.d
SUBSYSTEM=="tty",ENV{ID_MODEL}=="My_FlowMeter_Model",ENV{ID_USB_INTERFACE_NUM}=="00",SYMLINK+="flowmeter",RUN+="/bin/su pi -c /home/pi/record-flowmeter.sh
That's a very slightly modified version of an actual udev rule my research group uses to collect data from USB devices connected to battery-powered Raspberry Pi boxes. It also runs a script automatically, which has commands like
stty -F /dev/flowmeter 500000 -ixon -echo -icanon
If you want to know the "real" device filename, you could do readlink /dev/flowmeter. But for most uses you can just use the link: fd = open("/dev/flowmeter"); (or pass it as an argument to your program)
Naturally you should replace flowmeter with a short name for your own device, as well as updating the ID_MODEL based on the output from lsusb.
Multiple devices are a bit more complicated, but there are plenty of examples of udev rules out there.
On Linux, the information you are looking for is in the /sys filesystem, specifically under /sys/bus/usb/devices. From there you will need to search the filesystem to find your device.
For example, I just plugged a USB-serial dongle into my Linux (kernel version 2.6.35) and the device appeared under /sys/bus/usb/devices/2.1-8. Here, I am able to find that this is my device by vendorId:deviceId by checking the files idVendor and idProduct. Here, there is a directory named 2.1-8:1:0 which contains a directory named ttyUSB0.
Obviously, to find your device you will need code (or a shell script using find) to scan the directory tree, looking for the right entries.

Resources