revert between 56095 -> 55830 in arch
[AROS.git] / arch / m68k-amiga / hidd / keyboard / kbdclass.c
blobdfdfd7e14943b820eb3dea2f34fe95fc68de04d2
1 /*
2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: The main keyboard class.
6 Lang: English.
7 */
9 /****************************************************************************************/
11 #define DEBUG 0
12 #include <aros/debug.h>
14 #define AROS_ALMOST_COMPATIBLE
15 #include <proto/exec.h>
16 #include <proto/utility.h>
17 #include <proto/oop.h>
18 #include <oop/oop.h>
20 #include <exec/alerts.h>
21 #include <exec/memory.h>
23 #include <hidd/hidd.h>
24 #include <hidd/keyboard.h>
26 #include <aros/system.h>
27 #include <aros/symbolsets.h>
29 #include <hardware/custom.h>
30 #include <hardware/cia.h>
31 #include <proto/cia.h>
32 #include <proto/timer.h>
34 #include <devices/inputevent.h>
35 #include <devices/rawkeycodes.h>
36 #include <devices/timer.h>
38 #include "kbd.h"
40 // CIA-A level 2 serial interrupt handler
42 static AROS_INTH1(keyboard_interrupt, struct kbd_data *, kbddata)
44 AROS_INTFUNC_INIT
46 volatile struct CIA *ciaa = (struct CIA*)0xbfe001;
47 struct Library *TimerBase = kbddata->TimerBase;
48 struct EClockVal eclock1, eclock2;
49 UBYTE keycode;
51 if (kbddata->resetstate == 2) {
52 // do nothing, we'll reset automatically in 10seconds
53 return 0;
56 keycode = ciaa->ciasdr;
58 ciaa->ciacra |= 0x40;
59 ReadEClock(&eclock1);
61 keycode = ~((keycode >> 1) | (keycode << 7));
63 if (keycode == 0x78) { // reset warning
64 kbddata->resetstate++;
65 if (kbddata->resetstate == 2) {
66 kbddata->kbd_callback(kbddata->callbackdata, keycode);
67 // second reset warning, no handshake = starts 10s delay before forced reset
68 return 0;
70 // first reset warning, handle it normally
71 } else {
72 kbddata->kbd_callback(kbddata->callbackdata, keycode);
74 /* "release" UAE mouse wheel up/down key codes */
75 if (keycode == 0x7a || keycode == 0x7b)
76 kbddata->kbd_callback(kbddata->callbackdata, 0x80 | keycode);
78 // busy wait until handshake pulse has been long enough
79 for (;;) {
80 ReadEClock(&eclock2);
81 if ((LONG)(eclock2.ev_lo - eclock1.ev_lo) >= 80)
82 break;
85 ciaa->ciacra &= ~0x40; // end handshake
87 return 0;
89 AROS_INTFUNC_EXIT
92 OOP_Object * AmigaKbd__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
94 /* Add some descriptional tags to our attributes */
95 struct TagItem kbd_tags[] =
97 {aHidd_Name , (IPTR)"AmigaKbd" },
98 {aHidd_HardwareName, (IPTR)"Amiga(tm) Keyboard"},
99 {TAG_MORE , (IPTR)msg->attrList }
101 struct pRoot_New new_msg =
103 .mID = msg->mID,
104 .attrList = kbd_tags
106 struct TagItem *tag, *tstate;
107 APTR callback = NULL;
108 APTR callbackdata = NULL;
109 BOOL has_kbd_hidd = FALSE;
110 struct Library *UtilityBase = TaggedOpenLibrary(TAGGEDOPEN_UTILITY);
112 EnterFunc(bug("Kbd::New()\n"));
114 if (!UtilityBase)
115 ReturnPtr("Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
117 ObtainSemaphoreShared( &XSD(cl)->sema);
119 if (XSD(cl)->kbdhidd)
120 has_kbd_hidd = TRUE;
122 ReleaseSemaphore( &XSD(cl)->sema);
124 if (has_kbd_hidd) { /* Cannot open twice */
125 CloseLibrary(UtilityBase);
126 ReturnPtr("Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
129 tstate = msg->attrList;
130 D(bug("Kbd: tstate: %p, tag=%x\n", tstate, tstate->ti_Tag));
132 while ((tag = NextTagItem(&tstate)))
134 ULONG idx;
136 D(bug("Kbd: Got tag %d, data %x\n", tag->ti_Tag, tag->ti_Data));
138 if (IS_HIDDKBD_ATTR(tag->ti_Tag, idx))
140 D(bug("Kbd hidd tag\n"));
141 switch (idx)
143 case aoHidd_Kbd_IrqHandler:
144 callback = (APTR)tag->ti_Data;
145 D(bug("Got callback %p\n", (APTR)tag->ti_Data));
146 break;
148 case aoHidd_Kbd_IrqHandlerData:
149 callbackdata = (APTR)tag->ti_Data;
150 D(bug("Got data %p\n", (APTR)tag->ti_Data));
151 break;
155 } /* while (tags to process) */
156 CloseLibrary(UtilityBase);
158 if (NULL == callback)
159 ReturnPtr("Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
161 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, &new_msg.mID);
163 if (o)
165 struct Interrupt *inter = &XSD(cl)->kbint;
166 struct kbd_data *data = OOP_INST_DATA(cl, o);
168 data->kbd_callback = (VOID (*)(APTR, UWORD))callback;
169 data->callbackdata = callbackdata;
171 XSD(cl)->timerio = (struct timerequest*)AllocMem(sizeof(struct timerequest), MEMF_CLEAR | MEMF_PUBLIC);
172 if (OpenDevice("timer.device", UNIT_ECLOCK, (struct IORequest*)XSD(cl)->timerio, 0))
173 Alert(AT_DeadEnd | AG_OpenDev | AN_Unknown);
174 XSD(cl)->TimerBase = data->TimerBase = (struct Library*)XSD(cl)->timerio->tr_node.io_Device;
176 if (!(XSD(cl)->ciares = OpenResource("ciaa.resource")))
177 Alert(AT_DeadEnd | AG_OpenRes | AN_Unknown);
179 inter = &XSD(cl)->kbint;
180 inter->is_Node.ln_Pri = 0;
181 inter->is_Node.ln_Type = NT_INTERRUPT;
182 inter->is_Node.ln_Name = "kbr";
183 inter->is_Code = (APTR)keyboard_interrupt;
184 inter->is_Data = data;
186 if (AddICRVector(XSD(cl)->ciares, 3, inter))
187 Alert(AT_DeadEnd | AG_NoMemory | AN_Unknown);
190 ReturnPtr("Kbd::New", OOP_Object *, o);
193 VOID AmigaKbd__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
195 ObtainSemaphore(&XSD(cl)->sema);
196 if (XSD(cl)->ciares)
197 RemICRVector(XSD(cl)->ciares, 3, &XSD(cl)->kbint);
198 if (XSD(cl)->TimerBase)
199 CloseDevice((struct IORequest*)XSD(cl)->timerio);
200 ReleaseSemaphore(&XSD(cl)->sema);
201 OOP_DoSuperMethod(cl, o, msg);