2 Copyright (C) 2004-2010, The AROS Development Team. All rights reserved.
6 #define __OOP_NOATTRBASES__
8 #include <aros/debug.h>
9 #include <aros/symbolsets.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
20 #define HiddMouseAB (CSD(cl)->hiddMouseAB)
22 #include <hidd/mouse.h>
24 /*****************************************************************************************
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 /*****************************************************************************************
65 A hardware driver should implement the same interface according to the following
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
;
93 xev
.flags
= drv
->flags
;
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 /*****************************************************************************************
106 aoHidd_Mouse_IrqHandler
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
125 button - button code, or vHidd_Mouse_NoButton of the event describes a simple
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.
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.
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.
151 aoHidd_Mouse_IrqHandlerData, aoHidd_Mouse_Extended
155 *****************************************************************************************/
157 /*****************************************************************************************
160 aoHidd_Mouse_IrqHandlerData
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.
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.
184 aoHidd_Mouse_IrqHandler
188 *****************************************************************************************/
190 /*****************************************************************************************
196 [..G], struct pHidd_Mouse_Event
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.
213 Not implemented, considered reserved.
219 *****************************************************************************************/
221 /*****************************************************************************************
224 aoHidd_Mouse_RelativeCoords
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
250 aoHidd_Mouse_IrqHandler, aoHidd_Mouse_Extended
254 *****************************************************************************************/
256 /*****************************************************************************************
259 aoHidd_Mouse_Extended
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.
281 aoHidd_Mouse_IrqHandler
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
;
291 struct Library
*UtilityBase
= TaggedOpenLibrary(TAGGEDOPEN_UTILITY
);
296 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
298 CloseLibrary(UtilityBase
);
302 data
= OOP_INST_DATA(cl
, o
);
303 data
->callback
= NULL
;
304 data
->callbackdata
= NULL
;
306 tstate
= msg
->attrList
;
307 D(bug("tstate: %p\n", tstate
));
309 while ((tag
= NextTagItem(&tstate
)))
313 D(bug("Got tag %d, data %x\n", tag
->ti_Tag
, tag
->ti_Data
));
315 if (IS_HIDDMOUSE_ATTR(tag
->ti_Tag
, idx
))
317 D(bug("Mouse hidd tag\n"));
320 case aoHidd_Mouse_IrqHandler
:
321 data
->callback
= (APTR
)tag
->ti_Data
;
322 D(bug("Got callback %p\n", (APTR
)tag
->ti_Data
));
325 case aoHidd_Mouse_IrqHandlerData
:
326 data
->callbackdata
= (APTR
)tag
->ti_Data
;
327 D(bug("Got data %p\n", (APTR
)tag
->ti_Data
));
331 } /* while (tags to process) */
333 /* Add to interrupts list if we have a callback */
334 if (data
->callback
) {
336 AddTail((struct List
*)&CSD(cl
)->callbacks
, (struct Node
*)data
);
340 CloseLibrary(UtilityBase
);
345 VOID
Mouse__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
347 struct mouse_data
*data
= OOP_INST_DATA(cl
, o
);
349 if (data
->callback
) {
351 Remove((struct Node
*)data
);
354 OOP_DoSuperMethod(cl
, o
, msg
);
357 VOID
Mouse__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
359 struct mouse_data
*data
= OOP_INST_DATA(cl
, o
);
362 if (IS_HIDDMOUSE_ATTR(msg
->attrID
, idx
))
366 case aoHidd_Mouse_IrqHandler
:
367 *msg
->storage
= (IPTR
)data
->callback
;
370 case aoHidd_Mouse_IrqHandlerData
:
371 *msg
->storage
= (IPTR
)data
->callbackdata
;
374 /* case aoHidd_Mouse_State:
376 TODO: Implement this, by ORing buttons from all registered mice (?)
380 case aoHidd_Mouse_Extended
:
381 *msg
->storage
= TRUE
;
386 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
390 * In future we could support enumeration of devices and specifying
391 * which device we wish to read events from (in case if we want to implement
392 * amigainput.library or something like it)
395 /*****************************************************************************************
398 moHidd_Mouse_AddHardwareDriver
401 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Mouse_AddHardwareDriver *Msg);
403 OOP_Object *HIDD_Mouse_AddHardwareDriver(OOP_Object *obj, OOP_Class *driverClass, struct TagItem *tags)
409 Creates a hardware driver object and registers it in the system.
411 It does not matter on which instance of CLID_Hidd_Mouse class this method is
412 used. Hardware driver objects are shared between all of them.
415 obj - Any object of CLID_Hidd_Mouse class.
416 driverClass - A pointer to OOP class of the driver. In order to create an object
417 of some previously registered public class, use
418 oop.library/OOP_FindClass().
419 tags - An optional taglist which will be passed to driver class' New() method.
422 A pointer to driver object.
425 Do not dispose the returned object yourself, use HIDD_Mouse_RemHardwareDriver() for it.
432 moHidd_Mouse_RemHardwareDriver
435 This method supplies own interrupt handler to the driver, do not override this.
437 *****************************************************************************************/
439 OOP_Object
*Mouse__Hidd_Mouse__AddHardwareDriver(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Mouse_AddHardwareDriver
*Msg
)
441 struct Library
*OOPBase
= CSD(cl
)->cs_OOPBase
;
442 struct TagItem tags
[] = {
443 { aHidd_Mouse_IrqHandler
, (IPTR
)GlobalCallback
},
444 { aHidd_Mouse_IrqHandlerData
, 0 },
445 { TAG_MORE
, (IPTR
)Msg
->tags
}
447 struct driverNode
*drvnode
;
449 D(bug("[Mouse] AddHardwareDriver(0x%p)\n", Msg
->driverClass
));
451 drvnode
= AllocMem(sizeof(struct driverNode
), MEMF_PUBLIC
);
455 tags
[1].ti_Data
= (IPTR
)drvnode
;
456 drvnode
->drv
= OOP_NewObject(Msg
->driverClass
, NULL
, tags
);
457 D(bug("[Mouse] Driver node 0x%p, driver 0x%p\n", drvnode
, drvnode
->drv
));
460 struct mouse_staticdata
*csd
= CSD(cl
);
463 drvnode
->callbacks
= &csd
->callbacks
;
465 OOP_GetAttr(drvnode
->drv
, aHidd_Mouse_Extended
, &val
);
466 D(bug("[Mouse] Extended event: %d\n", val
));
468 drvnode
->flags
= vHidd_Mouse_Extended
;
471 OOP_GetAttr(drvnode
->drv
, aHidd_Mouse_RelativeCoords
, &val
);
472 D(bug("[Mouse] Relative coordinates: %d\n", val
));
473 drvnode
->flags
= val
? vHidd_Mouse_Relative
: 0;
476 ObtainSemaphore(&csd
->drivers_sem
);
477 AddTail((struct List
*)&csd
->drivers
, (struct Node
*)drvnode
);
478 ReleaseSemaphore(&csd
->drivers_sem
);
483 FreeMem(drvnode
, sizeof(struct driverNode
));
487 /*****************************************************************************************
490 moHidd_Mouse_RemHardwareDriver
493 void OOP_DoMethod(OOP_Object *obj, struct pHidd_Mouse_RemHardwareDriver *Msg);
495 void HIDD_Mouse_RemHardwareDriver(OOP_Object *obj, OOP_Object *driver);
501 Unregisters and disposes pointing device hardware driver object.
503 It does not matter on which instance of CLID_Hidd_Mouse class this method is
504 used. Hardware driver objects are shared between all of them.
507 obj - Any object of CLID_Hidd_Mouse class.
508 driver - A pointer to a driver object, returned by HIDD_Mouse_AddHardwareDriver().
520 moHidd_Mouse_AddHardwareDriver
524 *****************************************************************************************/
526 void Mouse__Hidd_Mouse__RemHardwareDriver(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Mouse_RemHardwareDriver
*Msg
)
528 struct mouse_staticdata
*csd
= CSD(cl
);
529 struct Library
*OOPBase
= csd
->cs_OOPBase
;
530 struct driverNode
*node
;
532 ObtainSemaphore(&csd
->drivers_sem
);
534 for (node
= (struct driverNode
*)csd
->drivers
.mlh_Head
; node
->node
.mln_Succ
;
535 node
= (struct driverNode
*)node
->node
.mln_Succ
) {
536 if (node
->drv
== Msg
->driverObject
) {
537 Remove((struct Node
*)node
);
542 ReleaseSemaphore(&csd
->drivers_sem
);
544 OOP_DisposeObject(Msg
->driverObject
);
546 if (node
->drv
== Msg
->driverObject
)
547 FreeMem(node
, sizeof(struct driverNode
));
550 /* Class initialization and destruction */
552 static int Mouse_ExpungeClass(LIBBASETYPEPTR LIBBASE
)
554 struct Library
*OOPBase
= LIBBASE
->csd
.cs_OOPBase
;
555 D(bug("[Mouse] Base Class destruction\n"));
557 OOP_ReleaseAttrBase(IID_Hidd_Mouse
);
562 static int Mouse_InitClass(LIBBASETYPEPTR LIBBASE
)
564 struct Library
*OOPBase
= LIBBASE
->csd
.cs_OOPBase
;
565 D(bug("[Mouse] base class initialization\n"));
567 LIBBASE
->csd
.hiddMouseAB
= OOP_ObtainAttrBase(IID_Hidd_Mouse
);
569 if (LIBBASE
->csd
.hiddMouseAB
)
571 NewList((struct List
*)&LIBBASE
->csd
.callbacks
);
572 NewList((struct List
*)&LIBBASE
->csd
.drivers
);
573 InitSemaphore(&LIBBASE
->csd
.drivers_sem
);
574 D(bug("[Mouse] Everything OK\n"));
581 ADD2INITLIB(Mouse_InitClass
, 0)
582 ADD2EXPUNGELIB(Mouse_ExpungeClass
, 0)