📄 ps2kbdmou_ecos.c
字号:
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_uint32ps2_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 voidps2_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 voidps2_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 voidps2_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 voidps2_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 voidps2_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 + -