3 * Copyright (c) 2003 The Regents of the University of California. All
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Neither the name of the University nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * FUSD: the Framework for User-Space Devices
35 * Public header function for user-space library. This is the API
36 * that user-space device drivers should write to.
43 #include <sys/types.h>
51 /* FUSD_NOREPLY is a special error code. If a user-space driver
52 * implementing a system call returns -FUSD_NOREPLY (note it's
53 * negative!), the calling application will be blocked. When
54 * conditions enable a response to the system call (e.g. the read or
55 * write has completed), the user-space driver must call the
56 * fusd_return() function. */
57 #define FUSD_NOREPLY 0x1000
59 /* FUSD defines several bitmasks for describing which channels of
60 * notification are being requested or signaled. These flags are
61 * used in the arguments and return value of the notify() callback. */
62 #define FUSD_NOTIFY_INPUT 0x1
63 #define FUSD_NOTIFY_OUTPUT 0x2
64 #define FUSD_NOTIFY_EXCEPT 0x4
67 #define FUSD_KOR_HACKED_VERSION
69 struct fusd_file_info
; /* forward decl */
72 struct fusd_file_operations
{
73 int (*open
) (struct fusd_file_info
*file
);
74 int (*close
) (struct fusd_file_info
*file
);
75 ssize_t (*read
) (struct fusd_file_info
*file
, char *buffer
, size_t length
,
77 ssize_t (*write
) (struct fusd_file_info
*file
, const char *buffer
,
78 size_t length
, loff_t
*offset
);
79 int (*ioctl
) (struct fusd_file_info
*file
, int request
, void *data
);
80 int (*poll_diff
) (struct fusd_file_info
*file
, unsigned int cached_state
);
81 int (*unblock
) (struct fusd_file_info
*file
);
82 int (*mmap
) (struct fusd_file_info
*file
, int offset
, size_t length
, int flags
, void** addr
, size_t* out_length
);
83 } fusd_file_operations_t
;
86 /* state-keeping structure passed to device driver callbacks */
88 struct fusd_file_info
{
89 void *device_info
; /* This is set by the library to
90 * whatever you passed to
91 * fusd_register. Changing this in a
92 * file_operations callback has no
95 void *private_data
; /* File-specific data you can change
96 * in a file_operations callback.
97 * e.g., you can set this in an open()
98 * callback, then get it in a
99 * corresponding read() callback. */
101 unsigned int flags
; /* Kept synced with file->f_flags */
102 pid_t pid
; /* PID of process making the request */
103 uid_t uid
; /* UID of process making the request */
104 gid_t gid
; /* GID of process making the request */
106 /* other info might be added later, e.g. state needed to complete
109 /* request message associated with this call */
111 fusd_msg_t
*fusd_msg
;
118 /*************************** Library Functions ****************************/
120 /* fusd_register: create a device file and register callbacks for it
124 * name - the name of the device file, to be created wherever devfs
125 * is mounted (usually dev). example: pass "mydevice" will create
128 * As a convenience, passing a string that starts with "/dev/" will
129 * automatically skip over that portion of the name.
131 * mode - the file protections to be given to the device
133 * device_info - you can provide arbitrary data that will later be
134 * passed back to your driver's callbacks in file->device_info.
135 * value has no effect on FUSD itself.
137 * fops - a table of callbacks to be called for this device; see
141 * On failure, -1 is returned and errno is set to indicate the error.
143 * On success, a valid file descriptor is returned which represents
144 * the control channel to your new device. You should never read
145 * from or write to that control channel directcly, but you can
146 * select on it to see when it needs attention (see fusd_run and
150 int fusd_register(const char *name
, const char* clazz
, const char* devname
, mode_t mode
, void *device_info
,
151 struct fusd_file_operations
*fops
);
155 /* "simple" interface to fusd_register. */
156 #define fusd_simple_register(name, clazz, devname, perms, arg, ops...) do { \
157 struct fusd_file_operations f = { ops } ; \
158 if (fusd_register(name, clazz, devname, perms, arg, &f) < 0) \
159 perror("warning: fusd unavailable"); \
162 /* fusd_unregister: unregister a previously registered device
165 * fd - the file descriptor previously returned to you by fusd_register.
169 * -1 on failure with errno set to indicate the failure.
171 int fusd_unregister(int fd
);
174 /* fusd_return: unblock a previously blocked system call
177 * file - the file info struct that was previously blocked
178 * retval - the return value that would have been returned by the
179 * returning system call
183 * -1 on failure with errno set to indicate the failure
185 int fusd_return(struct fusd_file_info
*file
, ssize_t retval
);
189 * fusd_destroy destroys all state associated with a fusd_file_info
190 * pointer. (It is implicitly called by fusd_return.) If a driver
191 * saves a fusd_file_info pointer by calling -FUSD_NOREPLY in order to
192 * block a read, but gets a "close" request on the file before the
193 * pointer is returned with fusd_return, it should be thrown away
194 * using fusd_destroy.
196 void fusd_destroy(struct fusd_file_info
*file
);
199 /* fusd_dispatch: handles an event on a fusd file descriptor
202 * fd - the file descriptor of the device that received an event
208 * May (but may not) call a callback function originally passed to
211 * Prints an error to stderr in case of a dispatching error.
213 void fusd_dispatch(int fd
);
217 * fusd_run: convenience function that handles dispatch for all
220 * No return value; runs forever.
226 * fusd_fdset_add: given an FDSET and "max", add the currently valid
227 * FUSD fds to the set and update max accordingly.
229 void fusd_fdset_add(fd_set
*set
, int *max
);
233 * fusd_dispatch_fdset: given an fd_set full of descriptors, call
234 * fusd_dispatch on every descriptor in the set which is a valid FUSD
237 void fusd_dispatch_fdset(fd_set
*set
);
240 /********************************************************************
244 * This API enables a driver implementation to store state about a
245 * blocked call more easily, extracting the call arguments directly
246 * with no need to store them separately.
248 ********************************************************************/
251 static inline int fusd_get_call_type(struct fusd_file_info
*file
)
252 { return file
->fusd_msg
->subcmd
; }
254 static inline char * fusd_get_read_buffer(struct fusd_file_info
*file
)
255 { return file
->fusd_msg
->data
; }
257 static inline const char * fusd_get_write_buffer(struct fusd_file_info
*file
)
258 { return (const char *)file
->fusd_msg
->data
; }
260 static inline size_t fusd_get_length(struct fusd_file_info
*file
)
261 { return (size_t)file
->fusd_msg
->datalen
; }
263 static inline loff_t
*fusd_get_offset(struct fusd_file_info
*file
)
264 { return &(file
->fusd_msg
->parm
.fops_msg
.offset
); }
266 static inline int fusd_get_ioctl_request(struct fusd_file_info
*file
)
267 { return file
->fusd_msg
->parm
.fops_msg
.cmd
; }
269 static inline unsigned long fusd_get_ioctl_arg(struct fusd_file_info
*file
)
270 { return file
->fusd_msg
->parm
.fops_msg
.arg
.arg
; }
272 static inline void * fusd_get_ioctl_buffer(struct fusd_file_info
*file
)
273 { return (void *)file
->fusd_msg
->data
; }
275 static inline int fusd_get_poll_diff_cached_state(struct fusd_file_info
*file
)
276 { return file
->fusd_msg
->parm
.fops_msg
.cmd
; }
278 /* returns static string representing the flagset (e.g. RWE) */
279 char *fusd_unparse_flags(int flags
);
285 #endif /* __FUSD_H__ */