Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / hidds / kbd / kbdclass.c
blob873444eb4690f29bf36fd23500af317eb589ad1b
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 <hidd/keyboard.h>
11 #include <oop/oop.h>
12 #include <utility/tagitem.h>
13 #include <proto/alib.h>
14 #include <proto/exec.h>
15 #include <proto/utility.h>
16 #include <proto/oop.h>
18 #include LC_LIBDEFS_FILE
20 #undef HiddKbdAB
21 #define HiddKbdAB (CSD(cl)->hiddKbdAB)
23 #include <hidd/keyboard.h>
25 /*****************************************************************************************
27 NAME
28 --background--
30 LOCATION
31 CLID_Hidd_Kbd
33 NOTES
34 This class represents a "hub" for collecting input from various
35 keyboard devices in the system and sending them to clients.
37 In order to get an access to keyboard input subsystem you need to
38 create an object of CLID_Hidd_Kbd class. There can be two use
39 scenarios: driver mode and client mode.
41 If you wish to run in client mode (receive keyboard events), you
42 have to supply a callback using aoHidd_Kbd_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 keyboard 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_Kbd_AddHardwareDriver(). It is safe to
52 dispose the master object after adding a driver, the driver will
53 be internally kept in place.
55 *****************************************************************************************/
57 /*****************************************************************************************
59 NAME
60 --hardware_drivers--
62 LOCATION
63 CLID_Hidd_Kbd
65 NOTES
66 A hardware driver should implement the same interface according to the following
67 rules:
69 1. A single object of driver class represents a single hardware unit.
70 2. A single driver object maintains a single callback address (passed to it
71 using aoHidd_Kbd_IrqHandler). Under normal conditions this callback is supplied
72 by CLID_Hidd_Kbd class.
73 3. HIDD_Kbd_AddHardwareDriver() and HIDD_Kbd_RemHardwareDriver() on a driver object
74 itself do not make sense, so there's no need to implement them.
76 A hardware driver class should be a subclass of CLID_Hidd in order to ensure
77 compatibility in future.
79 *****************************************************************************************/
81 static void GlobalCallback(struct kbd_staticdata *csd, UWORD code)
83 struct kbd_data *data;
85 for (data = (struct kbd_data *)csd->callbacks.mlh_Head; data->node.mln_Succ;
86 data = (struct kbd_data *)data->node.mln_Succ)
87 data->callback(data->callbackdata, code);
90 /*****************************************************************************************
92 NAME
93 aoHidd_Kbd_IrqHandler
95 SYNOPSIS
96 [I..], APTR
98 LOCATION
99 CLID_Hidd_Kbd
101 FUNCTION
102 Specifies a keyboard event handler. The handler will called be every time a
103 keyboard event happens. A "C" calling convention is used, declare the handler
104 functions as follows:
106 void KeyboardIRQ(APTR data, UWORD keyCode)
108 Handler parameters are:
109 data - Anything you specify using aoHidd_Kbd_IrqHandlerData
110 keyCode - A raw key code as specified in devices/rawkeycodes.h.
111 Key release event is indicated by ORing this value
112 with IECODE_UP_PREFIX (defined in devices/inputevent.h)
114 The handler is called inside interrupts, so usual restrictions apply to it.
116 NOTES
118 EXAMPLE
120 BUGS
121 Not all hosted drivers provide this attribute.
123 SEE ALSO
124 aoHidd_Kbd_IrqHandlerData
126 INTERNALS
128 *****************************************************************************************/
130 /*****************************************************************************************
132 NAME
133 aoHidd_Kbd_IrqHandlerData
135 SYNOPSIS
136 [I..], APTR
138 LOCATION
139 CLID_Hidd_Kbd
141 FUNCTION
142 Specifies a user-defined value that will be passed to IRQ handler as a first
143 parameter. The purpose of this is to pass some static data to the handler.
144 The system will not assume anything about this value.
146 Defaults to NULL if not specified.
148 NOTES
150 EXAMPLE
152 BUGS
154 SEE ALSO
155 aoHidd_Kbd_IrqHandler
157 INTERNALS
159 ******************************************************************************************/
161 OOP_Object *KBD__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
163 struct kbd_data *data;
164 struct TagItem *tag, *tstate;
166 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
167 if (!o)
168 return NULL;
170 data = OOP_INST_DATA(cl, o);
171 data->callback = NULL;
172 data->callbackdata = NULL;
174 tstate = msg->attrList;
175 D(bug("tstate: %p\n", tstate));
177 while ((tag = NextTagItem((const struct TagItem **)&tstate)))
179 ULONG idx;
181 D(bug("Got tag %d, data %x\n", tag->ti_Tag, tag->ti_Data));
183 if (IS_HIDDKBD_ATTR(tag->ti_Tag, idx))
185 D(bug("Kbd hidd tag\n"));
186 switch (idx)
188 case aoHidd_Kbd_IrqHandler:
189 data->callback = (APTR)tag->ti_Data;
190 D(bug("Got callback %p\n", (APTR)tag->ti_Data));
191 break;
193 case aoHidd_Kbd_IrqHandlerData:
194 data->callbackdata = (APTR)tag->ti_Data;
195 D(bug("Got data %p\n", (APTR)tag->ti_Data));
196 break;
199 } /* while (tags to process) */
201 /* Add to interrupts list if we have a callback */
202 if (data->callback) {
203 Disable();
204 AddTail((struct List *)&CSD(cl)->callbacks, (struct Node *)data);
205 Enable();
208 return o;
211 VOID KBD__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
213 struct kbd_data *data = OOP_INST_DATA(cl, o);
215 if (data->callback) {
216 Disable();
217 Remove((struct Node *)data);
218 Enable();
220 OOP_DoSuperMethod(cl, o, msg);
224 * The following two methods are small stubs providing means for future expansion.
225 * In future we could support enumeration of devices and specifying
226 * which device we wish to read events from (in case if we want to implement
227 * amigainput.library or something like it)
230 /*****************************************************************************************
232 NAME
233 moHidd_Kbd_AddHardwareDriver
235 SYNOPSIS
236 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Kbd_AddHardwareDriver *Msg);
238 OOP_Object *HIDD_Kbd_AddHardwareDriver(OOP_Object *obj, OOP_Class *driverClass,
239 struct TagItem *tags);
241 LOCATION
242 CLID_Hidd_Kbd
244 FUNCTION
245 Creates a hardware driver object and registers it in the system.
247 It does not matter on which instance of CLID_Hidd_Kbd class this method is
248 used. Hardware driver objects are shared between all of them.
250 INPUTS
251 obj - Any object of CLID_Hidd_Kbd class.
252 driverClass - A pointer to OOP class of the driver. In order to create an object
253 of some previously registered public class, use
254 oop.library/OOP_FindClass().
255 tags - An optional taglist which will be passed to driver class' New() method.
257 RESULT
258 A pointer to driver object.
260 NOTES
261 Do not dispose the returned object yourself, use HIDD_Kbd_RemHardwareDriver() for it.
263 EXAMPLE
265 BUGS
267 SEE ALSO
268 moHidd_Kbd_RemHardwareDriver
270 INTERNALS
271 This method supplies own interrupt handler to the driver, do not override this.
273 *****************************************************************************************/
275 OOP_Object *KBD__Hidd_Kbd__AddHardwareDriver(OOP_Class *cl, OOP_Object *o, struct pHidd_Kbd_AddHardwareDriver *Msg)
277 struct TagItem tags[] = {
278 { aHidd_Kbd_IrqHandler , (IPTR)GlobalCallback },
279 { aHidd_Kbd_IrqHandlerData, (IPTR)CSD(cl) },
280 { TAG_MORE , (IPTR)Msg->tags }
283 return OOP_NewObject(Msg->driverClass, NULL, tags);
286 /*****************************************************************************************
288 NAME
289 moHidd_Kbd_RemHardwareDriver
291 SYNOPSIS
292 void OOP_DoMethod(OOP_Object *obj, struct pHidd_Kbd_RemHardwareDriver *Msg);
294 void HIDD_Kbd_RemHardwareDriver(OOP_Object *obj, OOP_Object *driver);
296 LOCATION
297 CLID_Hidd_Kbd
299 FUNCTION
300 Unregisters and disposes keyboard hardware driver object.
302 It does not matter on which instance of CLID_Hidd_Kbd class this method is
303 used. Hardware driver objects are shared between all of them.
305 INPUTS
306 obj - Any object of CLID_Hidd_Kbd class.
307 driver - A pointer to a driver object, returned by HIDD_Kbd_AddHardwareDriver().
309 RESULT
310 None
312 NOTES
314 EXAMPLE
316 BUGS
318 SEE ALSO
319 moHidd_Kbd_AddHardwareDriver
321 INTERNALS
323 *****************************************************************************************/
325 void KBD__Hidd_Kbd__RemHardwareDriver(OOP_Class *cl, OOP_Object *o, struct pHidd_Kbd_RemHardwareDriver *Msg)
327 OOP_DisposeObject(Msg->driverObject);
330 /* Class initialization and destruction */
332 static int KBD_ExpungeClass(LIBBASETYPEPTR LIBBASE)
334 D(bug("[KBD] Base Class destruction\n"));
336 OOP_ReleaseAttrBase(IID_Hidd_Kbd);
338 return TRUE;
341 static int KBD_InitClass(LIBBASETYPEPTR LIBBASE)
343 D(bug("[KBD] base class initialization\n"));
345 LIBBASE->csd.hiddKbdAB = OOP_ObtainAttrBase(IID_Hidd_Kbd);
347 if (LIBBASE->csd.hiddKbdAB)
349 NewList((struct List *)&LIBBASE->csd.callbacks);
350 D(bug("[KBD] Everything OK\n"));
351 return TRUE;
354 return FALSE;
357 ADD2INITLIB(KBD_InitClass, 0)
358 ADD2EXPUNGELIB(KBD_ExpungeClass, 0)