gonzui


Format: Advanced Search

tkernel_2/driver/tef_em1d/kbpd/src/key.cbare sourcepermlink (0.05 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by T-Engine Forum at 2014/09/10.
   11:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   12:  *
   13:  *----------------------------------------------------------------------
   14:  */
   15: 
   16: /*
   17:  *      inkey.c
   18:  *
   19:  *       KB/PD device manager
   20:  *       Enableware function for key input (state machine) processing
   21:  */
   22: 
   23: #include "kbpd.h"
   24: 
   25: #define keyMode         (kpMgrInfo.kb.keyMode)
   26: 
   27: /*
   28:  * sending quasi-device message for shift press
   29:  */
   30: LOCAL void sendPseudoSPressMsg( void )
   31: {
   32:         CommonMsg      *msg = &kpMgrInfo.statMach.spressMsg;
   33: 
   34:         if ( msg->cmd.read == 0 ) {
   35:                 /* It was already send, and so unnecessary */
   36:                 return;
   37:         }
   38: 
   39:         msg->cmd.read = 0;
   40: 
   41:         /* sending shift press message */
   42:         kpSendPseudoMsg((T_MSG*)msg);
   43: }
   44: 
   45: /*
   46:  * generate shift key event
   47:  */
   48: LOCAL void makeShiftKeyEvent( InnerEvent *evt, InnEvtType type,
   49:                                                 ShiftKeyKind skind )
   50: {
   51:         evt->type = type;
   52:         evt->i.sft.kind = skind;
   53: 
   54:         if ( type == IE_S_PRESS ) {
   55:                 /* sending quasi-device message for shift press */
   56:                 sendPseudoSPressMsg();
   57:         }
   58: }
   59: 
   60: #if 0   // unused function
   61: /*
   62:  * generate shift key error event
   63:  */
   64: LOCAL void makeShiftKeyErrorEvent( InnerEvent *evt )
   65: {
   66:         evt->type = IE_KEYERR;
   67:         evt->i.key.keytop.w = InvalidKeytop;
   68: }
   69: #endif
   70: 
   71: /*
   72:  * shift key : release status
   73:  */
   74: LOCAL KState ssRelease( KeyState *skey, InnerEvent *evt, ReceiveData *msg )
   75: {
   76:         W              keykind;
   77:         SYSTIM         lnow;
   78:         UW             now;
   79:         ER             err;
   80: 
   81:         if ( msg == NULL ) return SS_RELEASE;
   82: 
   83:         switch ( msg->head.cmd.cmd ) {
   84:           case INP_KEY:
   85:                 if ( msg->kb.stat.press != 0 ) break;
   86:                 /* no break */
   87:           default:
   88:                 return SS_RELEASE;
   89:         }
   90: 
   91:         /* current time */
   92:         err = tk_get_tim(&lnow);
   93:         if ( err != E_OK ) {
   94:                 DEBUG_PRINT(("ssRelease, tk_get_tim err = %d\n", err));
   95:                 return SS_ERROR;
   96:         }
   97:         now = lnow.lo;
   98: 
   99:         /* repeated press during the time interval for double click, key type is not changed. */
  100:         if ( !(skey->u.s.pressCount == 1
  101:                 && (now - skey->u.s.pressTime) <= keyMode.dclktime) ) {
  102: 
  103:                 /* key type */
  104:                 keykind = kpGetKeyKind(skey->keytop);
  105: 
  106:                 if ( keykind <= NormalKey ) {
  107:                         /* enter the ordinary state machine for normal keys */
  108:                         MEMSET(&skey->u.i, 0, sizeof(skey->u.i));
  109:                         return KS_RELEASE;
  110:                 }
  111: 
  112:                 skey->u.s.skind = keykind;
  113:         }
  114: 
  115:         return SS_ONTIME;
  116: }
  117: 
  118: /*
  119:  * shift key : ON wait during effective time
  120:  */
  121: LOCAL KState ssOnTime( KeyState *skey, InnerEvent *evt, ReceiveData *msg )
  122: {
  123:         SYSTIM         lnow;
  124:         UW             now;
  125:         ER             err;
  126: 
  127:         if ( msg == NULL ) {
  128:                 if ( keyMode.ontime == 0 ) goto spress;
  129: 
  130:                 /* timeout setting for ON effective time */
  131:                 err = kpSetAlarm(&skey->alm, keyMode.ontime);
  132:                 if ( err != E_OK ) {
  133:                         DEBUG_PRINT(("ssOnTime, SetAlarm err = %d\n", err));
  134:                         return SS_ERROR;
  135:                 }
  136:                 return SS_ONTIME;
  137:         }
  138: 
  139:         switch ( msg->head.cmd.cmd ) {
  140:           case INP_KEY:
  141:                 if ( msg->kb.stat.press == 0 ) return SS_RELEASE;
  142:                 return SS_ONTIME;
  143: 
  144:           case PIC_TIMEOUT:
  145:                 if ( !kpChkAlarm(&skey->alm, &msg->tmout) ) return SS_ONTIME;
  146:                 break;
  147: 
  148:           default:
  149:                 return SS_ONTIME;
  150:         }
  151: 
  152: spress:
  153:         /* current time */
  154:         err = tk_get_tim(&lnow);
  155:         if ( err != E_OK ) {
  156:                 DEBUG_PRINT(("ssOnTime, tk_get_tim err = %d\n", err));
  157:                 return SS_ERROR;
  158:         }
  159:         now = lnow.lo;
  160: 
  161:         if ( skey->u.s.pressCount == 1
  162:           && (now - skey->u.s.pressTime) <= keyMode.dclktime ) {
  163: 
  164:                 skey->u.s.pressCount = 2;
  165:         } else {
  166:                 skey->u.s.pressCount = 1;
  167:                 skey->u.s.pressTime = now;
  168:         }
  169: 
  170:         /* shift press event generated */
  171:         makeShiftKeyEvent(evt, IE_S_PRESS, skey->u.s.skind);
  172: 
  173:         return SS_PRESS;
  174: }
  175: 
  176: /*
  177:  * shift key: press status
  178:  */
  179: LOCAL KState ssPress( KeyState *skey, InnerEvent *evt, ReceiveData *msg )
  180: {
  181:         if ( msg == NULL ) return SS_PRESS;
  182: 
  183:         switch ( msg->head.cmd.cmd ) {
  184:           case INP_KEY:
  185:                 if ( msg->kb.stat.press != 0 ) return SS_PRESS;
  186:                 break;
  187: 
  188:           default:
  189:                 return SS_PRESS;
  190:         }
  191: 
  192:         return SS_OFFTIME;
  193: }
  194: 
  195: /*
  196:  * shift key: OFF wait during effective time
  197:  */
  198: LOCAL KState ssOffTime( KeyState *skey, InnerEvent *evt, ReceiveData *msg )
  199: {
  200:         InnEvtType     innEvtType;
  201:         SYSTIM         lnow;
  202:         UW             now;
  203:         ER             err;
  204: 
  205:         if ( msg == NULL ) {
  206:                 if ( keyMode.offtime == 0 ) goto srelease;
  207: 
  208:                 /* time out setting for OFF effective time */
  209:                 err = kpSetAlarm(&skey->alm, keyMode.offtime);
  210:                 if ( err != E_OK ) {
  211:                         DEBUG_PRINT(("ssOffTime, SetAlarm err = %d\n", err));
  212:                         return SS_ERROR;
  213:                 }
  214:                 return SS_OFFTIME;
  215:         }
  216: 
  217:         switch ( msg->head.cmd.cmd ) {
  218:           case INP_KEY:
  219:                 if ( msg->kb.stat.press != 0 ) return SS_PRESS;
  220:                 return SS_OFFTIME;
  221: 
  222:           case PIC_TIMEOUT:
  223:                 if ( !kpChkAlarm(&skey->alm, &msg->tmout) ) return SS_OFFTIME;
  224:                 break;
  225: 
  226:           default:
  227:                 return SS_OFFTIME;
  228:         }
  229: 
  230: srelease:
  231:         /* current time */
  232:         err = tk_get_tim(&lnow);
  233:         if ( err != E_OK ) {
  234:                 DEBUG_PRINT(("ssOffTime, tk_get_tim err = %d\n", err));
  235:                 return SS_ERROR;
  236:         }
  237:         now = lnow.lo;
  238: 
  239:         switch ( skey->u.s.pressCount ) {
  240:           case 1:
  241:                 if ( (now - skey->u.s.pressTime) < keyMode.sclktime ) {
  242:                         /* single click */
  243:                         innEvtType = IE_S_SCLK;
  244:                 } else {
  245:                         innEvtType = IE_S_REL;
  246:                 }
  247:                 break;
  248: 
  249:           case 2:
  250:                 if ( (now - skey->u.s.pressTime) < keyMode.dclktime ) {
  251:                         /* double click */
  252:                         innEvtType = IE_S_DCLK;
  253:                 } else {
  254:                         innEvtType = IE_S_REL;
  255:                 }
  256:                 skey->u.s.pressCount = 0;
  257:                 break;
  258: 
  259:           default:
  260:                 innEvtType = IE_S_REL;
  261:                 skey->u.s.pressCount = 0;
  262:         }
  263: 
  264:         /* event generated */
  265:         makeShiftKeyEvent(evt, innEvtType, skey->u.s.skind);
  266: 
  267:         return SS_RELEASE;
  268: }
  269: 
  270: /*
  271:  * shift key: status reset
  272:  */
  273: LOCAL KState ssReset( KeyState *skey, InnerEvent *evt )
  274: {
  275:         /* generate shift release event */
  276:         makeShiftKeyEvent(evt, IE_S_REL, skey->u.s.skind);
  277: 
  278:         kpReleaseKey(skey);
  279: 
  280:         return SS_RELEASE;
  281: }
  282: 
  283: /*
  284:  * cancel shift click
  285:  *       clear the press count of the shift key specified by skind,
  286:  *       and cancel the click or double click which was being monitored.
  287:  */
  288: LOCAL void kpCancelShiftClick( ShiftKeyKind skind )
  289: {
  290:         KeyState       *skey;
  291: 
  292:         for ( skey = (KeyState*)StatMach.useq.next;
  293:                                 skey != (KeyState*)&StatMach.useq;
  294:                                 skey = (KeyState*)skey->q.next ) {
  295: 
  296:                 if ( skey->state >= SS_RELEASE
  297:                   && (skey->u.s.skind & skind) != 0 ) {
  298:                         /* cancel shift click */
  299:                         skey->u.s.pressCount = 0;
  300: 
  301:                         if ( (skind &= ~skey->u.s.skind) == 0 ) break;
  302:                 }
  303:         }
  304: }
  305: 
  306: /* ------------------------------------------------------------------------ */
  307: 
  308: /*
  309:  * send quasi-device message for key up notification
  310:  */
  311: LOCAL void sendPseudoKeyUpMsg( void )
  312: {
  313:         if ( StatMach.keyupMsg.cmd.read != 0 ) {
  314:                 /* send */
  315:                 StatMach.keyupMsg.cmd.read = 0;
  316:                 kpSendPseudoMsg((T_MSG*)&StatMach.keyupMsg);
  317:         }
  318: }
  319: 
  320: /*
  321:  * generate key down event
  322:  */
  323: LOCAL void makeKeyDownEvent( KeyState *inkey, InnerEvent *evt )
  324: {
  325:         KpMetaBut      meta;
  326: 
  327:         /* meta key status when key down occurrs */
  328:         meta.o = kpMgrInfo.kpState.stat;
  329:         meta.u.shift |= inkey->u.i.meta.u.shift;
  330: 
  331:         evt->type = IE_KEYDOWN;
  332:         evt->i.key.keytop = inkey->keytop;
  333:         evt->i.key.meta = inkey->u.i.meta = meta;
  334: 
  335:         inkey->u.i.keydown = TRUE;
  336: }
  337: 
  338: /*
  339:  * generate key up event
  340:  */
  341: LOCAL void makeKeyUpEvent( KeyState *inkey, InnerEvent *evt )
  342: {
  343:         evt->type = IE_KEYUP;
  344:         evt->i.key.keytop = inkey->keytop;
  345:         evt->i.key.meta = inkey->u.i.meta;
  346: 
  347:         inkey->u.i.keydown = FALSE;
  348: }
  349: 
  350: /*
  351:  * generate key error event
  352:  */
  353: LOCAL void makeKeyErrorEvent( KeyState *inkey, InnerEvent *evt )
  354: {
  355:         evt->type = IE_KEYERR;
  356:         evt->i.key.keytop = inkey->keytop;
  357:         evt->i.key.meta = inkey->u.i.meta;
  358: 
  359:         inkey->u.i.keydown = FALSE;
  360: }
  361: 
  362: /*
  363:  * direct input key: release status
  364:  */
  365: LOCAL KState ksRelease( KeyState *inkey, InnerEvent *evt, ReceiveData *msg )
  366: {
  367:         W      keykind = kpGetKeyKind(inkey->keytop);
  368: 
  369:         if ( msg == NULL ) {
  370:                 if ( keykind == NormalKey ) {
  371:                         StatMach.keyPress--;
  372: 
  373:                         /* quasi-event for key up notification */
  374:                         sendPseudoKeyUpMsg();
  375:                 }
  376:                 kpReleaseKey(inkey);
  377:                 return KS_RELEASE;
  378:         }
  379: 
  380:         switch ( msg->head.cmd.cmd ) {
  381:           case INP_KEY:
  382:                 if ( msg->kb.stat.press == 0 ) {
  383:                         kpReleaseKey(inkey);
  384:                         return KS_RELEASE;
  385:                 }
  386:                 break;
  387: 
  388:           case PIC_KEYUP:  /* previous key was released */
  389:                 break;
  390: 
  391:           default:
  392:                 return KS_RELEASE;
  393:         }
  394: 
  395:         /* If ON effective or ineffective period is not zero, simultaneous pressing of multiple keys is
  396:          * not allowed. However, main CC keys are exceptions.
  397:          */
  398:         if ( StatMach.keyPress > 0 && keykind == NormalKey
  399:           && (keyMode.ontime > 0 || keyMode.invtime > 0) ) return KS_RELEASE;
  400: 
  401:         if ( keykind == NormalKey ) StatMach.keyPress++;
  402:         return KS_ONTIME;
  403: }
  404: 
  405: /*
  406:  * direct input key: ON wait during effective time
  407:  */
  408: LOCAL KState ksOnTime( KeyState *inkey, InnerEvent *evt, ReceiveData *msg )
  409: {
  410:         ER     err;
  411: 
  412:         if ( msg == NULL ) {
  413:                 if ( keyMode.ontime == 0 ) return KS_CONTIME;
  414: 
  415:                 /* timeout setting for ON effective time */
  416:                 err = kpSetAlarm(&inkey->alm, keyMode.ontime);
  417:                 if ( err != E_OK ) {
  418:                         DEBUG_PRINT(("ksOnTime, SetAlarm err = %d\n", err));
  419:                         return KS_ERROR;
  420:                 }
  421:                 return KS_ONTIME;
  422:         }
  423: 
  424:         switch ( msg->head.cmd.cmd ) {
  425:           case INP_KEY:
  426:                 if ( msg->kb.stat.press == 0 ) return KS_RELEASE;
  427:                 break;
  428: 
  429:           case PIC_TIMEOUT:
  430:                 if ( kpChkAlarm(&inkey->alm, &msg->tmout) ) return KS_CONTIME;
  431:                 break;
  432: 
  433:           default:
  434:                 return KS_ONTIME;
  435:         }
  436: 
  437:         return KS_ONTIME;
  438: }
  439: 
  440: /*
  441:  * direct input key: wait during simultaneous press period
  442:  */
  443: LOCAL KState ksConTime( KeyState *inkey, InnerEvent *evt, ReceiveData *msg )
  444: {
  445:         KState         next = KS_PRESS;
  446:         ER             err;
  447: 
  448:         if ( msg == NULL ) {
  449:                 /* record shift key status */
  450:                 inkey->u.i.meta.u.shift = kpMgrInfo.spress;
  451: 
  452:                 /* Shift key used for modifying direct input key has its shift click
  453:                    cancelled */
  454:                 kpCancelShiftClick(kpMgrInfo.spress);
  455: 
  456:                 if ( keyMode.contime == 0 ) goto keydown;
  457: 
  458:                 /* timeout setting for simultaneous press period */
  459:                 err = kpSetAlarm(&inkey->alm, keyMode.contime);
  460:                 if ( err != E_OK ) {
  461:                         DEBUG_PRINT(("ksConTime, SetAlarm err = %d\n", err));
  462:                         return KS_ERROR;
  463:                 }
  464:                 return KS_CONTIME;
  465:         }
  466: 
  467:         switch ( msg->head.cmd.cmd ) {
  468:           case INP_KEY:
  469:                 if ( msg->kb.stat.press != 0 ) return KS_CONTIME;
  470:                 next = KS_OFFTIME;
  471:                 break;
  472: 
  473:           case PIC_SPRESS:
  474:                 /* record shift key status, and cancel shift click */
  475:                 inkey->u.i.meta.u.shift |= kpMgrInfo.spress;
  476:                 kpCancelShiftClick(kpMgrInfo.spress);
  477:                 return KS_CONTIME;
  478: 
  479:           case PIC_TIMEOUT:
  480:                 if ( !kpChkAlarm(&inkey->alm, &msg->tmout) ) return KS_CONTIME;
  481:                 break;
  482: 
  483:           default:
  484:                 return KS_CONTIME;
  485:         }
  486: 
  487: keydown:
  488:         /* generate key down event */
  489:         makeKeyDownEvent(inkey, evt);
  490: 
  491:         return next;
  492: }
  493: 
  494: /*
  495:  * direct input key: press status
  496:  */
  497: LOCAL KState ksPress( KeyState *inkey, InnerEvent *evt, ReceiveData *msg )
  498: {
  499:         if ( msg == NULL ) return KS_PRESS;
  500: 
  501:         switch ( msg->head.cmd.cmd ) {
  502:           case INP_KEY:
  503:                 if ( msg->kb.stat.press != 0 ) return KS_PRESS;
  504:                 break;
  505: 
  506:           default:
  507:                 return KS_PRESS;
  508:         }
  509: 
  510:         return KS_OFFTIME;
  511: }
  512: 
  513: /*
  514:  * direct input key: OFF wait during effective time
  515:  */
  516: LOCAL KState ksOffTime( KeyState *inkey, InnerEvent *evt, ReceiveData *msg )
  517: {
  518:         ER     err;
  519: 
  520:         if ( msg == NULL ) {
  521:                 /* time out setting for OFF effective time (offtime == 0 allowed) */
  522:                 err = kpSetAlarm(&inkey->alm, keyMode.offtime);
  523:                 if ( err != E_OK ) {
  524:                         DEBUG_PRINT(("ksOffTime, SetAlarm err = %d\n", err));
  525:                         return KS_ERROR;
  526:                 }
  527:                 return KS_OFFTIME;
  528:         }
  529: 
  530:         switch ( msg->head.cmd.cmd ) {
  531:           case INP_KEY:
  532:                 if ( msg->kb.stat.press != 0 ) return KS_PRESS;
  533:                 return KS_OFFTIME;
  534: 
  535:           case PIC_TIMEOUT:
  536:                 if ( !kpChkAlarm(&inkey->alm, &msg->tmout) ) return KS_OFFTIME;
  537:                 break;
  538: 
  539:           default:
  540:                 return KS_OFFTIME;
  541:         }
  542: 
  543:         /* generate key up event */
  544:         makeKeyUpEvent(inkey, evt);
  545: 
  546:         return KS_INVTIME;
  547: }
  548: 
  549: /*
  550:  * direct input key: wait during ineffective time
  551:  */
  552: LOCAL KState ksInvTime( KeyState *inkey, InnerEvent *evt, ReceiveData *msg )
  553: {
  554:         ER     err;
  555: 
  556:         if ( msg == NULL ) {
  557:                 inkey->u.i.invpress = FALSE;
  558: 
  559:                 /* timeout setting for inffective period (invtime == 0 allowed) */
  560:                 err = kpSetAlarm(&inkey->alm, keyMode.invtime);
  561:                 if ( err != E_OK ) {
  562:                         DEBUG_PRINT(("ksInvTime, SetAlarm err = %d\n", err));
  563:                         return KS_ERROR;
  564:                 }
  565:                 return KS_INVTIME;
  566:         }
  567: 
  568:         switch ( msg->head.cmd.cmd ) {
  569:           case INP_KEY:
  570:                 inkey->u.i.invpress = ( msg->kb.stat.press != 0 );
  571:                 return KS_INVTIME;
  572: 
  573:           case PIC_TIMEOUT:
  574:                 if ( !kpChkAlarm(&inkey->alm, &msg->tmout) ) return KS_INVTIME;
  575:                 break;
  576: 
  577:           default:
  578:                 return KS_INVTIME;
  579:         }
  580: 
  581:         if ( inkey->u.i.invpress ) {
  582:                 /* same key is pushed again during ineffective time period */
  583:                 return KS_ONTIME;
  584:         }
  585: 
  586:         return KS_RELEASE;
  587: }
  588: 
  589: /*
  590:  * direct input key: status reset
  591:  */
  592: LOCAL KState ksReset( KeyState *inkey, InnerEvent *evt )
  593: {
  594:         if ( inkey->u.i.keydown ) {
  595:                 /* generate key errror event */
  596:                 makeKeyErrorEvent(inkey, evt);
  597:         }
  598: 
  599:         if ( inkey->state > KS_RELEASE ) StatMach.keyPress--;
  600:         kpReleaseKey(inkey);
  601: 
  602:         return KS_RELEASE;
  603: }
  604: 
  605: /* ------------------------------------------------------------------------ */
  606: 
  607: /*
  608:  * key state machine
  609:  */
  610: EXPORT void kpExecKeyStateMachine( KeyState *ks, InnerEvent *evt, ReceiveData *msg )
  611: {
  612:         KState prev;
  613: 
  614:         if ( msg->head.cmd.err != DEV_OK ) {
  615:                 if ( ks->state < SS_RELEASE ) {
  616:                         /* reset key status */
  617:                         ks->state = ksReset(ks, evt);
  618:                 } else {
  619:                         /* reset shift status */
  620:                         ks->state = ssReset(ks, evt);
  621:                 }
  622:                 return;
  623:         }
  624: 
  625:         do {
  626:                 switch ( prev = ks->state ) {
  627:                   case KS_RELEASE:
  628:                         ks->state = ksRelease(ks, evt, msg);
  629:                         break;
  630:                   case KS_ONTIME:
  631:                         ks->state = ksOnTime(ks, evt, msg);
  632:                         break;
  633:                   case KS_CONTIME:
  634:                         ks->state = ksConTime(ks, evt, msg);
  635:                         break;
  636:                   case KS_PRESS:
  637:                         ks->state = ksPress(ks, evt, msg);
  638:                         break;
  639:                   case KS_OFFTIME:
  640:                         ks->state = ksOffTime(ks, evt, msg);
  641:                         break;
  642:                   case KS_INVTIME:
  643:                         ks->state = ksInvTime(ks, evt, msg);
  644:                         break;
  645: 
  646:                   case SS_RELEASE:
  647:                         ks->state = ssRelease(ks, evt, msg);
  648:                         break;
  649:                   case SS_ONTIME:
  650:                         ks->state = ssOnTime(ks, evt, msg);
  651:                         break;
  652:                   case SS_PRESS:
  653:                         ks->state = ssPress(ks, evt, msg);
  654:                         break;
  655:                   case SS_OFFTIME:
  656:                         ks->state = ssOffTime(ks, evt, msg);
  657:                         break;
  658: 
  659:                   default:
  660:                         DEBUG_PRINT(("unknown KState(%d)\n", ks->state));
  661:                         return;
  662:                 }
  663:                 if ( (prev < SS_RELEASE) == (ks->state < SS_RELEASE) ) {
  664:                         msg = NULL;
  665:                 }
  666:         } while ( ks->state != prev );
  667: }