Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
472265ae8a | ||
|
|
789713fa0b | ||
|
|
efd39ff55a | ||
|
|
788c45bd77 | ||
|
|
a667d5412c | ||
|
|
8db24fbd1d | ||
|
|
57dc545fad |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* ident=true
|
||||||
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Ignore all generated files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.cmd
|
||||||
|
*.a
|
||||||
|
*.d
|
||||||
|
*.mod
|
||||||
|
*.mod.c
|
||||||
|
*.order
|
||||||
|
*.so*
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Generated demo executables
|
||||||
|
examples/console-read
|
||||||
|
examples/drums
|
||||||
|
examples/drums2
|
||||||
|
examples/drums3
|
||||||
|
examples/echo
|
||||||
|
examples/helloworld
|
||||||
|
examples/ioctl
|
||||||
|
examples/logring
|
||||||
|
examples/pager
|
||||||
|
examples/uid-filter
|
||||||
6
Makefile
6
Makefile
@@ -6,10 +6,10 @@ PREFIX = /usr/local
|
|||||||
LIBDIR = $(PREFIX)/lib
|
LIBDIR = $(PREFIX)/lib
|
||||||
INCDIR = $(PREFIX)/include
|
INCDIR = $(PREFIX)/include
|
||||||
|
|
||||||
CC = gcc
|
CC = $(CROSS_COMPILE)gcc
|
||||||
LD = gcc
|
LD = $(CROSS_COMPILE)gcc
|
||||||
INSTALL = install
|
INSTALL = install
|
||||||
STRIP = strip
|
STRIP = $(CROSS_COMPILE)strip
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
BINDIR = $(PREFIX)/bin
|
BINDIR = $(PREFIX)/bin
|
||||||
ETCDIR = /etc/$(TARGET)
|
ETCDIR = /etc/$(TARGET)
|
||||||
|
|||||||
@@ -2,13 +2,20 @@
|
|||||||
FUSD: A Linux Framework for User-Space Devices
|
FUSD: A Linux Framework for User-Space Devices
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
Welcome to FUSD!
|
**Welcome to FUSD!**
|
||||||
|
|
||||||
This is FUSD snapshot 20070111, released 11 January 2007. You can get
|
This is FUSD snapshot 20110401, released 18 January 2012. This fork is based
|
||||||
the most recent source, along with online documentation, from xiph.org
|
on the found on the xiph.org SVN tracker. ( http://svn.xiph.org/trunk/fusd )
|
||||||
SVN:
|
They seems to no longuer update this tool (since 11 January 2007) and since it
|
||||||
|
longuer compile with recent Linux kernel (at around 2.6.21) and since I need
|
||||||
|
it in personal project, I ported it to newer version (current version is 2.6.32)
|
||||||
|
|
||||||
http://svn.xiph.org/trunk/fusd
|
Some feature are still missing missing or buggy form the Xiph version (due to
|
||||||
|
changes on the kernel source tree), but it's completly useable.
|
||||||
|
|
||||||
|
The official URL for this fork is:
|
||||||
|
|
||||||
|
http://github.com/Godzil/fusd
|
||||||
|
|
||||||
There is extensive documentation available in the 'doc' directory.
|
There is extensive documentation available in the 'doc' directory.
|
||||||
The FUSD User Manual is available in PDF, Postscript, and HTML format.
|
The FUSD User Manual is available in PDF, Postscript, and HTML format.
|
||||||
@@ -17,7 +24,7 @@ it is fully updated, it may not cover all features that exist in the
|
|||||||
current version of fusd.
|
current version of fusd.
|
||||||
|
|
||||||
FUSD is free and open source software, released under a BSD-style
|
FUSD is free and open source software, released under a BSD-style
|
||||||
license. See the file 'LICENSE' for details.
|
license. See the file 'LICENSE' for details.
|
||||||
|
|
||||||
|
|
||||||
QUICK START GUIDE
|
QUICK START GUIDE
|
||||||
@@ -25,81 +32,81 @@ QUICK START GUIDE
|
|||||||
|
|
||||||
Instructions for the impatient:
|
Instructions for the impatient:
|
||||||
|
|
||||||
1- Make sure you're using a system running Linux 2.6.x with udev; this
|
1. Make sure you're using a system running Linux 2.6.x with udev; this
|
||||||
version of fusd is incompatable with the now-deprecated devfs. If the
|
version of fusd is incompatable with the now-deprecated devfs. If the
|
||||||
kernel is a packaged version from a distribution, also verify any
|
kernel is a packaged version from a distribution, also verify any
|
||||||
optional packages needed for building new kernel modules are also
|
optional packages needed for building new kernel modules are also
|
||||||
installed.
|
installed.
|
||||||
|
|
||||||
2- 'make ; make install' builds everything including examples, then
|
2. 'make ; make install' builds everything including examples, then
|
||||||
installs the libraries, includes and kernel module.
|
installs the libraries, includes and kernel module.
|
||||||
|
|
||||||
3- Update the udev configuration (usually in /etc/udev/rules.d/) to
|
3. Update the udev configuration (usually in /etc/udev/rules.d/) to
|
||||||
include the following rule:
|
include the following rule:
|
||||||
|
|
||||||
# fusd device
|
fusd device
|
||||||
SUBSYSTEM=="fusd", NAME="fusd/%k"
|
SUBSYSTEM=="fusd", NAME="fusd/%k"
|
||||||
|
|
||||||
After updating, restart udevd (skill udevd; udevd -d).
|
After updating, restart udevd (skill udevd; udevd -d).
|
||||||
|
|
||||||
4- Insert the FUSD kernel module (modprobe kfusd)
|
4. Insert the FUSD kernel module (`modprobe kfusd`)
|
||||||
|
|
||||||
5- Verify the fusd devices /dev/fusd/status and /dev/fusd/control
|
5. Verify the fusd devices /dev/fusd/status and /dev/fusd/control
|
||||||
exist. If the modprobe succeeds but no fusd devices appear,
|
exist. If the modprobe succeeds but no fusd devices appear,
|
||||||
doublecheck the udev rule config change and make sure udevd restarted
|
doublecheck the udev rule config change and make sure udevd restarted
|
||||||
successfully. The kfusd kernel module must be inserted after udev has
|
successfully. The kfusd kernel module must be inserted after udev has
|
||||||
been correctly configured and restarted.
|
been correctly configured and restarted.
|
||||||
|
|
||||||
6- Try running the helloworld example program (examples/helloworld).
|
6. Try running the `helloworld` example program (examples/helloworld).
|
||||||
When helloworld is running, 'cat /dev/helloworld' should return
|
When helloworld is running, `cat /dev/helloworld` should return
|
||||||
'Hello, world!'.
|
`Hello, world!`.
|
||||||
|
|
||||||
7- For more information, read the User's Manual in the 'doc' directory.
|
7. For more information, read the User's Manual in the 'doc' directory.
|
||||||
|
|
||||||
WHAT IS FUSD?
|
WHAT IS FUSD?
|
||||||
=============
|
=============
|
||||||
|
|
||||||
FUSD (pronounced "fused") is a Linux framework for proxying device
|
FUSD (pronounced "fused") is a Linux framework for proxying device
|
||||||
file callbacks into user-space, allowing device files to be
|
file callbacks into user-space, allowing device files to be
|
||||||
implemented by daemons instead of kernel code. Despite being
|
implemented by daemons instead of kernel code. Despite being
|
||||||
implemented in user-space, FUSD devices can look and act just like any
|
implemented in user-space, FUSD devices can look and act just like any
|
||||||
other file under /dev which is implemented by kernel callbacks.
|
other file under /dev which is implemented by kernel callbacks.
|
||||||
|
|
||||||
A user-space device driver can do many of the things that kernel
|
A user-space device driver can do many of the things that kernel
|
||||||
drivers can't, such as perform a long-running computation, block while
|
drivers can't, such as perform a long-running computation, block while
|
||||||
waiting for an event, or read files from the file system. Unlike
|
waiting for an event, or read files from the file system. Unlike
|
||||||
kernel drivers, a user-space device driver can use other device
|
kernel drivers, a user-space device driver can use other device
|
||||||
drivers--that is, access the network, talk to a serial port, get
|
drivers--that is, access the network, talk to a serial port, get
|
||||||
interactive input from the user, pop up GUI windows, or read from
|
interactive input from the user, pop up GUI windows, or read from
|
||||||
disks. User-space drivers implemented using FUSD can be much easier to
|
disks. User-space drivers implemented using FUSD can be much easier to
|
||||||
debug; it is impossible for them to crash the machine, are easily
|
debug; it is impossible for them to crash the machine, are easily
|
||||||
traceable using tools such as gdb, and can be killed and restarted
|
traceable using tools such as gdb, and can be killed and restarted
|
||||||
without rebooting. FUSD drivers don't have to be in C--Perl, Python,
|
without rebooting. FUSD drivers don't have to be in C--Perl, Python,
|
||||||
or any other language that knows how to read from and write to a file
|
or any other language that knows how to read from and write to a file
|
||||||
descriptor can work with FUSD. User-space drivers can be swapped out,
|
descriptor can work with FUSD. User-space drivers can be swapped out,
|
||||||
whereas kernel drivers lock physical memory.
|
whereas kernel drivers lock physical memory.
|
||||||
|
|
||||||
FUSD drivers are conceptually similar to kernel drivers: a set of
|
FUSD drivers are conceptually similar to kernel drivers: a set of
|
||||||
callback functions called in response to system calls made on file
|
callback functions called in response to system calls made on file
|
||||||
descriptors by user programs. FUSD's C library provides a device
|
descriptors by user programs. FUSD's C library provides a device
|
||||||
registration function, similar to the kernel's devfs_register_chrdev()
|
registration function, similar to the kernel's devfs_register_chrdev()
|
||||||
function, to create new devices. fusd_register() accepts the device
|
function, to create new devices. fusd_register() accepts the device
|
||||||
name and a structure full of pointers. Those pointers are callback
|
name and a structure full of pointers. Those pointers are callback
|
||||||
functions which are called in response to certain user system
|
functions which are called in response to certain user system
|
||||||
calls--for example, when a process tries to open, close, read from, or
|
calls--for example, when a process tries to open, close, read from, or
|
||||||
write to the device file. The callback functions should conform to
|
write to the device file. The callback functions should conform to
|
||||||
the standard definitions of POSIX system call behavior. In many ways,
|
the standard definitions of POSIX system call behavior. In many ways,
|
||||||
the user-space FUSD callback functions are identical to their kernel
|
the user-space FUSD callback functions are identical to their kernel
|
||||||
counterparts.
|
counterparts.
|
||||||
|
|
||||||
The proxying of kernel system calls that makes this kind of program
|
The proxying of kernel system calls that makes this kind of program
|
||||||
possible is implemented by FUSD, using a combination of a kernel
|
possible is implemented by FUSD, using a combination of a kernel
|
||||||
module and cooperating user-space library. The kernel module
|
module and cooperating user-space library. The kernel module
|
||||||
implements a character device, /dev/fusd, which is used as a control
|
implements a character device, /dev/fusd, which is used as a control
|
||||||
channel between the two. fusd_register() uses this channel to send a
|
channel between the two. fusd_register() uses this channel to send a
|
||||||
message to the FUSD kernel module, telling the name of the device the
|
message to the FUSD kernel module, telling the name of the device the
|
||||||
user wants to register. The kernel module, in turn, registers that
|
user wants to register. The kernel module, in turn, registers that
|
||||||
device with the kernel proper using devfs. devfs and the kernel don't
|
device with the kernel proper using devfs. devfs and the kernel don't
|
||||||
know anything unusual is happening; it appears from their point of
|
know anything unusual is happening; it appears from their point of
|
||||||
view that the registered devices are simply being implemented by the
|
view that the registered devices are simply being implemented by the
|
||||||
FUSD module.
|
FUSD module.
|
||||||
@@ -107,22 +114,22 @@ FUSD module.
|
|||||||
Later, when kernel makes a callback due to a system call (e.g. when
|
Later, when kernel makes a callback due to a system call (e.g. when
|
||||||
the character device file is opened or read), the FUSD kernel module's
|
the character device file is opened or read), the FUSD kernel module's
|
||||||
callback blocks the calling process, marshals the arguments of the
|
callback blocks the calling process, marshals the arguments of the
|
||||||
callback into a message and sends it to user-space. Once there, the
|
callback into a message and sends it to user-space. Once there, the
|
||||||
library half of FUSD unmarshals it and calls whatever user-space
|
library half of FUSD unmarshals it and calls whatever user-space
|
||||||
callback the FUSD driver passed to fusd_register(). When that
|
callback the FUSD driver passed to fusd_register(). When that
|
||||||
user-space callback returns a value, the process happens in reverse:
|
user-space callback returns a value, the process happens in reverse:
|
||||||
the return value and its side-effects are marshaled by the library
|
the return value and its side-effects are marshaled by the library
|
||||||
and sent to the kernel. The FUSD kernel module unmarshals this
|
and sent to the kernel. The FUSD kernel module unmarshals this
|
||||||
message, matches it up with a corresponding outstanding request, and
|
message, matches it up with a corresponding outstanding request, and
|
||||||
completes the system call. The calling process is completely unaware
|
completes the system call. The calling process is completely unaware
|
||||||
of this trickery; it simply enters the kernel once, blocks, unblocks,
|
of this trickery; it simply enters the kernel once, blocks, unblocks,
|
||||||
and returns from the system call---just as it would for any other
|
and returns from the system call---just as it would for any other
|
||||||
blocking call.
|
blocking call.
|
||||||
|
|
||||||
One of the primary design goals of FUSD is stability. It should
|
One of the primary design goals of FUSD is stability. It should
|
||||||
not be possible for a FUSD driver to corrupt or crash the kernel,
|
not be possible for a FUSD driver to corrupt or crash the kernel,
|
||||||
either due to error or malice. Of course, a buggy driver itself may
|
either due to error or malice. Of course, a buggy driver itself may
|
||||||
corrupt itself (e.g., due to a buffer overrun). However, strict error
|
corrupt itself (e.g., due to a buffer overrun). However, strict error
|
||||||
checking is implemented at the user-kernel boundary which should
|
checking is implemented at the user-kernel boundary which should
|
||||||
prevent drivers from corrupting the kernel or any other user-space
|
prevent drivers from corrupting the kernel or any other user-space
|
||||||
process---including the errant driver's own clients, and other FUSD
|
process---including the errant driver's own clients, and other FUSD
|
||||||
@@ -131,9 +138,13 @@ drivers.
|
|||||||
For more information, please see the comprehensive documentation in
|
For more information, please see the comprehensive documentation in
|
||||||
the 'doc' directory.
|
the 'doc' directory.
|
||||||
|
|
||||||
Jeremy Elson <jelson@circlemud.org>
|
> Jeremy Elson <jelson@circlemud.org> <br>
|
||||||
August 19, 2003
|
> August 19, 2003 <br>
|
||||||
|
|
||||||
updated,
|
> updated,<br>
|
||||||
Monty <monty@xiph.org>
|
> Monty <monty@xiph.org> <br>
|
||||||
January 11, 2007
|
> January 11, 2007 <br>
|
||||||
|
|
||||||
|
> Updated, <br>
|
||||||
|
> Godzil <godzil@godzil.net> <br>
|
||||||
|
> March 01, 2011 / January 18, 2012 (public release on github)
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
* need a template from which to start on a real driver, use pager.c
|
* need a template from which to start on a real driver, use pager.c
|
||||||
* instead.
|
* instead.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: console-read.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
* directory: /dev/drums/bam, /dev/drums/bum, etc. If you cat one of
|
* directory: /dev/drums/bam, /dev/drums/bum, etc. If you cat one of
|
||||||
* these devices, it returns a string that's the same as its name.
|
* these devices, it returns a string that's the same as its name.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: drums.c 12355 2007-01-19 17:44:17Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
* to remember if this user has read before; cat /dev/drums/X will
|
* to remember if this user has read before; cat /dev/drums/X will
|
||||||
* read infinitely
|
* read infinitely
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: drums2.c 12355 2007-01-19 17:44:17Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
* However, it also prints a prompt to the console, asking the user if
|
* However, it also prints a prompt to the console, asking the user if
|
||||||
* how loud the drums should be.
|
* how loud the drums should be.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: drums3.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
* stored. Then, when you read (e.g. "cat /dev/echo"), you get back
|
* stored. Then, when you read (e.g. "cat /dev/echo"), you get back
|
||||||
* whatever you wrote most recently.
|
* whatever you wrote most recently.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: echo.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
* hello-world: Simply creates a device called /dev/hello-world, which
|
* hello-world: Simply creates a device called /dev/hello-world, which
|
||||||
* greets you when you try to get it.
|
* greets you when you try to get it.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: helloworld.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* EXAMPLE START helloworld.c */
|
/* EXAMPLE START helloworld.c */
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
* the other examples, anyway), because this program is both an
|
* the other examples, anyway), because this program is both an
|
||||||
* example and part of the regression test suite.
|
* example and part of the regression test suite.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: ioctl.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
* but want to use it on a system that does not have FUSD, check out
|
* but want to use it on a system that does not have FUSD, check out
|
||||||
* emlog at http://www.circlemud.org/~jelson/software/emlog.
|
* emlog at http://www.circlemud.org/~jelson/software/emlog.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: logring.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
* If you close the FD and then reopen it, there will be a race (pages
|
* If you close the FD and then reopen it, there will be a race (pages
|
||||||
* that arrive between the close and open will not be delivered).
|
* that arrive between the close and open will not be delivered).
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: pager.c 12355 2007-01-19 17:44:17Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
* not be read by anyone other than the driver owner (not even root!).
|
* not be read by anyone other than the driver owner (not even root!).
|
||||||
* When you read from the device, it returns your PID to you.
|
* When you read from the device, it returns your PID to you.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: uid-filter.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
110
include/kfusd.h
110
include/kfusd.h
@@ -37,28 +37,29 @@
|
|||||||
*
|
*
|
||||||
* Private header file used by the Linux Kernel Module
|
* Private header file used by the Linux Kernel Module
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: kfusd.h 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __KFUSD_H__
|
#ifndef __KFUSD_H__
|
||||||
#define __KFUSD_H__
|
# define __KFUSD_H__
|
||||||
|
|
||||||
#include "fusd_msg.h"
|
# include "fusd_msg.h"
|
||||||
|
# include <linux/version.h>
|
||||||
|
|
||||||
/* magic numbers for structure checking; unique w.r.t
|
/* magic numbers for structure checking; unique w.r.t
|
||||||
* /usr/src/linux/Documentation/magic-number.txt */
|
* /usr/src/linux/Documentation/magic-number.txt */
|
||||||
#define FUSD_DEV_MAGIC 0x8b43a123
|
# define FUSD_DEV_MAGIC 0x8b43a123
|
||||||
#define FUSD_FILE_MAGIC 0x613aa8fe
|
# define FUSD_FILE_MAGIC 0x613aa8fe
|
||||||
|
|
||||||
/* number of devices that can be created with fusd */
|
/* number of devices that can be created with fusd */
|
||||||
#define MAX_FUSD_DEVICES 128
|
# define MAX_FUSD_DEVICES 128
|
||||||
|
|
||||||
/* number of times each device can be opened simultaneously */
|
/* number of times each device can be opened simultaneously */
|
||||||
#define MIN_FILEARRAY_SIZE 8 /* initialize allocation */
|
# define MIN_FILEARRAY_SIZE 8 /* initialize allocation */
|
||||||
#define MAX_FILEARRAY_SIZE 1024 /* maximum it can grow to */
|
# define MAX_FILEARRAY_SIZE 1024 /* maximum it can grow to */
|
||||||
|
|
||||||
/* maximum read/write size we're willing to service */
|
/* maximum read/write size we're willing to service */
|
||||||
#define MAX_RW_SIZE (1024*128)
|
# define MAX_RW_SIZE (1024*128)
|
||||||
|
|
||||||
|
|
||||||
/********************** Structure Definitions *******************************/
|
/********************** Structure Definitions *******************************/
|
||||||
@@ -88,7 +89,7 @@ struct fusd_transaction
|
|||||||
struct fusd_dev_t_s;
|
struct fusd_dev_t_s;
|
||||||
typedef struct fusd_dev_t_s fusd_dev_t;
|
typedef struct fusd_dev_t_s fusd_dev_t;
|
||||||
struct CLASS;
|
struct CLASS;
|
||||||
struct class_device;
|
struct device;
|
||||||
|
|
||||||
/* state kept per opened file (i.e., an instance of a device) */
|
/* state kept per opened file (i.e., an instance of a device) */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -125,8 +126,11 @@ struct fusd_dev_t_s {
|
|||||||
char *dev_name;
|
char *dev_name;
|
||||||
struct CLASS *clazz;
|
struct CLASS *clazz;
|
||||||
int owns_class;
|
int owns_class;
|
||||||
struct class_device *class_device;
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
|
||||||
|
struct class_device *device;
|
||||||
|
#else
|
||||||
|
struct device *device;
|
||||||
|
#endif
|
||||||
void *private_data; /* User's private data */
|
void *private_data; /* User's private data */
|
||||||
struct cdev* handle;
|
struct cdev* handle;
|
||||||
dev_t dev_id;
|
dev_t dev_id;
|
||||||
@@ -174,34 +178,34 @@ STATIC struct fusd_transaction* fusd_find_transaction_by_pid(fusd_file_t *fusd_f
|
|||||||
|
|
||||||
/**** Utility functions & macros ****/
|
/**** Utility functions & macros ****/
|
||||||
|
|
||||||
#ifdef CONFIG_FUSD_USE_WAKEUPSYNC
|
# ifdef CONFIG_FUSD_USE_WAKEUPSYNC
|
||||||
#define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible_sync(x)
|
# define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible_sync(x)
|
||||||
#else
|
# else
|
||||||
#define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible(x)
|
# define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible(x)
|
||||||
#endif /* CONFIG_FUSD_USE_WAKEUPSYNC */
|
# endif /* CONFIG_FUSD_USE_WAKEUPSYNC */
|
||||||
|
|
||||||
#ifdef CONFIG_FUSD_DEBUG
|
# ifdef CONFIG_FUSD_DEBUG
|
||||||
static void rdebug_real(char *fmt, ...)
|
static void rdebug_real(char *fmt, ...)
|
||||||
__attribute__ ((format (printf, 1, 2)));
|
__attribute__ ((format (printf, 1, 2)));
|
||||||
|
|
||||||
#define RDEBUG(message_level, args...) do { \
|
# define RDEBUG(message_level, args...) do { \
|
||||||
if (fusd_debug_level >= message_level) rdebug_real(args); \
|
if (fusd_debug_level >= message_level) rdebug_real(args); \
|
||||||
} while(0)
|
} while(0)
|
||||||
#else
|
# else
|
||||||
#define RDEBUG(message_level, args...)
|
# define RDEBUG(message_level, args...)
|
||||||
#endif /* CONFIG_FUSD_DEBUG */
|
# endif /* CONFIG_FUSD_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
#define ZOMBIE(fusd_dev) ((fusd_dev)->zombie)
|
# define ZOMBIE(fusd_dev) ((fusd_dev)->zombie)
|
||||||
|
|
||||||
|
|
||||||
#define GET_FUSD_DEV(candidate, fusd_dev) do { \
|
# define GET_FUSD_DEV(candidate, fusd_dev) do { \
|
||||||
fusd_dev = candidate; \
|
fusd_dev = candidate; \
|
||||||
if (fusd_dev == NULL || fusd_dev->magic != FUSD_DEV_MAGIC) \
|
if (fusd_dev == NULL || fusd_dev->magic != FUSD_DEV_MAGIC) \
|
||||||
goto invalid_dev; \
|
goto invalid_dev; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define GET_FUSD_FILE_AND_DEV(candidate, fusd_file, fusd_dev) do { \
|
# define GET_FUSD_FILE_AND_DEV(candidate, fusd_file, fusd_dev) do { \
|
||||||
fusd_file = candidate; \
|
fusd_file = candidate; \
|
||||||
if (fusd_file == NULL || fusd_file->magic != FUSD_FILE_MAGIC) \
|
if (fusd_file == NULL || fusd_file->magic != FUSD_FILE_MAGIC) \
|
||||||
goto invalid_file; \
|
goto invalid_file; \
|
||||||
@@ -210,36 +214,40 @@ static void rdebug_real(char *fmt, ...)
|
|||||||
goto invalid_file; \
|
goto invalid_file; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
# define LOCK_FUSD_DEV(fusd_dev) \
|
||||||
#define LOCK_FUSD_DEV(fusd_dev) \
|
|
||||||
do { down(&fusd_dev->dev_sem); \
|
do { down(&fusd_dev->dev_sem); \
|
||||||
if (ZOMBIE(fusd_dev)) { up(&fusd_dev->dev_sem); goto zombie_dev; } \
|
if (ZOMBIE(fusd_dev)) { up(&fusd_dev->dev_sem); goto zombie_dev; } \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* rawlock does not do a zombie check */
|
/* rawlock does not do a zombie check */
|
||||||
#define RAWLOCK_FUSD_DEV(fusd_dev) \
|
|
||||||
|
# define RAWLOCK_FUSD_DEV(fusd_dev) \
|
||||||
do { down(&fusd_dev->dev_sem); } while (0)
|
do { down(&fusd_dev->dev_sem); } while (0)
|
||||||
|
|
||||||
#define UNLOCK_FUSD_DEV(fusd_dev) \
|
# define UNLOCK_FUSD_DEV(fusd_dev) \
|
||||||
do { up(&fusd_dev->dev_sem); } while (0)
|
do { up(&fusd_dev->dev_sem); } while (0)
|
||||||
|
|
||||||
|
# define LOCK_FUSD_FILE(fusd_file) \
|
||||||
#define LOCK_FUSD_FILE(fusd_file) \
|
|
||||||
do { down(&fusd_file->file_sem); \
|
do { down(&fusd_file->file_sem); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define UNLOCK_FUSD_FILE(fusd_file) \
|
# define UNLOCK_FUSD_FILE(fusd_file) \
|
||||||
do { up(&fusd_file->file_sem); } while (0)
|
do { up(&fusd_file->file_sem); } while (0)
|
||||||
|
|
||||||
#define FREE_FUSD_MSGC(fusd_msgc) do { \
|
# define FREE_FUSD_MSGC(fusd_msgc) do { \
|
||||||
if ((fusd_msgc)->fusd_msg.data != NULL) VFREE(fusd_msgc->fusd_msg.data); \
|
if ((fusd_msgc)->fusd_msg.data != NULL) VFREE(fusd_msgc->fusd_msg.data); \
|
||||||
KFREE(fusd_msgc); \
|
KFREE(fusd_msgc); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define NAME(fusd_dev) ((fusd_dev)->name == NULL ? \
|
# define FREE_FUSD_MSGC(fusd_msgc) do { \
|
||||||
|
if ((fusd_msgc)->fusd_msg.data != NULL) VFREE(fusd_msgc->fusd_msg.data); \
|
||||||
|
KFREE(fusd_msgc); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
# define NAME(fusd_dev) ((fusd_dev)->name == NULL ? \
|
||||||
"<noname>" : (fusd_dev)->name)
|
"<noname>" : (fusd_dev)->name)
|
||||||
|
|
||||||
#ifdef CONFIG_FUSD_MEMDEBUG
|
# ifdef CONFIG_FUSD_MEMDEBUG
|
||||||
static int fusd_mem_init(void);
|
static int fusd_mem_init(void);
|
||||||
static void fusd_mem_cleanup(void);
|
static void fusd_mem_cleanup(void);
|
||||||
static void fusd_mem_add(void *ptr, int line, int size);
|
static void fusd_mem_add(void *ptr, int line, int size);
|
||||||
@@ -248,25 +256,28 @@ static void *fusd_kmalloc(size_t size, int type, int line);
|
|||||||
static void fusd_kfree(void *ptr);
|
static void fusd_kfree(void *ptr);
|
||||||
static void *fusd_vmalloc(size_t size, int line);
|
static void *fusd_vmalloc(size_t size, int line);
|
||||||
static void fusd_vfree(void *ptr);
|
static void fusd_vfree(void *ptr);
|
||||||
# define KMALLOC(size, type) fusd_kmalloc(size, type, __LINE__)
|
# define KMALLOC(size, type) fusd_kmalloc(size, type, __LINE__)
|
||||||
# define KFREE(ptr) fusd_kfree(ptr)
|
# define KFREE(ptr) fusd_kfree(ptr)
|
||||||
# define VMALLOC(size) fusd_vmalloc(size, __LINE__)
|
# define VMALLOC(size) fusd_vmalloc(size, __LINE__)
|
||||||
# define VFREE(ptr) fusd_vfree(ptr)
|
# define VFREE(ptr) fusd_vfree(ptr)
|
||||||
#else /* no memory debugging */
|
# else /* no memory debugging */
|
||||||
# define KMALLOC(size, type) kmalloc(size, type)
|
# define KMALLOC(size, type) kmalloc(size, type)
|
||||||
# define KFREE(ptr) kfree(ptr)
|
# define KFREE(ptr) kfree(ptr)
|
||||||
/*# define VMALLOC(size) vmalloc(size)*/
|
/*# define VMALLOC(size) vmalloc(size)*/
|
||||||
# define VMALLOC(size) kmalloc(size, GFP_KERNEL)
|
# define VMALLOC(size) kmalloc(size, GFP_KERNEL)
|
||||||
# define VFREE(ptr) kfree(ptr)
|
# define VFREE(ptr) kfree(ptr)
|
||||||
#endif /* CONFIG_FUSD_MEMDEBUG */
|
# endif /* CONFIG_FUSD_MEMDEBUG */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Functions like this should be in the kernel, but they are not. Sigh. */
|
/* Functions like this should be in the kernel, but they are not. Sigh. */
|
||||||
#ifdef CONFIG_SMP
|
# ifdef CONFIG_SMP
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
|
||||||
DECLARE_MUTEX(atomic_ops);
|
DECLARE_MUTEX(atomic_ops);
|
||||||
|
#else
|
||||||
|
DEFINE_SEMAPHORE(atomic_ops);
|
||||||
|
#endif
|
||||||
static __inline__ int atomic_inc_and_ret(int *i)
|
static __inline__ int atomic_inc_and_ret(int *i)
|
||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
@@ -276,12 +287,11 @@ static __inline__ int atomic_inc_and_ret(int *i)
|
|||||||
up(&atomic_ops);
|
up(&atomic_ops);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
#else
|
# else
|
||||||
static __inline__ int atomic_inc_and_ret(int *i)
|
static __inline__ int atomic_inc_and_ret(int *i)
|
||||||
{
|
{
|
||||||
return (++(*i));
|
return (++(*i));
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* __KFUSD_H__ */
|
#endif /* __KFUSD_H__ */
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
ifneq ($(KERNELRELEASE),)
|
ifneq ($(KERNELRELEASE),)
|
||||||
obj-m := kfusd.o
|
obj-m := kfusd.o
|
||||||
|
KERNEL_VER ?= $(KERNELRELEASE)
|
||||||
else
|
else
|
||||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||||
PWD := $(shell pwd)
|
PWD := $(shell pwd)
|
||||||
|
ROOTFS ?=
|
||||||
|
|
||||||
|
KERNEL_VER ?= 2.6.32.7
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) EXTRA_CFLAGS=-I$(PWD)/../include modules
|
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) EXTRA_CFLAGS=-I$(PWD)/../include modules
|
||||||
|
|
||||||
install:
|
install:
|
||||||
$(INSTALL) -d -m 0755 /lib/modules/$(shell uname -r)/kernel/drivers/misc
|
install -d -m 0755 $(ROOTFS)/lib/modules/$(KERNEL_VER)/kernel/drivers/misc
|
||||||
$(INSTALL) -m 0755 kfusd.ko /lib/modules/$(shell uname -r)/kernel/drivers/misc
|
install -m 0755 kfusd.ko $(ROOTFS)/lib/modules/$(KERNEL_VER)/kernel/drivers/misc
|
||||||
/sbin/depmod -a
|
|
||||||
|
# /sbin/depmod -a
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f .kfusd* Modules.symvers \
|
rm -f .kfusd* Modules.symvers \
|
||||||
|
|||||||
4437
kfusd/kfusd.c
4437
kfusd/kfusd.c
File diff suppressed because it is too large
Load Diff
@@ -35,10 +35,10 @@
|
|||||||
*
|
*
|
||||||
* authors: jelson and girod
|
* authors: jelson and girod
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: libfusd.c 12351 2007-01-19 07:22:54Z xiphmont $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char libfusd_c_id[] = "$Id$";
|
char libfusd_c_id[] = "$Id: libfusd.c 12351 2007-01-19 07:22:54Z xiphmont $";
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -328,8 +328,6 @@ void fusd_fdset_add(fd_set *set, int *max)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fusd_dispatch_fdset: given an fd_set full of descriptors, call
|
* fusd_dispatch_fdset: given an fd_set full of descriptors, call
|
||||||
* fusd_dispatch on every descriptor in the set which is a valid FUSD
|
* fusd_dispatch on every descriptor in the set which is a valid FUSD
|
||||||
@@ -410,16 +408,21 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
|
|||||||
|
|
||||||
/* dispatch on operation type */
|
/* dispatch on operation type */
|
||||||
user_retval = -ENOSYS;
|
user_retval = -ENOSYS;
|
||||||
|
//printf("dispatch_one: subcmd: %d - ", msg->subcmd);
|
||||||
|
|
||||||
switch (msg->subcmd) {
|
switch (msg->subcmd) {
|
||||||
case FUSD_OPEN:
|
case FUSD_OPEN:
|
||||||
|
//printf("FUSD_OPEN\n");
|
||||||
if (fops && fops->open)
|
if (fops && fops->open)
|
||||||
user_retval = fops->open(file);
|
user_retval = fops->open(file);
|
||||||
break;
|
break;
|
||||||
case FUSD_CLOSE:
|
case FUSD_CLOSE:
|
||||||
|
//printf("FUSD_CLOSE\n");
|
||||||
if (fops && fops->close)
|
if (fops && fops->close)
|
||||||
user_retval = fops->close(file);
|
user_retval = fops->close(file);
|
||||||
break;
|
break;
|
||||||
case FUSD_READ:
|
case FUSD_READ:
|
||||||
|
//printf("FUSD_READ\n");
|
||||||
/* allocate a buffer and make the call */
|
/* allocate a buffer and make the call */
|
||||||
if (fops && fops->read) {
|
if (fops && fops->read) {
|
||||||
if ((msg->data = malloc(msg->parm.fops_msg.length)) == NULL) {
|
if ((msg->data = malloc(msg->parm.fops_msg.length)) == NULL) {
|
||||||
@@ -433,11 +436,13 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FUSD_WRITE:
|
case FUSD_WRITE:
|
||||||
|
//printf("FUSD_WRITE\n");
|
||||||
if (fops && fops->write)
|
if (fops && fops->write)
|
||||||
user_retval = fops->write(file, msg->data, msg->datalen,
|
user_retval = fops->write(file, msg->data, msg->datalen,
|
||||||
&msg->parm.fops_msg.offset);
|
&msg->parm.fops_msg.offset);
|
||||||
break;
|
break;
|
||||||
case FUSD_MMAP:
|
case FUSD_MMAP:
|
||||||
|
//printf("FUSD_MMAP\n");
|
||||||
if (fops && fops->mmap)
|
if (fops && fops->mmap)
|
||||||
{
|
{
|
||||||
user_retval = fops->mmap(file, msg->parm.fops_msg.offset, msg->parm.fops_msg.length, msg->parm.fops_msg.flags,
|
user_retval = fops->mmap(file, msg->parm.fops_msg.offset, msg->parm.fops_msg.length, msg->parm.fops_msg.flags,
|
||||||
@@ -445,6 +450,7 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FUSD_IOCTL:
|
case FUSD_IOCTL:
|
||||||
|
//printf("FUSD_IOCTL\n");
|
||||||
if (fops && fops->ioctl) {
|
if (fops && fops->ioctl) {
|
||||||
/* in the case of an ioctl read, allocate a buffer for the
|
/* in the case of an ioctl read, allocate a buffer for the
|
||||||
* driver to write to, IF there isn't already a buffer. (there
|
* driver to write to, IF there isn't already a buffer. (there
|
||||||
@@ -466,6 +472,7 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FUSD_POLL_DIFF:
|
case FUSD_POLL_DIFF:
|
||||||
|
//printf("FUSD_POLL_DIFF\n");
|
||||||
/* This callback requests notification when an event occurs on a file,
|
/* This callback requests notification when an event occurs on a file,
|
||||||
* e.g. becoming readable or writable */
|
* e.g. becoming readable or writable */
|
||||||
if (fops && fops->poll_diff)
|
if (fops && fops->poll_diff)
|
||||||
@@ -473,6 +480,7 @@ static int fusd_dispatch_one(int fd, fusd_file_operations_t *fops)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FUSD_UNBLOCK:
|
case FUSD_UNBLOCK:
|
||||||
|
//printf("FUSD_UNBLOCK\n");
|
||||||
/* This callback is called when a system call is interrupted */
|
/* This callback is called when a system call is interrupted */
|
||||||
if (fops && fops->unblock)
|
if (fops && fops->unblock)
|
||||||
user_retval = fops->unblock(file);
|
user_retval = fops->unblock(file);
|
||||||
@@ -533,6 +541,7 @@ void fusd_dispatch(int fd)
|
|||||||
if (!FUSD_FD_VALID(fd)) {
|
if (!FUSD_FD_VALID(fd)) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
retval = -1;
|
retval = -1;
|
||||||
|
fprintf(stderr, "libfusd: not a valid FUSD FD\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fops = FUSD_GET_FOPS(fd);
|
fops = FUSD_GET_FOPS(fd);
|
||||||
@@ -555,7 +564,7 @@ void fusd_dispatch(int fd)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
if (retval < 0 && errno != EPIPE)
|
if (retval < 0 && errno != EPIPE)
|
||||||
fprintf(stderr, "libfusd: fusd_dispatch error on fd %d: %m\n", fd);
|
fprintf(stderr, "libfusd: fusd_dispatch error on fd %d: [%d] %m \n", fd, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -648,11 +657,16 @@ int fusd_return(fusd_file_info_t *file, ssize_t retval)
|
|||||||
|
|
||||||
/* send message to kernel */
|
/* send message to kernel */
|
||||||
if (msg->datalen && msg->data != NULL) {
|
if (msg->datalen && msg->data != NULL) {
|
||||||
|
//printf("(msg->datalen [%d] && msg->data != NULL [%p]", msg->datalen, msg->data);
|
||||||
iov[0].iov_base = msg;
|
iov[0].iov_base = msg;
|
||||||
iov[0].iov_len = sizeof(fusd_msg_t);
|
iov[0].iov_len = sizeof(fusd_msg_t);
|
||||||
iov[1].iov_base = msg->data;
|
iov[1].iov_base = msg->data;
|
||||||
iov[1].iov_len = msg->datalen;
|
iov[1].iov_len = msg->datalen;
|
||||||
|
#if 0
|
||||||
driver_retval = writev(fd, iov, 2);
|
driver_retval = writev(fd, iov, 2);
|
||||||
|
#else
|
||||||
|
driver_retval = ioctl(fd, 0xb16b00b5, iov);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
driver_retval = write(fd, msg, sizeof(fusd_msg_t));
|
driver_retval = write(fd, msg, sizeof(fusd_msg_t));
|
||||||
|
|||||||
Reference in New Issue
Block a user