smckbpdd.cpp

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C++ 代码 · 共 2,209 行 · 第 1/5 页

CPP
2,209
字号
       bcsr->bcsr0 |= smc->Rs232Enable;   /* Assert the transceiver enable */
       #endif
    #endif


// #else

//    KernelIoControl( ENABLE_EXT_HW or POWER_ON or RD_AND_OR_WT, ...);

#endif // SDB_RPXL || SDB_CLLF

    /******************************************************
     * Give keyboard receiver time to recover from power-up reset - IMPORTANT !!
     *
     *   NOTE: The value from Sejin by word of mouth/guess
     *   is 540 ms.  The Sejin value is not enough time for
     *   all receivers.
     ******************************************************/

    DEBUGMSG(ZONE_INIT, 
      (TEXT("Waiting for IR Receiver to recover from power-up reset\r\n")));
    DEBUGMSG(ZONE_INIT, (TEXT("Using OEM_IOCTL_BUSY_STALL . . .\r\n")));

//  Not long enough for NOKD version - works in KD version
//  delay 540 ms
//  KernelIoControl( OEM_IOCTL_BUSY_STALL, 0, 540000*1, 0, 0, 0 );     

    // delay 540 ms * 2
    KernelIoControl( OEM_IOCTL_BUSY_STALL, 
                     NOTUSED, 
                     540000*2, 
                     NOTUSED, 
                     NOTUSED, 
                     NOTUSED );


//  SMCKBD_DEBUG( smc, "Leaving SMC Channel Init routine!!!\r\n" );

    DEBUGMSG(ZONE_INIT, (TEXT("SmcKbd_SmcInit: Exit OK\r\n")));

    return TRUE;
}



////////////////////////////////////////////////////////////////////////////////
//
//  @doc EXTERNAL 
//
//  @func
//
//  Initialize IR Receiver on SMCx port. 
//
//  @parm   SMC_CHANNEL structure pointer
//
//  @rdesc  Return TRUE if able to initialize IR rcvr on SMCx port.
//          Otherwise, return FALSE.
//
////////////////////////////////////////////////////////////////////////////////

unsigned char IrRcvrLED[] =
{
    IR_RCVR_LED_CMD | IR_RCVR_NUM_LOCK_LED | IR_RCVR_SCROLL_LOCK_LED,
    IR_RCVR_LED_CMD,
    IR_RCVR_LED_CMD | IR_RCVR_NUM_LOCK_LED | IR_RCVR_CAPS_LOCK_LED,
    IR_RCVR_LED_CMD,
    IR_RCVR_LED_CMD | IR_RCVR_CAPS_LOCK_LED | IR_RCVR_SCROLL_LOCK_LED,
    IR_RCVR_LED_CMD,
    IR_RCVR_LED_CMD | IR_RCVR_NUM_LOCK_LED,
    IR_RCVR_LED_CMD | IR_RCVR_CAPS_LOCK_LED,
    IR_RCVR_LED_CMD | IR_RCVR_SCROLL_LOCK_LED,
    IR_RCVR_LED_CMD
};

// NOTE:  It is necessary to define RCVR_RETRY_COUNT because of an
//        anomaly in some of the 821 chips that causes a failure 
//        on the first read operation.

#define RCVR_RETRY_COUNT 3

BOOLEAN
SmcKbd_SmcIrKbdRcvrInit(
    SMC_CHANNEL *smc
    )
{
    unsigned char event;
    int i;
    int poll_count;
    BOOLEAN status_ok = FALSE;

    UINT32 rcvrInitFailCount = 0;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("SmcKbd_SmcIrKbdRcvrInit: Entry.\r\n")));

