Re-enabled use of AROS.Boot file due to lack of general enthusiasm for
[tangerine.git] / arch / all-linux / hidd / inputtask.c
blob68ea3ed890155c0157b5a4fcaa64ee6f1e313045
1 /*
2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Task used for wainting on events from linux
6 Lang: English.
7 */
10 #include <unistd.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <signal.h>
15 #include <proto/exec.h>
16 #include <proto/oop.h>
17 #include <proto/arossupport.h>
19 #include <exec/memory.h>
20 #include <exec/tasks.h>
21 #include <exec/lists.h>
23 #include <dos/dos.h>
25 #include <oop/oop.h>
26 #include <hidd/unixio.h>
27 #include <hidd/mouse.h>
29 #include "linux_intern.h"
31 #define INPUTTASK_PRIORITY 50
33 #define INPUTTASK_STACKSIZE (AROS_STACKSIZE)
34 #define INPUTTASK_NAME "Linux input event task"
36 /* this task should wait for mouse and keyboard events */
38 struct inputtask_params {
39 struct Task *parent;
40 ULONG ok_signal;
41 ULONG fail_signal;
42 ULONG kill_signal;
43 struct linux_staticdata *lsd;
47 struct mouse_state {
48 BOOL buts[3];
49 BYTE dx;
50 BYTE dy;
53 #undef LSD
54 #define LSD lsd
57 static void update_mouse_state( struct mouse_state *oldstate
58 , struct mouse_state *newstate
59 , struct pHidd_Mouse_Event *mev)
61 ULONG i;
62 ULONG hidd2but[] = {
63 vHidd_Mouse_Button1,
64 vHidd_Mouse_Button2,
65 vHidd_Mouse_Button3
68 /* Discover the difference between the old and the new state */
69 for (i = 0; i < 3; i ++) {
70 if (oldstate->buts[i] != newstate->buts[i]) {
71 mev->button = hidd2but[i];
72 mev->type = ( oldstate->buts[i] ? vHidd_Mouse_Release : vHidd_Mouse_Press );
73 return;
78 if ( (oldstate->dx != newstate->dx)
79 || (oldstate->dy != newstate->dy) ) {
81 mev->x = newstate->dx;
82 mev->y = newstate->dy;
83 mev->type = vHidd_Mouse_Motion;
88 static void free_unixio_message(struct MsgPort *msgport, struct linux_staticdata *lsd)
90 struct Message *msg;
92 msg = GetMsg(msgport);
93 if (NULL == msg) {
94 kprintf("!!! linux input task: NO MSG FROM UNIXIO !!!\n");
95 } else {
96 FreeMem(msg, sizeof (struct uioMessage));
100 static VOID inputtask_entry(struct inputtask_params *inputparams)
102 struct linux_staticdata *lsd;
103 struct inputtask_params itp;
104 UBYTE lastcode = 0xFF;
106 struct MsgPort *kbd_port = NULL;
107 struct MsgPort *mouse_port = NULL;
109 struct mouse_state oldstate = { { 0, 0, 0 }, 0, 0 };
110 struct pHidd_Mouse_Event mouse_event;
112 HIDD *unixio = NULL;
113 ULONG kbdsig, mousesig, sigs;
114 /* We must copy the parameter struct because they are allocated
115 on the parent's stack */
116 kprintf("INSIDE INPUT TASK\n");
117 itp = *inputparams;
118 lsd = itp.lsd;
119 kprintf("in inputtask: lsd = %p\n", lsd);
121 kprintf("CREATING UNIXIO,,, OOPBase=%p\n", OOPBase);
122 kprintf("now\n");
123 unixio = (HIDD)New_UnixIO(OOPBase, SysBase);
124 kprintf("UNIXIO %p\n", unixio);
125 if (NULL == unixio) {
126 goto failexit;
129 kbd_port = CreateMsgPort();
130 mouse_port = CreateMsgPort();
132 if (NULL == kbd_port || NULL == mouse_port)
133 goto failexit;
135 Signal(itp.parent, itp.ok_signal);
137 kbdsig = 1L << kbd_port->mp_SigBit;
138 mousesig = 1L << mouse_port->mp_SigBit;
139 kprintf("SIGS: %p, %p\n", kbdsig, mousesig);
140 kprintf("FDS: %d, %d\n", lsd->kbdfd, lsd->mousefd);
142 Hidd_UnixIO_AsyncIO(unixio, lsd->kbdfd, vHidd_UnixIO_Terminal, kbd_port, vHidd_UnixIO_Read, SysBase);
143 Hidd_UnixIO_AsyncIO(unixio, lsd->mousefd, vHidd_UnixIO_Terminal, mouse_port, vHidd_UnixIO_Read, SysBase);
145 for (;;) {
146 LONG err_kbd, err_mouse;
148 //kprintf("GETTING INPUT FROM UNIXIO\n");
149 /* Turn on kbd support */
150 // init_kbd(lsd);
153 // ret = (int)Hidd_UnixIO_Wait( unixio, lsd->kbdfd, vHidd_UnixIO_Read, NULL, NULL);
154 // cleanup_kbd(lsd);
155 // kprintf("GOT INPUT FROM UNIXIO\n");
157 sigs = Wait( kbdsig | mousesig );
159 if (sigs & kbdsig) {
161 //kprintf("---------- GOT KBD INPUT --------------------\n");
162 for (;;) {
163 UBYTE code;
164 size_t bytesread;
167 bytesread = read(lsd->kbdfd, &code, 1);
168 if (-1 == bytesread) {
169 kprintf("!!! COULD NOT READ FROM LINUX KBD DEVICE: %s\n"
170 , strerror(errno));
171 break;
173 } else {
174 /* Let the kbd hidd handle it */
175 /* Key doewn ? */
177 //kprintf("## code %d\n", code);
178 if (code == lastcode)
179 break;
181 // if (!(code & 0x80)) kprintf("GOT SCANCODE %d from kbd hidd\n", code);
182 if (code == 88) /* F12 */
184 kill(getpid(), SIGTERM);
187 /* Send code to the application */
188 ObtainSemaphore(&lsd->sema);
189 if (lsd->kbdhidd) HIDD_LinuxKbd_HandleEvent(lsd->kbdhidd, code);
190 ReleaseSemaphore(&lsd->sema);
192 lastcode = code;
194 break;
196 } /* for (;;) */
197 free_unixio_message(kbd_port, lsd);
199 err_kbd = Hidd_UnixIO_AsyncIO(unixio, lsd->kbdfd, vHidd_UnixIO_Terminal, kbd_port, vHidd_UnixIO_Read, SysBase);
201 } /* if (sigs & kbdsig) */
203 if (sigs & mousesig)
205 ULONG i;
206 LONG bytesread;
207 UBYTE buf[4];
208 BYTE dx = 0, dy = 0;
209 struct mouse_state newstate;
211 /* Got mouse event */
212 //kprintf("------------- MOUSE EVENT ------------\n");
213 for (i = 0; i < 4; i ++) {
214 bytesread = read(lsd->mousefd, &buf[i], 1);
215 if (-1 == bytesread)
217 if (errno == EAGAIN)
219 i--;
220 continue;
222 kprintf("!!! linux input task: Could not read from mouse device: %s\n", strerror(errno));
223 goto end_mouse_event;
226 if ((buf[0] & 8) != 8) i--;
229 //kprintf("%02x: %02x: %02x\n", buf[0], buf[1], buf[2]);
230 /* Get button states */
231 newstate.buts[0] = (buf[0] & 0x01) ? 1 : 0;
232 newstate.buts[1] = (buf[0] & 0x02) ? 1 : 0;
233 newstate.buts[2] = (buf[0] & 0x04) ? 1 : 0;
235 if (buf[1] != 0) {
236 dx = (buf[0] & 0x10) ? buf[1] - 256 : buf[1];
239 if (buf[2] != 0) {
240 dy = (buf[0] & 0x20) ? buf[2] - 256 : buf[2];
243 newstate.dx = dx;
244 newstate.dy = -dy;
246 //kprintf("EVENT: STATE 1:%d, 2:%d, 3:%d, dx:%d, dy:%d\n"
247 // , newstate.buts[0], newstate.buts[1], newstate.buts[2]
248 // , newstate.dx, newstate.dy);
250 ObtainSemaphore(&lsd->sema);
251 if (lsd->mousehidd)
253 mouse_event.x = newstate.dx;
254 mouse_event.y = newstate.dy;
256 if (newstate.dx || newstate.dy)
258 mouse_event.button = vHidd_Mouse_NoButton;
259 mouse_event.type = vHidd_Mouse_Motion;
261 HIDD_LinuxMouse_HandleEvent(lsd->mousehidd, &mouse_event);
264 if (newstate.buts[0] != oldstate.buts[0])
266 mouse_event.button = vHidd_Mouse_Button1;
267 mouse_event.type = newstate.buts[0] ? vHidd_Mouse_Press : vHidd_Mouse_Release;
269 HIDD_LinuxMouse_HandleEvent(lsd->mousehidd, &mouse_event);
272 if (newstate.buts[1] != oldstate.buts[1])
274 mouse_event.button = vHidd_Mouse_Button2;
275 mouse_event.type = newstate.buts[1] ? vHidd_Mouse_Press : vHidd_Mouse_Release;
277 HIDD_LinuxMouse_HandleEvent(lsd->mousehidd, &mouse_event);
280 if (newstate.buts[2] != oldstate.buts[2])
282 mouse_event.button = vHidd_Mouse_Button3;
283 mouse_event.type = newstate.buts[2] ? vHidd_Mouse_Press : vHidd_Mouse_Release;
285 HIDD_LinuxMouse_HandleEvent(lsd->mousehidd, &mouse_event);
288 ReleaseSemaphore(&lsd->sema);
290 oldstate = newstate;
292 end_mouse_event:
293 free_unixio_message(mouse_port, lsd);
295 err_mouse = Hidd_UnixIO_AsyncIO(unixio, lsd->mousefd, vHidd_UnixIO_Terminal, mouse_port, vHidd_UnixIO_Read, SysBase);
299 } /* Forever */
301 failexit:
303 if (NULL != kbd_port)
304 DeleteMsgPort(kbd_port);
306 if (NULL != mouse_port)
307 DeleteMsgPort(mouse_port);
309 if (NULL != unixio)
310 OOP_DisposeObject((OOP_Object *)unixio);
312 Signal(itp.parent, itp.fail_signal);
314 return;
318 static struct Task *create_inputtask( struct inputtask_params *params, struct ExecBase *SysBase)
320 struct Task *task;
321 APTR stack;
323 task = AllocMem(sizeof (struct Task), MEMF_PUBLIC|MEMF_CLEAR);
324 if (NULL != task) {
325 NEWLIST(&task->tc_MemEntry);
326 task->tc_Node.ln_Type=NT_TASK;
327 task->tc_Node.ln_Name= INPUTTASK_NAME;
328 task->tc_Node.ln_Pri = INPUTTASK_PRIORITY;
330 stack=AllocMem(INPUTTASK_STACKSIZE, MEMF_PUBLIC);
331 if(NULL != stack) {
332 task->tc_SPLower=stack;
333 task->tc_SPUpper=(BYTE *)stack + INPUTTASK_STACKSIZE;
335 #if AROS_STACK_GROWS_DOWNWARDS
336 task->tc_SPReg = (BYTE *)task->tc_SPUpper-SP_OFFSET-sizeof(APTR);
337 ((APTR *)task->tc_SPUpper)[-1] = params;
338 #else
339 task->tc_SPReg=(BYTE *)task->tc_SPLower-SP_OFFSET + sizeof(APTR);
340 *(APTR *)task->tc_SPLower = params;
341 #endif
342 /* You have to clear signals first. */
343 SetSignal(0, params->ok_signal | params->fail_signal);
345 if(AddTask(task, inputtask_entry, NULL) != NULL) {
346 /* Everything went OK. Wait for task to initialize */
347 ULONG sigset;
349 kprintf("WAITING FOR SIGNAL\n");
351 sigset = Wait( params->ok_signal | params->fail_signal );
352 kprintf("GOT SIGNAL\n");
353 if (sigset & params->ok_signal) {
354 return task;
357 FreeMem(stack, INPUTTASK_STACKSIZE);
359 FreeMem(task,sizeof(struct Task));
361 return NULL;
364 struct Task *init_linuxinput_task(struct linux_staticdata *lsd)
366 struct inputtask_params p;
367 p.ok_signal = AllocSignal(-1L);
368 p.fail_signal = AllocSignal(-1L);
369 p.kill_signal = SIGBREAKF_CTRL_C;
370 p.lsd = lsd;
371 p.parent = FindTask(NULL);
373 kprintf("init_input_task: p.lsd = %p\n", p.lsd);
375 kprintf("SIGNALS ALLOCATED\n");
377 lsd->input_task = create_inputtask(&p, SysBase);
378 kprintf("INPUTTASK CREATED\n");
380 /* No need for these anymore */
381 FreeSignal(p.ok_signal);
382 FreeSignal(p.fail_signal);
384 return lsd->input_task;
387 VOID kill_linuxinput_task(struct linux_staticdata *lsd)
389 #warning This will not work since the task does not Wait() for this signal.
390 #warning Also we should wait for the child task to exit
391 Signal(lsd->input_task, SIGBREAKF_CTRL_C);