wip prep commit in lieu of gfx subsystem update changes.
[AROS.git] / arch / all-android / hidd / androidgfx / android_server.c
blobfd3d96843ed009f7b4e0e2069aa24c507788f6f6
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
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"
23 #undef XSD
24 #define XSD(x) ((struct agfx_staticdata *)x)
27 * WARNING!
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)
37 int res;
38 int err;
40 res = Hidd_UnixIO_ReadFile(xsd->unixio, pipe, data, len, &err);
41 if (res != len)
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;
54 struct KeyEvent ke;
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));
78 status = STATUS_NAK;
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 */
105 header.len = 0;
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);)
112 switch (header.cmd)
114 case cmd_Mouse:
115 ReadPipe(pipe, &e, sizeof(e), data);
117 if (XSD(data)->mousehidd)
118 AMouse_ReportEvent(XSD(data)->mousehidd, &e);
120 break;
122 case cmd_Touch:
123 ReadPipe(pipe, &e, sizeof(e), data);
125 if (XSD(data)->mousehidd)
126 AMouse_ReportTouch(XSD(data)->mousehidd, &e);
128 break;
130 case cmd_Key:
131 ReadPipe(pipe, &ke, sizeof(ke), data);
133 switch (ke.code)
135 case AKEYCODE_MENU:
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);
139 break;
141 default:
142 if (XSD(data)->kbdhidd)
143 AKbd_ReportKey(XSD(data)->kbdhidd, &ke);
144 break;
147 break;
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.
155 default:
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);
164 break;
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);
180 int res, err;
182 res = Hidd_UnixIO_WriteFile(xsd->unixio, xsd->DisplayPipe, req, len, &err);
183 if (res != len)
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)
193 * Set request owner.
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 */
201 Disable();
202 AddTail((struct List *)&xsd->waitQueue, (struct Node *)req);
203 Enable();
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);
211 /* Wait for reply */
212 Wait(SIGF_BLIT);