Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / hidds / mouse / mouseclass.c
blob150ca0bcc4e26acaf1589a8623d19e8677f9e651
1 /*
2 Copyright (C) 2004-2010, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define __OOP_NOATTRBASES__
8 #include <aros/debug.h>
9 #include <aros/symbolsets.h>
10 #include <oop/oop.h>
11 #include <utility/tagitem.h>
12 #include <proto/alib.h>
13 #include <proto/exec.h>
14 #include <proto/utility.h>
15 #include <proto/oop.h>
17 #include LC_LIBDEFS_FILE
19 #undef HiddMouseAB
20 #define HiddMouseAB (CSD(cl)->hiddMouseAB)
22 #include <hidd/mouse.h>
24 /*****************************************************************************************
26 NAME
27 --background--
29 LOCATION
30 CLID_Hidd_Mouse
32 NOTES
33 This class represents a "hub" for collecting input from various
34 pointing devices (mice, tablets, touchscreens, etc) in the
35 system and sending them to clients.
37 In order to get an access to pointing input subsystem you need to
38 create an object of CLID_Hidd_Mouse class. There can be two use
39 scenarios: driver mode and client mode.
41 If you wish to run in client mode (receive pointing events), you
42 have to supply a callback using aoHidd_Mouse_IrqHandler attribute.
43 After this your callback will be called every time the event arrives
44 until you dispose your object.
46 Events from all pointing devices are merged into a single stream
47 and propagated to all clients.
49 In driver mode you don't need to supply a callback (however it's not
50 forbidden). Instead you use the master object for registering your
51 hardware driver using HIDD_Mouse_AddHardwareDriver(). It is safe to
52 dispose the master object after adding a driver, the driver will
53 be internally kept in place.
54 *****************************************************************************************/
56 /*****************************************************************************************
58 NAME
59 --hardware_drivers--
61 LOCATION
62 CLID_Hidd_Mouse
64 NOTES
65 A hardware driver should implement the same interface according to the following
66 rules:
68 1. A single object of driver class represents a single hardware unit.
69 2. A single driver object maintains a single callback address (passed to it
70 using aoHidd_Mouse_IrqHandler). Under normal conditions this callback is supplied
71 by CLID_Hidd_Mouse class.
72 3. HIDD_Mouse_AddHardwareDriver() and HIDD_Mouse_RemHardwareDriver() on a driver object
73 itself do not make sense, so there's no need to implement them.
75 A hardware driver class should be a subclass of CLID_Hidd in order to ensure
76 compatibility in future.
78 *****************************************************************************************/
81 static void GlobalCallback(struct driverNode *drv, struct pHidd_Mouse_ExtEvent *ev)
83 struct pHidd_Mouse_ExtEvent xev;
84 struct mouse_data *data;
86 /* The event passed in may be pHidd_Mouse_Event instead of pHidd_Mouse_ExtEvent,
87 according to flags. In this case we add own flags */
88 if (drv->flags != vHidd_Mouse_Extended) {
89 xev.button = ev->button;
90 xev.x = ev->x;
91 xev.y = ev->y;
92 xev.type = ev->type;
93 xev.flags = drv->flags;
95 ev = &xev;
98 for (data = (struct mouse_data *)drv->callbacks->mlh_Head; data->node.mln_Succ;
99 data = (struct mouse_data *)data->node.mln_Succ)
100 data->callback(data->callbackdata, ev);
103 /*****************************************************************************************
105 NAME
106 aoHidd_Mouse_IrqHandler
108 SYNOPSIS
109 [I..], APTR
111 LOCATION
112 CLID_Hidd_Mouse
114 FUNCTION
115 Specifies a pointing device interrupt handler. The handler will called be every time a
116 keyboard event happens. A "C" calling convention is used, declare the handler
117 functions as follows:
119 void MouseIRQ(APTR data, struct pHidd_Mouse_Event *event);
121 Handler parameters are:
122 data - Anything you specify using aoHidd_Mouse_IrqHandlerData
123 event - A pointer to a read-only event descriptor structure with the following
124 contents:
125 button - button code, or vHidd_Mouse_NoButton of the event describes a simple
126 motion.
127 x, y - event coordinates. Need to be always valid, even if the event describes
128 a button pressed without actual motion.
129 In case of mouse wheel event these fields specify horizontal and vertical
130 wheel delta respectively.
131 type - type of event (button press, button release, wheel or motion).
132 flags - event flags. Currently only one value of vHidd_Mouse_Relative is defined.
133 If this flag is not set, coordinates are assumed to be absolute.
134 This member is actually present in the structure only if the driver
135 supplies TRUE value for aoHidd_Mouse_Extended attribute.
137 The handler is called inside interrupts, so usual restrictions apply to it.
139 NOTES
140 CLID_Hidd_Mouse class always provides extended form of event structure
141 (struct pHidd_Mouse_ExtEvent). Drivers will not always provide it, depending
142 on their aoHidd_Mouse_Extended attribute value.
144 EXAMPLE
146 BUGS
147 CLID_Hidd_Mouse and some hardware driver classes allow to get value of this attribute,
148 however there is currently no use for it. The attribute is considered non-getable.
150 SEE ALSO
151 aoHidd_Mouse_IrqHandlerData, aoHidd_Mouse_Extended
153 INTERNALS
155 *****************************************************************************************/
157 /*****************************************************************************************
159 NAME
160 aoHidd_Mouse_IrqHandlerData
162 SYNOPSIS
163 [I..], APTR
165 LOCATION
166 CLID_Hidd_Mouse
168 FUNCTION
169 Specifies a user-defined value that will be passed to interrupt handler as a first
170 parameter. The purpose of this is to pass some static data to the handler.
171 The system will not assume anything about this value.
173 Defaults to NULL if not specified.
175 NOTES
177 EXAMPLE
179 BUGS
180 CLID_Hidd_Mouse and some hardware driver classes allow to get value of this attribute,
181 however there is currently no use for it. The attribute is considered non-getable.
183 SEE ALSO
184 aoHidd_Mouse_IrqHandler
186 INTERNALS
188 *****************************************************************************************/
190 /*****************************************************************************************
192 NAME
193 aoHidd_Mouse_State
195 SYNOPSIS
196 [..G], struct pHidd_Mouse_Event
198 LOCATION
199 CLID_Hidd_Mouse
201 FUNCTION
202 Obtains current pointing devices state.
204 This attribute was historically implemented only in PS/2 mouse driver, but the
205 implementation was broken and incomplete. At the moment this attribute is considered
206 reserved. Do not use it, the specification may change in future.
208 NOTES
210 EXAMPLE
212 BUGS
213 Not implemented, considered reserved.
215 SEE ALSO
217 INTERNALS
219 *****************************************************************************************/
221 /*****************************************************************************************
223 NAME
224 aoHidd_Mouse_RelativeCoords
226 SYNOPSIS
227 [..G], BOOL
229 LOCATION
230 CLID_Hidd_Mouse
232 FUNCTION
233 Asks the driver it the device provides relative (like mouse) or absolute (like
234 touchscreen or tabled) coordinates.
236 Drivers which provide extended event structure may not implement this attribute
237 because they may provide mixed set of events. In this case coordinates type
238 is determined by flags member of struct pHidd_Mouse_ExtEvent.
240 CLID_Hidd_Mouse class does not implement this attribute since it provides mixed
241 stream of events.
243 NOTES
245 EXAMPLE
247 BUGS
249 SEE ALSO
250 aoHidd_Mouse_IrqHandler, aoHidd_Mouse_Extended
252 INTERNALS
254 *****************************************************************************************/
256 /*****************************************************************************************
258 NAME
259 aoHidd_Mouse_Extended
261 SYNOPSIS
262 [..G], BOOL
264 LOCATION
265 CLID_Hidd_Mouse
267 FUNCTION
268 Asks the driver if it provides extended event descriptor structure
269 (struct pHidd_Mouse_ExtEvent).
271 If value of this attribute is FALSE, the flags member is actually missing from
272 the structure, not just zeroed out! So do not use it at all in this case.
274 NOTES
276 EXAMPLE
278 BUGS
280 SEE ALSO
281 aoHidd_Mouse_IrqHandler
283 INTERNALS
285 ******************************************************************************************/
287 OOP_Object *Mouse__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
289 struct mouse_data *data;
290 struct TagItem *tag, *tstate;
292 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
293 if (!o)
294 return NULL;
296 data = OOP_INST_DATA(cl, o);
297 data->callback = NULL;
298 data->callbackdata = NULL;
300 tstate = msg->attrList;
301 D(bug("tstate: %p\n", tstate));
303 while ((tag = NextTagItem((const struct TagItem **)&tstate)))
305 ULONG idx;
307 D(bug("Got tag %d, data %x\n", tag->ti_Tag, tag->ti_Data));
309 if (IS_HIDDMOUSE_ATTR(tag->ti_Tag, idx))
311 D(bug("Mouse hidd tag\n"));
312 switch (idx)
314 case aoHidd_Mouse_IrqHandler:
315 data->callback = (APTR)tag->ti_Data;
316 D(bug("Got callback %p\n", (APTR)tag->ti_Data));
317 break;
319 case aoHidd_Mouse_IrqHandlerData:
320 data->callbackdata = (APTR)tag->ti_Data;
321 D(bug("Got data %p\n", (APTR)tag->ti_Data));
322 break;
325 } /* while (tags to process) */
327 /* Add to interrupts list if we have a callback */
328 if (data->callback) {
329 Disable();
330 AddTail((struct List *)&CSD(cl)->callbacks, (struct Node *)data);
331 Enable();
334 return o;
337 VOID Mouse__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
339 struct mouse_data *data = OOP_INST_DATA(cl, o);
341 if (data->callback) {
342 Disable();
343 Remove((struct Node *)data);
344 Enable();
346 OOP_DoSuperMethod(cl, o, msg);
349 VOID Mouse__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
351 struct mouse_data *data = OOP_INST_DATA(cl, o);
352 ULONG idx;
354 if (IS_HIDDMOUSE_ATTR(msg->attrID, idx))
356 switch (idx)
358 case aoHidd_Mouse_IrqHandler:
359 *msg->storage = (IPTR)data->callback;
360 return;
362 case aoHidd_Mouse_IrqHandlerData:
363 *msg->storage = (IPTR)data->callbackdata;
364 return;
366 /* case aoHidd_Mouse_State:
368 TODO: Implement this, by ORing buttons from all registered mice (?)
370 return;*/
372 case aoHidd_Mouse_Extended:
373 *msg->storage = TRUE;
374 return;
378 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
382 * In future we could support enumeration of devices and specifying
383 * which device we wish to read events from (in case if we want to implement
384 * amigainput.library or something like it)
387 /*****************************************************************************************
389 NAME
390 moHidd_Mouse_AddHardwareDriver
392 SYNOPSIS
393 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Mouse_AddHardwareDriver *Msg);
395 OOP_Object *HIDD_Mouse_AddHardwareDriver(OOP_Object *obj, OOP_Class *driverClass, struct TagItem *tags)
397 LOCATION
398 CLID_Hidd_Mouse
400 FUNCTION
401 Creates a hardware driver object and registers it in the system.
403 It does not matter on which instance of CLID_Hidd_Mouse class this method is
404 used. Hardware driver objects are shared between all of them.
406 INPUTS
407 obj - Any object of CLID_Hidd_Mouse class.
408 driverClass - A pointer to OOP class of the driver. In order to create an object
409 of some previously registered public class, use
410 oop.library/OOP_FindClass().
411 tags - An optional taglist which will be passed to driver class' New() method.
413 RESULT
414 A pointer to driver object.
416 NOTES
417 Do not dispose the returned object yourself, use HIDD_Mouse_RemHardwareDriver() for it.
419 EXAMPLE
421 BUGS
423 SEE ALSO
424 moHidd_Mouse_RemHardwareDriver
426 INTERNALS
427 This method supplies own interrupt handler to the driver, do not override this.
429 *****************************************************************************************/
431 OOP_Object *Mouse__Hidd_Mouse__AddHardwareDriver(OOP_Class *cl, OOP_Object *o, struct pHidd_Mouse_AddHardwareDriver *Msg)
433 struct TagItem tags[] = {
434 { aHidd_Mouse_IrqHandler , (IPTR)GlobalCallback},
435 { aHidd_Mouse_IrqHandlerData, 0 },
436 { TAG_MORE , (IPTR)Msg->tags }
438 struct driverNode *drvnode;
440 D(bug("[Mouse] AddHardwareDriver(0x%p)\n", Msg->driverClass));
442 drvnode = AllocMem(sizeof(struct driverNode), MEMF_PUBLIC);
443 if (!drvnode)
444 return NULL;
446 tags[1].ti_Data = (IPTR)drvnode;
447 drvnode->drv = OOP_NewObject(Msg->driverClass, NULL, tags);
448 D(bug("[Mouse] Driver node 0x%p, driver 0x%p\n", drvnode, drvnode->drv));
450 if (drvnode->drv) {
451 struct mouse_staticdata *csd = CSD(cl);
452 IPTR val = FALSE;
454 drvnode->callbacks = &csd->callbacks;
456 OOP_GetAttr(drvnode->drv, aHidd_Mouse_Extended, &val);
457 D(bug("[Mouse] Extended event: %d\n", val));
458 if (val)
459 drvnode->flags = vHidd_Mouse_Extended;
460 else
462 OOP_GetAttr(drvnode->drv, aHidd_Mouse_RelativeCoords, &val);
463 D(bug("[Mouse] Relative coordinates: %d\n", val));
464 drvnode->flags = val ? vHidd_Mouse_Relative : 0;
467 ObtainSemaphore(&csd->drivers_sem);
468 AddTail((struct List *)&csd->drivers, (struct Node *)drvnode);
469 ReleaseSemaphore(&csd->drivers_sem);
471 return drvnode->drv;
474 FreeMem(drvnode, sizeof(struct driverNode));
475 return NULL;
478 /*****************************************************************************************
480 NAME
481 moHidd_Mouse_RemHardwareDriver
483 SYNOPSIS
484 void OOP_DoMethod(OOP_Object *obj, struct pHidd_Mouse_RemHardwareDriver *Msg);
486 void HIDD_Mouse_RemHardwareDriver(OOP_Object *obj, OOP_Object *driver);
488 LOCATION
489 CLID_Hidd_Mouse
491 FUNCTION
492 Unregisters and disposes pointing device hardware driver object.
494 It does not matter on which instance of CLID_Hidd_Mouse class this method is
495 used. Hardware driver objects are shared between all of them.
497 INPUTS
498 obj - Any object of CLID_Hidd_Mouse class.
499 driver - A pointer to a driver object, returned by HIDD_Mouse_AddHardwareDriver().
501 RESULT
502 None
504 NOTES
506 EXAMPLE
508 BUGS
510 SEE ALSO
511 moHidd_Mouse_AddHardwareDriver
513 INTERNALS
515 *****************************************************************************************/
517 void Mouse__Hidd_Mouse__RemHardwareDriver(OOP_Class *cl, OOP_Object *o, struct pHidd_Mouse_RemHardwareDriver *Msg)
519 struct mouse_staticdata *csd = CSD(cl);
520 struct driverNode *node;
522 ObtainSemaphore(&csd->drivers_sem);
524 for (node = (struct driverNode *)csd->drivers.mlh_Head; node->node.mln_Succ;
525 node = (struct driverNode *)node->node.mln_Succ) {
526 if (node->drv == Msg->driverObject) {
527 Remove((struct Node *)node);
528 break;
532 ReleaseSemaphore(&csd->drivers_sem);
534 OOP_DisposeObject(Msg->driverObject);
536 if (node->drv == Msg->driverObject)
537 FreeMem(node, sizeof(struct driverNode));
540 /* Class initialization and destruction */
542 static int Mouse_ExpungeClass(LIBBASETYPEPTR LIBBASE)
544 D(bug("[Mouse] Base Class destruction\n"));
546 OOP_ReleaseAttrBase(IID_Hidd_Mouse);
548 return TRUE;
551 static int Mouse_InitClass(LIBBASETYPEPTR LIBBASE)
553 D(bug("[Mouse] base class initialization\n"));
555 LIBBASE->csd.hiddMouseAB = OOP_ObtainAttrBase(IID_Hidd_Mouse);
557 if (LIBBASE->csd.hiddMouseAB)
559 NewList((struct List *)&LIBBASE->csd.callbacks);
560 NewList((struct List *)&LIBBASE->csd.drivers);
561 InitSemaphore(&LIBBASE->csd.drivers_sem);
562 D(bug("[Mouse] Everything OK\n"));
563 return TRUE;
566 return FALSE;
569 ADD2INITLIB(Mouse_InitClass, 0)
570 ADD2EXPUNGELIB(Mouse_ExpungeClass, 0)