diff options
-rw-r--r-- | include/litmus/ftdev.h | 5 | ||||
-rw-r--r-- | litmus/ftdev.c | 16 |
2 files changed, 20 insertions, 1 deletions
diff --git a/include/litmus/ftdev.h b/include/litmus/ftdev.h index 348387e9adf9..0b959874dd70 100644 --- a/include/litmus/ftdev.h +++ b/include/litmus/ftdev.h | |||
@@ -16,7 +16,8 @@ typedef int (*ftdev_can_open_t)(struct ftdev* dev, unsigned int buf_no); | |||
16 | /* return 0 on success, otherwise -$REASON */ | 16 | /* return 0 on success, otherwise -$REASON */ |
17 | typedef int (*ftdev_alloc_t)(struct ftdev* dev, unsigned int buf_no); | 17 | typedef int (*ftdev_alloc_t)(struct ftdev* dev, unsigned int buf_no); |
18 | typedef void (*ftdev_free_t)(struct ftdev* dev, unsigned int buf_no); | 18 | typedef void (*ftdev_free_t)(struct ftdev* dev, unsigned int buf_no); |
19 | 19 | /* Let devices handle writes from userspace. No synchronization provided. */ | |
20 | typedef ssize_t (*ftdev_write_t)(struct ft_buffer* buf, size_t len, const char __user *from); | ||
20 | 21 | ||
21 | struct ftdev_event; | 22 | struct ftdev_event; |
22 | 23 | ||
@@ -27,6 +28,7 @@ struct ftdev_minor { | |||
27 | /* FIXME: filter for authorized events */ | 28 | /* FIXME: filter for authorized events */ |
28 | struct ftdev_event* events; | 29 | struct ftdev_event* events; |
29 | struct device* device; | 30 | struct device* device; |
31 | struct ftdev* ftdev; | ||
30 | }; | 32 | }; |
31 | 33 | ||
32 | struct ftdev { | 34 | struct ftdev { |
@@ -39,6 +41,7 @@ struct ftdev { | |||
39 | ftdev_alloc_t alloc; | 41 | ftdev_alloc_t alloc; |
40 | ftdev_free_t free; | 42 | ftdev_free_t free; |
41 | ftdev_can_open_t can_open; | 43 | ftdev_can_open_t can_open; |
44 | ftdev_write_t write; | ||
42 | }; | 45 | }; |
43 | 46 | ||
44 | struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size); | 47 | struct ft_buffer* alloc_ft_buffer(unsigned int count, size_t size); |
diff --git a/litmus/ftdev.c b/litmus/ftdev.c index 216dc0b4cb94..06fcf4cf77dc 100644 --- a/litmus/ftdev.c +++ b/litmus/ftdev.c | |||
@@ -114,6 +114,7 @@ static int ftdev_open(struct inode *in, struct file *filp) | |||
114 | goto out; | 114 | goto out; |
115 | 115 | ||
116 | ftdm = ftdev->minor + buf_idx; | 116 | ftdm = ftdev->minor + buf_idx; |
117 | ftdm->ftdev = ftdev; | ||
117 | filp->private_data = ftdm; | 118 | filp->private_data = ftdm; |
118 | 119 | ||
119 | if (mutex_lock_interruptible(&ftdm->lock)) { | 120 | if (mutex_lock_interruptible(&ftdm->lock)) { |
@@ -284,11 +285,25 @@ out: | |||
284 | return err; | 285 | return err; |
285 | } | 286 | } |
286 | 287 | ||
288 | static ssize_t ftdev_write(struct file *filp, const char __user *from, | ||
289 | size_t len, loff_t *f_pos) | ||
290 | { | ||
291 | struct ftdev_minor* ftdm = filp->private_data; | ||
292 | ssize_t err = -EINVAL; | ||
293 | struct ftdev* ftdev = ftdm->ftdev; | ||
294 | |||
295 | /* dispatch write to buffer-specific code, if available */ | ||
296 | if (ftdev->write) | ||
297 | err = ftdev->write(ftdm->buf, len, from); | ||
298 | |||
299 | return err; | ||
300 | } | ||
287 | 301 | ||
288 | struct file_operations ftdev_fops = { | 302 | struct file_operations ftdev_fops = { |
289 | .owner = THIS_MODULE, | 303 | .owner = THIS_MODULE, |
290 | .open = ftdev_open, | 304 | .open = ftdev_open, |
291 | .release = ftdev_release, | 305 | .release = ftdev_release, |
306 | .write = ftdev_write, | ||
292 | .read = ftdev_read, | 307 | .read = ftdev_read, |
293 | .unlocked_ioctl = ftdev_ioctl, | 308 | .unlocked_ioctl = ftdev_ioctl, |
294 | }; | 309 | }; |
@@ -308,6 +323,7 @@ int ftdev_init( struct ftdev* ftdev, struct module* owner, | |||
308 | ftdev->alloc = NULL; | 323 | ftdev->alloc = NULL; |
309 | ftdev->free = NULL; | 324 | ftdev->free = NULL; |
310 | ftdev->can_open = NULL; | 325 | ftdev->can_open = NULL; |
326 | ftdev->write = NULL; | ||
311 | 327 | ||
312 | ftdev->minor = kcalloc(ftdev->minor_cnt, sizeof(*ftdev->minor), | 328 | ftdev->minor = kcalloc(ftdev->minor_cnt, sizeof(*ftdev->minor), |
313 | GFP_KERNEL); | 329 | GFP_KERNEL); |