📄 ps2kbdmou_ecos.c
字号:
// Start by masking out the interrupts. Other code such as the HAL // or RedBoot may think it currently owns the keyboard, and I do // not want any interference from them while setting up the // interrupt handlers. cyg_drv_interrupt_mask_intunsafe(CYGNUM_HAL_INTERRUPT_KEYBOARD); cyg_drv_interrupt_mask_intunsafe(CYGNUM_HAL_INTERRUPT_IRQ12); // Install my own interrupt handler, overwriting anything that might // be there already. cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_KEYBOARD, 0, 0, &ps2_isr, &ps2_dsr, &ps2kbd_interrupt_handle, &ps2kbd_interrupt_data); cyg_drv_interrupt_attach(ps2kbd_interrupt_handle); cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_IRQ12, 0, 0, &ps2_isr, &ps2_dsr, &ps2mouse_interrupt_handle, &ps2mouse_interrupt_data); cyg_drv_interrupt_attach(ps2mouse_interrupt_handle); // Get the device into a known state. ps2_send_command(KC_CONTROL_DISABLE_AUX, NULL, 0, 0); ps2_send_command(KC_CONTROL_DISABLE_KBD, NULL, 0, 0); // Discard any current data. HAL_READ_UINT8(KC_STATUS, status); while (status & KC_STATUS_OUTB) { HAL_READ_UINT8(KC_OUTPUT, data); HAL_READ_UINT8(KC_STATUS, status); } // Now restart and reset the keyboard. ps2_send_command(KC_CONTROL_ENABLE_KBD, NULL, 0, 0); buf[0] = KC_KBDC_STANDARD_DISABLE; ps2_send_command_poll(KC_CONTROL_NULL, buf, 1, 0); buf[0] = KC_KBDC_LED_ONOFF; buf[1] = 0; ps2_send_command_poll(KC_CONTROL_NULL, buf, 2, 0); // The keyboard-specific initialization can now reenable the keyboard // using enable // Similarly for a mouse // Standard mode means 100 samples/s, 1:1 scaling, stream mode, 4 counts/mm resolution, // and transferdisabled. Stream mode is important, that means mouse data will // be immediately available rather than requiring separate control messages to // read a packet. ps2_send_command(KC_CONTROL_ENABLE_AUX, NULL, 0, 0); buf[0] = KC_MOUSEC_SET_STANDARD; ps2_send_command_poll(KC_CONTROL_NULL, buf, 1, 1); buf[0] = KC_MOUSEC_SET_SAMPLE_RATE; buf[1] = 0x0A; ps2_send_command_poll(KC_CONTROL_NULL, buf, 2, 1); // WRITE_MODE does not appear to involve an ACK ps2_send_command_poll(KC_CONTROL_WRITE_MODE, NULL, 0, 0); do { HAL_READ_UINT8(KC_STATUS, status); } while (status & KC_STATUS_INPB); HAL_WRITE_UINT8(KC_INPUT, KC_MODE_KBD_INT | KC_MODE_MOU_INT | KC_MODE_SYS | KC_MODE_KCC); cyg_drv_interrupt_unmask_intunsafe(CYGNUM_HAL_INTERRUPT_KEYBOARD); cyg_drv_interrupt_unmask_intunsafe(CYGNUM_HAL_INTERRUPT_IRQ12);}// ----------------------------------------------------------------------------static intPS2Mouse_Open(MOUSEDEVICE* pmd){ unsigned char buf[1]; ps2_initialize(); buf[0] = KC_MOUSEC_ENABLE; ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 1);}// Closing the mouse is equivalent to disabling. It is assumed that we// are not in the middle of a packet transfer, which could really// confuse things.static voidPS2Mouse_Close(void){ unsigned char buf[1]; buf[0] = KC_MOUSEC_SET_STANDARD; ps2_send_command_wait(KC_CONTROL_NULL, buf, 1, 1); ps2mou_buffer_index = 0;}static intPS2Mouse_GetButtonInfo(void){ return MWBUTTON_L | MWBUTTON_R;}// The mouse is used in its default setup, which means 1:1 scaling.// Setting the threshold to 5 seems to match most other drivers...static voidPS2Mouse_GetDefaultAccel(int* pscale, int* pthresh){ if (NULL != pscale) { *pscale = 1; } if (NULL != pthresh) { *pthresh = 5; }}static intPS2Mouse_Read(MWCOORD* dx_arg, MWCOORD* dy_arg, MWCOORD* dz_arg, int* bp_arg){ int result = 0; MWCOORD dx = 0; MWCOORD dy = 0; int buttons = 0; cyg_drv_isr_lock(); if (ps2mou_changed) { dx = ps2mou_dx; dy = 0 - ps2mou_dy; // microwindows directions are the opposite from the hardware buttons = ps2mou_buttons; ps2mou_dx = 0; ps2mou_dy = 0; ps2mou_changed = 0; result = 1; } cyg_drv_isr_unlock(); if (result) { if (NULL != dx_arg) { *dx_arg = dx; } if (NULL != dy_arg) { *dy_arg = dy; } if (NULL != dz_arg) { *dz_arg = 0; } if (NULL != bp_arg) { *bp_arg = buttons; } } return result;}static intPS2Mouse_Poll(void){ return 0 != ps2mou_changed;}MOUSEDEVICE mousedev = { PS2Mouse_Open, PS2Mouse_Close, PS2Mouse_GetButtonInfo, PS2Mouse_GetDefaultAccel, PS2Mouse_Read, PS2Mouse_Poll};// ----------------------------------------------------------------------------// Extracting data from the scancode buffer and turning it into// ASCII. This is only called from thread context by the poll() and// read() routines, although the scancode buffer is updated in ISR// context.// The current keyboard event, if any. This involves processing// the scancodes held in the circular buffer and translating them// to ASCII.static MWKEY ps2kbd_current_key = MWKEY_UNKNOWN;static MWKEYMOD ps2kbd_current_modifiers = 0;static MWSCANCODE ps2kbd_current_scancode = 0;static int ps2kbd_current_keydown = 0;// Translation between scancodes and characters, i.e. keymaps.// For now a relatively simple approach is used. The keymaps// only cope with shifted vs. unshifted. The control key// is handled specially. Anything cleverer is left to microwindows.//// Microwindows excepts key events in the form of MWKEY's, which// are unsigned shorts. Special keys such as the function keys// have suitable #define's in mwtypes.h.//// There is a complication with PC keyboards in that some keys// generate multi-byte sequences, usually starting with 0xE0typedef struct ps2kbd_keymap_entry { MWKEY normal; MWKEY shifted;} ps2kbd_keymap_entry;// This keymap is for a Dell Inspiron laptop with a Japanese// keyboard. It may not match exactly with other keyboards,// but is probably good enough for now.static const ps2kbd_keymap_entry ps2kbd_keymap[] = { { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // Scancode 0 unused { MWKEY_ESCAPE, MWKEY_ESCAPE }, { '1', '!' }, { '2', '"' }, { '3', '#' }, { '4', '$' }, { '5', '%' }, { '6', '&' }, { '7', '\'' }, { '8', '(' }, { '9', ')' }, // Scancode 10 { '0', '~' }, { '-', '=' }, { '^', '_' }, { MWKEY_BACKSPACE, MWKEY_BACKSPACE }, { MWKEY_TAB, MWKEY_TAB }, { 'q', 'Q' }, // 0x10 { 'w', 'W' }, { 'e', 'E' }, { 'r', 'R' }, { 't', 'T' }, // 20 { 'y', 'Y' }, { 'u', 'U' }, { 'i', 'I' }, { 'o', 'O' }, { 'p', 'P' }, { '@', '`' }, { '[', '{' }, { MWKEY_ENTER, MWKEY_ENTER }, { MWKEY_LCTRL, MWKEY_LCTRL }, { 'a', 'A' }, // 30 { 's', 'S' }, { 'd', 'D' }, // 0x20 { 'f', 'F' }, { 'g', 'G' }, { 'h', 'H' }, { 'j', 'J' }, { 'k', 'K' }, { 'l', 'L' }, { ';', '+' }, { ':', '*' }, // 40 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // Japanese-only, top-left below escape { MWKEY_LSHIFT, MWKEY_LSHIFT }, { ']', '}' }, { 'z', 'Z' }, { 'x', 'X' }, { 'c', 'C' }, { 'v', 'V' }, { 'b', 'B' }, // 0x30 { 'n', 'N' }, { 'm', 'M' }, // 50 { ',', '<' }, { '.', '>' }, { '/', '?' }, { MWKEY_RSHIFT, MWKEY_RSHIFT }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // unused ? { MWKEY_LALT, MWKEY_LALT }, { ' ', ' ' }, // space bar { MWKEY_CAPSLOCK, MWKEY_CAPSLOCK }, { MWKEY_F1, MWKEY_F1 }, { MWKEY_F2, MWKEY_F2 }, // 60 { MWKEY_F3, MWKEY_F3 }, { MWKEY_F4, MWKEY_F4 }, { MWKEY_F5, MWKEY_F5 }, { MWKEY_F6, MWKEY_F6 }, // 0x40 { MWKEY_F7, MWKEY_F7 }, { MWKEY_F8, MWKEY_F8 }, { MWKEY_F9, MWKEY_F9 }, { MWKEY_F10, MWKEY_F10 }, { MWKEY_NUMLOCK, MWKEY_NUMLOCK }, { MWKEY_SCROLLOCK, MWKEY_SCROLLOCK }, // 70 { MWKEY_KP7, MWKEY_KP7 }, // Keypad, not actually present on laptop { MWKEY_KP8, MWKEY_KP8 }, // But accessible via Fn and some centre keys { MWKEY_KP9, MWKEY_KP9 }, { MWKEY_KP_MINUS, MWKEY_KP_MINUS }, { MWKEY_KP4, MWKEY_KP4 }, { MWKEY_KP5, MWKEY_KP5 }, { MWKEY_KP6, MWKEY_KP6 }, { MWKEY_KP_PLUS, MWKEY_KP_PLUS }, { MWKEY_KP1, MWKEY_KP1 }, { MWKEY_KP2, MWKEY_KP2 }, // 80, 0x50 { MWKEY_KP3, MWKEY_KP3 }, { MWKEY_KP0, MWKEY_KP0 }, { MWKEY_KP_PERIOD, MWKEY_KP_PERIOD }, // There are now big gaps // F11 and F12 are 0x57 and 0x58 // 0x70, 0x79 and 0x7b are Japanese compose keys. // 0x73 is backslash and another _ // 0x7d is yen and pipe. // These could be handled by special-case code in the scancode // translation routine, but at 4 bytes per table entry // it is probably just as efficient to extend the table. { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // 84, 0x53 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_F11, MWKEY_F11 }, { MWKEY_F12, MWKEY_F12 }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // 90 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // 0x60 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // 100 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // 110 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, // 0x70 { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN }, { '\\', '_' }, { MWKEY_UNKNOWN, MWKEY_UNKNOWN },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -