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>
14 #include "agfx_keyboard.h"
15 #include "agfx_mouse.h"
19 #define XSD(x) ((struct agfx_staticdata *)x)
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
)
35 res
= Hidd_UnixIO_ReadFile(xsd
->unixio
, pipe
, data
, len
, &err
);
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
;
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
));
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 */
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
);)
110 ReadPipe(pipe
, &e
, sizeof(e
), data
);
112 if (XSD(data
)->mousehidd
)
113 AMouse_ReportEvent(XSD(data
)->mousehidd
, &e
);
118 ReadPipe(pipe
, &e
, sizeof(e
), data
);
120 if (XSD(data
)->mousehidd
)
121 AMouse_ReportTouch(XSD(data
)->mousehidd
, &e
);
126 ReadPipe(pipe
, &ke
, sizeof(ke
), data
);
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
);
137 if (XSD(data
)->kbdhidd
)
138 AKbd_ReportKey(XSD(data
)->kbdhidd
, &ke
);
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.
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
);
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
);
177 res
= Hidd_UnixIO_WriteFile(xsd
->unixio
, xsd
->DisplayPipe
, req
, len
, &err
);
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
)
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 */
197 AddTail((struct List
*)&xsd
->waitQueue
, (struct Node
*)req
);
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
);