Annotation of tme/serial/kb-sun.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.