|
|
1.1 root 1: /* $Id: kb-sun.c,v 1.2 2003/10/16 02:48:25 fredette Exp $ */
2:
3: /* serial/kb-sun.c - Sun serial keyboard emulation: */
4:
5: /*
6: * Copyright (c) 2003 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <tme/common.h>
37: _TME_RCSID("$Id: kb-sun.c,v 1.2 2003/10/16 02:48:25 fredette Exp $");
38:
39: /* includes: */
40: #include "serial-kb.h"
41:
42: /* macros: */
43:
44: /* Sun keyboard serial output data: */
45: #define KB_SUN_DATAOUT_RESET (0xff)
46: #define KB_SUN_DATAOUT_LAYOUT (0xfe)
47: #define KB_SUN_DATAOUT_IDLE (0x7f)
48: #define KB_SUN_DATAOUT_ERROR (0x7e)
49: #define KB_SUN_DATAOUT_KEYCODE_MASK (0x7f)
50: #define KB_SUN_DATAOUT_KEYCODE_RELEASE (0x80)
51:
52: /* Sun keyboard serial input data. these are also
53: used as state machine states: */
54: #define KB_SUN_DATAIN_NONE (0x00)
55: #define KB_SUN_DATAIN_RESET (0x01)
56: #define KB_SUN_DATAIN_BELL_ON (0x02)
57: #define KB_SUN_DATAIN_BELL_OFF (0x03)
58: #define KB_SUN_DATAIN_CLICK_ON (0x0a)
59: #define KB_SUN_DATAIN_CLICK_OFF (0x0b)
60: #define KB_SUN_DATAIN_LEDS_SET (0x0e)
61: #define KB_SUN_DATAIN_LAYOUT_GET (0x0f)
62:
63: /* Sun LED numbers: */
64: #define KB_SUN_LED_NUM_LOCK (0x1)
65: #define KB_SUN_LED_COMPOSE (0x2)
66: #define KB_SUN_LED_SCROLL_LOCK (0x4)
67: #define KB_SUN_LED_CAPS_LOCK (0x8)
68:
69: /* types: */
70:
71: /* keyboard type information: */
72: struct tme_kb_sun_type_info {
73:
74: /* the keyboard type name: */
75: const char *tme_kb_sun_type_name;
76:
77: /* the keyboard type code: */
78: tme_uint8_t tme_kb_sun_type_code;
79:
80: /* the keyboard type layout: */
81: tme_uint8_t tme_kb_sun_type_layout;
82: };
83:
84: /* the Sun serial keyboard state: */
85: struct tme_serial_kb_sun {
86:
87: /* the keyboard type information: */
88: const struct tme_kb_sun_type_info *tme_serial_kb_sun_type;
89:
90: /* our serial input state: */
91: tme_uint8_t tme_serial_kb_sun_input_state;
92:
93: /* the Num_Lock modifier: */
94: int tme_serial_kb_sun_mod_num_lock;
95: };
96:
97: /* globals: */
98: const struct tme_kb_sun_type_info tme_kb_sun_types[] = {
99:
100: /* the type 2 keyboard: */
101: { "sun-type-2", 2, 0x00 },
102:
103: /* the type 3 keyboard: */
104: { "sun-type-3", 3, 0x00 },
105:
106: /* the type 4 keyboards: */
107: { "sun-type-4-us", 4, 0x00 },
108:
109: /* the type 5 keyboards: */
110: { "sun-type-5-us", 5, 0x21 },
111: { "sun-type-5-unix", 5, 0x22 },
112: };
113:
114: /* this is called to handle serial input: */
115: static int
116: _tme_kb_sun_input(struct tme_serial_kb *serial_kb,
117: tme_uint8_t *data,
118: unsigned int count,
119: tme_serial_data_flags_t data_flags)
120: {
121: struct tme_serial_kb_sun *kb_sun;
122: tme_uint8_t c, output_buffer[2];
123: int new_callouts;
124: unsigned int old_empty, old_controls;
125: tme_keyboard_modifiers_t modifiers_clear, modifiers_set;
126: int modifier;
127:
128: /* recover our data structure: */
129: kb_sun = serial_kb->tme_serial_kb_type_state;
130:
131: /* assume that we won't need any new callouts: */
132: new_callouts = 0;
133:
134: /* note if the serial buffer was empty, and its old controls: */
135: old_empty
136: = tme_serial_buffer_is_empty(&serial_kb->tme_serial_kb_serial_buffer);
137: old_controls
138: = serial_kb->tme_serial_kb_keyboard_ctrl;
139:
140: /* loop over the data: */
141: for (; count > 0; count--) {
142:
143: /* get this data: */
144: c = *(data++);
145:
146: /* dispatch on our state: */
147: switch (kb_sun->tme_serial_kb_sun_input_state) {
148: case KB_SUN_DATAIN_NONE:
149:
150: /* dispatch on the data: */
151: switch (c) {
152:
153: case KB_SUN_DATAIN_RESET:
154:
155: /* add the RESET byte and our keyboard type byte to our output: */
156: output_buffer[0] = KB_SUN_DATAOUT_RESET;
157: output_buffer[1] = kb_sun->tme_serial_kb_sun_type->tme_kb_sun_type_code;
158: tme_serial_buffer_copyin(&serial_kb->tme_serial_kb_serial_buffer,
159: output_buffer,
160: 2,
161: TME_SERIAL_DATA_NORMAL,
162: TME_SERIAL_COPY_FULL_IS_OVERRUN);
163: break;
164:
165: case KB_SUN_DATAIN_BELL_ON:
166: serial_kb->tme_serial_kb_keyboard_ctrl
167: |= TME_KEYBOARD_CTRL_BELL;
168: break;
169:
170: case KB_SUN_DATAIN_BELL_OFF:
171: serial_kb->tme_serial_kb_keyboard_ctrl
172: &= ~TME_KEYBOARD_CTRL_BELL;
173: break;
174:
175: case KB_SUN_DATAIN_CLICK_ON:
176: case KB_SUN_DATAIN_CLICK_OFF:
177: /* do nothing for now; the generic keyboard interface
178: doesn't support keyboard click: */
179: break;
180:
181: /* KB_SUN_DATAIN_LEDS_SET is only supported on type 4 and
182: later keyboards: */
183: case KB_SUN_DATAIN_LEDS_SET:
184: if (kb_sun->tme_serial_kb_sun_type->tme_kb_sun_type_code
185: >= 4) {
186: kb_sun->tme_serial_kb_sun_input_state = c;
187: }
188: break;
189:
190: /* KB_SUN_DATAIN_LAYOUT_GET is only supported on type 4 and
191: later keyboards: */
192: case KB_SUN_DATAIN_LAYOUT_GET:
193: if (kb_sun->tme_serial_kb_sun_type->tme_kb_sun_type_code
194: >= 4) {
195:
196: /* add the LAYOUT byte and our keyboard layout byte to our output: */
197: output_buffer[0] = KB_SUN_DATAOUT_LAYOUT;
198: output_buffer[1] = kb_sun->tme_serial_kb_sun_type->tme_kb_sun_type_layout;
199: tme_serial_buffer_copyin(&serial_kb->tme_serial_kb_serial_buffer,
200: output_buffer,
201: 2,
202: TME_SERIAL_DATA_NORMAL,
203: TME_SERIAL_COPY_FULL_IS_OVERRUN);
204: }
205: break;
206:
207: default:
208: /* ignore this byte: */
209: break;
210: }
211: break;
212:
213: case KB_SUN_DATAIN_LEDS_SET:
214:
215: /* update the keyboard controls and the output modifiers: */
216: /* XXX the mapping of Sun keyboard LED to generic LED is
217: arbitrary: */
218: modifiers_clear = 0;
219: modifiers_set = 0;
220: modifier = kb_sun->tme_serial_kb_sun_mod_num_lock;
221: if (c & KB_SUN_LED_NUM_LOCK) {
222: serial_kb->tme_serial_kb_keyboard_ctrl
223: |= TME_KEYBOARD_CTRL_LED0;
224: if (modifier != TME_KEYBOARD_MODIFIER_NONE) {
225: modifiers_set |= (1 << modifier);
226: }
227: }
228: else {
229: serial_kb->tme_serial_kb_keyboard_ctrl
230: &= ~TME_KEYBOARD_CTRL_LED0;
231: if (modifier != TME_KEYBOARD_MODIFIER_NONE) {
232: modifiers_clear |= (1 << modifier);
233: }
234: }
235: if (c & KB_SUN_LED_COMPOSE) {
236: serial_kb->tme_serial_kb_keyboard_ctrl
237: |= TME_KEYBOARD_CTRL_LED1;
238: }
239: else {
240: serial_kb->tme_serial_kb_keyboard_ctrl
241: &= ~TME_KEYBOARD_CTRL_LED1;
242: }
243: if (c & KB_SUN_LED_SCROLL_LOCK) {
244: serial_kb->tme_serial_kb_keyboard_ctrl
245: |= TME_KEYBOARD_CTRL_LED2;
246: }
247: else {
248: serial_kb->tme_serial_kb_keyboard_ctrl
249: &= ~TME_KEYBOARD_CTRL_LED2;
250: }
251: if (c & KB_SUN_LED_CAPS_LOCK) {
252: serial_kb->tme_serial_kb_keyboard_ctrl
253: |= TME_KEYBOARD_CTRL_LED3;
254: modifiers_set |= (1 << TME_KEYBOARD_MODIFIER_LOCK);
255: }
256: else {
257: serial_kb->tme_serial_kb_keyboard_ctrl
258: &= ~TME_KEYBOARD_CTRL_LED3;
259: modifiers_clear |= (1 << TME_KEYBOARD_MODIFIER_LOCK);
260: }
261:
262: tme_keyboard_buffer_out_modifiers(serial_kb->tme_serial_kb_keyboard_buffer,
263: modifiers_clear,
264: modifiers_set);
265:
266: kb_sun->tme_serial_kb_sun_input_state = KB_SUN_DATAIN_NONE;
267: break;
268:
269: default: assert(FALSE);
270: }
271: }
272:
273: /* if the serial buffer was empty before and it isn't now,
274: update the serial controls and call them out: */
275: if (old_empty
276: && !tme_serial_buffer_is_empty(&serial_kb->tme_serial_kb_serial_buffer)) {
277: new_callouts
278: |= TME_SERIAL_KB_CALLOUT_SERIAL_CTRL;
279: }
280:
281: /* if the keyboard controls have changed, call them out: */
282: if (old_controls
283: != serial_kb->tme_serial_kb_keyboard_ctrl) {
284: new_callouts
285: |= TME_SERIAL_KB_CALLOUT_KEYBOARD_CTRL;
286: }
287:
288: /* set these new callouts: */
289: serial_kb->tme_serial_kb_callout_flags |= new_callouts;
290:
291: return (TME_OK);
292: }
293:
294: /* this is called before a map entry has been added: */
295: static int
296: _tme_kb_sun_map_add_pre(struct tme_serial_kb *serial_kb,
297: struct tme_keyboard_map *map)
298: {
299: /* make sure that the keyboard code is within range: */
300: if (map->tme_keyboard_map_keycode >= KB_SUN_DATAOUT_IDLE) {
301: return (EINVAL);
302: }
303: return (TME_OK);
304: }
305:
306: /* this is called after a map entry has been added: */
307: static int
308: _tme_kb_sun_map_add_post(struct tme_serial_kb *serial_kb,
309: const struct tme_keyboard_map *map)
310: {
311: struct tme_serial_kb_sun *kb_sun;
312: int mode;
313: int rc;
314:
315: /* recover our data structure: */
316: kb_sun = serial_kb->tme_serial_kb_type_state;
317:
318: /* if this key is attached to a modifier: */
319: if (map->tme_keyboard_map_modifier
320: != TME_KEYBOARD_MODIFIER_NONE) {
321:
322: /* modifiers cannot autorepeat: */
323: mode
324: = (TME_KEYBOARD_MODE_PASSTHROUGH
325: | TME_KEYBOARD_MODE_FLAG_NO_AUTOREPEATS);
326:
327: /* if this key is attached to the lock modifier, it soft-locks: */
328: if (map->tme_keyboard_map_modifier
329: == TME_KEYBOARD_MODIFIER_LOCK) {
330: mode |= TME_KEYBOARD_MODE_FLAG_LOCK_SOFT;
331: }
332:
333: /* set the output mode on this key: */
334: rc = tme_keyboard_buffer_out_mode(serial_kb->tme_serial_kb_keyboard_buffer,
335: map->tme_keyboard_map_keycode,
336: mode);
337: assert (rc == TME_OK);
338:
339: /* if this key is Num_Lock, remember
340: which modifier: */
341: if (map->tme_keyboard_map_keysym_note
342: == TME_KEYBOARD_KEYSYM_NOTE_NUM_LOCK) {
343: kb_sun->tme_serial_kb_sun_mod_num_lock
344: = map->tme_keyboard_map_modifier;
345: }
346: }
347:
348: return (TME_OK);
349: }
350:
351: /* this is called to get serial data from a keyboard event: */
352: static tme_uint8_t
353: _tme_kb_sun_event(struct tme_serial_kb *serial_kb,
354: const struct tme_keyboard_event *event)
355: {
356: tme_uint8_t data;
357:
358: /* Sun keyboard key-release data has the high bit set: */
359: data = event->tme_keyboard_event_keyval;
360: if (event->tme_keyboard_event_type
361: == TME_KEYBOARD_EVENT_RELEASE) {
362: data |= KB_SUN_DATAOUT_KEYCODE_RELEASE;
363: }
364: return (data);
365: }
366:
367: /* this initializes Sun serial keyboard emulation: */
368: int
369: _tme_serial_kb_sun_init(struct tme_serial_kb *serial_kb)
370: {
371: struct tme_serial_kb_sun *kb_sun;
372: const struct tme_kb_sun_type_info *type_info;
373: struct tme_serial_config *config;
374: unsigned int type_info_i;
375: int rc;
376:
377: /* allocate the Sun serial keyboard state: */
378: kb_sun = tme_new0(struct tme_serial_kb_sun, 1);
379: serial_kb->tme_serial_kb_type_state = kb_sun;
380:
381: /* initialize our state: */
382: kb_sun->tme_serial_kb_sun_mod_num_lock
383: = TME_KEYBOARD_MODIFIER_NONE;
384:
385: /* find the information for this keyboard type: */
386: type_info = NULL;
387: for (type_info_i = 0;
388: type_info_i < TME_ARRAY_ELS(tme_kb_sun_types);
389: type_info_i++) {
390: if (!strcmp(tme_kb_sun_types[type_info_i].tme_kb_sun_type_name,
391: serial_kb->tme_serial_kb_type)) {
392: type_info = &tme_kb_sun_types[type_info_i];
393: break;
394: }
395: }
396: assert (type_info != NULL);
397: kb_sun->tme_serial_kb_sun_type = type_info;
398:
399: /* set the global output keyboard mode. most keys on Sun keyboards
400: can follow the host: */
401: rc = tme_keyboard_buffer_out_mode(serial_kb->tme_serial_kb_keyboard_buffer,
402: TME_KEYBOARD_KEYVAL_UNDEF,
403: TME_KEYBOARD_MODE_PASSTHROUGH);
404: assert (rc == TME_OK);
405:
406: /* set our type-dependent functions: */
407: serial_kb->tme_serial_kb_type_map_add_pre = _tme_kb_sun_map_add_pre;
408: serial_kb->tme_serial_kb_type_map_add_post = _tme_kb_sun_map_add_post;
409: serial_kb->tme_serial_kb_type_event = _tme_kb_sun_event;
410: serial_kb->tme_serial_kb_type_serial_ctrl = NULL;
411: serial_kb->tme_serial_kb_type_serial_input = _tme_kb_sun_input;
412:
413: /* set our serial configuration: */
414: config = &serial_kb->tme_serial_kb_type_config;
415: memset(config, 0, sizeof(*config));
416: config->tme_serial_config_baud = 1200;
417: config->tme_serial_config_bits_data = 8;
418: config->tme_serial_config_bits_stop = 1;
419: config->tme_serial_config_parity = TME_SERIAL_PARITY_NONE;
420:
421: return (TME_OK);
422: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.