⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2kbdmou_ecos.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 4 页
字号:
        new_buttons |= MWBUTTON_R;
    }
    ps2mou_buttons  = new_buttons;

    dx = ps2mou_buffer[1];
    if (0 != (ps2mou_buffer[0] & (0x001 << 4))) {
        // Negative number.
        if (0 != (ps2mou_buffer[0] & (0x01 << 6))) {
            // -ve overflow
            dx = -256;
        } else {
            dx = 0 - (256 - dx);
        }
    } else if (0 != (ps2mou_buffer[0] & (0x01 << 6))) {
        // +ve overflow
        dx = 256;
    }
    ps2mou_dx += dx;
    
    dy = ps2mou_buffer[2];
    if (0 != (ps2mou_buffer[0] & (0x01 << 5))) {
        // Negative number.
        if (0 != (ps2mou_buffer[0] & (0x01 << 7))) {
            // -ve overflow
            dy = -256;
        } else {
            // -ve signed, bottom byte only
            dy = 0 - (256 - dy);
        }
    } else if (0 != (ps2mou_buffer[0] & (0x01 << 7))) {
        // +ve overflow
        dy = 256;
    }
    ps2mou_dy += dy;
    
    ps2mou_changed      = 1;
}

// Mouse data. A PS/2 mouse sends events in the form of
// eight-byte packets. Some of the fields are officially
// reserved and ignored for now.
#define KC_MOUSE_DATA_FLAGS         0x00
#define KC_MOUSE_DATA_FLAGS_YOV     (0x01 << 7)
#define KC_MOUSE_DATA_FLAGS_XOV     (0x01 << 6)
#define KC_MOUSE_DATA_FLAGS_YNG     (0x01 << 5)
#define KC_MOUSE_DATA_FLAGS_XNG     (0x01 << 4)
#define KC_MOUSE_DATA_FLAGS_RIG     (0x01 << 1)
#define KC_MOUSE_DATA_FLAGS_LEF     (0x01 << 0)
#define KC_MOUSE_DATA_X             0x02
#define KC_MOUSE_DATA_Y             0x04
#define KC_MOUSE_DATA_SIZE          0x08

// ----------------------------------------------------------------------------
// An interrupt has occurred. Usually this means that there is data
// in the output register, although errors are possible as well. The
// data can be keyboard scancodes, parts of a mouse packet, or
// replies to control messages.
//
// For now errors are ignored, including parity and timeout errors. In
// theory these are supposed to be handled by requesting a resend. In
// practice that seems to cause as many complications as it might
// solve. For example what should happen if there is already a command
// being sent?
//
// The controller interrupts at two separate vectors, one for keyboard
// and another for mouse. If nested interrupts are enabled this could
// cause problems with nested calls to ps2_isr() updating the global
// data in the wrong order. It may be necessary to have a volatile flag
// to detect nesting, accompanied by an early acknowledge and return to
// the interrupted interrupt handler.

