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 + -
显示快捷键?