Annotation of tme/serial/kb-sun.c, revision 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.