Bringing flexcat 2.15 into the main branch (again)
[AROS.git] / arch / m68k-amiga / hidd / keyboard / kbdclass.c
blob97be85dea8a5c5ee380c81943a168bbda5ea120c
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: The main keyboard class.
6 Lang: English.
7 */
9 /****************************************************************************************/
11 #define AROS_ALMOST_COMPATIBLE
12 #include <proto/exec.h>
13 #include <proto/utility.h>
14 #include <proto/oop.h>
15 #include <oop/oop.h>
17 #include <exec/alerts.h>
18 #include <exec/memory.h>
20 #include <hidd/hidd.h>
21 #include <hidd/keyboard.h>
23 #include <aros/system.h>
24 #include <aros/symbolsets.h>
26 #include <hardware/custom.h>
27 #include <hardware/cia.h>
28 #include <proto/cia.h>
29 #include <proto/timer.h>
31 #include <devices/inputevent.h>
32 #include <devices/rawkeycodes.h>
33 #include <devices/timer.h>
35 #include "kbd.h"
37 #include LC_LIBDEFS_FILE
39 #define DEBUG 0
40 #include <aros/debug.h>
43 #undef HiddKbdAB
44 #define HiddKbdAB (XSD(cl)->hiddKbdAB)
46 // CIA-A level 2 serial interrupt handler
48 static AROS_INTH1(keyboard_interrupt, struct kbd_data *, kbddata)
50 AROS_INTFUNC_INIT
52 volatile struct CIA *ciaa = (struct CIA*)0xbfe001;
53 struct Library *TimerBase = kbddata->TimerBase;
54 struct EClockVal eclock1, eclock2;
55 UBYTE keycode;
57 if (kbddata->resetstate == 2) {
58 // do nothing, we'll reset automatically in 10seconds
59 return 0;
62 keycode = ciaa->ciasdr;
64 ciaa->ciacra |= 0x40;
65 ReadEClock(&eclock1);
67 keycode = ~((keycode >> 1) | (keycode << 7));
69 if (keycode == 0x78) { // reset warning
70 kbddata->resetstate++;
71 if (kbddata->resetstate == 2) {
72 kbddata->kbd_callback(kbddata->callbackdata, keycode);
73 // second reset warning, no handshake = starts 10s delay before forced reset
74 return 0;
76 // first reset warning, handle it normally
77 } else {
78 kbddata->kbd_callback(kbddata->callbackdata, keycode);
80 /* "release" UAE mouse wheel up/down key codes */
81 if (keycode == 0x7a || keycode == 0x7b)
82 kbddata->kbd_callback(kbddata->callbackdata, 0x80 | keycode);
84 // busy wait until handshake pulse has been long enough
85 for (;;) {
86 ReadEClock(&eclock2);
87 if ((LONG)(eclock2.ev_lo - eclock1.ev_lo) >= 80)
88 break;
91 ciaa->ciacra &= ~0x40; // end handshake
93 return 0;
95 AROS_INTFUNC_EXIT
98 OOP_Object * AmigaKbd__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
100 struct TagItem *tag, *tstate;
101 APTR callback = NULL;
102 APTR callbackdata = NULL;
103 BOOL has_kbd_hidd = FALSE;
104 struct Library *UtilityBase = TaggedOpenLibrary(TAGGEDOPEN_UTILITY);
106 EnterFunc(bug("Kbd::New()\n"));
108 if (!UtilityBase)
109 ReturnPtr("Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
111 ObtainSemaphoreShared( &XSD(cl)->sema);
113 if (XSD(cl)->kbdhidd)
114 has_kbd_hidd = TRUE;
116 ReleaseSemaphore( &XSD(cl)->sema);
118 if (has_kbd_hidd) { /* Cannot open twice */
119 CloseLibrary(UtilityBase);
120 ReturnPtr("Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
123 tstate = msg->attrList;
124 D(bug("Kbd: tstate: %p, tag=%x\n", tstate, tstate->ti_Tag));
126 while ((tag = NextTagItem(&tstate)))
128 ULONG idx;
130 D(bug("Kbd: Got tag %d, data %x\n", tag->ti_Tag, tag->ti_Data));
132 if (IS_HIDDKBD_ATTR(tag->ti_Tag, idx))
134 D(bug("Kbd hidd tag\n"));
135 switch (idx)
137 case aoHidd_Kbd_IrqHandler:
138 callback = (APTR)tag->ti_Data;
139 D(bug("Got callback %p\n", (APTR)tag->ti_Data));
140 break;
142 case aoHidd_Kbd_IrqHandlerData:
143 callbackdata = (APTR)tag->ti_Data;
144 D(bug("Got data %p\n", (APTR)tag->ti_Data));
145 break;
149 } /* while (tags to process) */
150 CloseLibrary(UtilityBase);
152 if (NULL == callback)
153 ReturnPtr("Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
155 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
157 if (o)
159 struct Interrupt *inter = &XSD(cl)->kbint;
160 struct kbd_data *data = OOP_INST_DATA(cl, o);
162 data->kbd_callback = (VOID (*)(APTR, UWORD))callback;
163 data->callbackdata = callbackdata;
165 XSD(cl)->timerio = (struct timerequest*)AllocMem(sizeof(struct timerequest), MEMF_CLEAR | MEMF_PUBLIC);
166 if (OpenDevice("timer.device", UNIT_ECLOCK, (struct IORequest*)XSD(cl)->timerio, 0))
167 Alert(AT_DeadEnd | AG_OpenDev | AN_Unknown);
168 XSD(cl)->TimerBase = data->TimerBase = (struct Library*)XSD(cl)->timerio->tr_node.io_Device;
170 if (!(XSD(cl)->ciares = OpenResource("ciaa.resource")))
171 Alert(AT_DeadEnd | AG_OpenRes | AN_Unknown);
173 inter = &XSD(cl)->kbint;
174 inter->is_Node.ln_Pri = 0;
175 inter->is_Node.ln_Type = NT_INTERRUPT;
176 inter->is_Node.ln_Name = "kbr";
177 inter->is_Code = (APTR)keyboard_interrupt;
178 inter->is_Data = data;
180 if (AddICRVector(XSD(cl)->ciares, 3, inter))
181 Alert(AT_DeadEnd | AG_NoMemory | AN_Unknown);
184 ReturnPtr("Kbd::New", OOP_Object *, o);
187 VOID AmigaKbd__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
189 ObtainSemaphore(&XSD(cl)->sema);
190 if (XSD(cl)->ciares)
191 RemICRVector(XSD(cl)->ciares, 3, &XSD(cl)->kbint);
192 if (XSD(cl)->TimerBase)
193 CloseDevice((struct IORequest*)XSD(cl)->timerio);
194 ReleaseSemaphore(&XSD(cl)->sema);
195 OOP_DoSuperMethod(cl, o, msg);
198 /****************************************************************************************/
200 static int AmigaKbd_InitAttrs(LIBBASETYPEPTR LIBBASE)
202 struct Library *OOPBase = LIBBASE->ksd.cs_OOPBase;
203 struct OOP_ABDescr attrbases[] =
205 {IID_Hidd_Kbd , &LIBBASE->ksd.hiddKbdAB },
206 {NULL , NULL }
209 ReturnInt("AmigaKbd_InitAttrs", ULONG, OOP_ObtainAttrBases(attrbases));
212 /****************************************************************************************/
214 static int AmigaKbd_ExpungeAttrs(LIBBASETYPEPTR LIBBASE)
216 struct Library *OOPBase = LIBBASE->ksd.cs_OOPBase;
217 struct OOP_ABDescr attrbases[] =
219 {IID_Hidd_Kbd , &LIBBASE->ksd.hiddKbdAB },
220 {NULL , NULL }
223 EnterFunc(bug("AmigaKbd_ExpungeAttrs\n"));
225 OOP_ReleaseAttrBases(attrbases);
227 ReturnInt("AmigaKbd_ExpungeAttrs", int, TRUE);
230 /****************************************************************************************/
232 ADD2INITLIB(AmigaKbd_InitAttrs, 0)
233 ADD2EXPUNGELIB(AmigaKbd_ExpungeAttrs, 0)