2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
5 Desc: The main keyboard class.
9 /****************************************************************************************/
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>
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>
40 // CIA-A level 2 serial interrupt handler
42 static AROS_INTH1(keyboard_interrupt
, struct kbd_data
*, kbddata
)
46 volatile struct CIA
*ciaa
= (struct CIA
*)0xbfe001;
47 struct Library
*TimerBase
= kbddata
->TimerBase
;
48 struct EClockVal eclock1
, eclock2
;
51 if (kbddata
->resetstate
== 2) {
52 // do nothing, we'll reset automatically in 10seconds
56 keycode
= ciaa
->ciasdr
;
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
70 // first reset warning, handle it normally
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
81 if ((LONG
)(eclock2
.ev_lo
- eclock1
.ev_lo
) >= 80)
85 ciaa
->ciacra
&= ~0x40; // end handshake
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
=
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"));
115 ReturnPtr("Kbd::New", OOP_Object
*, NULL
); /* Should have some error code here */
117 ObtainSemaphoreShared( &XSD(cl
)->sema
);
119 if (XSD(cl
)->kbdhidd
)
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
)))
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"));
143 case aoHidd_Kbd_IrqHandler
:
144 callback
= (APTR
)tag
->ti_Data
;
145 D(bug("Got callback %p\n", (APTR
)tag
->ti_Data
));
148 case aoHidd_Kbd_IrqHandlerData
:
149 callbackdata
= (APTR
)tag
->ti_Data
;
150 D(bug("Got data %p\n", (APTR
)tag
->ti_Data
));
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
);
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
);
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
);