2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: The main keyboard class.
9 /****************************************************************************************/
11 #define AROS_ALMOST_COMPATIBLE
12 #include <proto/exec.h>
13 #include <proto/utility.h>
14 #include <proto/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>
37 #include LC_LIBDEFS_FILE
40 #include <aros/debug.h>
44 #define HiddKbdAB (XSD(cl)->hiddKbdAB)
46 // CIA-A level 2 serial interrupt handler
48 static AROS_INTH1(keyboard_interrupt
, struct kbd_data
*, kbddata
)
52 volatile struct CIA
*ciaa
= (struct CIA
*)0xbfe001;
53 struct Library
*TimerBase
= kbddata
->TimerBase
;
54 struct EClockVal eclock1
, eclock2
;
57 if (kbddata
->resetstate
== 2) {
58 // do nothing, we'll reset automatically in 10seconds
62 keycode
= ciaa
->ciasdr
;
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
76 // first reset warning, handle it normally
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
87 if ((LONG
)(eclock2
.ev_lo
- eclock1
.ev_lo
) >= 80)
91 ciaa
->ciacra
&= ~0x40; // end handshake
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"));
109 ReturnPtr("Kbd::New", OOP_Object
*, NULL
); /* Should have some error code here */
111 ObtainSemaphoreShared( &XSD(cl
)->sema
);
113 if (XSD(cl
)->kbdhidd
)
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
)))
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"));
137 case aoHidd_Kbd_IrqHandler
:
138 callback
= (APTR
)tag
->ti_Data
;
139 D(bug("Got callback %p\n", (APTR
)tag
->ti_Data
));
142 case aoHidd_Kbd_IrqHandlerData
:
143 callbackdata
= (APTR
)tag
->ti_Data
;
144 D(bug("Got data %p\n", (APTR
)tag
->ti_Data
));
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
);
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
);
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
},
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
},
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)