Remove building with NOCRYPTO option
[minix.git] / minix / lib / libinputdriver / inputdriver.c
blob3c360cdcb4979b72d6b2ccb1cb646b0ff284986b
1 /* This file contains the device independent input driver interface. */
2 /*
3 * Changes:
4 * Sep 22, 2013 created (D.C. van Moolenbroek)
5 */
7 #include <minix/drivers.h>
8 #include <minix/inputdriver.h>
9 #include <minix/ds.h>
11 static endpoint_t input_endpt = NONE;
12 static int kbd_id = INVALID_INPUT_ID;
13 static int mouse_id = INVALID_INPUT_ID;
15 static int running;
18 * Announce that we are up after a fresh start or restart.
20 void
21 inputdriver_announce(unsigned int type)
23 const char *driver_prefix = "drv.inp.";
24 char key[DS_MAX_KEYLEN];
25 char label[DS_MAX_KEYLEN];
26 int r;
28 /* Publish a driver up event. */
29 if ((r = ds_retrieve_label_name(label, sef_self())) != OK)
30 panic("libinputdriver: unable to retrieve own label: %d", r);
32 snprintf(key, sizeof(key), "%s%s", driver_prefix, label);
33 if ((r = ds_publish_u32(key, type, DSF_OVERWRITE)) != OK)
34 panic("libinputdriver: unable to publish up event: %d", r);
36 /* Now we wait for the input server to contact us. */
40 * Send an event to the input server.
42 void
43 inputdriver_send_event(int mouse, unsigned short page, unsigned short code,
44 int value, int flags)
46 message m;
47 int id;
49 if (input_endpt == NONE)
50 return;
52 id = mouse ? mouse_id : kbd_id;
53 if (id == INVALID_INPUT_ID)
54 return;
56 memset(&m, 0, sizeof(m));
58 m.m_type = INPUT_EVENT;
59 m.m_linputdriver_input_event.id = id;
60 m.m_linputdriver_input_event.page = page;
61 m.m_linputdriver_input_event.code = code;
62 m.m_linputdriver_input_event.value = value;
63 m.m_linputdriver_input_event.flags = flags;
66 * Use a blocking send call, for two reasons. First, this avoids the
67 * situation that we ever end up queuing too many asynchronous messages
68 * to the input server. Second, it allows us to detect trivially if
69 * the input server has crashed, in which case we should stop sending
70 * more messages to it.
72 if (ipc_send(input_endpt, &m) != OK)
73 input_endpt = NONE;
77 * The input server requests that we configure the driver. This request should
78 * be sent to us once, although it may be sent multiple times if the input
79 * server crashes and recovers. The configuration consists of device IDs for
80 * use in keyboard and/or mouse events, one per each device type.
82 static void
83 do_conf(message *m_ptr)
85 endpoint_t ep;
86 int r;
88 /* Make sure that the sender is actually the input server. */
89 if ((r = ds_retrieve_label_endpt("input", &ep)) != OK) {
90 printf("libinputdriver: unable to get input endpoint (%d)\n",
91 r);
93 return; /* ignore message */
96 if (ep != m_ptr->m_source) {
97 printf("libinputdriver: ignoring CONF request from %u\n",
98 m_ptr->m_source);
100 return;
103 /* Save the new state. */
104 input_endpt = m_ptr->m_source;
105 kbd_id = m_ptr->m_input_linputdriver_input_conf.kbd_id;
106 mouse_id = m_ptr->m_input_linputdriver_input_conf.mouse_id;
108 /* If the input server is "full" there's nothing for us to do. */
109 if (kbd_id == INVALID_INPUT_ID && mouse_id == INVALID_INPUT_ID)
110 printf("libinputdriver: no IDs given, driver disabled\n");
114 * The input server is telling us to change the LEDs to a particular mask.
115 * For now this is for keyboards only, so no device type is provided.
116 * This approach was chosen over sending toggle events for the individual LEDs
117 * for convenience reasons only.
119 static void
120 do_setleds(struct inputdriver *idp, message *m_ptr)
122 unsigned int mask;
124 if (m_ptr->m_source != input_endpt) {
125 printf("libinputdriver: ignoring SETLEDS request from %u\n",
126 m_ptr->m_source);
128 return;
131 mask = m_ptr->m_input_linputdriver_setleds.led_mask;
133 if (idp->idr_leds)
134 idp->idr_leds(mask);
138 * Call the appropriate driver function, based on the type of message.
139 * All messages in the input protocol are one-way, so we never send a reply.
141 void
142 inputdriver_process(struct inputdriver *idp, message *m_ptr, int ipc_status)
144 /* Check for notifications first. */
145 if (is_ipc_notify(ipc_status)) {
146 switch (_ENDPOINT_P(m_ptr->m_source)) {
147 case HARDWARE:
148 if (idp->idr_intr)
149 idp->idr_intr(m_ptr->m_notify.interrupts);
150 break;
152 case CLOCK:
153 if (idp->idr_alarm)
154 idp->idr_alarm(m_ptr->m_notify.timestamp);
155 break;
157 default:
158 if (idp->idr_other)
159 idp->idr_other(m_ptr, ipc_status);
162 return;
165 switch (m_ptr->m_type) {
166 case INPUT_CONF: do_conf(m_ptr); break;
167 case INPUT_SETLEDS: do_setleds(idp, m_ptr); break;
168 default:
169 if (idp->idr_other)
170 idp->idr_other(m_ptr, ipc_status);
175 * Break out of the main loop after finishing the current request.
177 void
178 inputdriver_terminate(void)
180 running = FALSE;
182 sef_cancel();
186 * Main program of any input driver task.
188 void
189 inputdriver_task(struct inputdriver *idp)
191 message m;
192 int r, ipc_status;
194 running = TRUE;
196 while (running) {
197 if ((r = sef_receive_status(ANY, &m, &ipc_status)) != OK) {
198 if (r == EINTR && !running)
199 break;
201 panic("libinputdriver: receive failed: %d", r);
204 inputdriver_process(idp, &m, ipc_status);