1 /* This file contains the device independent input driver interface. */
4 * Sep 22, 2013 created (D.C. van Moolenbroek)
7 #include <minix/drivers.h>
8 #include <minix/inputdriver.h>
11 static endpoint_t input_endpt
= NONE
;
12 static int kbd_id
= INVALID_INPUT_ID
;
13 static int mouse_id
= INVALID_INPUT_ID
;
18 * Announce that we are up after a fresh start or restart.
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
];
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.
43 inputdriver_send_event(int mouse
, unsigned short page
, unsigned short code
,
49 if (input_endpt
== NONE
)
52 id
= mouse
? mouse_id
: kbd_id
;
53 if (id
== INVALID_INPUT_ID
)
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
)
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.
83 do_conf(message
*m_ptr
)
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",
93 return; /* ignore message */
96 if (ep
!= m_ptr
->m_source
) {
97 printf("libinputdriver: ignoring CONF request from %u\n",
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.
120 do_setleds(struct inputdriver
*idp
, message
*m_ptr
)
124 if (m_ptr
->m_source
!= input_endpt
) {
125 printf("libinputdriver: ignoring SETLEDS request from %u\n",
131 mask
= m_ptr
->m_input_linputdriver_setleds
.led_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.
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
)) {
149 idp
->idr_intr(m_ptr
->m_notify
.interrupts
);
154 idp
->idr_alarm(m_ptr
->m_notify
.timestamp
);
159 idp
->idr_other(m_ptr
, ipc_status
);
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;
170 idp
->idr_other(m_ptr
, ipc_status
);
175 * Break out of the main loop after finishing the current request.
178 inputdriver_terminate(void)
186 * Main program of any input driver task.
189 inputdriver_task(struct inputdriver
*idp
)
197 if ((r
= sef_receive_status(ANY
, &m
, &ipc_status
)) != OK
) {
198 if (r
== EINTR
&& !running
)
201 panic("libinputdriver: receive failed: %d", r
);
204 inputdriver_process(idp
, &m
, ipc_status
);