do {

    if( rcvrInitFailCount != 0)
    {
        DEBUGMSG( ZONE_ERROR, 
          ( TEXT("Receiver INIT Failure Count = %x - Retry in progress\r\n"),
                rcvrInitFailCount ) );
    }

    DEBUGMSG(ZONE_INIT, (TEXT("Issuing RESET Command to IR Receiver\r\n")));

    /* send reset command to receiver */
    if ( ! (SmcKbd_PutChar( smc, IR_RCVR_RESET_CMD ))) {
        DEBUGMSG(ZONE_ERROR, ( TEXT("SmcKbd_PutChar() FAILED!!!\r\n") ) );
    }

    /* Wait for Tx Event or timeout */
    poll_count = 0x100000;

    DEBUGMSG(ZONE_INIT, (TEXT("Polling for Tx Event . . .\r\n")));

    do
    {
        /* Wait for transmit to complete (character in FIFO) */
        SmcKbd_Poll( smc, &event );
    }
    while( !(event & EVENT_TX) && --poll_count );

    if( poll_count == 0 )
    {
        SMCKBD_DEBUG( smc, "No Tx event after issuing Receiver RESET\r\n" );

        DEBUGMSG(ZONE_ERROR, 
          (TEXT("No Tx event after issuing Receiver RESET\r\n" )));
    }

    if( !(event & EVENT_TX) )
    {
        SMCKBD_DEBUG( smc, "Unexpected event status\r\n" );
        return( FALSE );   /* This may be abrupt but will do for now */
    }
    else
#ifdef SMC_KBD_DEBUG
        smc->tx_event_count++;
#endif

    /******************************************************
     *
     * Give keyboard receiver time to recover from reset - IMPORTANT !!!
     *
     *   NOTE: The value from Sejin by word of mouth/guess
     *   is 540 ms.  The Sejin value is not enough time for
     *   all receivers.
     *
     ******************************************************/

    DEBUGMSG(ZONE_INIT, 
      (TEXT("Waiting for IR Receiver to recover from RESET command\r\n")));
    DEBUGMSG(ZONE_INIT, (TEXT("Using OEM_IOCTL_BUSY_STALL . . .\r\n")));

//  Not long enough for NOKD version - works in KD version
//  delay 540 ms
//  KernelIoControl( OEM_IOCTL_BUSY_STALL, 0, 540000*1, 0, 0, 0 );     

    // delay 540 ms * 2
    KernelIoControl( OEM_IOCTL_BUSY_STALL, 
                    NOTUSED, 
                    540000*2, 
                    NOTUSED, 
                    NOTUSED, 
                    NOTUSED );     


    /********************************************************/
    /* set up Rx BD to timeout after 100 character times    */
    /* Idle checking begins after first received character. */
    /********************************************************/

    smc->PramPtr->max_idl = 100;

    /* send Self-test/revision command to receiver */

    DEBUGMSG(ZONE_INIT, (TEXT("Issuing SELF_TEST Command to IR Receiver\r\n")));

    if ( ! (SmcKbd_PutChar( smc, IR_RCVR_SELFTEST_CMD ))) {
        DEBUGMSG(ZONE_ERROR, ( TEXT("SmcKbd_PutChar() FAILED!!!\r\n") ) );
    }

    /* Wait for response from keyboard receiver */
    poll_count = 0x200000;

    do
    {
        /* Wait for IR receiver to respond with SelfTest result/revision */
        SmcKbd_Poll( smc, &event );
    }
    while( !(event & EVENT_RX) && --poll_count );


    /* Disable idle checking */

    smc->PramPtr->max_idl = 0;

    if( event & EVENT_RX )
    {
        status_ok = TRUE;

        DEBUGMSG(ZONE_INIT, 
          (TEXT("Rx Event detected after ST command issued . . .\r\n")));

#ifdef SMC_KBD_DEBUG
        smc->rx_event_count++;
#endif

        /* Loop if rxbd empty */
        while( smc->ProcRxBD->bd_status & RBD_EMPTY )
            ;

        /*
         * Make sure no errors occurred for the packet
         */

        if( smc->ProcRxBD->bd_status & RBD_IDLE )
        {
            // NOTE: MUST clear status in BD !!
            smc->ProcRxBD->bd_status &= ~RBD_IDLE;
        }
        else
        {
            SMCKBD_DEBUG( smc, "RX IDLE Event NOT Detected after SelfTest\r\n");
            DEBUGMSG( ZONE_ERROR,
          (TEXT("RX IDLE Event NOT Detected after SelfTest - Status = %2x\r\n"),
                smc->ProcRxBD->bd_status ) );
        }

        if( smc->ProcRxBD->bd_status & RBD_STATUS_ERROR_MASK )
        {
            SMCKBD_DEBUG( smc, "Error Detected in ST result ProcRxBD\r\n" );
            DEBUGMSG( ZONE_ERROR,
              ( TEXT("Error Detected in ST result ProcRxBD - Status = %2x\r\n"),
            smc->ProcRxBD->bd_status ) );
            status_ok = FALSE;
            rcvrInitFailCount++;
        }

        else if( smc->ProcRxBD->bd_length != 2 )
        {
            SMCKBD_DEBUG( smc, "Bad BD length for ST result\r\n" );
            DEBUGMSG( ZONE_ERROR,
              ( TEXT("Bad BD length for ST result - Length = %2x\r\n"),
                smc->ProcRxBD->bd_length ) );
            status_ok = FALSE;
            rcvrInitFailCount++;
        }

        else
        {
            /* verify receiver status ok and return status */

            DEBUGMSG( 1, ( TEXT("Verifying SelfTest Results OK\r\n") ) );

// INTERNAL BUFFERS

// This works since VirtualAlloc() allocates pages on 64k bourndaries.
// The problem is that the BD buffer addresses are physical addresses,
// and for CPU access we use virtual addresses.  The BD buffer address
// entry must be converted to the virtual address before accessing
// packet data.

            PM_IR_RCVR_ST_RESPONSE *stResponsePkt =
                                                (PM_IR_RCVR_ST_RESPONSE *) 
            ( ((UINT32)(smc->ProcRxBD->bd_addr) & 0xffff) | (UINT32) v_pDPRam );

            if( stResponsePkt->stResult != (unsigned char)IR_RCVR_SELFTEST_OK )
            {
                SMCKBD_DEBUG( smc, "Bad SELFTEST status from IR Receiver\r\n" );
                DEBUGMSG( ZONE_ERROR, 
                  ( TEXT("Bad SelfTest Status = %2x\r\n"), 
                        stResponsePkt->stResult ) );
                status_ok = FALSE;
                rcvrInitFailCount++;
            }

#ifdef SMC_KBD_DEBUG
            smc->rx_count += smc->ProcRxBD->bd_length;
#endif
        }

        //
        // release BD for reception (should have enough packets for this)
        //
        smc->ProcRxBD->bd_status |= RBD_EMPTY;

        ////////////////////////////////////////////////
        //
        // Adjust InProcess BD pointer for wrap
        //

        if( smc->ProcRxBD == smc->LastRxBD )
        {
            smc->ProcRxBD = smc->RxBDbase;
        }
        else
        {
            smc->ProcRxBD += 1;
        }
    }
    else
    {
        status_ok = FALSE;
        SMCKBD_DEBUG( smc, "No RX event detected before timeout\r\n" );
        DEBUGMSG( ZONE_ERROR, 
          ( TEXT("No RX event detected before timeout\r\n") ) );
        rcvrInitFailCount++;
    }
  }
  while( (status_ok == FALSE) && (rcvrInitFailCount < RCVR_RETRY_COUNT) );

    if( status_ok == FALSE )
    {
        SMCKBD_DEBUG( smc, "Problem in Receiver Init - Bailing out . . . \r\n");
        return( FALSE );
    }

    /*******************************
     * Do LED scan on IR Receiver
     *******************************/

    DEBUGMSG( ZONE_INIT, ( TEXT("Commencing LED Scan Sequence\r\n") ) );

    for( i = 0; i < sizeof(IrRcvrLED); i++ )
    {
        v_LEDstate = IrRcvrLED[i];

        /* send led command to receiver */
        if ( ! (SmcKbd_PutChar( smc, v_LEDstate ))) {
            DEBUGMSG(ZONE_ERROR, ( TEXT("SmcKbd_PutChar() FAILED!!!\r\n") ) );
        }

        /* Wait for Tx Event or timeout */
        poll_count = 0x20000;

        do
        {
            /* Wait for transmit to complete (character in FIFO) */
            SmcKbd_Poll( smc, &event );
        }
        while( !(event & EVENT_TX) && --poll_count );

        if( poll_count == 0 )
        {
            SMCKBD_DEBUG( smc, "No Tx event after issuing LED command\r\n" );
            DEBUGMSG( ZONE_ERROR, 
              ( TEXT( "No Tx event after issuing LED command\r\n") ) );
            return( FALSE );   /* This may be abrupt but will do for now */
        }

        if( !(event & EVENT_TX) )
        {
            SMCKBD_DEBUG( smc, "Unexpected event status during LED scan\r\n" );
            DEBUGMSG( ZONE_ERROR, 
              ( TEXT( "Unexpected event status during LED scan\r\n") ) );
            return( FALSE );   /* This may be abrupt but will do for now */
        }
        else
#ifdef SMC_KBD_DEBUG
            smc->tx_event_count++;
#endif

        /*
         * Give user time to see LED pattern
         */

        // delay 250ms
        KernelIoControl( OEM_IOCTL_BUSY_STALL, 
                         NOTUSED, 
                         250000*1, 
                         NOTUSED, 
                         NOTUSED, 
                         NOTUSED );  
    }

