Re: Basic device driver question
Date: 4 Oct 2004 07:49:16 GMT
Mike <email@example.com> wrote:
> If I develop a device driver, which allowed access to a specific piece of
> hardware, how could I access the function in the device driver? So for
> example, let's say I have a PCI card for which I develop a device driver.
> And let's say the device driver has a function called
> write_to_pci_card(...). And let's also say that I was developing an
> application, which needed to use the write_to_pci_card(...) function. How
> would I call the write_to_pci_card(...) function from my application?
You can't call a function in a module directly - your program is
operating in user space but the module in kernel space, and both
must always stay completely and cleanly separated. The only way
to get the write_to_pci_card() function executed due to a request
by your user space program is indirectly by asking the kernel
nicely, i.e. by making a system call.
> Or is it a case that the device driver would create a file in the /devs
> directory, which I would then access from the application? To access the
> /devs file would I need to use fread() and fwrite()?
You need a device file in /dev in any case. This is always used
when someone wants access to the device, in which case open(2) is
called on that file (BTW, the functions like fopen(3), fread(3),
fwrite(3) and fclose(3) are rather high-level standard C functions,
which in turn use the lower-level open(2), read(2), write(2) and
close(2) functions and these are what you're dealing with when you
write device drivers). So in your device driver you will need at
least a function that gets called on open(2) and another one that
gets called on close(2). Beside these you can have functions that
get called on write(2) and read(2) (plus several others, like, for
example, for select(2), poll(2) etc.). So, one way to move data
between the card and the user is to use these read(2) and write(2)
functions. But beside these you nearly always have another function
in your driver, that gets invoked by calls of the ioctl(2) function.
ioctl(2) calls (I think the name stands for I/O control) are used
for more or less all kinds of things that can't be done with the
functions for read(2) and write(2) etc. ioctl(2) has two or three
arguments, the first one always being the file descriptor associa-
ted with the device file (i.e. what you got back from your call of
open(2))) and the second one is an integer. Each integer stands for
a different functionality in your device driver. In many cases the
driver will need some additional information or has to report back
some data on an ioctl(2) call - and that's what the optional third
argument is good for: the user program can pass a pointer to a set
of data via this argument to the driver or which can be used by the
driver to send back data to the program using the device.
For example, if your device is an ADC (analog-to-digital-converter)
card and has different input sensitivities, then you typically
will have picked an integer that stands for "set a different input
sensitivity" and where you send the value of the new input sensiti-
vity via a pointer to this value as the third argument to ioctl(2).
And, if the card has different channels, the third argument would
typically be a pointer to a structure with the channel number and
the new setting for the sensitivity. Of course, the same method
could be used to query the current sensitivity setting - just have
another ioctl-number which makes the driver expect the channel
number in such a structure the third argument of ioctl(2) points to
and where the current sensitivity setting for that channels gets
written into by the device driver, so the program doing the call
can read it afterwards.
-- \ Jens Thoms Toerring ___ Jens.Toerring@physik.fu-berlin.de \__________________________ http://www.toerring.de