initial revision
[ucgine.git] / lib / gloss / include / ucg_gloss_chardev.h
1 /*
2  * Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifndef UCG_GLOSS_DEVICE_H_
29 #define UCG_GLOSS_DEVICE_H_
30
31 #include <sys/queue.h>
32 #include <string.h>
33
34 /**
35  * Maximum number of devices stored in cache.
36  *
37  * Instead of only storing the devices in a list, the first ones are
38  * stored in a table indexed by the file descriptor. This avoids a
39  * linear browsing on lookup.
40  */
41 #define GLOSS_DEVICE_CACHE_MAX 4
42
43 /**
44  * Structure describing a device
45  *
46  * It can be registered using ucg_chardev_register(), and allows to
47  * redirect file operations to any channel (uart, spi, ...).
48  */
49 struct ucg_chardev {
50         /* filled by ucg_chardev_register() */
51         TAILQ_ENTRY(ucg_chardev) next;
52         int fd;
53
54         /* filled by user before registration */
55         const char *name;
56         int (*open_r)(struct _reent *r, const char *path, int flags, int mode);
57         int (*close_r)(struct _reent *r, int fd);
58         _ssize_t (*read_r)(struct _reent *r, int fd, void *ptr, size_t len);
59         _ssize_t (*write_r)(struct _reent *r, int fd, const void *ptr, size_t len);
60 };
61
62 /**
63  * The list of devices.
64  */
65 TAILQ_HEAD(ucg_chardev_list, ucg_chardev);
66 struct ucg_chardev_list ucg_chardev_list;
67
68 /**
69  * Table of first ucg_chardev pointers, initialized to NULL.
70  */
71 struct ucg_chardev *ucg_chardev_cache[GLOSS_DEVICE_CACHE_MAX];
72
73 /**
74  * Register a device
75  *
76  * Register device operations. The structure is appended to the device
77  * list, and its name and fd fields are modified. Therefore, a structure
78  * cannot be registered twice.
79  *
80  * The first three devices to be registered are stdin, stdout and stderr.
81  *
82  * @param dev
83  *   The filled device structure
84  * @return
85  *   0 on success, negative on error
86  */
87 int ucg_chardev_register(struct ucg_chardev *dev);
88
89 /**
90  * Return the device associated to the given file descriptor.
91  *
92  * @param fd
93  *   The file descriptor.
94  * @return
95  *   The device matching the file descriptor.
96  */
97 static inline const struct ucg_chardev *
98 ucg_chardev_lookup_from_fd(int fd)
99 {
100         const struct ucg_chardev *dev;
101
102         if (fd >= 0 && fd < GLOSS_DEVICE_CACHE_MAX)
103                 return ucg_chardev_cache[fd];
104
105         TAILQ_FOREACH(dev, &ucg_chardev_list, next) {
106                 if (dev->fd == fd)
107                         return dev;
108         }
109         return NULL;
110 }
111
112 /**
113  * Return the device associated to the given name.
114  *
115  * @param name
116  *   The name of the file.
117  * @return
118  *   The device matching the file name.
119  */
120 static inline const struct ucg_chardev *
121 ucg_chardev_lookup_from_name(const char *name)
122 {
123         const struct ucg_chardev *dev;
124
125         TAILQ_FOREACH(dev, &ucg_chardev_list, next) {
126                 if (strcmp(name, dev->name) == 0)
127                         return dev;
128         }
129         return NULL;
130 }
131
132 #endif /* UCG_GLOSS_DEVICE_H_ */