📄 keyboard.c
字号:
int s; retries = MAX_KB_BUSY_RETRIES + 1; /* wait until not busy */ do { s = sys_inb(KB_STATUS, &status); if (status & KB_OUT_FULL) { s = sys_inb(KEYBD, &temp); /* discard value */ } if (! (status & (KB_IN_FULL|KB_OUT_FULL)) ) break; /* wait until ready */ } while (--retries != 0); /* continue unless timeout */ return(retries); /* zero on timeout, positive if ready */}/*===========================================================================* * kb_ack * *===========================================================================*/PRIVATE int kb_ack(){/* Wait until kbd acknowledges last command; return zero if this times out. */ int retries, s; u8_t u8val; retries = MAX_KB_ACK_RETRIES + 1; do { s = sys_inb(KEYBD, &u8val); if (u8val == KB_ACK) break; /* wait for ack */ } while(--retries != 0); /* continue unless timeout */ return(retries); /* nonzero if ack received */}/*===========================================================================* * kb_init * *===========================================================================*/PUBLIC void kb_init(tp)tty_t *tp;{/* Initialize the keyboard driver. */ tp->tty_devread = kb_read; /* input function */}/*===========================================================================* * kb_init_once * *===========================================================================*/PUBLIC void kb_init_once(void){ int i; set_leds(); /* turn off numlock led */ scan_keyboard(); /* discard leftover keystroke */ /* Clear the function key observers array. Also see func_key(). */ for (i=0; i<12; i++) { fkey_obs[i].proc_nr = NONE; /* F1-F12 observers */ fkey_obs[i].events = 0; /* F1-F12 observers */ sfkey_obs[i].proc_nr = NONE; /* Shift F1-F12 observers */ sfkey_obs[i].events = 0; /* Shift F1-F12 observers */ } /* Set interrupt handler and enable keyboard IRQ. */ irq_hook_id = KEYBOARD_IRQ; /* id to be returned on interrupt */ if ((i=sys_irqsetpolicy(KEYBOARD_IRQ, IRQ_REENABLE, &irq_hook_id)) != OK) panic("TTY", "Couldn't set keyboard IRQ policy", i); if ((i=sys_irqenable(&irq_hook_id)) != OK) panic("TTY", "Couldn't enable keyboard IRQs", i); kbd_irq_set |= (1 << KEYBOARD_IRQ);}/*===========================================================================* * kbd_loadmap * *===========================================================================*/PUBLIC int kbd_loadmap(m)message *m;{/* Load a new keymap. */ int result; result = sys_vircopy(m->PROC_NR, D, (vir_bytes) m->ADDRESS, SELF, D, (vir_bytes) keymap, (vir_bytes) sizeof(keymap)); return(result);}/*===========================================================================* * do_fkey_ctl * *===========================================================================*/PUBLIC void do_fkey_ctl(m_ptr)message *m_ptr; /* pointer to the request message */{/* This procedure allows processes to register a function key to receive * notifications if it is pressed. At most one binding per key can exist. */ int i; int result; switch (m_ptr->FKEY_REQUEST) { /* see what we must do */ case FKEY_MAP: /* request for new mapping */ result = OK; /* assume everything will be ok*/ for (i=0; i < 12; i++) { /* check F1-F12 keys */ if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {#if DEAD_CODE /* Currently, we don't check if the slot is in use, so that IS * can recover after a crash by overtaking its existing mappings. * In future, a better solution will be implemented. */ if (fkey_obs[i].proc_nr == NONE) { #endif fkey_obs[i].proc_nr = m_ptr->m_source; fkey_obs[i].events = 0; bit_unset(m_ptr->FKEY_FKEYS, i+1);#if DEAD_CODE } else { printf("WARNING, fkey_map failed F%d\n", i+1); result = EBUSY; /* report failure, but try rest */ }#endif } } for (i=0; i < 12; i++) { /* check Shift+F1-F12 keys */ if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {#if DEAD_CODE if (sfkey_obs[i].proc_nr == NONE) { #endif sfkey_obs[i].proc_nr = m_ptr->m_source; sfkey_obs[i].events = 0; bit_unset(m_ptr->FKEY_SFKEYS, i+1);#if DEAD_CODE } else { printf("WARNING, fkey_map failed Shift F%d\n", i+1); result = EBUSY; /* report failure but try rest */ }#endif } } break; case FKEY_UNMAP: result = OK; /* assume everything will be ok*/ for (i=0; i < 12; i++) { /* check F1-F12 keys */ if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) { if (fkey_obs[i].proc_nr == m_ptr->m_source) { fkey_obs[i].proc_nr = NONE; fkey_obs[i].events = 0; bit_unset(m_ptr->FKEY_FKEYS, i+1); } else { result = EPERM; /* report failure, but try rest */ } } } for (i=0; i < 12; i++) { /* check Shift+F1-F12 keys */ if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) { if (sfkey_obs[i].proc_nr == m_ptr->m_source) { sfkey_obs[i].proc_nr = NONE; sfkey_obs[i].events = 0; bit_unset(m_ptr->FKEY_SFKEYS, i+1); } else { result = EPERM; /* report failure, but try rest */ } } } break; case FKEY_EVENTS: m_ptr->FKEY_FKEYS = m_ptr->FKEY_SFKEYS = 0; for (i=0; i < 12; i++) { /* check (Shift+) F1-F12 keys */ if (fkey_obs[i].proc_nr == m_ptr->m_source) { if (fkey_obs[i].events) { bit_set(m_ptr->FKEY_FKEYS, i+1); fkey_obs[i].events = 0; } } if (sfkey_obs[i].proc_nr == m_ptr->m_source) { if (sfkey_obs[i].events) { bit_set(m_ptr->FKEY_SFKEYS, i+1); sfkey_obs[i].events = 0; } } } break; default: result = EINVAL; /* key cannot be observed */ } /* Almost done, return result to caller. */ m_ptr->m_type = result; send(m_ptr->m_source, m_ptr);}/*===========================================================================* * func_key * *===========================================================================*/PRIVATE int func_key(scode)int scode; /* scan code for a function key */{/* This procedure traps function keys for debugging purposes. Observers of * function keys are kept in a global array. If a subject (a key) is pressed * the observer is notified of the event. Initialization of the arrays is done * in kb_init, where NONE is set to indicate there is no interest in the key. * Returns FALSE on a key release or if the key is not observable. */ message m; int key; int proc_nr; int i,s; /* Ignore key releases. If this is a key press, get full key code. */ if (scode & KEY_RELEASE) return(FALSE); /* key release */ key = map_key(scode); /* include modifiers */ /* Key pressed, now see if there is an observer for the pressed key. * F1-F12 observers are in fkey_obs array. * SHIFT F1-F12 observers are in sfkey_req array. * CTRL F1-F12 reserved (see kb_read) * ALT F1-F12 reserved (see kb_read) * Other combinations are not in use. Note that Alt+Shift+F1-F12 is yet * defined in <minix/keymap.h>, and thus is easy for future extensions. */ if (F1 <= key && key <= F12) { /* F1-F12 */ proc_nr = fkey_obs[key - F1].proc_nr; fkey_obs[key - F1].events ++ ; } else if (SF1 <= key && key <= SF12) { /* Shift F2-F12 */ proc_nr = sfkey_obs[key - SF1].proc_nr; sfkey_obs[key - SF1].events ++; } else { return(FALSE); /* not observable */ } /* See if an observer is registered and send it a message. */ if (proc_nr != NONE) { m.NOTIFY_TYPE = FKEY_PRESSED; notify(proc_nr); } return(TRUE);}/*===========================================================================* * show_key_mappings * *===========================================================================*/PRIVATE void show_key_mappings(){ int i,s; struct proc proc; printf("\n"); printf("System information. Known function key mappings to request debug dumps:\n"); printf("-------------------------------------------------------------------------\n"); for (i=0; i<12; i++) { printf(" %sF%d: ", i+1<10? " ":"", i+1); if (fkey_obs[i].proc_nr != NONE) { if ((s=sys_getproc(&proc, fkey_obs[i].proc_nr))!=OK) printf("sys_getproc: %d\n", s); printf("%-14.14s", proc.p_name); } else { printf("%-14.14s", "<none>"); } printf(" %sShift-F%d: ", i+1<10? " ":"", i+1); if (sfkey_obs[i].proc_nr != NONE) { if ((s=sys_getproc(&proc, sfkey_obs[i].proc_nr))!=OK) printf("sys_getproc: %d\n", s); printf("%-14.14s", proc.p_name); } else { printf("%-14.14s", "<none>"); } printf("\n"); } printf("\n"); printf("Press one of the registered function keys to trigger a debug dump.\n"); printf("\n");}/*===========================================================================* * scan_keyboard * *===========================================================================*/PRIVATE int scan_keyboard(){/* Fetch the character from the keyboard hardware and acknowledge it. */ pvb_pair_t byte_in[2], byte_out[2]; byte_in[0].port = KEYBD; /* get the scan code for the key struck */ byte_in[1].port = PORT_B; /* strobe the keyboard to ack the char */ sys_vinb(byte_in, 2); /* request actual input */ pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT); /* strobe bit high */ pv_set(byte_out[1], PORT_B, byte_in[1].value); /* then strobe low */ sys_voutb(byte_out, 2); /* request actual output */ return(byte_in[0].value); /* return scan code */}/*===========================================================================* * do_panic_dumps * *===========================================================================*/PUBLIC void do_panic_dumps(m)message *m; /* request message to TTY */{/* Wait for keystrokes for printing debugging info and reboot. */ int quiet, code; /* A panic! Allow debug dumps until user wants to shutdown. */ printf("\nHit ESC to reboot, DEL to shutdown, F-keys for debug dumps\n"); (void) scan_keyboard(); /* ack any old input */ quiet = scan_keyboard();/* quiescent value (0 on PC, last code on AT)*/ for (;;) { tickdelay(10); /* See if there are pending request for output, but don't block. * Diagnostics can span multiple printf()s, so do it in a loop. */ while (nb_receive(ANY, m) == OK) { switch(m->m_type) { case FKEY_CONTROL: do_fkey_ctl(m); break; case SYS_SIG: do_new_kmess(m); break; case DIAGNOSTICS: do_diagnostics(m); break; default: ; /* do nothing */ } tickdelay(1); /* allow more */ } code = scan_keyboard(); if (code != quiet) { /* A key has been pressed. */ switch (code) { /* possibly abort MINIX */ case ESC_SCAN: sys_abort(RBT_REBOOT); return; case DEL_SCAN: sys_abort(RBT_HALT); return; } (void) func_key(code); /* check for function key */ quiet = scan_keyboard(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -