xref: /minix/minix/drivers/examples/hello/hello.c (revision 0a6a1f1d)
1 #include <minix/drivers.h>
2 #include <minix/chardriver.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <minix/ds.h>
6 #include "hello.h"
7 
8 /*
9  * Function prototypes for the hello driver.
10  */
11 static int hello_open(devminor_t minor, int access, endpoint_t user_endpt);
12 static int hello_close(devminor_t minor);
13 static ssize_t hello_read(devminor_t minor, u64_t position, endpoint_t endpt,
14     cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
15 
16 /* SEF functions and variables. */
17 static void sef_local_startup(void);
18 static int sef_cb_init(int type, sef_init_info_t *info);
19 static int sef_cb_lu_state_save(int, int);
20 static int lu_state_restore(void);
21 
22 /* Entry points to the hello driver. */
23 static struct chardriver hello_tab =
24 {
25     .cdr_open	= hello_open,
26     .cdr_close	= hello_close,
27     .cdr_read	= hello_read,
28 };
29 
30 /** State variable to count the number of times the device has been opened.
31  * Note that this is not the regular type of open counter: it never decreases.
32  */
33 static int open_counter;
34 
35 static int hello_open(devminor_t UNUSED(minor), int UNUSED(access),
36     endpoint_t UNUSED(user_endpt))
37 {
38     printf("hello_open(). Called %d time(s).\n", ++open_counter);
39     return OK;
40 }
41 
42 static int hello_close(devminor_t UNUSED(minor))
43 {
44     printf("hello_close()\n");
45     return OK;
46 }
47 
48 static ssize_t hello_read(devminor_t UNUSED(minor), u64_t position,
49     endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
50     cdev_id_t UNUSED(id))
51 {
52     u64_t dev_size;
53     char *ptr;
54     int ret;
55     char *buf = HELLO_MESSAGE;
56 
57     printf("hello_read()\n");
58 
59     /* This is the total size of our device. */
60     dev_size = (u64_t) strlen(buf);
61 
62     /* Check for EOF, and possibly limit the read size. */
63     if (position >= dev_size) return 0;		/* EOF */
64     if (position + size > dev_size)
65         size = (size_t)(dev_size - position);	/* limit size */
66 
67     /* Copy the requested part to the caller. */
68     ptr = buf + (size_t)position;
69     if ((ret = sys_safecopyto(endpt, grant, 0, (vir_bytes) ptr, size)) != OK)
70         return ret;
71 
72     /* Return the number of bytes read. */
73     return size;
74 }
75 
76 static int sef_cb_lu_state_save(int UNUSED(state), int UNUSED(flags)) {
77 /* Save the state. */
78     ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
79 
80     return OK;
81 }
82 
83 static int lu_state_restore() {
84 /* Restore the state. */
85     u32_t value;
86 
87     ds_retrieve_u32("open_counter", &value);
88     ds_delete_u32("open_counter");
89     open_counter = (int) value;
90 
91     return OK;
92 }
93 
94 static void sef_local_startup()
95 {
96     /*
97      * Register init callbacks. Use the same function for all event types
98      */
99     sef_setcb_init_fresh(sef_cb_init);
100     sef_setcb_init_lu(sef_cb_init);
101     sef_setcb_init_restart(sef_cb_init);
102 
103     /*
104      * Register live update callbacks.
105      */
106     sef_setcb_lu_state_save(sef_cb_lu_state_save);
107 
108     /* Let SEF perform startup. */
109     sef_startup();
110 }
111 
112 static int sef_cb_init(int type, sef_init_info_t *UNUSED(info))
113 {
114 /* Initialize the hello driver. */
115     int do_announce_driver = TRUE;
116 
117     open_counter = 0;
118     switch(type) {
119         case SEF_INIT_FRESH:
120             printf("%s", HELLO_MESSAGE);
121         break;
122 
123         case SEF_INIT_LU:
124             /* Restore the state. */
125             lu_state_restore();
126             do_announce_driver = FALSE;
127 
128             printf("%sHey, I'm a new version!\n", HELLO_MESSAGE);
129         break;
130 
131         case SEF_INIT_RESTART:
132             printf("%sHey, I've just been restarted!\n", HELLO_MESSAGE);
133         break;
134     }
135 
136     /* Announce we are up when necessary. */
137     if (do_announce_driver) {
138         chardriver_announce();
139     }
140 
141     /* Initialization completed successfully. */
142     return OK;
143 }
144 
145 int main(void)
146 {
147     /*
148      * Perform initialization.
149      */
150     sef_local_startup();
151 
152     /*
153      * Run the main loop.
154      */
155     chardriver_task(&hello_tab);
156     return OK;
157 }
158 
159