unixio.hidd: Move to autogenerated interface includes
[AROS.git] / arch / all-android / hidd / androidgfx / server.c
blob64cc5cf101b1c179581f9dca005674344269ea67
1 #define DEBUG 1
3 #include <aros/debug.h>
4 #include <exec/alerts.h>
5 #include <devices/inputevent.h>
6 #include <hidd/mouse.h>
7 #include <hidd/unixio.h>
9 #include <proto/exec.h>
11 #include <android/keycodes.h>
13 #include "agfx.h"
14 #include "agfx_keyboard.h"
15 #include "agfx_mouse.h"
16 #include "server.h"
18 #undef XSD
19 #define XSD(x) ((struct agfx_staticdata *)x)
22 * WARNING!
23 * In this code every pipe error causes instant shutdown.
24 * This is intentional because error likely means broken pipe. This can happen
25 * if the parent process (bootstrap) exited. In this case we should immediately exit too,
26 * otherwise we end up in AROS process running out of any control. On non-rooted phone
27 * it can be shut down only by rebooting the phone.
30 static void ReadPipe(int pipe, void *data, int len, struct agfx_staticdata *xsd)
32 int res;
33 int err;
35 res = Hidd_UnixIO_ReadFile(xsd->unixio, pipe, data, len, &err);
36 if (res != len)
38 D(bug("[AGFX.server] Error reading pipe. Wanted %d bytes, got %d, error %d\n", len, res, err));
39 ShutdownA(SD_ACTION_POWEROFF);
43 void agfxInt(int pipe, int mode, void *data)
45 while (mode & (vHidd_UnixIO_Read | vHidd_UnixIO_Error))
47 struct Request header;
48 struct PointerEvent e;
49 struct KeyEvent ke;
50 ULONG status = STATUS_ACK;
52 DB2(bug("[AGFX.server] Event 0x%08X on pipe %d\n", mode, pipe));
54 if (mode & vHidd_UnixIO_Error)
56 D(bug("[AGFX.server] Error condition on input pipe\n"));
57 ShutdownA(SD_ACTION_POWEROFF);
60 /* First read packet header */
61 ReadPipe(pipe, &header, sizeof(header), data);
62 DB2(bug("[AGFX.server] Command 0x%08X with %u parameters from server\n", header.cmd, header.len));
64 if (header.cmd == cmd_Nak)
67 * Special handling for NAK reply.
68 * We know it has one parameter - original command.
70 ReadPipe(pipe, &header.cmd, sizeof(ULONG), data);
72 D(bug("[AGFX.server] NAK %d received\n", header.cmd));
73 status = STATUS_NAK;
76 if (header.cmd & CMD_NEED_REPLY)
78 /* A WaitRequest is being replied */
79 if (!IsListEmpty(&XSD(data)->waitQueue))
81 struct WaitRequest *request = (struct WaitRequest *)XSD(data)->waitQueue.mlh_Head;
83 if (request->cmd == header.cmd)
85 if (header.len && (status == STATUS_ACK))
87 ULONG *pkt = &request->cmd;
89 /* Read reply parameters */
90 ReadPipe(pipe, &pkt[request->len + 2], header.len * sizeof(ULONG), data);
93 DB2(bug("[AGFX.server] Replying request 0x%p\n", request));
95 Remove((struct Node *)request);
96 request->status = status;
97 Signal(request->owner, request->signal);
99 /* We have read the data */
100 header.len = 0;
102 D(else bug("[AGFX.server] Bogus reply 0x%08X for request 0x%08X\n", header.cmd, request->cmd);)
104 D(else bug("[AGFX.server] Bogus reply 0x%08X without a request\n", header.cmd);)
107 switch (header.cmd)
109 case cmd_Mouse:
110 ReadPipe(pipe, &e, sizeof(e), data);
112 if (XSD(data)->mousehidd)
113 AMouse_ReportEvent(XSD(data)->mousehidd, &e);
115 break;
117 case cmd_Touch:
118 ReadPipe(pipe, &e, sizeof(e), data);
120 if (XSD(data)->mousehidd)
121 AMouse_ReportTouch(XSD(data)->mousehidd, &e);
123 break;
125 case cmd_Key:
126 ReadPipe(pipe, &ke, sizeof(ke), data);
128 switch (ke.code)
130 case AKEYCODE_MENU:
131 /* MENU key emulates right mouse button */
132 if (XSD(data)->mousehidd)
133 AMouse_ReportButton(XSD(data)->mousehidd, vHidd_Mouse_Button2, (ke.flags & IECODE_UP_PREFIX) ? vHidd_Mouse_Release : vHidd_Mouse_Press);
134 break;
136 default:
137 if (XSD(data)->kbdhidd)
138 AKbd_ReportKey(XSD(data)->kbdhidd, &ke);
139 break;
142 break;
145 * TODO: Process cmd_Flush() here.
146 * It's not a good idea to call AllocMem() from within an interrupt,
147 * so we need to delegate this to some task.
150 default:
152 * If we are here, we haven't read the data portion.
153 * This is either unknown command or bogus response.
154 * We don't know what to do with arguments, so just swallow them.
156 for (status = 0; status < header.len; status++)
157 ReadPipe(pipe, &header.cmd, sizeof(ULONG), data);
159 break;
163 * Poll the pipe and repeat if still ready.
164 * This has to be done if commands are sent too quickly.
165 * We won't get a second SIGIO while we are here.
167 mode = Hidd_UnixIO_Poll(XSD(data)->unixio, pipe, vHidd_UnixIO_Read, NULL);
171 void SendRequest(struct Request *req, struct agfx_staticdata *xsd)
173 /* Total packet length is header plus specified number of ULONG parameters */
174 int len = sizeof(struct Request) + req->len * sizeof(ULONG);
175 int res, err;
177 res = Hidd_UnixIO_WriteFile(xsd->unixio, xsd->DisplayPipe, req, len, &err);
178 if (res != len)
180 D(bug("[AGFX.server] Error writing pipe. Wanted %d bytes, wrote %d, error %d\n", len, res, err));
181 ShutdownA(SD_ACTION_POWEROFF);
185 void DoRequest(struct WaitRequest *req, struct agfx_staticdata *xsd)
188 * Set request owner.
189 * Limitation: one task can have only one request pending. But
190 * it's faster than CreateMsgPort() every time.
192 req->owner = FindTask(NULL);
193 req->signal = SIGF_BLIT;
195 /* Add the request to the wait queue */
196 Disable();
197 AddTail((struct List *)&xsd->waitQueue, (struct Node *)req);
198 Enable();
200 /* Make sure the signal isn't already set */
201 SetSignal(0, SIGF_BLIT);
203 /* Actually send the request */
204 SendRequest((struct Request *)&req->cmd, xsd);
206 /* Wait for reply */
207 Wait(SIGF_BLIT);