The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/chips/dtop_handlers.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1992 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        dtop_handlers.c,v $
   29  * Revision 2.8  93/05/15  19:37:47  mrt
   30  *      machparam.h -> machspl.h
   31  * 
   32  * Revision 2.7  93/05/10  20:07:30  rvb
   33  *      No more sys/types.h
   34  *      [93/05/06  09:55:58  af]
   35  * 
   36  * Revision 2.6  93/01/14  17:15:42  danner
   37  *      My attempt at DO-key finessing.
   38  *      [92/12/14            af]
   39  *      Proper spl typing.
   40  *      [92/11/30            af]
   41  * 
   42  *      Throw away the kdb hot key from the keyboard input buffer if
   43  *      lk201_input returned -2. This prevents bogus autorepeat of the
   44  *      hot key and bogus kdb interrupts.
   45  *      [92/10/24            jvh]
   46  * 
   47  * Revision 2.5  92/05/22  15:47:38  jfriedl
   48  *      Got autorepeat to work under X11: just generate two events
   49  *      (up+down) instead of the single metronome one that would
   50  *      not really work.
   51  *      [92/05/20  22:43:35  af]
   52  * 
   53  * Revision 2.3.1.1  92/05/04  14:16:54  af
   54  *      Fixed to not call autorepeat when invoked from debugger.
   55  *      It might be too early (e.g. boothowto=0xc) for timeout().
   56  *      [92/05/04            af]
   57  * 
   58  * Revision 2.3  92/03/05  17:08:21  rpd
   59  *      Changed locators handler to always pass relative coords
   60  *      to screen_motion_event.
   61  *      [92/03/05            af]
   62  * 
   63  * Revision 2.2  92/03/02  18:32:22  rpd
   64  *      Created from DEC specs:
   65  *      "DESKTOPinterconnect Description and Protocol Specification"
   66  *      Version 0.9, Jun 17 1991
   67  *      "Open Desktop Bus, Locator Device Protocol Specification"
   68  *      Version 0.4, Dec 13 1990
   69  *      "Open Desktop Bus, Keyboard Device Protocol Specification"
   70  *      Version 0.7, Jan 9 1991
   71  *      [92/01/19            af]
   72  * 
   73  */
   74 /*
   75  *      File: dtop_handlers.c
   76  *      Author: Alessandro Forin, Carnegie Mellon University
   77  *      Date:   1/92
   78  *
   79  *      Handler functions for devices attached to the DESKTOP bus.
   80  */
   81 
   82 #include <dtop.h>
   83 #if     NDTOP > 0
   84 
   85 #include <mach_kdb.h>
   86 
   87 #include <machine/machspl.h>            /* spl definitions */
   88 #include <mach/std_types.h>
   89 #include <device/io_req.h>
   90 #include <device/tty.h>
   91 
   92 #include <chips/busses.h>
   93 #include <chips/serial_defs.h>
   94 #include <chips/screen_defs.h>
   95 #include <mips/PMAX/tc.h>
   96 
   97 #include <chips/dtop.h>
   98 #include <chips/lk201.h>
   99 
  100 /*
  101  * Default handler function
  102  */
  103 int
  104 dtop_null_device_handler(
  105          dtop_device_t  dev,
  106          dtop_message_t msg,
  107          int            event,
  108          unsigned char  outc)
  109 {
  110         /* See if the message was to the default address (powerup) */
  111 
  112         /* Uhmm, donno how to handle this. Drop it */
  113         if (event == DTOP_EVENT_RECEIVE_PACKET)
  114                 dev->unknown_report = *msg;
  115         return 0;
  116 }
  117 
  118 /*
  119  * Handler for locator devices (mice)
  120  */
  121 int
  122 dtop_locator_handler(
  123          dtop_device_t  dev,
  124          dtop_message_t msg,
  125          int            event,
  126          unsigned char  outc)
  127 {
  128         register unsigned short buttons;
  129         register short          coord;
  130 #if     BYTE_MSF
  131 #       define  get_short(b0,b1)        (((b1)<<8)|(b0))
  132 #else
  133 #       define  get_short(b0,b1)        (((b0)<<8)|(b1))
  134 #endif
  135 
  136         /*
  137          * Do the position first
  138          */
  139         {
  140                 register int            i;
  141                 register boolean_t      moved;
  142                 int                     delta_coords[L_COORD_MAX];
  143 
  144                 /*
  145                  * Get all coords, see if it moved at all (buttons!)
  146                  */
  147                 moved = FALSE;
  148                 for (i = 0; i < dev->locator.n_coords; i++) {
  149 
  150                         coord = get_short(msg->body[2+(i<<1)],
  151                                           msg->body[3+(i<<1)]);
  152 
  153                         if (dev->locator.relative) {
  154                                 /*
  155                                  * Flame on
  156                                  * I am getting tired of this, why do they have to
  157                                  * keep this bug around ?  Religion ?  Damn, they
  158                                  * design a keyboard for X11 use and forget the mouse ?
  159                                  * Flame off
  160                                  */
  161 #define BOGUS_DEC_X_AXIS
  162 #ifdef  BOGUS_DEC_X_AXIS
  163                                 if (i == 1) coord = - coord;
  164 #endif  /* BOGUS_DEC_X_AXIS */
  165                                 /* dev->locator.coordinate[i] += coord; */
  166                         } else {
  167                                 register unsigned int   old_coord;
  168 
  169                                 old_coord = dev->locator.coordinate[i];
  170                                 dev->locator.coordinate[i] = coord;
  171                                 coord = old_coord - coord;
  172                         }
  173                         delta_coords[i] = coord;
  174                         if (coord != 0)
  175                                 moved = TRUE;
  176                 }
  177                 if (moved) {
  178                         /* scale and threshold done higher up */
  179                         screen_motion_event( 0,
  180                                 dev->locator.type,
  181                                 delta_coords[0],
  182                                 delta_coords[1]);
  183                 }
  184         }
  185 
  186         /*
  187          * Time for the buttons now
  188          */
  189 #define new_buttons     coord
  190         new_buttons = get_short(msg->body[0],msg->body[1]);
  191         buttons = new_buttons ^ dev->locator.prev_buttons;
  192         if (buttons) {
  193                 register int    i, type;
  194 
  195                 dev->locator.prev_buttons = new_buttons;
  196                 for (i = 0; buttons; i++, buttons >>= 1) {
  197 
  198                         if ((buttons & 1) == 0) continue;
  199 
  200                         type = (new_buttons & (1<<i)) ? 
  201                                 EVT_BUTTON_DOWN : EVT_BUTTON_UP;
  202                         screen_keypress_event(  0,
  203                                                 dev->locator.type,
  204                                                 dev->locator.button_code[i],
  205                                                 type);
  206                 }
  207         }
  208 #undef  new_buttons
  209 }
  210 
  211 /*
  212  * Handler for keyboard devices
  213  * Special case: outc set for recv packet means
  214  * we are inside the kernel debugger
  215  */
  216 int
  217 dtop_keyboard_handler(
  218          dtop_device_t  dev,
  219          dtop_message_t msg,
  220          int            event,
  221          unsigned char  outc)
  222 {
  223         char            save[11];
  224         register int    msg_len, c;
  225 
  226         /*
  227          * Well, really this code handles just an lk401 and in
  228          * a very primitive way at that.  Should at least emulate
  229          * an lk201 decently, and make that a pluggable module.
  230          * Sigh.
  231          */
  232 
  233         if (event != DTOP_EVENT_RECEIVE_PACKET) {
  234                 switch (event) {
  235                 case DTOP_EVENT_POLL:
  236                     {
  237                         register unsigned int   t, t0;
  238 
  239                         /*
  240                          * Note we will always have at least the
  241                          * end-of-list marker present (a zero)
  242                          * Here stop and trigger of autorepeat.
  243                          * Do not repeat shift keys, either.
  244                          */
  245                         {
  246                                 register unsigned char  uc, i = 0;
  247 
  248 rpt_char:
  249                                 uc = dev->keyboard.last_codes[i];
  250 
  251                                 if (uc == DTOP_KBD_EMPTY) {
  252                                         dev->keyboard.k_ar_state = K_AR_OFF;
  253                                         return 0;
  254                                 }
  255                                 if ((uc >= LK_R_SHIFT) && (uc <= LK_R_ALT)) {
  256                                         /* sometimes swapped. Grrr. */
  257                                         if (++i < dev->keyboard.last_codes_count) 
  258                                                 goto rpt_char;
  259                                         dev->keyboard.k_ar_state = K_AR_OFF;
  260                                         return 0;
  261                                 }
  262                                 c = uc;
  263                         }
  264 
  265                         /*
  266                          * Got a char. See if enough time from stroke,
  267                          * or from last repeat.
  268                          */
  269                         t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500;
  270                         t = approx_time_in_msec();
  271                         if ((t - dev->keyboard.last_msec) < t0)
  272                                 return 0;
  273 
  274                         dev->keyboard.k_ar_state = K_AR_TRIGGER;
  275 
  276                         /*
  277                          * Simplest thing to do is to mimic lk201
  278                          */
  279                         outc = lk201_input(0, LK_REPEAT);
  280                         if ( ! screen_keypress_event(   0,
  281                                                         DEV_KEYBD,
  282                                                         c,
  283                                                         EVT_BUTTON_UP)) {
  284                                 if (outc > 0) cons_input(0, outc, 0);
  285                         } else
  286                                 screen_keypress_event(  0,
  287                                                         DEV_KEYBD,
  288                                                         c,
  289                                                         EVT_BUTTON_DOWN);
  290                         return 0;
  291                     }
  292                 default:        gimmeabreak();/*fornow*/
  293                 }
  294                 return -1;
  295         }
  296 
  297         msg_len = msg->code.val.len;
  298 
  299         /* Check for errors */
  300         c = msg->body[0];
  301         if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) {
  302                 printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]);
  303                 if (c != DTOP_KBD_OUT_ERR) return -1;
  304                 /* spec sez if scan list overflow still there is data */
  305                 msg->body[0] = 0;
  306         }
  307 
  308         dev->keyboard.last_msec = approx_time_in_msec();
  309 
  310         switch (dev->keyboard.k_ar_state) {
  311         case K_AR_IDLE:
  312                 /* if from debugger, timeouts might not be working yet */
  313                 if (outc == 0xff)
  314                         break;
  315                 dtop_keyboard_autorepeat( dev );
  316                 /* fall through */
  317         case K_AR_TRIGGER:
  318                 dev->keyboard.k_ar_state = K_AR_ACTIVE;
  319                 break;
  320         case K_AR_ACTIVE:
  321                 break;
  322         case K_AR_OFF:  gimmeabreak();  /* ??? */
  323                 dev->keyboard.k_ar_state = K_AR_IDLE;
  324         }
  325 
  326         /*
  327          * We can only assume that pressed keys are reported in the
  328          * same order (a minimum of sanity, please) across scans.
  329          * To make things readable, do a first pass cancelling out
  330          * all keys that are still pressed, and a second one generating
  331          * events.  While generating events, do the upstrokes first
  332          * from oldest to youngest, then the downstrokes from oldest
  333          * to youngest.  This copes with lost packets and provides
  334          * a reasonable model even if scans are too slow.
  335          */
  336 
  337         /* make a copy of new state first */
  338         {
  339                 register char   *p, *q, *e;
  340 
  341                 p = save;
  342                 q = (char*)msg->body;
  343                 e = (char*)&msg->body[msg_len];
  344 
  345                 while (q < e)
  346                         *p++ = *q++;
  347         }
  348 
  349         /*
  350          * Do the cancelling pass
  351          */
  352         {
  353                 register char   *ls, *le, *ns, *ne, *sync;
  354 
  355                 ls = (char*)dev->keyboard.last_codes;
  356                 le = (char*)&dev->keyboard.last_codes[dev->keyboard.last_codes_count];
  357                 ns = (char*)msg->body;
  358                 ne = (char*)&msg->body[msg_len];
  359 
  360                 /* sync marks where to restart scanning, saving
  361                    time thanks to ordering constraints */
  362                 for (sync = ns; ls < le; ls++) {
  363                         register char   c = *ls;
  364                         for (ns = sync; ns < ne; ns++)
  365                                 if (c == *ns) {
  366                                         *ls = *ns = 0;
  367                                         sync = ns + 1;
  368                                         break;
  369                                 }
  370                         /* we could already tell if c is an upstroke,
  371                            but see the above discussion about errors */
  372                 }
  373         }
  374         /*
  375          * Now generate all upstrokes
  376          */
  377         {
  378                 register char   *ls, *le;
  379                 register unsigned char  c;
  380 
  381                 le = (char*)dev->keyboard.last_codes;
  382                 ls = (char*)&dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1];
  383 
  384                 for ( ; ls >= le; ls--)
  385                     if (c = *ls) {
  386                         /* keep kernel notion of lk201 state consistent */
  387                         (void) lk201_input(0,c);                        
  388 
  389                         if (outc == 0)
  390                             screen_keypress_event(0,
  391                                                   DEV_KEYBD,
  392                                                   c,
  393                                                   EVT_BUTTON_UP);
  394                     }
  395         }
  396         /*
  397          * And finally the downstrokes
  398          */
  399         {
  400                 register char   *ns, *ne, c, retc;
  401 
  402                 ne = (char*)msg->body;
  403                 ns = (char*)&msg->body[msg_len - 1];
  404                 retc = 0;
  405 
  406                 for ( ; ns >= ne; ns--)
  407                     if (c = *ns) {
  408                         register unsigned char  data;
  409 
  410                         data = c;
  411                         c = lk201_input(0, data);
  412 
  413                         if (c == -2) {  /* just returned from kdb */
  414                                 /* NOTE: many things have happened while
  415                                    we were sitting on the stack, now it
  416                                    is last_codes that holds the truth */
  417 #if 1
  418                                 /* But the truth might not be welcome.
  419                                    If we get out because we hit RETURN
  420                                    on the rconsole line all is well,
  421                                    but if we did it from the keyboard
  422                                    we get here on the downstroke. Then
  423                                    we will get the upstroke which we
  424                                    would give to X11. People complained
  425                                    about this extra keypress..  so they
  426                                    lose everything. */
  427 
  428                                 dev->keyboard.last_codes_count = 1;
  429                                 dev->keyboard.last_codes[0] = 0;
  430 #endif
  431                                 return -1;
  432                         }
  433 
  434                         /*
  435                          * If X11 had better code for the keyboard this
  436                          * would be an EVT_BUTTON_DOWN.  But that would
  437                          * screwup the REPEAT function. Grrr.
  438                          */
  439                         /* outc non zero sez we are in the debugger */
  440                         if (outc == 0) {
  441                             if (screen_keypress_event(0,
  442                                                   DEV_KEYBD,
  443                                                   data,
  444                                                   EVT_BUTTON_DOWN))
  445                                 c = -1; /* consumed by X */
  446                             else
  447                                 if (c > 0) cons_input(0, c, 0);
  448                         }
  449                         /* return the xlated keycode anyways */
  450                         if ((c > 0) && (retc == 0))
  451                             retc = c;
  452                     }
  453                 outc = retc;
  454         }
  455         /* install new scan state */
  456         {
  457                 register char   *p, *q, *e;
  458 
  459                 p = (char*)dev->keyboard.last_codes;
  460                 q = (char*)save;
  461                 e = (char*)&save[msg_len];
  462 
  463                 while (q < e)
  464                         *p++ = *q++;
  465                 dev->keyboard.last_codes_count = msg_len;
  466         }
  467         return outc;
  468 }
  469 
  470 /*
  471  * Polled operations: we must do autorepeat by hand. Sigh.
  472  */
  473 dtop_keyboard_autorepeat(
  474         dtop_device_t   dev)
  475 {
  476         spl_t   s = spltty();
  477 
  478         if (dev->keyboard.k_ar_state != K_AR_IDLE)
  479                 dtop_keyboard_handler( dev, 0, DTOP_EVENT_POLL, 0);
  480 
  481         if (dev->keyboard.k_ar_state == K_AR_OFF)
  482                 dev->keyboard.k_ar_state = K_AR_IDLE;
  483         else
  484                 timeout( dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency);
  485 
  486         splx(s);
  487 }
  488 
  489 #endif  /*NDTOP>0*/

Cache object: a5221c4c18ee02db8d7e2c38b93ff9a0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.