Call CloseDevice() before DeleteIORequest(), and don't call
[AROS.git] / rom / hidds / mouse / mouseclass.c
blob210bab5b6263cea0849bb339add12cd80eb6214e
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;
291 struct Library *UtilityBase = TaggedOpenLibrary(TAGGEDOPEN_UTILITY);
293 if (!UtilityBase)
294 return NULL;
296 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
297 if (!o) {
298 CloseLibrary(UtilityBase);
299 return NULL;
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)))
311 ULONG idx;
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"));
318 switch (idx)
320 case aoHidd_Mouse_IrqHandler:
321 data->callback = (APTR)tag->ti_Data;
322 D(bug("Got callback %p\n", (APTR)tag->ti_Data));
323 break;
325 case aoHidd_Mouse_IrqHandlerData:
326 data->callbackdata = (APTR)tag->ti_Data;
327 D(bug("Got data %p\n", (APTR)tag->ti_Data));
328 break;
331 } /* while (tags to process) */
333 /* Add to interrupts list if we have a callback */
334 if (data->callback) {
335 Disable();
336 AddTail((struct List *)&CSD(cl)->callbacks, (struct Node *)data);
337 Enable();
340 CloseLibrary(UtilityBase);
342 return o;
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) {
350 Disable();
351 Remove((struct Node *)data);
352 Enable();
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);
360 ULONG idx;
362 if (IS_HIDDMOUSE_ATTR(msg->attrID, idx))
364 switch (idx)
366 case aoHidd_Mouse_IrqHandler:
367 *msg->storage = (IPTR)data->callback;
368 return;
370 case aoHidd_Mouse_IrqHandlerData:
371 *msg->storage = (IPTR)data->callbackdata;
372 return;
374 /* case aoHidd_Mouse_State:
376 TODO: Implement this, by ORing buttons from all registered mice (?)
378 return;*/
380 case aoHidd_Mouse_Extended:
381 *msg->storage = TRUE;
382 return;
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 /*****************************************************************************************
397 NAME
398 moHidd_Mouse_AddHardwareDriver
400 SYNOPSIS
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)
405 LOCATION
406 CLID_Hidd_Mouse
408 FUNCTION
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.
414 INPUTS
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.
421 RESULT
422 A pointer to driver object.
424 NOTES
425 Do not dispose the returned object yourself, use HIDD_Mouse_RemHardwareDriver() for it.
427 EXAMPLE
429 BUGS
431 SEE ALSO
432 moHidd_Mouse_RemHardwareDriver
434 INTERNALS
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);
452 if (!drvnode)
453 return NULL;
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));
459 if (drvnode->drv) {
460 struct mouse_staticdata *csd = CSD(cl);
461 IPTR val = FALSE;
463 drvnode->callbacks = &csd->callbacks;
465 OOP_GetAttr(drvnode->drv, aHidd_Mouse_Extended, &val);
466 D(bug("[Mouse] Extended event: %d\n", val));
467 if (val)
468 drvnode->flags = vHidd_Mouse_Extended;
469 else
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);
480 return drvnode->drv;
483 FreeMem(drvnode, sizeof(struct driverNode));
484 return NULL;
487 /*****************************************************************************************
489 NAME
490 moHidd_Mouse_RemHardwareDriver
492 SYNOPSIS
493 void OOP_DoMethod(OOP_Object *obj, struct pHidd_Mouse_RemHardwareDriver *Msg);
495 void HIDD_Mouse_RemHardwareDriver(OOP_Object *obj, OOP_Object *driver);
497 LOCATION
498 CLID_Hidd_Mouse
500 FUNCTION
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.
506 INPUTS
507 obj - Any object of CLID_Hidd_Mouse class.
508 driver - A pointer to a driver object, returned by HIDD_Mouse_AddHardwareDriver().
510 RESULT
511 None
513 NOTES
515 EXAMPLE
517 BUGS
519 SEE ALSO
520 moHidd_Mouse_AddHardwareDriver
522 INTERNALS
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);
538 break;
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);
559 return TRUE;
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"));
575 return TRUE;
578 return FALSE;
581 ADD2INITLIB(Mouse_InitClass, 0)
582 ADD2EXPUNGELIB(Mouse_ExpungeClass, 0)