How i can retrieve data in my linux virtual device driver? - c

I have to implement virtual device driver, that will calculate sin of specified angle.
I found article how to write hello-world driver, it works nice, when i call cat on it.
But to calculate sin, i need to transfer some data to my driver. Which solution is most painless?
Should i first of all read all input data in separate method, remember it somewhere and then calculate & output?

The most painless solution would probably be to implement a ioctl.
The cat in the linked example uses read(), that is nice when your device generates data, such as a mouse or a video camera, but when a device replies to commands a ioctl is more appropriate: you send a command GET_SIN with an angle as argument and get a reply with the answer.
The alternative would be to write() the angle and then read() the solution: far more complicated, because there may be several processes reading and writing at the same time and it would be a mess!
BTW, beware! AFAIK, the kernel is not allowed to use floating point arithmentic, nor to link to -lm, so you will have to implement the sine as a fix-point integer function, maybe using a table...

Related

IIO Linux: notify another driver when samples are ready

I have a driver for the LSM6DSOX provided by ST which can be configured to use hardware interrupts and read data. I see that IIO interface is exposed to the user space but I need this data in the another driver.
I think that implementation of the hwmon may be quite good and shows what I wanted to achieve, the example code I found is here https://github.com/torvalds/linux/blob/master/drivers/hwmon/iio_hwmon.c so I can find a GYRO channels and read samples but in this case hwmon needs to call "iio_read_channel_processed" to get sample.
My problem is that I don't know when I should call "iio_read_channel_processed" because I wanted to be notified by the IIO that the sample is ready to read. I expected that I could pass some callback function that will be called each time IIO buffer will receive new sample from another driver. Is that possible?

Linux application decode mmc ext csd

Currently from a user space application with su access, I am parsing ext_csd from debugfs filesystem, converting the string into raw byte data and passing it into a decode ext_csd function to fill in the structure that I wrote myself.
I am wondering if there is any more efficient way to do this, or less error prone? For example there is a
mmc_read_ext_csd() and mmc_decode_ext_csd() in the kernel path drivers/mmc/core/mmc.c
Is there any way to use this driver function from user application? Or ioctl command? I can't seem to find any API documentation for ioctl commands for mmcblk0, only in the kernel source kode /block/ioctl.c
Is there also a way to see if the emmc is a high capacity card from user app?
mmc-utils can issue ext_csd read through ioctl and output parsed text.
http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git/
There are others like these that can parse hex strings obtained from debugfs. It is hard to say if it is any more reliable than your own code.
https://github.com/haoxingz/emmc5_register_reader
I am not sure about high capacity detection.

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.

48bit and 28bit ATA commands with ioctl

During sending ATA commands I found several classifications. For example, first one - we can divide the commands to Data-In, Data-Out and Non-Data commands. Another classification can be that there are 48bit commands and 28bit comands. First ones are for the disks, which are larger that 120Gb.
The question is: do I need to set up some values that the disk will know that it get the 48bit command or not? For example, if I send SCSI command with ATA through SATL or ATA PASS THROUGH command through the controller.
During the research it was found that every controller has its own specificities depending on the driver. That is why implementation of ATA PASS THROUGH commands are so difficult work.
Through reading the Linux driver and checking what structures are sent with ioctl it is possible to figure out if it is 28 or 48 bit command.
Moreover, it is also quite important to check how new is the software, because 48-bit Logical Block Addressing (LBA) was introduced in 2006 in ATA-6 standard. Most probably nowadays all the controllers supports 48-bit command set, but still you should check if the controller supports it.
So, the answer to this question strongly depends on the using controller.

C Linux Device Programming - Reading Straight from /Dev

I have been playing with creating sounds using mathematical wave functions in C. The next step in my project is getting user input from a MIDI keyboard controller in order to modulate the waves to different pitches.
My first notion was that this would be relatively simple and that Linux, being Linux, would allow me to read the raw data stream from my device like I would any other file.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
Despite these warnings, I did an experiment. I plugged in the MIDI controller and cat'ed the "/dev/midi1" device file. A steady stream of null characters appeared, and when I pressed a key on the MIDI controller several bytes appeared corresponding to the expected Message Chunks that a MIDI device should output. MIDI Protocol Info
So my questions are:
Why does the cat'ed stream behave this way?
Does this mean that there is a plug and play device driver already installed on my system?
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
Thank you in advanced for sharing your wisdom in these areas.
Why does the cat'ed stream behave this way?
Because that is presumably the raw MIDI data that is being received by the controller. The null bytes are probably some sort of sync tick.
Does this mean that there is a plug and play device driver already installed on my system?
Yes.
However, research overwhelmingly advises that I write a device driver for the MIDI controller. The general idea is that even though the device file may be present, the kernel will not know what system calls to execute when my application calls functions like read() and write().
<...>
Should I still go ahead and write a device driver, or can I get away with reading it like a file?
I'm not sure what you're reading or how you're coming to this conclusion, but it's wrong. :) You've already got a perfectly good driver installed for your MIDI controller -- go ahead and use it!
Are you sure you are reading NUL bytes? And not 0xf8 bytes? Because 0xf8 is the MIDI time tick status and is usually sent periodically to keep the instruments in sync. Try reading the device using od:
od -vtx1 /dev/midi1
If you're seeing a bunch of 0xf8, it's okay. If you don't need the tempo information sent by your MIDI controller, either disable it on your controller or ignore those 0xf8 status bytes.
Also, for MIDI, keep in mind that the current MIDI status is usually sent once (to save on bytes) and then the payload bytes follow for as long as needed. For example, the pitch bend status is byte 0xeK (where K is the channel number, i.e. 0 to 15) and its payload is 7 bits of the least significant byte followed by 7 bits of the most significant bytes. Thus, maybe you got a weird controller and you're seeing only repeated payloads of some status, but any controller that's not stupid won't repeat what it doesn't need to.
Now for the driver: have a look at dmesg when you plug in your MIDI controller. Now if your OSS /dev/midi1 appears when you plug in your device (udev is doing this job), and dmesg doesn't shoot any error, you don't need anything else. The MIDI protocol is yet-another-serial-protocol that has a fixed baudrate and transmits/receives bytes. There's nothing complicated about that... just read from or write to the device and you're done.
The only issue is that queuing at some place could result in bad audio latency (if you're using the MIDI commands to control live audio, which I believe is what you're doing). It seems like those devices are mostly made for system exclusive messages, that is, for example, downloading some patch/preset for a synthesizer online and uploading it to the device using MIDI. Latency doesn't really matter in this situation.
Also have a look at the ALSA way of playing with MIDI on Linux.
If you are not developing a new MIDI controller hardware, you shouldn't worry about writing a driver for it. It's the user's concern installing their hardware, and the vendor's obligation to supply the drivers.
Under Linux, you just read the file. Now to interpret and make useful things with the data.

Resources