5 #ifdef HAVE_LIBVNCSERVER
7 #include <rfb/keysym.h>
8 #endif /* HAVE_LIBVNCSERVER */
11 #include "hw_keyboard.h"
15 #ifdef WANT_VARIADIC_VOIDP_CAST
16 #define VOIDP(__x__) ((void *)(__x__))
18 #define VOIDP(__x__) (__x__)
21 static dcpu16_hw_signal_t keyboard_reset_
;
22 static dcpu16_hw_signal_t keyboard_cycle_
;
23 static dcpu16_hw_signal_t keyboard_hwi_
;
24 static struct dcpu16_hw hw_
= {
26 .name_
= "Generic Keyboard (compatible)",
33 .cycle
= keyboard_cycle_
,
34 .reset
= keyboard_reset_
,
35 .data
= (struct keyboard_
*)NULL
43 DCPU16_WORD interrupt_message
;
44 unsigned char keys_pressed
[256];
47 #ifdef HAVE_LIBVNCSERVER
49 static const struct keysym_map_
{
50 unsigned int rfb_start
;
52 DCPU16_WORD dcpu_start
;
54 { XK_space
, XK_asciitilde
, 0x20 }, /* ASCII range */
55 { XK_Delete
, XK_Delete
, 0x7f }, /* ASCII del */
56 { XK_BackSpace
, XK_BackSpace
, 0x10 }, /* bs */
57 { XK_Return
, XK_Return
, 0x11 }, /* ret */
58 { XK_Insert
, XK_Insert
, 0x12 }, /* ins */
59 { XK_Delete
, XK_Delete
, 0x13 }, /* del */
60 { XK_Up
, XK_Up
, 0x80 }, /* arrow up */
61 { XK_Down
, XK_Down
, 0x81 }, /* arrow down */
62 { XK_Left
, XK_Left
, 0x82 }, /* arrow left */
63 { XK_Right
, XK_Right
, 0x83 }, /* arrow right */
64 { XK_Shift_L
, XK_Shift_R
, 0x90 }, /* shift range */
65 { XK_Control_L
, XK_Control_R
, 0x91 }, /* control range */
69 static int keysym_rfbtodcpu(unsigned int rfb
, DCPU16_WORD
*dcpu
) {
70 const struct keysym_map_
*map
;
72 for (map
= keymap_
; map
->rfb_start
; map
++) {
73 if (rfb
>= map
->rfb_start
74 && rfb
<= map
->rfb_end
) {
75 *dcpu
= (map
->dcpu_start
+ (rfb
- map
->rfb_start
));
85 void keyboard_rfbevent_(rfbBool down
, rfbKeySym key
, rfbClientPtr cl
) {
87 struct dcpu16_hw
*hw
= (struct dcpu16_hw
*)cl
->screen
->screenData
;
88 struct keyboard_
*keyboard
= (struct keyboard_
*)hw
->data
;
90 keysym_rfbtodcpu(key
, &dcpu_key
);
92 fprintf(stderr
, "%s: down:%u key:0x%04x dcpu_key:0x%04x\n",
98 fprintf(stderr
, "%s: hw:%p name:%s vm:%p\n",
104 keyboard
->keys_pressed
[dcpu_key
] = (down
? 1 : 0);
106 if ((keyboard
->buf_tail
+ 1) % keyboard
->buf_sz
== keyboard
->buf_head
) {
107 hw
->vm
->warn_cb_("keyboard buffer overflow");
110 keyboard
->buf
[keyboard
->buf_tail
] = dcpu_key
;
111 keyboard
->buf_tail
+= 1;
112 keyboard
->buf_tail
%= keyboard
->buf_sz
;
114 if (keyboard
->interrupt_message
) {
115 dcpu16_interrupt(hw
->vm
, keyboard
->interrupt_message
);
119 void keyboard_vnc_associate(struct dcpu16_hw
*hw
, rfbScreenInfoPtr rfbScreen
) {
120 rfbScreen
->screenData
= hw
;
121 rfbScreen
->kbdAddEvent
= keyboard_rfbevent_
;
123 #endif /* HAVE_LIBVNCSERVER */
126 void keyboard_reset_(struct dcpu16
*vm
, void *data
) {
127 struct keyboard_
*keyboard
= (struct keyboard_
*)data
;
131 keyboard
->interrupt_message
= 0;
132 memset(keyboard
->buf
, 0, keyboard
->buf_sz
);
136 void keyboard_cycle_(struct dcpu16
*vm
, void *data
) {
137 struct keyboard_
*keyboard
= (struct keyboard_
*)data
;
139 (void)vm
, (void)keyboard
;
143 void keyboard_hwi_(struct dcpu16
*vm
, void *data
) {
144 struct keyboard_
*keyboard
= (struct keyboard_
*)data
;
145 DCPU16_WORD reg_a
= vm
->reg
[DCPU16_REG_A
];
146 DCPU16_WORD reg_b
= vm
->reg
[DCPU16_REG_B
];
149 case 0: /* clear keyboard buffer */
150 memset(keyboard
->buf
, 0, keyboard
->buf_sz
);
151 keyboard
->buf_head
= 0;
152 keyboard
->buf_tail
= 0;
155 case 1: /* get next key from buffer as C */
156 if (keyboard
->buf_head
== keyboard
->buf_tail
)
158 vm
->reg
[DCPU16_REG_C
] = keyboard
->buf
[keyboard
->buf_head
];
159 keyboard
->buf_head
+= 1;
160 keyboard
->buf_head
%= keyboard
->buf_sz
;
163 case 2: /* get currently-pressed-state of key in B as C */
164 vm
->reg
[DCPU16_REG_C
] = keyboard
->keys_pressed
[reg_b
& 0x00ff];
167 case 3: /* set interrupt state */
168 keyboard
->interrupt_message
= reg_b
;
174 struct dcpu16_hw
*keyboard_new(struct dcpu16
*vm
) {
175 struct dcpu16_hw
*hw
;
178 hw
= calloc(1, sizeof *hw
);
180 vm
->warn_cb_("%s():%s", "calloc", strerror(errno
));
183 memcpy(hw
, &hw_
, sizeof *hw
);
184 hw
->data
= calloc(1, sizeof hw
->data
);
185 if (hw
->data
== NULL
) {
186 vm
->warn_cb_("%s():%s", "calloc", strerror(errno
));
191 b
= calloc(BUF_SZ
, sizeof *b
);
193 vm
->warn_cb_("%s():%s", "calloc", strerror(errno
));
198 ((struct keyboard_
*)(hw
->data
))->buf
= b
;
199 ((struct keyboard_
*)(hw
->data
))->buf_sz
= BUF_SZ
;
206 void keyboard_del(struct dcpu16_hw
**hw
) {
210 free(((struct keyboard_
*)((*hw
)->data
))->buf
);
211 ((struct keyboard_
*)((*hw
)->data
))->buf
= NULL
;