//  SMCKBD_DEBUG( smc, "Leaving IR Receiver Init routine!!!\r\n" );
    DEBUGMSG(ZONE_FUNCTION, (TEXT("SmcKbd_SmcIrKbdRcvrInit: Exit OK.\r\n")));

    return( TRUE );
}



////////////////////////////////////////////////////////////////////////////////
//
//  @doc EXTERNAL 
//
//  @func
//
//  Poll the SMCx, returns TRUE if any SMC UART event is detected. 
//
//  @parm   SMC_CHANNEL structure pointer
//  @parm   unsigned char UART event
//
//  @rdesc  Updates caller's event status byte via passed pointer.
//          Returns TRUE if event detected, else returns FALSE.
//
////////////////////////////////////////////////////////////////////////////////
 
BOOLEAN
SmcKbd_Poll(
    SMC_CHANNEL *smc,
    unsigned char *event
    )
{
    unsigned char reg_image;

    /*
     * Get current Receive Buffer Descriptor pointer
     */

    SMC_BD *rbd = smc->ProcRxBD;

    reg_image = smc->RegsPtr->smc_smce;

    if( reg_image )
    {
        *event = reg_image;
#ifdef SMC_KBD_DEBUG
        smc->last_event = reg_image;
#endif
        smc->RegsPtr->smc_smce = reg_image;   /* clear event status */
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}


////////////////////////////////////////////////////////////////////////////////
//
//  @doc EXTERNAL
//
//  @func
//
//  Output a character to SMC. 
//
//  @parm   SMC_CHANN

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?