POSIX defines a text file as:
A file that contains characters organized into one or more lines.
POSIX defines a line as
A sequence of zero or more non-newline characters plus a terminating newline character.
Given this, should the read() function of a Linux character device driver append '\n' to the user buffer when it reaches EOF/has no more data?
Concept of char drivers is analogous to a stream. In this light, read just returns whatever happens to be available next. Now what is available will usually be part of definition of the device whose driver it is. If the device returns newline character then so should the driver. Note that this means the device will return newline on all platforms, not just Linux.
In general, interpretating the bytes returned by read is a matter of higher level abstraction. In terms of policy vs mechanism, char driver can be thought of as providing mechanism, leaving policy to higher layers.
In classic Unix, the difference between character devices and block devices is that block devices support seek, which implies that they are addressable, in units of fixed sized disk blocks. Character devices do not support seek, they just deliver or accept a stream of characters.
In linux, a device driver is implemented as a struct, containing some flags and parameters plus a collection of function pointers, implementing the methods for read()/write()/etc. Block (disk) drivers will also implement seek(), and maybe even mmap().
Normally, device drivers do not interfere with the actual content being transferred, they only move bytes or blocks to/from the device, using the (hardware) protocol that the device needs (such as manipulating the internal control registers, inspecting status registers, ...)
Related
in the book 2017 " UNIX and Linux System Administration " i've read the article below :
Modern systems manage their device files automatically. However, a few rare corner
cases may still require you to create devices manually with the mknod command.
So here’s how to do it:
mknod filename type major minor
Here, filename is the device file to be created, type is c for a character device or b
for a block device, and major and minor are the major and minor device numbers.
If you are creating a device file that refers to a driver that’s already present in your
kernel, check the documentation for the driver to find the appropriate major and
minor device numbers.
where can i find this doc and how to find Major & Minor for a device driver ???
The command cat /proc/devices shows the character and block major device numbers in use by drivers in the currently running Linux kernel, but provides no information about minor device numbers.
There is a list of pre-assigned (reserved) device numbers in the Linux kernel user's and administrator's guide: Linux allocated devices (4.x+ version). (The same list also appears in "Documentation/admin-guide/devices.txt" in the Linux kernel sources.) The list shows how minor device numbers are interpreted for each pre-assigned character and block major device number.
Some major device numbers are reserved for local or experimental use, or for dynamic assignment:
60-63 char LOCAL/EXPERIMENTAL USE
60-63 block LOCAL/EXPERIMENTAL USE
Allocated for local/experimental use. For devices not
assigned official numbers, these ranges should be
used in order to avoid conflicting with future assignments.
120-127 char LOCAL/EXPERIMENTAL USE
120-127 block LOCAL/EXPERIMENTAL USE
Allocated for local/experimental use. For devices not
assigned official numbers, these ranges should be
used in order to avoid conflicting with future assignments.
234-254 char RESERVED FOR DYNAMIC ASSIGNMENT
Character devices that request a dynamic allocation of major number will
take numbers starting from 254 and downward.
240-254 block LOCAL/EXPERIMENTAL USE
Allocated for local/experimental use. For devices not
assigned official numbers, these ranges should be
used in order to avoid conflicting with future assignments.
384-511 char RESERVED FOR DYNAMIC ASSIGNMENT
Character devices that request a dynamic allocation of major
number will take numbers starting from 511 and downward,
once the 234-254 range is full.
Character device drivers that call alloc_chrdev_region() to register a range of character device numbers will be assigned an unused major device number from the dynamic range. The same is true for character device drivers that call __register_chrdev() with the first argument (major) set to 0.
Some external ("out-of-tree") Linux kernel modules have a module parameter to allow their default major device number to be specified at module load time. That is useful for drivers that do not create their "/dev" entries dynamically, but want some flexibility for the system administrator to choose a major device number when creating device files manually with mknod.
docs:
https://www.oreilly.com/library/view/linux-device-drivers/0596000081/ch03s02.html
https://tldp.org/LDP/tlk/dd/drivers.html
how to find the appropriate minor & major number for a device number:
ls -l /dev/
cat /proc/devices shows the same as lsblk
Someone reports that given a stream of strings on the serial port which is pipelined to the OCaml program below, the output of the program is not continuous, but instead it appears in chunks (of a few tens of lines), as if buffered.
What can be the cause of the non-continuous output?
(The output buffer should be flushed after each new line due to the use of '%!'. So this shouldn't be the cause, right?)
let tp = ref 0
let get_next_entry ic =
try
let (ts, pred, v) = Scanf.fscanf ic " #%d %s#(%d)\n" (fun x y z -> (x,y,z)) in
Printf.printf "at timepoint %d (timestamp %d): %s(%d)\n%!" !tp ts pred v;
incr tp;
true
with End_of_file ->
false
let _ =
while get_next_entry stdin do
()
done
The OCaml version used is 4.05.
It is a threefold problem. From the least likely to the most likely.
The glitching output
It is all in the eye of the beholder, as how the program output will look like depends on the environment in which it is run, i.e., on a program that runs your program and renders this on a visual device. In other words, it involves a lot of variables that are beyond the context of this program.
With that said, let me explain what flush means for the printf function. The printf facility relies on buffered channels. And each channel is roughly a pair of a buffer and system-specific file descriptor. When someone (including printf) outputs to a channel, the information first goes into the buffer and remains there until the next portion of information overrides the buffer (i.e., there is no more space in the buffer) or until the flush function is called explicitly. Then the buffer is flushed, which means that the information in the buffer is transferred to the operating system (e.g., using the write system call or library function).
What happens afterward is system dependent. If the file descriptor was associated with a regular file, then you might expect that the information will be passed to it entirely(though the file system has its own hierarchy of caches, so there're caveats also). If the descriptor was associated with a Unix-style shell process through a pipe, then it will go into the pipe's buffer, extracted from it by the shell and printed using a terminal interface, usually fulfilled with some terminal emulator. By default shells are line-buffered, so the line should be printed as a whole unless the user of the shell changes its parameters somehow.
Basically, I hope you get the idea, it is not your program which is actually manipulating with the terminal and lighting up pixels on your monitors. Your program is just outputting data and some other program is receiving this data and drawing it on the screen. And this some other program (a terminal, or terminal emulator, e.g., minicom) is making this output glitchy, not your program. Your program is doing its best to be printed correctly - full line or nothing.
Your program is glitching
And it is. The in_channel is also buffered, so it will accumulate a few bytes before calling sprintf. Therefore, you can just read from the buffered channel and expect a realtime response to it. The most reliable way for you would be to use the Unix module and process the input using your own buffering.
The glitching input
Finally, the input program can also give you the information in chunks. This is especially true for serial interfaces, so make sure that you have correctly set up your terminal interface using the Unix.tcsetattr function. In particular, when your program is blocked on the input, the operating system may decide not to wake it up on each arrived character or line. This behavior is controlled by the terminal interface (see the Canonical and Non-canonical modes. If your input doesn't have newlines, then you shall use the non-canonical mode).
Finally, the device itself could be acting jittering, and if you have an oscilloscope nearby you can observe the signals it is sending. And make sure that you have configured your serial port as prescribed in the user manual of your device.
One possibility is that fscanf is waiting until it sees everything it's looking for.
As I understand the term "word length" (spi_bits_per_word) in spi, defines the CS (chip select) active time.
It therefore seems that linux driver will function correctly when dealing with simple spi protocols which keeps word size constant.
But, How can we deal with spi protocols which use different spi size as part of protocol.
for example cs need to be active for sending spi word - 9 bits, and then reading spi - 8 bits or 24 bits (the length of the register read is different each time, depends on register)
How can we implement that using spi_write_then_read ?
Do we need to set bits_per_word size for the sending and then another bits_per_word for the receiving ?
Regards,
Ran
"word length" means number of bits you can send in one transaction. It doesn't defines the CS (chip select) active time. You can keep it active for whatever time you want(least is for word-length).
SPI has got some format. You cannot randomly read-write whatever number of bits you want.Most of SPI supports 4-bit, 8-bit, 16-bit and 32-bit mode. If the given mode doesn't satisfy your requirement then you need to break your requirement. For eg:- To read 24-bit data, we need to use 8-bit word-length transfer for 3 times.
Generally SPI is fullduplex means it will read at same time it will write.
i was going through ioctl sample programs to check how it communicates with kernel space. in program WRITE_IOCTL is used as command
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
ioctl(fd, WRITE_IOCTL, "hello world")
I am not able to understand what is _IOW(MY_MACIG, 1, int).
here is the link from where i downloaded the program. please help me.
http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-4.html
As you may know, an ioctl should be unique, as explained in the Linux Device Drivers book:
The ioctl command numbers should be unique across the system in order
to prevent errors caused by issuing the right command to the wrong
device.Such a mismatch is not unlikely to happen, and a program might
find itself trying to change the baudrate of a non-serial-port input
stream, such as a FIFO or an audio device. If each ioctl number is
unique, the application gets an EINVAL error rather than succeeding in
doing something unintended.
Furthermore, an ioctl can require to write data to and/or read data from kernel space.
When one creates it's own driver that performs ioctls, he will need to describe all this in the ioctl command.
_IO, _IOW, _IOR, _IORW are helper macros to create a unique ioctl identifier and add the required R/W needed features (direction).
These can take the following params: magic number, the command id, and the data type that will be passed (if any)
The magic number is a unique number that will allow the driver to detect errors such as the one mentioned in the LDD book's quote.
The command id, is a way for your dirver to understand what command is needed to be called.
Last parameter (the type) will allow the kernel to understand the size to be copied.
hope this helps.
PS: you can have more details in Linux Device Drivers book (chapter 6)
https://lwn.net/images/pdf/LDD3/ch06.pdf
From http://www.circlemud.org/jelson/software/fusd/docs/node31.html:
The Linux header file /usr/include/asm/ioctl.h defines macros that must be used to create the ioctl command number. These macros take various combinations of three arguments:
type, an 8-bit integer selected to be specific to the device driver. type should be chosen so as not to conflict with other drivers that might be ``listening'' to the same file descriptor. (Inside the kernel, for example, the TCP and IP stacks use distinct numbers since an ioctl sent to a socket file descriptor might be examined by both stacks.)
number, an 8-bit integer command number. Within a driver, distinct numbers should be chosen for each different kind of ioctl command that the driver services
data_type, the name of a type used to compute how many bytes are exchanged between the client and the driver. This argument is, for example, the name of a structure.
The macros used to generate command numbers are:
_IO(int type, int number), used for a simple ioctl that sends nothing but the type and number, and receives back nothing but an (integer) retval
_IOR(int type, int number, data_type), used for an ioctl that reads data from the device driver. The driver will be allowed to return sizeof(data_type) bytes to the user
_IOW(int type, int number, data_type), similar to _IOR, but used to write data to the driver
_IORW(int type, int number, data_type), a combination of _IOR and _IOW. That is, data is both written to the driver and then read back from the driver by the client
I am writing a driver for a device that is connected by serial port. Unfortunately, the 9th data bit indicates whether the character should be interpreted as command or as data.
Using the built-in parity check does not work for me because an error is indicated by an additional character (NUL). And then I don't know wheter I received two data bytes or one with an parity error.
Is there a way to get this parity bit elsewhere?
EDIT: Apparently, this problem also exists on Windows (see http://gilzu.com/?p=6). It ended up with rewriting the serial driver. Is this also my only option on Linux?
As I see it, you should be able to use PARMRK as is, assuming that the \377 \0 pattern is unlikely to appear in your input. otherwise, yes, you may modify your serial driver to prepend the parity (or rather, if this byte had a parity error) to each byte. I'd go with the former, though.