Place personal working copy of fusd into revision control
git-svn-id: http://svn.xiph.org/trunk/fusd@12312 0101bb08-14d6-0310-b084-bc0e0c8e3800
This commit is contained in:
285
include/fusd.h
Executable file
285
include/fusd.h
Executable file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003 The Regents of the University of California. All
|
||||
* rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Neither the name of the University nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* FUSD: the Framework for User-Space Devices
|
||||
*
|
||||
* Public header function for user-space library. This is the API
|
||||
* that user-space device drivers should write to.
|
||||
*/
|
||||
|
||||
#ifndef __FUSD_H__
|
||||
#define __FUSD_H__
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <sys/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
#endif
|
||||
|
||||
|
||||
#include "fusd_msg.h"
|
||||
|
||||
/* FUSD_NOREPLY is a special error code. If a user-space driver
|
||||
* implementing a system call returns -FUSD_NOREPLY (note it's
|
||||
* negative!), the calling application will be blocked. When
|
||||
* conditions enable a response to the system call (e.g. the read or
|
||||
* write has completed), the user-space driver must call the
|
||||
* fusd_return() function. */
|
||||
#define FUSD_NOREPLY 0x1000
|
||||
|
||||
/* FUSD defines several bitmasks for describing which channels of
|
||||
* notification are being requested or signaled. These flags are
|
||||
* used in the arguments and return value of the notify() callback. */
|
||||
#define FUSD_NOTIFY_INPUT 0x1
|
||||
#define FUSD_NOTIFY_OUTPUT 0x2
|
||||
#define FUSD_NOTIFY_EXCEPT 0x4
|
||||
|
||||
|
||||
#define FUSD_KOR_HACKED_VERSION
|
||||
|
||||
struct fusd_file_info; /* forward decl */
|
||||
|
||||
typedef
|
||||
struct fusd_file_operations {
|
||||
int (*open) (struct fusd_file_info *file);
|
||||
int (*close) (struct fusd_file_info *file);
|
||||
ssize_t (*read) (struct fusd_file_info *file, char *buffer, size_t length,
|
||||
loff_t *offset);
|
||||
ssize_t (*write) (struct fusd_file_info *file, const char *buffer,
|
||||
size_t length, loff_t *offset);
|
||||
int (*ioctl) (struct fusd_file_info *file, int request, void *data);
|
||||
int (*poll_diff) (struct fusd_file_info *file, unsigned int cached_state);
|
||||
int (*unblock) (struct fusd_file_info *file);
|
||||
int (*mmap) (struct fusd_file_info *file, int offset, size_t length, int flags, void** addr, size_t* out_length);
|
||||
} fusd_file_operations_t;
|
||||
|
||||
|
||||
/* state-keeping structure passed to device driver callbacks */
|
||||
typedef
|
||||
struct fusd_file_info {
|
||||
void *device_info; /* This is set by the library to
|
||||
* whatever you passed to
|
||||
* fusd_register. Changing this in a
|
||||
* file_operations callback has no
|
||||
* effect. */
|
||||
|
||||
void *private_data; /* File-specific data you can change
|
||||
* in a file_operations callback.
|
||||
* e.g., you can set this in an open()
|
||||
* callback, then get it in a
|
||||
* corresponding read() callback. */
|
||||
|
||||
unsigned int flags; /* Kept synced with file->f_flags */
|
||||
pid_t pid; /* PID of process making the request */
|
||||
uid_t uid; /* UID of process making the request */
|
||||
gid_t gid; /* GID of process making the request */
|
||||
|
||||
/* other info might be added later, e.g. state needed to complete
|
||||
operations... */
|
||||
|
||||
/* request message associated with this call */
|
||||
int fd;
|
||||
fusd_msg_t *fusd_msg;
|
||||
|
||||
} fusd_file_info_t;
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************** Library Functions ****************************/
|
||||
|
||||
/* fusd_register: create a device file and register callbacks for it
|
||||
*
|
||||
* Arguments:
|
||||
*
|
||||
* name - the name of the device file, to be created wherever devfs
|
||||
* is mounted (usually dev). example: pass "mydevice" will create
|
||||
* /dev/mydevice.
|
||||
*
|
||||
* As a convenience, passing a string that starts with "/dev/" will
|
||||
* automatically skip over that portion of the name.
|
||||
*
|
||||
* mode - the file protections to be given to the device
|
||||
*
|
||||
* device_info - you can provide arbitrary data that will later be
|
||||
* passed back to your driver's callbacks in file->device_info.
|
||||
* value has no effect on FUSD itself.
|
||||
*
|
||||
* fops - a table of callbacks to be called for this device; see
|
||||
* structure above.
|
||||
*
|
||||
* Return value:
|
||||
* On failure, -1 is returned and errno is set to indicate the error.
|
||||
*
|
||||
* On success, a valid file descriptor is returned which represents
|
||||
* the control channel to your new device. You should never read
|
||||
* from or write to that control channel directcly, but you can
|
||||
* select on it to see when it needs attention (see fusd_run and
|
||||
* fusd_dispatch).
|
||||
*/
|
||||
|
||||
int fusd_register(const char *name, const char* clazz, const char* devname, mode_t mode, void *device_info,
|
||||
struct fusd_file_operations *fops);
|
||||
|
||||
|
||||
|
||||
/* "simple" interface to fusd_register. */
|
||||
#define fusd_simple_register(name, clazz, devname, perms, arg, ops...) do { \
|
||||
struct fusd_file_operations f = { ops } ; \
|
||||
if (fusd_register(name, clazz, devname, perms, arg, &f) < 0) \
|
||||
perror("warning: fusd unavailable"); \
|
||||
} while(0)
|
||||
|
||||
/* fusd_unregister: unregister a previously registered device
|
||||
*
|
||||
* Arguments:
|
||||
* fd - the file descriptor previously returned to you by fusd_register.
|
||||
*
|
||||
* Return value:
|
||||
* 0 on success.
|
||||
* -1 on failure with errno set to indicate the failure.
|
||||
*/
|
||||
int fusd_unregister(int fd);
|
||||
|
||||
|
||||
/* fusd_return: unblock a previously blocked system call
|
||||
*
|
||||
* Arguments:
|
||||
* file - the file info struct that was previously blocked
|
||||
* retval - the return value that would have been returned by the
|
||||
* returning system call
|
||||
*
|
||||
* Return value:
|
||||
* 0 on success.
|
||||
* -1 on failure with errno set to indicate the failure
|
||||
*/
|
||||
int fusd_return(struct fusd_file_info *file, ssize_t retval);
|
||||
|
||||
|
||||
/*
|
||||
* fusd_destroy destroys all state associated with a fusd_file_info
|
||||
* pointer. (It is implicitly called by fusd_return.) If a driver
|
||||
* saves a fusd_file_info pointer by calling -FUSD_NOREPLY in order to
|
||||
* block a read, but gets a "close" request on the file before the
|
||||
* pointer is returned with fusd_return, it should be thrown away
|
||||
* using fusd_destroy.
|
||||
*/
|
||||
void fusd_destroy(struct fusd_file_info *file);
|
||||
|
||||
|
||||
/* fusd_dispatch: handles an event on a fusd file descriptor
|
||||
*
|
||||
* Arguments:
|
||||
* fd - the file descriptor of the device that received an event
|
||||
*
|
||||
* Return value:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* May (but may not) call a callback function originally passed to
|
||||
* fusd_register.
|
||||
*
|
||||
* Prints an error to stderr in case of a dispatching error.
|
||||
*/
|
||||
void fusd_dispatch(int fd);
|
||||
|
||||
|
||||
/*
|
||||
* fusd_run: convenience function that handles dispatch for all
|
||||
* fusd devices
|
||||
*
|
||||
* No return value; runs forever.
|
||||
*/
|
||||
void fusd_run(void);
|
||||
|
||||
|
||||
/*
|
||||
* fusd_fdset_add: given an FDSET and "max", add the currently valid
|
||||
* FUSD fds to the set and update max accordingly.
|
||||
*/
|
||||
void fusd_fdset_add(fd_set *set, int *max);
|
||||
|
||||
|
||||
/*
|
||||
* fusd_dispatch_fdset: given an fd_set full of descriptors, call
|
||||
* fusd_dispatch on every descriptor in the set which is a valid FUSD
|
||||
* fd.
|
||||
*/
|
||||
void fusd_dispatch_fdset(fd_set *set);
|
||||
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
* Direct access API
|
||||
*
|
||||
* This API enables a driver implementation to store state about a
|
||||
* blocked call more easily, extracting the call arguments directly
|
||||
* with no need to store them separately.
|
||||
*
|
||||
********************************************************************/
|
||||
|
||||
/* accessors */
|
||||
static inline int fusd_get_call_type(struct fusd_file_info *file)
|
||||
{ return file->fusd_msg->subcmd; }
|
||||
|
||||
static inline char * fusd_get_read_buffer(struct fusd_file_info *file)
|
||||
{ return file->fusd_msg->data; }
|
||||
|
||||
static inline const char * fusd_get_write_buffer(struct fusd_file_info *file)
|
||||
{ return (const char *)file->fusd_msg->data; }
|
||||
|
||||
static inline size_t fusd_get_length(struct fusd_file_info *file)
|
||||
{ return (size_t)file->fusd_msg->datalen; }
|
||||
|
||||
static inline loff_t *fusd_get_offset(struct fusd_file_info *file)
|
||||
{ return &(file->fusd_msg->parm.fops_msg.offset); }
|
||||
|
||||
static inline int fusd_get_ioctl_request(struct fusd_file_info *file)
|
||||
{ return file->fusd_msg->parm.fops_msg.cmd; }
|
||||
|
||||
static inline unsigned long fusd_get_ioctl_arg(struct fusd_file_info *file)
|
||||
{ return file->fusd_msg->parm.fops_msg.arg.arg; }
|
||||
|
||||
static inline void * fusd_get_ioctl_buffer(struct fusd_file_info *file)
|
||||
{ return (void *)file->fusd_msg->data; }
|
||||
|
||||
static inline int fusd_get_poll_diff_cached_state(struct fusd_file_info *file)
|
||||
{ return file->fusd_msg->parm.fops_msg.cmd; }
|
||||
|
||||
/* returns static string representing the flagset (e.g. RWE) */
|
||||
char *fusd_unparse_flags(int flags);
|
||||
|
||||
#ifndef __KERNEL__
|
||||
__END_DECLS
|
||||
#endif
|
||||
|
||||
#endif /* __FUSD_H__ */
|
||||
151
include/fusd_msg.h
Executable file
151
include/fusd_msg.h
Executable file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003 The Regents of the University of California. All
|
||||
* rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Neither the name of the University nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* FUSD: the Framework for User-Space Devices
|
||||
*
|
||||
* Defines the interface between the kernel module and userspace library.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __FUSD_MSG_H__
|
||||
#define __FUSD_MSG_H__
|
||||
|
||||
/* filenames */
|
||||
#define DEFAULT_DEV_ROOT "/dev/"
|
||||
#define FUSD_CONTROL_FILENAME "fusd/control"
|
||||
#define FUSD_STATUS_FILENAME "fusd/status"
|
||||
|
||||
#define FUSD_CONTROL_DEVNAME DEFAULT_DEV_ROOT FUSD_CONTROL_FILENAME
|
||||
#define FUSD_STATUS_DEVNAME DEFAULT_DEV_ROOT FUSD_STATUS_FILENAME
|
||||
|
||||
/* ioctl number to tell FUSD status device to return binary info */
|
||||
#define FUSD_STATUS_USE_BINARY _IO('F', 100)
|
||||
|
||||
/* constants */
|
||||
#define FUSD_MAX_NAME_LENGTH 47 /* 47, to avoid expanding union size */
|
||||
|
||||
|
||||
/* commands */
|
||||
#define FUSD_REGISTER_DEVICE 0 /* device registration */
|
||||
#define FUSD_UNREGISTER_DEVICE 1 /* device unregistration */
|
||||
|
||||
/* these two must have successive numbers */
|
||||
#define FUSD_FOPS_CALL 2 /* synchronous round-trip call: request */
|
||||
#define FUSD_FOPS_REPLY (FUSD_FOPS_CALL + 1)
|
||||
|
||||
/* these two must have successive numbers */
|
||||
#define FUSD_FOPS_NONBLOCK 4 /* call that does not block for a reply */
|
||||
#define FUSD_FOPS_NONBLOCK_REPLY (FUSD_FOPS_NONBLOCK + 1)
|
||||
|
||||
#define FUSD_FOPS_CALL_DROPREPLY 6 /* call that doesn't want a reply */
|
||||
|
||||
/* subcommands */
|
||||
#define FUSD_OPEN 100
|
||||
#define FUSD_CLOSE 101
|
||||
#define FUSD_READ 102
|
||||
#define FUSD_WRITE 103
|
||||
#define FUSD_IOCTL 104
|
||||
#define FUSD_POLL_DIFF 105
|
||||
#define FUSD_UNBLOCK 106
|
||||
#define FUSD_MMAP 107
|
||||
|
||||
/* other constants */
|
||||
#define FUSD_MSG_MAGIC 0x7a6b93cd
|
||||
|
||||
/* user->kernel: register a device */
|
||||
typedef struct {
|
||||
char name[FUSD_MAX_NAME_LENGTH+1];
|
||||
char clazz[FUSD_MAX_NAME_LENGTH+1];
|
||||
char devname[FUSD_MAX_NAME_LENGTH+1];
|
||||
mode_t mode;
|
||||
void *device_info;
|
||||
} register_msg_t;
|
||||
|
||||
|
||||
/* kernel->user: fops request message (common data) */
|
||||
typedef struct {
|
||||
pid_t pid;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
unsigned int flags; /* flags from file struct */
|
||||
void *device_info; /* device info */
|
||||
void *private_info; /* file info */
|
||||
|
||||
/* parameters and return values for various calls. should be a
|
||||
* union but it just makes things too complex and doesn't save all
|
||||
* that much memory anyway */
|
||||
ssize_t retval;
|
||||
size_t length;
|
||||
loff_t offset;
|
||||
unsigned int cmd; /* ioctl cmd, poll_diff cached_state */
|
||||
|
||||
union {
|
||||
unsigned long arg; /* ioctl */
|
||||
void *ptr_arg;
|
||||
} arg;
|
||||
|
||||
/* the following are cookies that have meaning internal to the kernel
|
||||
* but must be returned, untouched, by userspace */
|
||||
void *fusd_file;
|
||||
long transid;
|
||||
int hint;
|
||||
} fops_msg_t;
|
||||
|
||||
|
||||
/* the message struct written to FUSD control channel */
|
||||
typedef struct {
|
||||
int magic;
|
||||
short int cmd;
|
||||
short int subcmd;
|
||||
|
||||
char *data; /* yes, it's slightly inefficient to push this useless
|
||||
* pointer between user and kernel space, but it makes
|
||||
* it much easier to have a pointer available in this
|
||||
* structure that both the kernel and userlib can make
|
||||
* their own use of. */
|
||||
int datalen;
|
||||
union {
|
||||
register_msg_t register_msg; /* device registration (U->K) */
|
||||
fops_msg_t fops_msg; /* U->K and K->U fops messages */
|
||||
} parm;
|
||||
} fusd_msg_t;
|
||||
|
||||
|
||||
/* structure read from FUSD binary status device */
|
||||
typedef struct {
|
||||
char name[FUSD_MAX_NAME_LENGTH+1];
|
||||
int zombie;
|
||||
pid_t pid;
|
||||
int num_open;
|
||||
} fusd_status_t;
|
||||
|
||||
#endif /* __FUSD_MSG_H__ */
|
||||
288
include/kfusd.h
Executable file
288
include/kfusd.h
Executable file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003 The Regents of the University of California. All
|
||||
* rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Neither the name of the University nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* FUSD: the Framework for User-Space Devices
|
||||
*
|
||||
* Jeremy Elson <jelson@circlemud.org>
|
||||
* Copyright (c) Sensoria Corporation 2001
|
||||
*
|
||||
* Private header file used by the Linux Kernel Module
|
||||
*
|
||||
* $Id: kfusd.h,v 1.41 2003/07/11 22:29:39 cerpa Exp $
|
||||
*/
|
||||
|
||||
#ifndef __KFUSD_H__
|
||||
#define __KFUSD_H__
|
||||
|
||||
#include "fusd_msg.h"
|
||||
|
||||
/* magic numbers for structure checking; unique w.r.t
|
||||
* /usr/src/linux/Documentation/magic-number.txt */
|
||||
#define FUSD_DEV_MAGIC 0x8b43a123
|
||||
#define FUSD_FILE_MAGIC 0x613aa8fe
|
||||
|
||||
/* number of devices that can be created with fusd */
|
||||
#define MAX_FUSD_DEVICES 128
|
||||
|
||||
/* number of times each device can be opened simultaneously */
|
||||
#define MIN_FILEARRAY_SIZE 8 /* initialize allocation */
|
||||
#define MAX_FILEARRAY_SIZE 1024 /* maximum it can grow to */
|
||||
|
||||
/* maximum read/write size we're willing to service */
|
||||
#define MAX_RW_SIZE (1024*128)
|
||||
|
||||
|
||||
/********************** Structure Definitions *******************************/
|
||||
|
||||
/* Container for a fusd msg */
|
||||
typedef struct fusd_msgC_s_t fusd_msgC_t;
|
||||
|
||||
struct fusd_msgC_s_t {
|
||||
fusd_msg_t fusd_msg; /* the message itself */
|
||||
fusd_msgC_t *next; /* pointer to next one in the list */
|
||||
|
||||
/* 1-bit flags */
|
||||
unsigned int peeked:1; /* has the first half of this been read? */
|
||||
};
|
||||
|
||||
struct fusd_transaction
|
||||
{
|
||||
struct list_head list;
|
||||
long transid;
|
||||
int subcmd;
|
||||
int pid;
|
||||
int size;
|
||||
fusd_msg_t* msg_in;
|
||||
};
|
||||
|
||||
/* magical forward declarations to break the circular dependency */
|
||||
struct fusd_dev_t_s;
|
||||
typedef struct fusd_dev_t_s fusd_dev_t;
|
||||
struct CLASS;
|
||||
struct class_device;
|
||||
|
||||
/* state kept per opened file (i.e., an instance of a device) */
|
||||
typedef struct {
|
||||
/* general state management */
|
||||
int magic; /* magic number for sanity checking */
|
||||
fusd_dev_t *fusd_dev; /* fusd device associated with this file */
|
||||
long fusd_dev_version; /* version number of fusd device */
|
||||
void *private_data; /* the user's private data (we ignore it) */
|
||||
struct file *file; /* kernel's file pointer for this file */
|
||||
int index; /* our index in our device's file array */
|
||||
struct semaphore file_sem; /* Semaphore for file structure */
|
||||
int cached_poll_state; /* Latest result from a poll diff req */
|
||||
int last_poll_sent; /* Last polldiff request we sent */
|
||||
|
||||
/* structures used for messaging */
|
||||
wait_queue_head_t file_wait; /* Wait on this for a user->kernel msg */
|
||||
wait_queue_head_t poll_wait; /* Given to kernel for poll() queue */
|
||||
struct list_head transactions;
|
||||
struct semaphore transactions_sem;
|
||||
|
||||
} fusd_file_t;
|
||||
|
||||
|
||||
/* state kept per device registered under fusd */
|
||||
struct fusd_dev_t_s {
|
||||
int magic; /* Magic number for sanity checking */
|
||||
long version; /* Instance number of this device */
|
||||
int zombie; /* Is the device dead? */
|
||||
pid_t pid; /* PID of device driver */
|
||||
struct task_struct* task;
|
||||
|
||||
char *name; /* Name of the device under devfs (/dev) */
|
||||
char *class_name;
|
||||
char *dev_name;
|
||||
struct CLASS *clazz;
|
||||
int owns_class;
|
||||
struct class_device *class_device;
|
||||
|
||||
void *private_data; /* User's private data */
|
||||
struct cdev* handle;
|
||||
dev_t dev_id;
|
||||
// devfs_handle_t handle; /* The devfs-provided handle */
|
||||
|
||||
fusd_file_t **files; /* Array of this device's open files */
|
||||
int array_size; /* Size of the array pointed to by 'files' */
|
||||
int num_files; /* Number of array entries that are valid */
|
||||
int open_in_progress; /* File is referencing this struct,
|
||||
but not yet part of the file array */
|
||||
/* messaging */
|
||||
fusd_msgC_t *msg_head; /* linked list head for message queue */
|
||||
fusd_msgC_t *msg_tail; /* linked list tail for message queue */
|
||||
|
||||
/* synchronization */
|
||||
wait_queue_head_t dev_wait; /* Wait queue for kernel->user msgs */
|
||||
struct semaphore dev_sem; /* Sempahore for device structure */
|
||||
|
||||
/* pointer to allow a dev to be placed on a dev_list */
|
||||
struct list_head devlist;
|
||||
};
|
||||
|
||||
|
||||
/**** Function Prototypes ****/
|
||||
|
||||
STATIC int maybe_free_fusd_dev(fusd_dev_t *fusd_dev);
|
||||
|
||||
STATIC int find_fusd_file(fusd_dev_t *fusd_dev, fusd_file_t *fusd_file);
|
||||
STATIC int free_fusd_file(fusd_dev_t *fusd_dev, fusd_file_t *fusd_file);
|
||||
|
||||
STATIC int fusd_fops_call_send(fusd_file_t *fusd_file_arg,
|
||||
fusd_msg_t *fusd_msg, struct fusd_transaction** transaction);
|
||||
STATIC int fusd_fops_call_wait(fusd_file_t *fusd_file_arg,
|
||||
fusd_msg_t **fusd_msg_reply, struct fusd_transaction* transaction);
|
||||
STATIC void fusd_fops_call_done(fusd_file_t *fusd_file);
|
||||
|
||||
STATIC void fusd_forge_close(fusd_msg_t *msg, fusd_dev_t *fusd_dev);
|
||||
|
||||
STATIC int fusd_add_transaction(fusd_file_t *fusd_file, int transid, int subcmd, int size, struct fusd_transaction** out_transaction);
|
||||
STATIC void fusd_cleanup_transaction(fusd_file_t *fusd_file, struct fusd_transaction* transaction);
|
||||
STATIC void fusd_remove_transaction(fusd_file_t *fusd_file, struct fusd_transaction* transaction);
|
||||
STATIC struct fusd_transaction* fusd_find_transaction(fusd_file_t *fusd_file, int transid);
|
||||
STATIC struct fusd_transaction* fusd_find_transaction_by_pid(fusd_file_t *fusd_file, int pid);
|
||||
|
||||
|
||||
|
||||
/**** Utility functions & macros ****/
|
||||
|
||||
#ifdef CONFIG_FUSD_USE_WAKEUPSYNC
|
||||
#define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible_sync(x)
|
||||
#else
|
||||
#define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible(x)
|
||||
#endif /* CONFIG_FUSD_USE_WAKEUPSYNC */
|
||||
|
||||
#ifdef CONFIG_FUSD_DEBUG
|
||||
static void rdebug_real(char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
#define RDEBUG(message_level, args...) do { \
|
||||
if (fusd_debug_level >= message_level) rdebug_real(args); \
|
||||
} while(0)
|
||||
#else
|
||||
#define RDEBUG(message_level, args...)
|
||||
#endif /* CONFIG_FUSD_DEBUG */
|
||||
|
||||
|
||||
#define ZOMBIE(fusd_dev) ((fusd_dev)->zombie)
|
||||
|
||||
|
||||
#define GET_FUSD_DEV(candidate, fusd_dev) do { \
|
||||
fusd_dev = candidate; \
|
||||
if (fusd_dev == NULL || fusd_dev->magic != FUSD_DEV_MAGIC) \
|
||||
goto invalid_dev; \
|
||||
} while (0)
|
||||
|
||||
#define GET_FUSD_FILE_AND_DEV(candidate, fusd_file, fusd_dev) do { \
|
||||
fusd_file = candidate; \
|
||||
if (fusd_file == NULL || fusd_file->magic != FUSD_FILE_MAGIC) \
|
||||
goto invalid_file; \
|
||||
GET_FUSD_DEV(fusd_file->fusd_dev, fusd_dev); \
|
||||
if (fusd_dev->version != fusd_file->fusd_dev_version) \
|
||||
goto invalid_file; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define LOCK_FUSD_DEV(fusd_dev) \
|
||||
do { down(&fusd_dev->dev_sem); \
|
||||
if (ZOMBIE(fusd_dev)) { up(&fusd_dev->dev_sem); goto zombie_dev; } \
|
||||
} while (0)
|
||||
|
||||
/* rawlock does not do a zombie check */
|
||||
#define RAWLOCK_FUSD_DEV(fusd_dev) \
|
||||
do { down(&fusd_dev->dev_sem); } while (0)
|
||||
|
||||
#define UNLOCK_FUSD_DEV(fusd_dev) \
|
||||
do { up(&fusd_dev->dev_sem); } while (0)
|
||||
|
||||
|
||||
#define LOCK_FUSD_FILE(fusd_file) \
|
||||
do { down(&fusd_file->file_sem); \
|
||||
} while (0)
|
||||
|
||||
#define UNLOCK_FUSD_FILE(fusd_file) \
|
||||
do { up(&fusd_file->file_sem); } while (0)
|
||||
|
||||
#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)
|
||||
|
||||
#ifdef CONFIG_FUSD_MEMDEBUG
|
||||
static int fusd_mem_init(void);
|
||||
static void fusd_mem_cleanup(void);
|
||||
static void fusd_mem_add(void *ptr, int line, int size);
|
||||
static void fusd_mem_del(void *ptr);
|
||||
static void *fusd_kmalloc(size_t size, int type, int line);
|
||||
static void fusd_kfree(void *ptr);
|
||||
static void *fusd_vmalloc(size_t size, int line);
|
||||
static void fusd_vfree(void *ptr);
|
||||
# define KMALLOC(size, type) fusd_kmalloc(size, type, __LINE__)
|
||||
# define KFREE(ptr) fusd_kfree(ptr)
|
||||
# define VMALLOC(size) fusd_vmalloc(size, __LINE__)
|
||||
# define VFREE(ptr) fusd_vfree(ptr)
|
||||
#else /* no memory debugging */
|
||||
# define KMALLOC(size, type) kmalloc(size, type)
|
||||
# define KFREE(ptr) kfree(ptr)
|
||||
/*# define VMALLOC(size) vmalloc(size)*/
|
||||
# define VMALLOC(size) kmalloc(size, GFP_KERNEL)
|
||||
# define VFREE(ptr) kfree(ptr)
|
||||
#endif /* CONFIG_FUSD_MEMDEBUG */
|
||||
|
||||
|
||||
|
||||
/* Functions like this should be in the kernel, but they are not. Sigh. */
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
DECLARE_MUTEX(atomic_ops);
|
||||
|
||||
static __inline__ int atomic_inc_and_ret(int *i)
|
||||
{
|
||||
int val;
|
||||
|
||||
down(&atomic_ops);
|
||||
val = (++(*i));
|
||||
up(&atomic_ops);
|
||||
return val;
|
||||
}
|
||||
#else
|
||||
static __inline__ int atomic_inc_and_ret(int *i)
|
||||
{
|
||||
return (++(*i));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __KFUSD_H__ */
|
||||
Reference in New Issue
Block a user