Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / test / serialmousetest.c
blobd5096c88415f752181cbdfae4ffcfdfe7eed3772
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>
24 #include <memory.h>
26 #define ARG_TEMPLATE "KILL/S,UNIT/N,PROBE/S"
28 enum
30 ARG_KILL = 0,
31 ARG_UNIT,
32 ARG_PROBE,
33 NOOFARGS
36 static UBYTE mousebuffer[3];
37 static ULONG bufptr;
40 struct mouse_action {
41 BYTE dx;
42 BYTE dy;
43 ULONG flags;
46 struct protocol {
47 const char * signature;
48 ULONG signature_length;
49 ULONG packet_length;
50 void (*handler)(char *, ULONG, struct mouse_action *);
51 const char * name;
56 * The following flags are defined:
58 #define MOUSE_LEFT_BUTTON 0x01
59 #define MOUSE_RIGHT_BUTTON 0x02
60 #define MOUSE_MIDDLE_BUTTON 0x04
62 #define MOUSE_DATA_VALID 0x8000
64 const char ms_mouse[] =
66 0x4d,0x40,0x00,
67 0x00,0x08,0x01,
68 0x24,0x30,0x2e,
69 0x30,0x10,0x26,
70 0x10,0x21,0x3c,
71 0x10,0x10,0x10,
72 0x15,0x10,0x12,
73 0x10,0x10,0x3c,
74 0x2d,0x2f,0x35,
75 0x33,0x25,0x3c,
76 0x30,0x2e,0x30,
77 0x10,0x26,0x10,
78 0x21,0x3c,0x2d,
79 0x29,0x23,0x32,
80 0x2f,0x33,0x2f,
81 0x26,0x34,0x00,
82 0x33,0x25,0x32,
83 0x29,0x21,0x2c,
84 0x00,0x2d,0x2f,
85 0x35,0x33,0x25,
86 0x00,0x12,0x0e,
87 0x11,0x21,0x15,
88 0x11,0x09
91 static void ms_mouse_protocol(char *, ULONG, struct mouse_action * );
95 * All known protocols and their handlers
97 const struct protocol protocols[] = {
98 {ms_mouse, sizeof(ms_mouse), 3, ms_mouse_protocol, "ms-mouse"},
99 {NULL , 0 , 0, NULL , NULL}
103 static struct NewBroker nb =
105 NB_VERSION,
106 NULL,
107 NULL,
108 NULL,
109 NBU_NOTIFY | NBU_UNIQUE,
112 NULL,
116 static CxObj * cxbroker;
121 static void ms_mouse_protocol(char * buffer,
122 ULONG len,
123 struct mouse_action * ma)
125 ULONG i = 0;
127 #if 1
128 ULONG j = 0;
129 while (j < len) {
130 printf("0x%02x,",buffer[j++]);
132 printf("\n");
133 #endif
135 while (len > 0) {
136 switch (bufptr) {
137 case 0:
138 case 1:
139 if (0 == (buffer[i] & 0x40)) {
140 mousebuffer[bufptr++] = buffer[i];
142 break;
144 case 2:
145 mousebuffer[bufptr] = buffer[i];
147 bufptr = 0;
149 if ((mousebuffer[2] & 0x40)) {
150 ma->flags = MOUSE_DATA_VALID;
151 if ((mousebuffer[2] & 0x20))
152 ma->flags |= MOUSE_LEFT_BUTTON;
153 if ((mousebuffer[2] & 0x10))
154 ma->flags |= MOUSE_RIGHT_BUTTON;
155 ma->dy = (mousebuffer[1] & 0x20)
156 ? (mousebuffer[1]-0x40)
157 : (mousebuffer[1]);
158 ma->dx = (mousebuffer[0] & 0x20)
159 ? (mousebuffer[0]-0x40)
160 : (mousebuffer[0]);
163 break;
165 default:
166 bufptr = 0;
168 i++;
169 len--;
173 static void check_mouse_action(struct mouse_action * old_action,
174 struct mouse_action * cur_action)
176 if (cur_action->flags & MOUSE_DATA_VALID &&
177 old_action->flags & MOUSE_DATA_VALID) {
179 * Check buttons
181 if (old_action->flags & MOUSE_LEFT_BUTTON) {
182 if (0 == (cur_action->flags & MOUSE_LEFT_BUTTON)) {
183 printf("Left mouse button released!\n");
185 } else
186 if (0 == (old_action->flags & MOUSE_LEFT_BUTTON)) {
187 if (cur_action->flags & MOUSE_LEFT_BUTTON) {
188 printf("Left mouse button pressed!\n");
192 if (old_action->flags & MOUSE_RIGHT_BUTTON) {
193 if (0 == (cur_action->flags & MOUSE_RIGHT_BUTTON)) {
194 printf("Right mouse button released!\n");
196 } else
197 if (0 == (old_action->flags & MOUSE_RIGHT_BUTTON)) {
198 if (cur_action->flags & MOUSE_RIGHT_BUTTON) {
199 printf("Right mouse button pressed!\n");
203 if (old_action->flags & MOUSE_MIDDLE_BUTTON) {
204 if (0 == (cur_action->flags & MOUSE_MIDDLE_BUTTON)) {
205 printf("Middle mouse button released!\n");
207 } else
208 if (0 == (old_action->flags & MOUSE_MIDDLE_BUTTON)) {
209 if (cur_action->flags & MOUSE_MIDDLE_BUTTON) {
210 printf("Middle mouse button pressed!\n");
214 if (cur_action->dx) {
215 printf("Mouse movement left/right: %d\n",cur_action->dx);
217 if (cur_action->dy) {
218 printf("Mouse movement up/down: %d\n",cur_action->dy);
223 static void read_input(struct IOExtSer * IORequest,
224 struct MsgPort * notifport,
225 struct MsgPort * cxport,
226 void (*handler)(char *, ULONG, struct mouse_action *))
228 struct mouse_action old_action, cur_action;
229 BOOL end = FALSE;
230 old_action.flags = 0;
231 cur_action.flags = 0;
232 int n = 3;
233 while (FALSE == end) {
234 BYTE buf[10];
235 struct Message * msg;
236 BOOL IODone = FALSE;
237 ULONG sigs;
238 ULONG cxsig = (NULL != cxport) ? (1 << cxport->mp_SigBit)
239 : 0;
241 memset(buf, 0x00, 10);
242 IORequest->IOSer.io_Command = CMD_READ;
243 IORequest->IOSer.io_Flags = IOF_QUICK;
244 IORequest->IOSer.io_Length = n;
245 IORequest->IOSer.io_Data = buf;
246 SendIO((struct IORequest *)IORequest);
247 sigs = Wait((1 << ((struct IORequest *)IORequest)->io_Message.mn_ReplyPort->mp_SigBit) |
248 (1 << notifport->mp_SigBit) |
249 cxsig |
250 SIGBREAKF_CTRL_C );
251 if (NULL != CheckIO((struct IORequest *)IORequest)) {
253 if (NULL == handler) {
254 printf("No handler given. Calling def. handler!\n");
255 ms_mouse_protocol(buf, n, &cur_action);
256 } else {
257 handler(buf, n, &cur_action);
260 check_mouse_action(&old_action, &cur_action);
262 if (cur_action.flags & MOUSE_DATA_VALID)
263 old_action = cur_action;
265 IODone = TRUE;
268 if (sigs & cxsig) {
269 CxMsg * cxmsg;
270 printf("Got a signal for me as commodity.\n");
271 while (NULL != (cxmsg = (CxMsg *)GetMsg(cxport))) {
272 switch (CxMsgType(cxmsg)) {
273 case CXM_COMMAND:
274 switch (CxMsgID(cxmsg)) {
275 case CXCMD_DISABLE:
276 ActivateCxObj(cxbroker, FALSE);
277 break;
279 case CXCMD_ENABLE:
280 ActivateCxObj(cxbroker, TRUE);
281 break;
283 case CXCMD_KILL:
284 end = TRUE;
285 break;
287 break;
289 ReplyMsg((struct Message *)cxmsg);
293 if (NULL != (msg = GetMsg(notifport))) {
294 printf("Serial mouse driver ends.\n");
295 if (FALSE == IODone)
296 AbortIO((struct IORequest *)IORequest);
297 FreeMem(msg, sizeof(struct Message));
298 end = TRUE;
301 if (sigs & SIGBREAKF_CTRL_C) {
302 end = TRUE;
304 } /* while (FALSE == end) */
305 } /* read_input */
308 static const struct protocol * probe_protocol(struct IOExtSer * IORequest, struct MsgPort * notifport)
310 const struct protocol * p = NULL;
311 ULONG n;
312 Delay(50);
313 printf("Supposed to probe for protocol!\n");
314 IORequest->IOSer.io_Command = SDCMD_QUERY;
315 DoIO((struct IORequest *)IORequest);
316 printf("Number of bytes in buffer: %d\n",(int)IORequest->IOSer.io_Actual);
317 if (0 != (n = IORequest->IOSer.io_Actual)) {
318 UBYTE * buffer = AllocMem(n, MEMF_CLEAR);
319 if (NULL != buffer) {
320 ULONG i = 0;
321 IORequest->IOSer.io_Command = CMD_READ;
322 IORequest->IOSer.io_Flags = IOF_QUICK;
323 IORequest->IOSer.io_Length = n;
324 IORequest->IOSer.io_Data = buffer;
325 DoIO((struct IORequest *)IORequest);
327 while (protocols[i].signature) {
328 printf("Possible: %s, sign_length=%ld\n",
329 protocols[i].name,
330 (long)protocols[i].signature_length);
332 if (n >= protocols[i].signature_length) {
333 ULONG d = n - protocols[i].signature_length;
334 ULONG k = 0;
335 while (k <= d) {
336 if (0 == memcmp(&buffer[k],
337 protocols[i].signature,
338 protocols[i].signature_length)) {
339 printf("Found signature for %s.\n",protocols[i].name);
340 p = &protocols[i];
341 break;
343 k++;
346 i++;
349 FreeMem(buffer, n);
352 return p;
355 static void mouse_driver(ULONG unit, BOOL probe_proto,struct MsgPort * notifport,struct MsgPort *cxport)
357 struct MsgPort * SerPort;
358 ULONG unitnum = unit;
360 SerPort = CreatePort(NULL,0);
361 if (NULL != SerPort) {
362 struct IOExtSer * IORequest;
363 IORequest = (struct IOExtSer *)CreateExtIO(SerPort, sizeof(struct IOExtSer));
364 if (NULL != IORequest) {
365 BYTE err = OpenDevice("serial.device", unitnum, (struct IORequest *)IORequest, 0);
366 if (0 == err) {
368 * Set parameters to read from mouse.
370 IORequest->IOSer.io_Command = SDCMD_SETPARAMS;
371 IORequest->io_Baud = 1200;
372 IORequest->io_ReadLen = 7;
373 IORequest->io_WriteLen = 7;
374 IORequest->io_StopBits = 1;
375 IORequest->io_RBufLen = 512;
376 IORequest->io_ExtFlags = 0;
377 IORequest->IOSer.io_Flags = 0;
378 DoIO((struct IORequest *)IORequest);
381 if (0 == ((struct IORequest *)IORequest)->io_Error) {
382 void (*handler) (char*,ULONG,struct mouse_action *) = NULL;
383 if (TRUE == probe_proto) {
384 const struct protocol * p;
385 p = probe_protocol(IORequest, notifport);
386 if (p) {
387 handler = p->handler;
388 } else {
389 printf("Could not detect mouse protocol!\n");
390 goto probe_fail;
393 read_input(IORequest, notifport, cxport, handler);
394 } else {
395 printf("Could not set parameters for serial port.\n");
396 printf("Error code: %d\n",((struct IORequest *)IORequest)->io_Error);
398 probe_fail:
399 CloseDevice((struct IORequest *)IORequest);
401 DeleteExtIO((struct IORequest *)IORequest);
403 DeletePort(SerPort);
409 static BOOL InitCommodity(void)
411 BOOL rc = FALSE;
413 if (NULL != CxBase) {
415 nb.nb_Name = strdup("Mouse Driver");
416 nb.nb_Title = strdup("Mouse Driver");
417 nb.nb_Descr = strdup("Mouse Driver for serial mice.");
419 if (NULL != (nb.nb_Port = CreateMsgPort())) {
420 if (NULL != (cxbroker = CxBroker(&nb, 0))) {
421 ActivateCxObj(cxbroker, TRUE);
422 rc = TRUE;
423 } else {
424 DeleteMsgPort(nb.nb_Port);
425 nb.nb_Port = NULL;
429 return rc;
433 static void CleanupCommodity(void)
435 if (NULL != CxBase) {
436 if (NULL != cxbroker)
437 DeleteCxObjAll(cxbroker);
438 if (NULL != nb.nb_Port) {
439 struct Message * msg;
440 while (NULL != (msg = GetMsg(nb.nb_Port))) {
441 ReplyMsg(msg);
443 DeleteMsgPort(nb.nb_Port);
444 nb.nb_Port = NULL;
449 #define MSGPORT_NAME "serial_mouse_driver"
451 int main(int argc, char **argv)
453 IPTR args[NOOFARGS] = {FALSE, // ARG_KILL
454 0, // ARG_UNIT
455 FALSE // ARG_PROBE
457 struct RDArgs *rda;
458 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
459 if (NULL != rda) {
460 if (TRUE == args[ARG_KILL]) {
461 struct MsgPort * mport = FindPort(MSGPORT_NAME);
462 if (NULL == mport) {
463 printf("Program seems not to be running. Cannot kill it.\n");
465 } else {
466 struct Message * msg = AllocMem(sizeof(struct Message), MEMF_CLEAR);
467 if (NULL != msg) {
469 * Just send a message to the port.
470 * The content does not matter so far.
472 PutMsg(mport, msg);
475 } else {
476 struct MsgPort * mport = FindPort(MSGPORT_NAME);
477 if (NULL != mport) {
478 printf("Program already running!\n");
479 } else {
480 BOOL have_cx = InitCommodity();
481 struct MsgPort * notifport = CreatePort(MSGPORT_NAME, 0);
482 if (NULL != notifport) {
483 mouse_driver(args[ARG_UNIT],
484 args[ARG_PROBE],
485 notifport,
486 nb.nb_Port);
487 DeletePort(notifport);
488 if (TRUE == have_cx) {
489 CleanupCommodity();
491 } else {
492 printf("Could not create notification port!\n");
496 FreeArgs(rda);
498 return 0;