dos.library: Fix race condition caught by mungwall in CreateNewProc()
[AROS.git] / test / serialmousetest.c
blob15b13ea992cf973debb06e6076c8d3e640a66cac
1 #define DEBUG 1
2 #include <aros/debug.h>
4 #include <exec/memory.h>
5 #include <dos/dos.h>
6 #include <dos/exall.h>
7 #include <dos/datetime.h>
8 #include <proto/dos.h>
9 #include <proto/utility.h>
10 #include <utility/tagitem.h>
11 #include <utility/utility.h>
12 #include <devices/serial.h>
14 #include <proto/alib.h>
15 #include <proto/exec.h>
16 #include <proto/dos.h>
17 #include <proto/commodities.h>
19 #include <devices/serial.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
25 #define ARG_TEMPLATE "KILL/S,UNIT/N,PROBE/S"
27 enum
29 ARG_KILL = 0,
30 ARG_UNIT,
31 ARG_PROBE,
32 NOOFARGS
35 static UBYTE mousebuffer[3];
36 static ULONG bufptr;
39 struct mouse_action {
40 BYTE dx;
41 BYTE dy;
42 ULONG flags;
45 struct protocol {
46 const char * signature;
47 ULONG signature_length;
48 ULONG packet_length;
49 void (*handler)(char *, ULONG, struct mouse_action *);
50 const char * name;
55 * The following flags are defined:
57 #define MOUSE_LEFT_BUTTON 0x01
58 #define MOUSE_RIGHT_BUTTON 0x02
59 #define MOUSE_MIDDLE_BUTTON 0x04
61 #define MOUSE_DATA_VALID 0x8000
63 const char ms_mouse[] =
65 0x4d,0x40,0x00,
66 0x00,0x08,0x01,
67 0x24,0x30,0x2e,
68 0x30,0x10,0x26,
69 0x10,0x21,0x3c,
70 0x10,0x10,0x10,
71 0x15,0x10,0x12,
72 0x10,0x10,0x3c,
73 0x2d,0x2f,0x35,
74 0x33,0x25,0x3c,
75 0x30,0x2e,0x30,
76 0x10,0x26,0x10,
77 0x21,0x3c,0x2d,
78 0x29,0x23,0x32,
79 0x2f,0x33,0x2f,
80 0x26,0x34,0x00,
81 0x33,0x25,0x32,
82 0x29,0x21,0x2c,
83 0x00,0x2d,0x2f,
84 0x35,0x33,0x25,
85 0x00,0x12,0x0e,
86 0x11,0x21,0x15,
87 0x11,0x09
90 static void ms_mouse_protocol(char *, ULONG, struct mouse_action * );
94 * All known protocols and their handlers
96 const struct protocol protocols[] = {
97 {ms_mouse, sizeof(ms_mouse), 3, ms_mouse_protocol, "ms-mouse"},
98 {NULL , 0 , 0, NULL , NULL}
102 static struct NewBroker nb =
104 NB_VERSION,
105 NULL,
106 NULL,
107 NULL,
108 NBU_NOTIFY | NBU_UNIQUE,
111 NULL,
115 static CxObj * cxbroker;
120 static void ms_mouse_protocol(char * buffer,
121 ULONG len,
122 struct mouse_action * ma)
124 ULONG i = 0;
126 #if 1
127 ULONG j = 0;
128 while (j < len) {
129 printf("0x%02x,",buffer[j++]);
131 printf("\n");
132 #endif
134 while (len > 0) {
135 switch (bufptr) {
136 case 0:
137 case 1:
138 if (0 == (buffer[i] & 0x40)) {
139 mousebuffer[bufptr++] = buffer[i];
141 break;
143 case 2:
144 mousebuffer[bufptr] = buffer[i];
146 bufptr = 0;
148 if ((mousebuffer[2] & 0x40)) {
149 ma->flags = MOUSE_DATA_VALID;
150 if ((mousebuffer[2] & 0x20))
151 ma->flags |= MOUSE_LEFT_BUTTON;
152 if ((mousebuffer[2] & 0x10))
153 ma->flags |= MOUSE_RIGHT_BUTTON;
154 ma->dy = (mousebuffer[1] & 0x20)
155 ? (mousebuffer[1]-0x40)
156 : (mousebuffer[1]);
157 ma->dx = (mousebuffer[0] & 0x20)
158 ? (mousebuffer[0]-0x40)
159 : (mousebuffer[0]);
162 break;
164 default:
165 bufptr = 0;
167 i++;
168 len--;
172 static void check_mouse_action(struct mouse_action * old_action,
173 struct mouse_action * cur_action)
175 if (cur_action->flags & MOUSE_DATA_VALID &&
176 old_action->flags & MOUSE_DATA_VALID) {
178 * Check buttons
180 if (old_action->flags & MOUSE_LEFT_BUTTON) {
181 if (0 == (cur_action->flags & MOUSE_LEFT_BUTTON)) {
182 printf("Left mouse button released!\n");
184 } else
185 if (0 == (old_action->flags & MOUSE_LEFT_BUTTON)) {
186 if (cur_action->flags & MOUSE_LEFT_BUTTON) {
187 printf("Left mouse button pressed!\n");
191 if (old_action->flags & MOUSE_RIGHT_BUTTON) {
192 if (0 == (cur_action->flags & MOUSE_RIGHT_BUTTON)) {
193 printf("Right mouse button released!\n");
195 } else
196 if (0 == (old_action->flags & MOUSE_RIGHT_BUTTON)) {
197 if (cur_action->flags & MOUSE_RIGHT_BUTTON) {
198 printf("Right mouse button pressed!\n");
202 if (old_action->flags & MOUSE_MIDDLE_BUTTON) {
203 if (0 == (cur_action->flags & MOUSE_MIDDLE_BUTTON)) {
204 printf("Middle mouse button released!\n");
206 } else
207 if (0 == (old_action->flags & MOUSE_MIDDLE_BUTTON)) {
208 if (cur_action->flags & MOUSE_MIDDLE_BUTTON) {
209 printf("Middle mouse button pressed!\n");
213 if (cur_action->dx) {
214 printf("Mouse movement left/right: %d\n",cur_action->dx);
216 if (cur_action->dy) {
217 printf("Mouse movement up/down: %d\n",cur_action->dy);
222 static void read_input(struct IOExtSer * IORequest,
223 struct MsgPort * notifport,
224 struct MsgPort * cxport,
225 void (*handler)(char *, ULONG, struct mouse_action *))
227 struct mouse_action old_action, cur_action;
228 BOOL end = FALSE;
229 old_action.flags = 0;
230 cur_action.flags = 0;
231 int n = 3;
232 while (FALSE == end) {
233 BYTE buf[10];
234 struct Message * msg;
235 BOOL IODone = FALSE;
236 ULONG sigs;
237 ULONG cxsig = (NULL != cxport) ? (1 << cxport->mp_SigBit)
238 : 0;
240 memset(buf, 0x00, 10);
241 IORequest->IOSer.io_Command = CMD_READ;
242 IORequest->IOSer.io_Flags = IOF_QUICK;
243 IORequest->IOSer.io_Length = n;
244 IORequest->IOSer.io_Data = buf;
245 SendIO((struct IORequest *)IORequest);
246 sigs = Wait((1 << ((struct IORequest *)IORequest)->io_Message.mn_ReplyPort->mp_SigBit) |
247 (1 << notifport->mp_SigBit) |
248 cxsig |
249 SIGBREAKF_CTRL_C );
250 if (NULL != CheckIO((struct IORequest *)IORequest)) {
252 if (NULL == handler) {
253 printf("No handler given. Calling def. handler!\n");
254 ms_mouse_protocol(buf, n, &cur_action);
255 } else {
256 handler(buf, n, &cur_action);
259 check_mouse_action(&old_action, &cur_action);
261 if (cur_action.flags & MOUSE_DATA_VALID)
262 old_action = cur_action;
264 IODone = TRUE;
267 if (sigs & cxsig) {
268 CxMsg * cxmsg;
269 printf("Got a signal for me as commodity.\n");
270 while (NULL != (cxmsg = (CxMsg *)GetMsg(cxport))) {
271 switch (CxMsgType(cxmsg)) {
272 case CXM_COMMAND:
273 switch (CxMsgID(cxmsg)) {
274 case CXCMD_DISABLE:
275 ActivateCxObj(cxbroker, FALSE);
276 break;
278 case CXCMD_ENABLE:
279 ActivateCxObj(cxbroker, TRUE);
280 break;
282 case CXCMD_KILL:
283 end = TRUE;
284 break;
286 break;
288 ReplyMsg((struct Message *)cxmsg);
292 if (NULL != (msg = GetMsg(notifport))) {
293 printf("Serial mouse driver ends.\n");
294 if (FALSE == IODone)
295 AbortIO((struct IORequest *)IORequest);
296 FreeMem(msg, sizeof(struct Message));
297 end = TRUE;
300 if (sigs & SIGBREAKF_CTRL_C) {
301 end = TRUE;
303 } /* while (FALSE == end) */
304 } /* read_input */
307 static const struct protocol * probe_protocol(struct IOExtSer * IORequest, struct MsgPort * notifport)
309 const struct protocol * p = NULL;
310 ULONG n;
311 Delay(50);
312 printf("Supposed to probe for protocol!\n");
313 IORequest->IOSer.io_Command = SDCMD_QUERY;
314 DoIO((struct IORequest *)IORequest);
315 printf("Number of bytes in buffer: %d\n",(int)IORequest->IOSer.io_Actual);
316 if (0 != (n = IORequest->IOSer.io_Actual)) {
317 UBYTE * buffer = AllocMem(n, MEMF_CLEAR);
318 if (NULL != buffer) {
319 ULONG i = 0;
320 IORequest->IOSer.io_Command = CMD_READ;
321 IORequest->IOSer.io_Flags = IOF_QUICK;
322 IORequest->IOSer.io_Length = n;
323 IORequest->IOSer.io_Data = buffer;
324 DoIO((struct IORequest *)IORequest);
326 while (protocols[i].signature) {
327 printf("Possible: %s, sign_length=%ld\n",
328 protocols[i].name,
329 (long)protocols[i].signature_length);
331 if (n >= protocols[i].signature_length) {
332 ULONG d = n - protocols[i].signature_length;
333 ULONG k = 0;
334 while (k <= d) {
335 if (0 == memcmp(&buffer[k],
336 protocols[i].signature,
337 protocols[i].signature_length)) {
338 printf("Found signature for %s.\n",protocols[i].name);
339 p = &protocols[i];
340 break;
342 k++;
345 i++;
348 FreeMem(buffer, n);
351 return p;
354 static void mouse_driver(ULONG unit, BOOL probe_proto,struct MsgPort * notifport,struct MsgPort *cxport)
356 struct MsgPort * SerPort;
357 ULONG unitnum = unit;
359 SerPort = CreatePort(NULL,0);
360 if (NULL != SerPort) {
361 struct IOExtSer * IORequest;
362 IORequest = (struct IOExtSer *)CreateExtIO(SerPort, sizeof(struct IOExtSer));
363 if (NULL != IORequest) {
364 BYTE err = OpenDevice("serial.device", unitnum, (struct IORequest *)IORequest, 0);
365 if (0 == err) {
367 * Set parameters to read from mouse.
369 IORequest->IOSer.io_Command = SDCMD_SETPARAMS;
370 IORequest->io_Baud = 1200;
371 IORequest->io_ReadLen = 7;
372 IORequest->io_WriteLen = 7;
373 IORequest->io_StopBits = 1;
374 IORequest->io_RBufLen = 512;
375 IORequest->io_ExtFlags = 0;
376 IORequest->IOSer.io_Flags = 0;
377 DoIO((struct IORequest *)IORequest);
380 if (0 == ((struct IORequest *)IORequest)->io_Error) {
381 void (*handler) (char*,ULONG,struct mouse_action *) = NULL;
382 if (TRUE == probe_proto) {
383 const struct protocol * p;
384 p = probe_protocol(IORequest, notifport);
385 if (p) {
386 handler = p->handler;
387 } else {
388 printf("Could not detect mouse protocol!\n");
389 goto probe_fail;
392 read_input(IORequest, notifport, cxport, handler);
393 } else {
394 printf("Could not set parameters for serial port.\n");
395 printf("Error code: %d\n",((struct IORequest *)IORequest)->io_Error);
397 probe_fail:
398 CloseDevice((struct IORequest *)IORequest);
400 DeleteExtIO((struct IORequest *)IORequest);
402 DeletePort(SerPort);
408 static BOOL InitCommodity(void)
410 BOOL rc = FALSE;
412 if (NULL != CxBase) {
414 nb.nb_Name = strdup("Mouse Driver");
415 nb.nb_Title = strdup("Mouse Driver");
416 nb.nb_Descr = strdup("Mouse Driver for serial mice.");
418 if (NULL != (nb.nb_Port = CreateMsgPort())) {
419 if (NULL != (cxbroker = CxBroker(&nb, 0))) {
420 ActivateCxObj(cxbroker, TRUE);
421 rc = TRUE;
422 } else {
423 DeleteMsgPort(nb.nb_Port);
424 nb.nb_Port = NULL;
428 return rc;
432 static void CleanupCommodity(void)
434 if (NULL != CxBase) {
435 if (NULL != cxbroker)
436 DeleteCxObjAll(cxbroker);
437 if (NULL != nb.nb_Port) {
438 struct Message * msg;
439 while (NULL != (msg = GetMsg(nb.nb_Port))) {
440 ReplyMsg(msg);
442 DeleteMsgPort(nb.nb_Port);
443 nb.nb_Port = NULL;
448 #define MSGPORT_NAME "serial_mouse_driver"
450 int main(int argc, char **argv)
452 IPTR args[NOOFARGS] = {FALSE, // ARG_KILL
453 0, // ARG_UNIT
454 FALSE // ARG_PROBE
456 struct RDArgs *rda;
457 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
458 if (NULL != rda) {
459 if (TRUE == args[ARG_KILL]) {
460 struct MsgPort * mport = FindPort(MSGPORT_NAME);
461 if (NULL == mport) {
462 printf("Program seems not to be running. Cannot kill it.\n");
464 } else {
465 struct Message * msg = AllocMem(sizeof(struct Message), MEMF_CLEAR);
466 if (NULL != msg) {
468 * Just send a message to the port.
469 * The content does not matter so far.
471 PutMsg(mport, msg);
474 } else {
475 struct MsgPort * mport = FindPort(MSGPORT_NAME);
476 if (NULL != mport) {
477 printf("Program already running!\n");
478 } else {
479 BOOL have_cx = InitCommodity();
480 struct MsgPort * notifport = CreatePort(MSGPORT_NAME, 0);
481 if (NULL != notifport) {
482 mouse_driver(args[ARG_UNIT],
483 args[ARG_PROBE],
484 notifport,
485 nb.nb_Port);
486 DeletePort(notifport);
487 if (TRUE == have_cx) {
488 CleanupCommodity();
490 } else {
491 printf("Could not create notification port!\n");
495 FreeArgs(rda);
497 return 0;