2 * GPIO driver. This driver acts as a file system to allow
3 * reading and toggling of GPIO's.
6 #include <minix/driver.h>
7 #include <minix/drvlib.h>
8 #include <minix/vtreefs.h>
12 #include <sys/queue.h>
28 /* used for logging */
29 static struct log log
= {
31 .log_level
= LEVEL_INFO
,
32 .log_func
= default_log
35 #define GPIO_CB_READ 0
39 /* The vtreefs library provides callback data when calling
40 * the read function of inode. gpio_cbdata is used here to
41 * map between inodes and gpio's. VTreeFS is read-only. to work
42 * around that issue for a single GPIO we create multiple virtual
43 * files that can be *read* to read the gpio value and power on
48 struct gpio
*gpio
; /* obtained from the driver */
49 int type
; /* read=0/on=1/off=2 */
50 TAILQ_ENTRY(gpio_cbdata
) next
;
53 /* list of inodes used in this driver */
54 TAILQ_HEAD(gpio_cbdata_head
, gpio_cbdata
)
55 gpio_cbdata_list
= TAILQ_HEAD_INITIALIZER(gpio_cbdata_list
);
57 static struct gpio_driver drv
;
59 /* Sane file stats for a directory */
60 static struct inode_stat default_file_stat
= {
69 add_gpio_inode(char *name
, int nr
, int mode
)
71 /* Create 2 files nodes for "name" "nameon" and "nameoff" to read and
72 * set values as we don't support writing yet */
74 struct gpio_cbdata
*cb
;
77 /* claim and configure the gpio */
78 if (drv
.claim("gpiofs", nr
, &gpio
)) {
79 log_warn(&log
, "Failed to claim GPIO %d\n", nr
);
84 if (drv
.pin_mode(gpio
, mode
)) {
85 log_warn(&log
, "Failed to switch GPIO %d to mode %d\n", nr
,
91 cb
= malloc(sizeof(struct gpio_cbdata
));
95 memset(cb
, 0, sizeof(*cb
));
97 cb
->type
= GPIO_CB_READ
;
100 snprintf(tmpname
, 200, "%s", name
);
101 add_inode(get_root_inode(), tmpname
, NO_INDEX
, &default_file_stat
, 0,
103 TAILQ_INSERT_HEAD(&gpio_cbdata_list
, cb
, next
);
105 if (mode
== GPIO_MODE_OUTPUT
) {
106 /* if we configured the GPIO pin as output mode also create
107 * two additional files to turn on and off the GPIO. */
109 cb
= malloc(sizeof(struct gpio_cbdata
));
113 memset(cb
, 0, sizeof(*cb
));
115 cb
->type
= GPIO_CB_ON
;
118 snprintf(tmpname
, 200, "%son", name
);
119 add_inode(get_root_inode(), tmpname
, NO_INDEX
,
120 &default_file_stat
, 0, (cbdata_t
) cb
);
121 TAILQ_INSERT_HEAD(&gpio_cbdata_list
, cb
, next
);
124 cb
= malloc(sizeof(struct gpio_cbdata
));
128 memset(cb
, 0, sizeof(*cb
));
130 cb
->type
= GPIO_CB_OFF
;
133 snprintf(tmpname
, 200, "%soff", name
);
134 add_inode(get_root_inode(), tmpname
, NO_INDEX
,
135 &default_file_stat
, 0, (cbdata_t
) cb
);
136 TAILQ_INSERT_HEAD(&gpio_cbdata_list
, cb
, next
);
144 /* This hook will be called once, after VTreeFS has initialized. */
145 if (omap_gpio_init(&drv
)) {
146 log_warn(&log
, "Failed to init gpio driver\n");
148 add_gpio_inode("USR0", 149, GPIO_MODE_OUTPUT
);
149 add_gpio_inode("USR1", 150, GPIO_MODE_OUTPUT
);
150 add_gpio_inode("Button", 4, GPIO_MODE_INPUT
);
153 add_gpio_inode("input1", 139, GPIO_MODE_INPUT
);
154 add_gpio_inode("input2", 144, GPIO_MODE_INPUT
);
160 (struct inode
*inode
, off_t offset
, char **ptr
, size_t * len
,
163 /* This hook will be called every time a regular file is read. We use
164 * it to dyanmically generate the contents of our file. */
165 static char data
[26];
167 struct gpio_cbdata
*gpio_cbdata
= (struct gpio_cbdata
*) cbdata
;
168 assert(gpio_cbdata
->gpio
!= NULL
);
170 if (gpio_cbdata
->type
== GPIO_CB_ON
) {
172 if (drv
.set(gpio_cbdata
->gpio
, 1)) {
178 } else if (gpio_cbdata
->type
== GPIO_CB_OFF
) {
180 if (drv
.set(gpio_cbdata
->gpio
, 0)) {
189 if (drv
.read(gpio_cbdata
->gpio
, &value
)) {
193 snprintf(data
, 26, "%d\n", value
);
195 /* If the offset is beyond the end of the string, return EOF. */
196 if (offset
> strlen(data
)) {
202 /* Otherwise, return a pointer into 'data'. If necessary, bound the
203 * returned length to the length of the rest of the string. Note that
204 * 'data' has to be static, because it will be used after this
205 * function returns. */
206 *ptr
= data
+ offset
;
208 if (*len
> strlen(data
) - offset
)
209 *len
= strlen(data
) - offset
;
215 main(int argc
, char **argv
)
218 struct fs_hooks hooks
;
219 struct inode_stat root_stat
;
221 /* Set and apply the environment */
222 env_setargs(argc
, argv
);
224 /* fill in the hooks */
225 memset(&hooks
, 0, sizeof(hooks
));
226 hooks
.init_hook
= init_hook
;
227 hooks
.read_hook
= read_hook
;
229 root_stat
.mode
= S_IFDIR
| S_IRUSR
| S_IRGRP
| S_IROTH
;
233 root_stat
.dev
= NO_DEV
;
235 /* limit the number of indexed entries */
236 start_vtreefs(&hooks
, 10, &root_stat
, 0);