xref: /minix3/minix/drivers/examples/hello/hello.c (revision 3f82ac6a4e188419336747098d0d6616cd2f3d3d)
1433d6423SLionel Sambuc #include <minix/drivers.h>
2433d6423SLionel Sambuc #include <minix/chardriver.h>
3433d6423SLionel Sambuc #include <stdio.h>
4433d6423SLionel Sambuc #include <stdlib.h>
5433d6423SLionel Sambuc #include <minix/ds.h>
6433d6423SLionel Sambuc #include "hello.h"
7433d6423SLionel Sambuc 
8433d6423SLionel Sambuc /*
9433d6423SLionel Sambuc  * Function prototypes for the hello driver.
10433d6423SLionel Sambuc  */
11433d6423SLionel Sambuc static int hello_open(devminor_t minor, int access, endpoint_t user_endpt);
12433d6423SLionel Sambuc static int hello_close(devminor_t minor);
13433d6423SLionel Sambuc static ssize_t hello_read(devminor_t minor, u64_t position, endpoint_t endpt,
14433d6423SLionel Sambuc     cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
15433d6423SLionel Sambuc 
16433d6423SLionel Sambuc /* SEF functions and variables. */
17433d6423SLionel Sambuc static void sef_local_startup(void);
18433d6423SLionel Sambuc static int sef_cb_init(int type, sef_init_info_t *info);
19*e1f889d2SCristiano Giuffrida static int sef_cb_lu_state_save(int, int);
20433d6423SLionel Sambuc static int lu_state_restore(void);
21433d6423SLionel Sambuc 
22433d6423SLionel Sambuc /* Entry points to the hello driver. */
23433d6423SLionel Sambuc static struct chardriver hello_tab =
24433d6423SLionel Sambuc {
25433d6423SLionel Sambuc     .cdr_open	= hello_open,
26433d6423SLionel Sambuc     .cdr_close	= hello_close,
27433d6423SLionel Sambuc     .cdr_read	= hello_read,
28433d6423SLionel Sambuc };
29433d6423SLionel Sambuc 
30433d6423SLionel Sambuc /** State variable to count the number of times the device has been opened.
31433d6423SLionel Sambuc  * Note that this is not the regular type of open counter: it never decreases.
32433d6423SLionel Sambuc  */
33433d6423SLionel Sambuc static int open_counter;
34433d6423SLionel Sambuc 
hello_open(devminor_t UNUSED (minor),int UNUSED (access),endpoint_t UNUSED (user_endpt))35433d6423SLionel Sambuc static int hello_open(devminor_t UNUSED(minor), int UNUSED(access),
36433d6423SLionel Sambuc     endpoint_t UNUSED(user_endpt))
37433d6423SLionel Sambuc {
38433d6423SLionel Sambuc     printf("hello_open(). Called %d time(s).\n", ++open_counter);
39433d6423SLionel Sambuc     return OK;
40433d6423SLionel Sambuc }
41433d6423SLionel Sambuc 
hello_close(devminor_t UNUSED (minor))42433d6423SLionel Sambuc static int hello_close(devminor_t UNUSED(minor))
43433d6423SLionel Sambuc {
44433d6423SLionel Sambuc     printf("hello_close()\n");
45433d6423SLionel Sambuc     return OK;
46433d6423SLionel Sambuc }
47433d6423SLionel Sambuc 
hello_read(devminor_t UNUSED (minor),u64_t position,endpoint_t endpt,cp_grant_id_t grant,size_t size,int UNUSED (flags),cdev_id_t UNUSED (id))48433d6423SLionel Sambuc static ssize_t hello_read(devminor_t UNUSED(minor), u64_t position,
49433d6423SLionel Sambuc     endpoint_t endpt, cp_grant_id_t grant, size_t size, int UNUSED(flags),
50433d6423SLionel Sambuc     cdev_id_t UNUSED(id))
51433d6423SLionel Sambuc {
52433d6423SLionel Sambuc     u64_t dev_size;
53433d6423SLionel Sambuc     char *ptr;
54433d6423SLionel Sambuc     int ret;
55433d6423SLionel Sambuc     char *buf = HELLO_MESSAGE;
56433d6423SLionel Sambuc 
57433d6423SLionel Sambuc     printf("hello_read()\n");
58433d6423SLionel Sambuc 
59433d6423SLionel Sambuc     /* This is the total size of our device. */
60433d6423SLionel Sambuc     dev_size = (u64_t) strlen(buf);
61433d6423SLionel Sambuc 
62433d6423SLionel Sambuc     /* Check for EOF, and possibly limit the read size. */
63433d6423SLionel Sambuc     if (position >= dev_size) return 0;		/* EOF */
64433d6423SLionel Sambuc     if (position + size > dev_size)
65433d6423SLionel Sambuc         size = (size_t)(dev_size - position);	/* limit size */
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc     /* Copy the requested part to the caller. */
68433d6423SLionel Sambuc     ptr = buf + (size_t)position;
69433d6423SLionel Sambuc     if ((ret = sys_safecopyto(endpt, grant, 0, (vir_bytes) ptr, size)) != OK)
70433d6423SLionel Sambuc         return ret;
71433d6423SLionel Sambuc 
72433d6423SLionel Sambuc     /* Return the number of bytes read. */
73433d6423SLionel Sambuc     return size;
74433d6423SLionel Sambuc }
75433d6423SLionel Sambuc 
sef_cb_lu_state_save(int UNUSED (state),int UNUSED (flags))76*e1f889d2SCristiano Giuffrida static int sef_cb_lu_state_save(int UNUSED(state), int UNUSED(flags)) {
77433d6423SLionel Sambuc /* Save the state. */
78433d6423SLionel Sambuc     ds_publish_u32("open_counter", open_counter, DSF_OVERWRITE);
79433d6423SLionel Sambuc 
80433d6423SLionel Sambuc     return OK;
81433d6423SLionel Sambuc }
82433d6423SLionel Sambuc 
lu_state_restore()83433d6423SLionel Sambuc static int lu_state_restore() {
84433d6423SLionel Sambuc /* Restore the state. */
85433d6423SLionel Sambuc     u32_t value;
86433d6423SLionel Sambuc 
87433d6423SLionel Sambuc     ds_retrieve_u32("open_counter", &value);
88433d6423SLionel Sambuc     ds_delete_u32("open_counter");
89433d6423SLionel Sambuc     open_counter = (int) value;
90433d6423SLionel Sambuc 
91433d6423SLionel Sambuc     return OK;
92433d6423SLionel Sambuc }
93433d6423SLionel Sambuc 
sef_local_startup()94433d6423SLionel Sambuc static void sef_local_startup()
95433d6423SLionel Sambuc {
96433d6423SLionel Sambuc     /*
97433d6423SLionel Sambuc      * Register init callbacks. Use the same function for all event types
98433d6423SLionel Sambuc      */
99433d6423SLionel Sambuc     sef_setcb_init_fresh(sef_cb_init);
100433d6423SLionel Sambuc     sef_setcb_init_lu(sef_cb_init);
101433d6423SLionel Sambuc     sef_setcb_init_restart(sef_cb_init);
102433d6423SLionel Sambuc 
103433d6423SLionel Sambuc     /*
104433d6423SLionel Sambuc      * Register live update callbacks.
105433d6423SLionel Sambuc      */
106433d6423SLionel Sambuc     sef_setcb_lu_state_save(sef_cb_lu_state_save);
107433d6423SLionel Sambuc 
108433d6423SLionel Sambuc     /* Let SEF perform startup. */
109433d6423SLionel Sambuc     sef_startup();
110433d6423SLionel Sambuc }
111433d6423SLionel Sambuc 
sef_cb_init(int type,sef_init_info_t * UNUSED (info))112433d6423SLionel Sambuc static int sef_cb_init(int type, sef_init_info_t *UNUSED(info))
113433d6423SLionel Sambuc {
114433d6423SLionel Sambuc /* Initialize the hello driver. */
115433d6423SLionel Sambuc     int do_announce_driver = TRUE;
116433d6423SLionel Sambuc 
117433d6423SLionel Sambuc     open_counter = 0;
118433d6423SLionel Sambuc     switch(type) {
119433d6423SLionel Sambuc         case SEF_INIT_FRESH:
120433d6423SLionel Sambuc             printf("%s", HELLO_MESSAGE);
121433d6423SLionel Sambuc         break;
122433d6423SLionel Sambuc 
123433d6423SLionel Sambuc         case SEF_INIT_LU:
124433d6423SLionel Sambuc             /* Restore the state. */
125433d6423SLionel Sambuc             lu_state_restore();
126433d6423SLionel Sambuc             do_announce_driver = FALSE;
127433d6423SLionel Sambuc 
128433d6423SLionel Sambuc             printf("%sHey, I'm a new version!\n", HELLO_MESSAGE);
129433d6423SLionel Sambuc         break;
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc         case SEF_INIT_RESTART:
132433d6423SLionel Sambuc             printf("%sHey, I've just been restarted!\n", HELLO_MESSAGE);
133433d6423SLionel Sambuc         break;
134433d6423SLionel Sambuc     }
135433d6423SLionel Sambuc 
136433d6423SLionel Sambuc     /* Announce we are up when necessary. */
137433d6423SLionel Sambuc     if (do_announce_driver) {
138433d6423SLionel Sambuc         chardriver_announce();
139433d6423SLionel Sambuc     }
140433d6423SLionel Sambuc 
141433d6423SLionel Sambuc     /* Initialization completed successfully. */
142433d6423SLionel Sambuc     return OK;
143433d6423SLionel Sambuc }
144433d6423SLionel Sambuc 
main(void)145433d6423SLionel Sambuc int main(void)
146433d6423SLionel Sambuc {
147433d6423SLionel Sambuc     /*
148433d6423SLionel Sambuc      * Perform initialization.
149433d6423SLionel Sambuc      */
150433d6423SLionel Sambuc     sef_local_startup();
151433d6423SLionel Sambuc 
152433d6423SLionel Sambuc     /*
153433d6423SLionel Sambuc      * Run the main loop.
154433d6423SLionel Sambuc      */
155433d6423SLionel Sambuc     chardriver_task(&hello_tab);
156433d6423SLionel Sambuc     return OK;
157433d6423SLionel Sambuc }
158433d6423SLionel Sambuc 
159