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
;
292 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
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
)))
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"));
314 case aoHidd_Mouse_IrqHandler
:
315 data
->callback
= (APTR
)tag
->ti_Data
;
316 D(bug("Got callback %p\n", (APTR
)tag
->ti_Data
));
319 case aoHidd_Mouse_IrqHandlerData
:
320 data
->callbackdata
= (APTR
)tag
->ti_Data
;
321 D(bug("Got data %p\n", (APTR
)tag
->ti_Data
));
325 } /* while (tags to process) */
327 /* Add to interrupts list if we have a callback */
328 if (data
->callback
) {
330 AddTail((struct List
*)&CSD(cl
)->callbacks
, (struct Node
*)data
);
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
) {
343 Remove((struct Node
*)data
);
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
);
354 if (IS_HIDDMOUSE_ATTR(msg
->attrID
, idx
))
358 case aoHidd_Mouse_IrqHandler
:
359 *msg
->storage
= (IPTR
)data
->callback
;
362 case aoHidd_Mouse_IrqHandlerData
:
363 *msg
->storage
= (IPTR
)data
->callbackdata
;
366 /* case aoHidd_Mouse_State:
368 TODO: Implement this, by ORing buttons from all registered mice (?)
372 case aoHidd_Mouse_Extended
:
373 *msg
->storage
= TRUE
;
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 /*****************************************************************************************
390 moHidd_Mouse_AddHardwareDriver
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)
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.
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.
414 A pointer to driver object.
417 Do not dispose the returned object yourself, use HIDD_Mouse_RemHardwareDriver() for it.
424 moHidd_Mouse_RemHardwareDriver
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
);
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
));
451 struct mouse_staticdata
*csd
= CSD(cl
);
454 drvnode
->callbacks
= &csd
->callbacks
;
456 OOP_GetAttr(drvnode
->drv
, aHidd_Mouse_Extended
, &val
);
457 D(bug("[Mouse] Extended event: %d\n", val
));
459 drvnode
->flags
= vHidd_Mouse_Extended
;
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
);
474 FreeMem(drvnode
, sizeof(struct driverNode
));
478 /*****************************************************************************************
481 moHidd_Mouse_RemHardwareDriver
484 void OOP_DoMethod(OOP_Object *obj, struct pHidd_Mouse_RemHardwareDriver *Msg);
486 void HIDD_Mouse_RemHardwareDriver(OOP_Object *obj, OOP_Object *driver);
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.
498 obj - Any object of CLID_Hidd_Mouse class.
499 driver - A pointer to a driver object, returned by HIDD_Mouse_AddHardwareDriver().
511 moHidd_Mouse_AddHardwareDriver
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
);
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
);
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"));
569 ADD2INITLIB(Mouse_InitClass
, 0)
570 ADD2EXPUNGELIB(Mouse_ExpungeClass
, 0)