|
|
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.