2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
8 #include <aros/debug.h>
9 #include <exec/alerts.h>
10 #include <devices/inputevent.h>
11 #include <hidd/mouse.h>
12 #include <hidd/unixio.h>
14 #include <proto/exec.h>
16 #include <android/keycodes.h>
18 #include "androidgfx_hidd.h"
19 #include "android_keyboard.h"
20 #include "android_mouse.h"
21 #include "android_server.h"
24 #define XSD(x) ((struct agfx_staticdata *)x)
28 * In this code every pipe error causes instant shutdown.
29 * This is intentional because error likely means broken pipe. This can happen
30 * if the parent process (bootstrap) exited. In this case we should immediately exit too,
31 * otherwise we end up in AROS process running out of any control. On non-rooted phone
32 * it can be shut down only by rebooting the phone.
35 static void ReadPipe(int pipe
, void *data
, int len
, struct agfx_staticdata
*xsd
)
40 res
= Hidd_UnixIO_ReadFile(xsd
->unixio
, pipe
, data
, len
, &err
);
43 D(bug("[AGFX.server] Error reading pipe. Wanted %d bytes, got %d, error %d\n", len
, res
, err
));
44 ShutdownA(SD_ACTION_POWEROFF
);
48 void agfxInt(int pipe
, int mode
, void *data
)
50 while (mode
& (vHidd_UnixIO_Read
| vHidd_UnixIO_Error
))
52 struct Request header
;
53 struct PointerEvent e
;
55 ULONG status
= STATUS_ACK
;
57 DB2(bug("[AGFX.server] Event 0x%08X on pipe %d\n", mode
, pipe
));
59 if (mode
& vHidd_UnixIO_Error
)
61 D(bug("[AGFX.server] Error condition on input pipe\n"));
62 ShutdownA(SD_ACTION_POWEROFF
);
65 /* First read packet header */
66 ReadPipe(pipe
, &header
, sizeof(header
), data
);
67 DB2(bug("[AGFX.server] Command 0x%08X with %u parameters from server\n", header
.cmd
, header
.len
));
69 if (header
.cmd
== cmd_Nak
)
72 * Special handling for NAK reply.
73 * We know it has one parameter - original command.
75 ReadPipe(pipe
, &header
.cmd
, sizeof(ULONG
), data
);
77 D(bug("[AGFX.server] NAK %d received\n", header
.cmd
));
81 if (header
.cmd
& CMD_NEED_REPLY
)
83 /* A WaitRequest is being replied */
84 if (!IsListEmpty(&XSD(data
)->waitQueue
))
86 struct WaitRequest
*request
= (struct WaitRequest
*)XSD(data
)->waitQueue
.mlh_Head
;
88 if (request
->cmd
== header
.cmd
)
90 if (header
.len
&& (status
== STATUS_ACK
))
92 ULONG
*pkt
= &request
->cmd
;
94 /* Read reply parameters */
95 ReadPipe(pipe
, &pkt
[request
->len
+ 2], header
.len
* sizeof(ULONG
), data
);
98 DB2(bug("[AGFX.server] Replying request 0x%p\n", request
));
100 Remove((struct Node
*)request
);
101 request
->status
= status
;
102 Signal(request
->owner
, request
->signal
);
104 /* We have read the data */
107 D(else bug("[AGFX.server] Bogus reply 0x%08X for request 0x%08X\n", header
.cmd
, request
->cmd
);)
109 D(else bug("[AGFX.server] Bogus reply 0x%08X without a request\n", header
.cmd
);)
115 ReadPipe(pipe
, &e
, sizeof(e
), data
);
117 if (XSD(data
)->mousehidd
)
118 AMouse_ReportEvent(XSD(data
)->mousehidd
, &e
);
123 ReadPipe(pipe
, &e
, sizeof(e
), data
);
125 if (XSD(data
)->mousehidd
)
126 AMouse_ReportTouch(XSD(data
)->mousehidd
, &e
);
131 ReadPipe(pipe
, &ke
, sizeof(ke
), data
);
136 /* MENU key emulates right mouse button */
137 if (XSD(data
)->mousehidd
)
138 AMouse_ReportButton(XSD(data
)->mousehidd
, vHidd_Mouse_Button2
, (ke
.flags
& IECODE_UP_PREFIX
) ? vHidd_Mouse_Release
: vHidd_Mouse_Press
);
142 if (XSD(data
)->kbdhidd
)
143 AKbd_ReportKey(XSD(data
)->kbdhidd
, &ke
);
150 * TODO: Process cmd_Flush() here.
151 * It's not a good idea to call AllocMem() from within an interrupt,
152 * so we need to delegate this to some task.
157 * If we are here, we haven't read the data portion.
158 * This is either unknown command or bogus response.
159 * We don't know what to do with arguments, so just swallow them.
161 for (status
= 0; status
< header
.len
; status
++)
162 ReadPipe(pipe
, &header
.cmd
, sizeof(ULONG
), data
);
168 * Poll the pipe and repeat if still ready.
169 * This has to be done if commands are sent too quickly.
170 * We won't get a second SIGIO while we are here.
172 mode
= Hidd_UnixIO_Poll(XSD(data
)->unixio
, pipe
, vHidd_UnixIO_Read
, NULL
);
176 void SendRequest(struct Request
*req
, struct agfx_staticdata
*xsd
)
178 /* Total packet length is header plus specified number of ULONG parameters */
179 int len
= sizeof(struct Request
) + req
->len
* sizeof(ULONG
);
182 res
= Hidd_UnixIO_WriteFile(xsd
->unixio
, xsd
->DisplayPipe
, req
, len
, &err
);
185 D(bug("[AGFX.server] Error writing pipe. Wanted %d bytes, wrote %d, error %d\n", len
, res
, err
));
186 ShutdownA(SD_ACTION_POWEROFF
);
190 void DoRequest(struct WaitRequest
*req
, struct agfx_staticdata
*xsd
)
194 * Limitation: one task can have only one request pending. But
195 * it's faster than CreateMsgPort() every time.
197 req
->owner
= FindTask(NULL
);
198 req
->signal
= SIGF_BLIT
;
200 /* Add the request to the wait queue */
202 AddTail((struct List
*)&xsd
->waitQueue
, (struct Node
*)req
);
205 /* Make sure the signal isn't already set */
206 SetSignal(0, SIGF_BLIT
);
208 /* Actually send the request */
209 SendRequest((struct Request
*)&req
->cmd
, xsd
);