static cyg_uint32
ps2_isr(cyg_vector_t isr_vector, cyg_addrword_t isr_data)
{
    int             status;
    unsigned char   data;

    CYG_UNUSED_PARAM(cyg_addrword_t, isr_data);

    HAL_READ_UINT8(KC_STATUS, status);
    while (status & KC_STATUS_OUTB) {
        HAL_READ_UINT8(KC_OUTPUT, data);
        
        if (status & KC_STATUS_AUXB) {
            // Data from the mouse. This will be either an ACK for a
            // command, a resend request, or a byte for the current
            // packet. When a complete 8-byte packet has been received
            // it can be processed. When an ACK is received the next
            // byte for the current command should get sent, or on
            // completion the sending code can be woken up.
            //
            // The mouse can also send back other data, e.g. in response
            // to a determine-status request. These are disallowed
            // because there is no obvious way of separating out such
            // data from a current mouse packet being transferred.
            //
            // There may also be special bytes sent for disconnect and
            // reconnect. It is not clear how to distinguish those
            // from packet data either.
            if (ps2_command_mouse_waiting_for_ack && ((KC_MOUSE_ACK == data) || (KC_MOUSE_RESEND == data))) {
                int tmp;
                
                if (KC_MOUSE_ACK == data) {
                    // Is there another byte to be sent?
                    ps2_command_index++;
                    if (ps2_command_index < ps2_command_length) {
                        // Send the next byte for the current command
                        do {
                            HAL_READ_UINT8(KC_STATUS, tmp);
                        } while (tmp & KC_STATUS_INPB);
                        HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
                        do {
                            HAL_READ_UINT8(KC_STATUS, tmp);
                        } while (tmp & KC_STATUS_INPB);
                        HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
                    } else {
                        // The whole command has been sent and acknowledged.
                        // Allow the polling thread to resume.
                        ps2_command_index   = 0;
                        ps2_command_length  = 0;
                        ps2_command         = NULL;
                        ps2_command_ack     = 1;
                        ps2_command_mouse_waiting_for_ack = 0;
                    }
                } else {
                    // A resend request for the current byte.
                    do {
                        HAL_READ_UINT8(KC_STATUS, tmp);
                    } while (tmp & KC_STATUS_INPB);
                    HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
                    do {
                        HAL_READ_UINT8(KC_STATUS, tmp);
                    } while (tmp & KC_STATUS_INPB);
                    HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
                }
            } else {
                ps2mou_buffer[ps2mou_buffer_index++] = data;
                if (ps2mou_packet_size == ps2mou_buffer_index) {
                    // A complete packet has been received.
                    ps2mou_synaptics_translate();
                    ps2mou_buffer_index = 0;    // Ready for the next packet
                }
            }
        } else {
            // Data from the keyboard. Usually this will be a scancode.
            // There are a number of other possibilities such as
            // echo replies, resend requests, and acks.
            if ((KC_KBD_ACK == data) && (NULL != ps2_command) && !ps2_command_mouse_waiting_for_ack) {
                // Send the next byte for the current command, or
                // else we have completed.
                ps2_command_index++;
                if (ps2_command_index < ps2_command_length) {
                    int tmp;
                    do {
                        HAL_READ_UINT8(KC_STATUS, tmp);
                    } while (tmp & KC_STATUS_INPB);
                    HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
                } else {
                    ps2_command_index   = 0;
                    ps2_command_length  = 0;
                    ps2_command         = NULL;
                    ps2_command_ack     = 1;
                }
            } else if ((KC_KBD_RESEND == data) && (NULL != ps2_command) && !ps2_command_mouse_waiting_for_ack) {
                int tmp;
                do {
                    HAL_READ_UINT8(KC_STATUS, tmp);
                } while (tmp & KC_STATUS_INPB);
                HAL_WRITE_UINT8(KC_INPUT, ps2_command[ps2_command_index]);
            } else {
                if (((ps2kbd_scancode_buffer_head + 1) % PS2KBD_SCANCODE_BUFSIZE) == ps2kbd_scancode_buffer_tail) {
                    // Already full. The data has to be discarded.
                } else {
                    ps2kbd_scancode_buffer[ps2kbd_scancode_buffer_head] = data;
                    ps2kbd_scancode_buffer_head = (ps2kbd_scancode_buffer_head + 1) % PS2KBD_SCANCODE_BUFSIZE;
                }
            }
        }

        // Just in case the keyboard controller is fast enough to send another byte,
        // go around again.
        HAL_READ_UINT8(KC_STATUS, status);
    }

    // The interrupt has been fully handled. For now there is no point
    // in running a DSR.
    cyg_drv_interrupt_acknowledge(isr_vector);
    return CYG_ISR_HANDLED;
}

// For now the DSR does nothing. 
static void
ps2_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
    CYG_UNUSED_PARAM(cyg_vector_t, vector);
    CYG_UNUSED_PARAM(cyg_ucount32, count);
    CYG_UNUSED_PARAM(cyg_addrword_t, data);
}


// Sending out a command. The controller command, if any, gets sent here.
// This is followed by the first byte for the keyboard or mouse. The
// remaining bytes and any retransmits will be handled by the interrupt
// handler.
static void
ps2_send_command(int controller_command, unsigned char* command, int length, int mouse)
{
    int     status;
    
    CYG_PRECONDITION(NULL == ps2_command, "Only one send command is allowed at a time");
    CYG_PRECONDITION((KC_CONTROL_NULL != controller_command) || (NULL != command), "no-op");
    CYG_PRECONDITION(!mouse || (KC_CONTROL_NULL == controller_command), "cannot combine controller and mouse commands");
    
    ps2_command         = command;
    ps2_command_index   = 0;
    ps2_command_length  = length;
    ps2_command_mouse   = 0;
    ps2_command_ack     = 0;

    if (KC_CONTROL_NULL != controller_command) {
        do {
            HAL_READ_UINT8(KC_STATUS, status);
        } while (status & KC_STATUS_INPB);
        HAL_WRITE_UINT8(KC_CONTROL, controller_command);
    }

    if (length > 0) {
        if (mouse) {
            do {
                HAL_READ_UINT8(KC_STATUS, status);
            } while (status & KC_STATUS_INPB);
            HAL_WRITE_UINT8(KC_CONTROL, KC_CONTROL_WRITE_AUX);
        }
        do {
            HAL_READ_UINT8(KC_STATUS, status);
        } while (status & KC_STATUS_INPB);
        HAL_WRITE_UINT8(KC_INPUT, command[0]);
    }
}

// For now there is little difference between polled and non-polled
// mode, they both just spin until the ACK byte is received. The
// polled version just calls the interrupt handler as well. This is
// probably acceptable for now because commands only get sent during
// initialization, but eventually the non-polled version should be
// using a synch primitive signalled by the dsr.
//
// ACKs are only generated when there is data to be sent, not for
// operations on the control register.
//
// For keyboard commands there is no real problem because the ACK
// character 0xFA does not match a valid scancode. For the mouse
// things are more difficult because 0xFA could be present in the
// data, e.g. as a fairly large movement. Therefore the interrupt
// handler needs to know whether or not a mouse ACK is expected.
// It is assumed that the ACK and any actual 0xFA data get sent
// within a byte of each other so that the 0xFA still ends up in
// the right place in the buffer.
//
// A couple of commands do not result in an ACK. For the mouse this
// includes reset-wrap-mode and reset. For the keyboard this includes
// echo. These commands are not currently used, so there is no need
// to worry about the special cases.

static void
ps2_send_command_poll(int controller_command, unsigned char* command, int length, int mouse)
{
    if ((NULL != command) && mouse) {
        ps2_command_mouse_waiting_for_ack = 1;
    }
    ps2_send_command(controller_command, command, length, mouse);
    if (NULL != command) {
        for ( ; !ps2_command_ack; ) {
            ps2_isr( CYGNUM_HAL_INTERRUPT_KEYBOARD, 0);
        }
        ps2_command_ack = 0;
    }
}

static void
ps2_send_command_wait(int controller_command, unsigned char* command, int length, int mouse)
{
    if ((NULL != command) && mouse) {
        ps2_command_mouse_waiting_for_ack = 1;
    }
    ps2_send_command(controller_command, command, length, mouse);
    if (NULL != command) {
        for ( ; !ps2_command_ack; )
            ;
        ps2_command_ack = 0;
    }
}


// ----------------------------------------------------------------------------
// Hardware initialization and the interrupt handling.

static cyg_handle_t     ps2kbd_interrupt_handle;
static cyg_interrupt    ps2kbd_interrupt_data;
static cyg_handle_t     ps2mouse_interrupt_handle;
static cyg_interrupt    ps2mouse_interrupt_data;

static void
ps2_initialize(void)
{
    unsigned char   buf[2];
    int             status, data;
    
    // Only perform initialization once, not for both kbd and mouse.
    static int  initialized = 0;
    if (initialized) {
        return;
    }
    initialized++;

⌨️ 快捷键说明

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