PC keyboard driver source code analysis

xiaoxiao2021-03-06  43

1. Writing purposes:

Describe the architecture and working principle of the PC keyboard drive in the UCLinux kernel, which is used to guide the preparation of the driver for the specific embedded keyboard.

II. Reference:

1. "Linux kernel source code scenario analysis (book)" Sections 8.7 and 8.8, Page330 ~ 412

2. Nuclear source code file:

../linux-2.4.x/drivers/char/keyboard.c

../linux-2.4.x/include/ASM-i386/keyboard.h

../linux-2.4.x/drivers/char/pc_keyb.c

../linux-2.4.x/drivers/input/*.*

../linux-2.0.x/drivers/char/keyboard.c

3. Network article: "Writing the kernel-based Linux keyboard logger"

3. PC keyboard drive workflow:

1. Keyboard initialization

This work is mainly implemented by the TTY initialization function TTY_INIT () calls the initialization function kbd_init () implementation of the keyboard driver module. The KBD_INIT () function mainly calls the initialize_kbd () function to complete the work.

Mainly complete work, keyboard self-test, detection, start, register setting, etc., and register the keyboard interrupt service function to the system.

2. Keyboard interrupt response process

When the user button or the release button, the keyboard generates an interrupt signal to the system, the system automatically enters the keyboard interrupt service function processing, which is mainly completed by the keyboard interrupt service function keyboard_interrupt ().

The main completion work is: read the keyboard state from the keyboard status register, read data from the keyboard buffer, according to the read state and data, to perform key code conversion, etc., save the result into the "flip_buffer" data buffer of TTY Area. At the end of the interrupt service function, the keyboard backend processing function (actually a tasklet of the console terminal, the console_tasklet ()) schedule.

3. Keyboard backend processing (not with keyboard driver processing category)

Before the keyboard interrupt service function, the keyboard backend process (actually a tasklet of the console terminal, the console_tasklet ()) is hung into the backend processing queue, and the system finally executes the function when scheduling.

In this function, some keyboards are completed, such as processing keyboard data in FLIP_BUFFER, and stores the result into TTY's READ_BUFFER data buffer.

4. Keyboard data final result passes to user processes (not belonging to keyboard driver processing category)

The READ function pointer of the TTY's File_Operations data structure points to the read_charn () function, which acquires data from the READ_BUFFER data buffer, returns to the user process.

Such a keyboard is completed.

5.

IV. Source file specific analysis:

One thing to note, in the kernel of Linux-2.0.x, keyboard drive main work is

../linux-2.0.x/drivers/char/keyboard.c

The file is completed, and there is no other file, not like Linux-2.4.x kernel except for the file:

../linux-2.4.x/drivers/char/keyboard.c

There are also the following files:

../linux-2.4.x/drivers/char/pc_keyb.c

../linux-2.4.x/include/ASM-i386/keyboard.h

We mainly analyze the keyboard drivers of the Linux-2.4.x kernel here. There are also some related code:

../linux-2.4.x/drivers/char/vt.c

../linux-2.4.x/drivers/char/tty_io.c

../linux-2.4.x/drivers/char/tty_ioctl.c

../linux-2.4.x/drivers/input/*.*

../linux-2.4.x/include/linux/kbd_kern.h

../linux-2.4.x/drivers/char/console.c

1. ../linux-2.4.x/drivers/char/pc_keyb.c

(1) void __init PCKBD_INIT_HW (VOID)

Keyboard initialization function, this function is called by KBD_INIT () (KBD_INIT () called KBD_INIT_HW (), but in i386, KBD_INIT_HW is #define as PCKBD_INIT_HW).

Mainly complete work:

a. Judging whether the keyboard controller exists according to KBD_CONTROLLLLER_PRESENT

b. Call KBD_REQUEST_REGON () Assignment Resources

C. Call KBD_CLEAR_INPUT () Clear Keyboard Controller Buffer Data

d. Keyboard If not reset, call function initialize_kbd () to initialize

e. Set the KBD_RATE function pointer to the PCKBD_RATE () function

f. Call KBD_REQUEST_IRQ (), register the keyboard interrupt service function keyboard_interrupt () to the system.

(2) static char * __INIT INITIALIZE_KBD (VOID)

Keyboard initialization function, the function is called by the PCKBD_INIT_HW ().

Mainly complete work:

a. Call KBD_WRITE_COMMAND_W (KBD_CCMD_SELF_TEST) to perform keyboard self-test

b. Call KBD_WRITE_COMMAND_W (KBD_CCMD_KBD_TEST), perform keyboard detection

C. Call KBD_WRITE_COMMAND_W (KBD_CCMD_KBD_ENABLE), enable keyboard

d. Call the KBD_WRITE_OUTPUT_W (KBD_CMD_RESET) Reset the keyboard, and call the function kbd_wait_for_input () accept the reset status byte and determine whether the reset is successful, if the reset is successful, continue, otherwise the function returns

e. Call KBD_WRITE_OUTPUT_W (KBD_CMD_DISABLE), stop the keyboard work before setting the keyboard work mode. Call KBD_WAIT_FOR_INPUT () accepts the stop keyboard status, if the stop is successful, continue, otherwise the function returns

f. Call KBD_WRITE_COMMAND_W (KBD_CCMD_WRITE_MODE) and KBD_WRITE_OUTPUT_W (...) Set the keyboard operating mode.

g. Some mode settings for the PowerPC keyboard

h. Call KBD_WRITE_OUTPUT_W_AND_WAIT (KBD_CMD_ENENABLE), after completing the keyboard working mode settings, enable keyboard work

i. Finally call KBD_WRITE_OUTPUT_W_AND_WAIT (KBD_CMD_SET_RATE), SET the TYPEMATIC RATE TO MAXIMUM (3) Static Int KBD_WRITE_OUTPUT_W_AND_WAIT (INT DATA)

Send data to keyboard data port functions

Mainly complete work:

a. Call the KBD_WRITE_OUTPUT_W (DATA) function, send data to the keyboard data port

b. Call the KBD_WAIT_FOR_INPUT () Wait for response data for the keyboard.

(4) Static int KBD_WRITE_COMMAND_W_AND_WAIT (INT DATA)

Send command to keyboard data port functions

Mainly complete work:

a. Call the KBD_WRITE_COMMAND_W (DATA) function, send a command to the keyboard command (control) port

b. Call the KBD_WAIT_FOR_INPUT () Wait for the response data of the keyboard

(5) static void kbd_write_output_w (int DATA)

Sending data to the data port function of the keyboard, mainly by KBD_WRITE_OUTPUT (DATA), the KBD_WRITE_OUTPUT (DATA) function and the architecture are very close, generally implemented by assembly code

(6) static void kbd_write_command_w (int data)

Send a command to the keyboard command (control) port function mainly by KBD_WRITE_COMMAND (DATA), the KBD_WRITE_COMMAND (DATA) function and the architecture are very close, generally implemented by the assembly code.

(7) static int __init kbd_wait_for_input (void)

Delay Wait the keyboard to return to the data function, that is, when the loop is waiting, the KBD_READ_DATA () call the function from the read data from the keyboard.

(8) static void __init kbd_clear_input (void)

Send a clear keyboard data, the call function kbd_read_data () keeps reading data from the keyboard, knowing that there is no data.

(9) static int __init kbd_read_data (void)

Read data from the keyboard

Mainly complete work:

a. Call the KBD_READ_STATUS () function read keyboard status from the keyboard status register, the function and the architecture relationship are close, generally implemented by assembly code.

b. Determine if the keyboard buffer has data, if there is a call function KBD_READ_INPUT () read data from the keyboard data register, the function and the architecture relationship are closely related, generally implemented by the assembly code.

C. Determine if the reading data is valid

(10) Line657 ~ 679 does not understand

(11) static int pckbd_rate (struct kbd_repeat * rep)

The value is assigned to the function pointer kbd_rate in the PCKBD_INIT_HW () function, was called by ../linux-2.4.x/drivers/char/vt.c file vt_iocTL ()

(12) static int write_kbd_rate (unsigned char r)

The function pckbd_rate () is an internal function (13) static unsigned char parse_kbd_rate (struct kbd_repeat * r)

Functions PCKBD_RATE (), is an internal function

(14) Void PCKBD_LEDS (unsigned char LEDs)

In the file ../linux-2.4.x/include/ASM-i386/keyboard.h is defined into a macro: KBD_LEDS (). Calls by the keyboard interrupt backend process function KBD_BH () function.

The main function:

Call the function send_data () Set the LED light of the keyboard if the failed setting keyboard does not exist.

(15) static int send_data (unsigned char data)

Send byte Data to the keyboard and wait for the response to the keyboard.

(16) static void keyboard_interrupt (int IRQ, Void * dev_id, struct pt_regs * regs)

Keyboard interrupt service function (most critical), mainly call function handle_kbd_event () to complete work. The interrupt must be turned off at the entire function execution process.

Note: PS mouse and keyboard share keyboard interrupt service function

(17) static unsigned char HANDLE_KBD_EVENT (VOID)

Interrupt event handler, this function is called by Keyboard_Interrupt ()

Mainly complete the following work:

a. Call the KBD_READ_STATUS () read the keyboard status port

b. The loop is executed, knowing that there is no data according to the status register, or has read 1000 data:

Call KBD_READ_INPUT () read data

Depending on the value of the status register, it is determined that the PS mouse is interrupted, then the mouse interrupt event handler handle_mouse_event () is called, if it is a keyboard interrupt, call Handle_Keyboard_Event (unsigned char scancode).

Reread status register

C.

(18) Static Inline Void Handle_Keyboard_Event (unsigned char scancode)

This function is a keyboard interrupt event handler, called by a handle_kbd_event () function, and the main work is implemented by the Handle_Scancode () function.

Mainly complete work:

a. Call Do_acknowledge (Scancode) Send Notification Data Receive Information to Keyboard

b. Call the handle_scancode () function to process scancode. Handle_scancode () function is implemented in the file ../linux-2.4.x/drivers/char/keyboard.c

C. Call the function tasklet_schedule (& keyboard_tasklet), put the remaining work to BH, so that the keyboard backend function keyboard_tasklet is hanging into the tasklet, and the system will automatically schedule the function.

(19) Static Inline Void Handle_Mouse_Event (unsigned char scancode)

Since the PS mouse is not in this category, there is no analysis.

(20) Static int Do_acknowledge (unsigned char scancode)

This function process sends an ACK information to the keyboard when a data is received from the keyboard. Mainly complete work:

a. Determine whether to send ACK information to the keyboard according to the reply_expected

b. If necessary, process according to the specific scancode

(21) INT PCKBD_PM_RESUME (Struct PM_DEV * DEV, PM_REQUEST_T RQST, VOID * DATA)

This function is a function of the PS mouse, which is not analyzed here.

(22) Char PCKBD_UNEXPECTED_UP (UNSIGNED Char Keycode)

Clear some flags accordingly for some non-expected buttons release, etc.

(23) INT PCKBD_TRANSLATE (unsigned char scancode, unsigned char * keycode, char Raw_mode)

Convert Scancode to KeyCode, which is defined in ../linux-2.4.x/include/ASM-i386/keyboard.h file is defined as kbd_translate, is called in the Handle_Scancode () function. Specific Reference Source Code

(24) int Pckbd_getKeyCode (unsigned int scancode)

Note keycode according to Scancode and Keycode array E0_keys [128] or "array, which is defined in ../linux-2.4.x/include/ASM-i386/keyboard.h is defined as macro KBD_GetKeycode, in the file ../ Linux-2.4.x / drivers / char / keyboard.c is called by a getKeyCode () function.

The main function:

Get the function key code of the PC keyboard according to Scancode

(25) INT PCKBD_SETKEYCODE (Unsigned Int Scancode, Unsigned Int Keycode)

Set the value of EO_KEYS [128] or High_KEYS [] or high_keycode according to Scancode, which is defined as macro KBD_GetSetKeyCode, in the file. ./linux-2.4.x/drivers/char/keyboard.c is called by getSetKeyCode () function.

The main function:

According to the function key of the PC keyboard is scheduted as scancode

(26) static void kb_wait (void)

Loop waiting, call the function handle_kbd_event () to wait for the keyboard state, timeout or status satisfaction exits the loop wait.

(27)

2. ../linux-2.4.x/drivers/char/keyboard.c

(1) Void Handle_Scancode (Unsigned Char Scancode, Int Down)

This function is a very critical function in the PC keyboard drive, mainly converting scancode to TTY can accept, such as ASCII code, Unicode et al, specifically depending on the requirements. And store the conversion result in flip_buffer; read data from FLIP_BUFFER to READ_BUFFER from FLIP_BUFFER; read: read_chan ()) read data from Read_Buffer, to complete keyboard A back. Please refer to the contents of the Page375 of the Linux kernel source code analysis (book) "

(2) INT __INIT KBD_INIT (VOID)

This function is also a very critical function in the PC keyboard drive. The keyboard driver, the initialization of the keyboard is implemented by the function, the main function is implemented by calling the function KBD_INIT_HW (), and the KBD_INIT_HW () is a macro, and the specific implementation function is PCD_INIT_HW. ).

This function is called by the TTY driven initialization function is ../linux-2.4.x/drivers/char/tty_io.c file call.

Implementation:

a. Initialize the KBD_TABLE array, that is, the keyboard status of each console.

b. Get the TTYTAB pointer (also a array, array member is TTY corresponding to each console).

C. Call the KBD_INIT_HW () function to implement initialization

d. Enable the keyboard interrupt service rear end function to run, and hook the keyboard_tasklet () (actually the KBD_BH () function) is the key execution function for the keyboard interrupt service.

e. Call function pm_register () Register the keyboard to the list of power management devices, the last parameter is a callback function, it seems to be null

(3) static void kbd_bh (unsigned long dummy)

The backend service function of the keyboard interrupt service program mainly completes console Changing, LED setting and copy_to_cooked, etc.

The main function:

Complete the Numlock, Capslock, and ScrollLock of the keyboard.

(4) Int getKeyCode (unsigned int scancode)

This function is called by Do_kbKeyCode_iocTL () at ../linux-2.4.x/drivers/char/vt.c files.

(5) Int setKeycode (unsigned int scalecode)

This function is called by do_kbkeycode_ioctl () at ../linux-2.4.x/drivers/char/vt.c files line262.

(6) static inline unsigned char Gets (void)

This function is called by the keyboard interrupt rear end processing function KBD_BH () call

(7) Void register_leds (int console, unsigned int LED, unsigned int * addr, unsigned int mask)

(8) Void setledState (Struct Kbd_Struct * KBD, Unsigned INT LED) This function is called in the VT_IOCTL () function of ./linux-2.4.x/drivers/char/vt.c file line690.

Specific function:

Set the status of the keyboard NUMLOCK, Capslock, or Scrollock's LED light.

(9) Unsigned char GetledState (Void)

This function is called in the VT_IOCTL () function of the ../linux-2.4.x/drivers/char/vt.c file line683.

Specific function:

Read the status of the keyboard NUMLOCK, Capslock, or Scrollock's LED light.

The following functions are the internal functions called when the Handle_Scancode () function is handled by scancode:

(10) Void Put_Queue (int CH)

(11) static void puts_queue (char * CP)

The above two functions (8), (9) are more critical, since it is stored by these two functions into FLIP_Buffer, and the backend service function of the console, that is, the BH function is entered into the tasklet.

(12) Void compute_shiftstate (void)

This function is called in many places, for example:

../linux-2.4.x/drivers/char/console.c

../linux-2.4.x/drivers/char/vt.c

The main function:

Set the Shift_State global variable, which is the state of the "Shift" key on the PC keyboard.

(13) Unsigned char Handle_diacr (unsigned char ch)

(14) static void sak (void)

(15) static void spawn_console (void)

(16) static void compose (void)

(17) static void boot_it (void)

(18) static void scroll_back (void)

(19) static void scroll_forw (void)

(20) static void send_intr (void)

(21) static void incr_console (void)

(22) Static void Decr_console (void)

(23) Static void Lastcons (Void)

(24) static void bare_num (void)

(25) static void num (void)

(26) Static void Hold (Void)

(27) static void show_ptregs (void) (28) static void caps_on (void)

(29) Static void Caps_Toggle (Void)

(30) static void enter (void)

(31) Static Void ApplKey (int key, char mode)

(32) Void To_UTF8 (Ushort C)

(33) Static void do_slock (unsigned char value, char up_flag)

(34) Static void do_lock (unsigned char value, char up_flag)

(35) Static void do_ascii (unsigned char value, char up_flag)

(36) Static void do_meta (unsigned char value, char up_flag)

(37) static void do_dead2 (unsigned char value, char up_flag)

(38) Static void do_shift (unsigned char value, char up_flag)

(39) Static void do_cur (unsigned char value, char up_flag)

(40) static void do_pad (unsigned char value, char up_flag)

(41) static void do_fn (unsigned char value, char up_flag)

(42) Static void do_cons (unsigned char value, char up_flag)

(43) static void do_dead (unsigned char value, char up_flag)

(44) static void do_sel (unsigned char value, char up_flag)

(45) static void do_spec (unsigned char value, char up_flag)

(46) Static void do_ignore (unsigned char value, char up_flag)

5. The interface of the keyboard drive and the upper layer of the system, the following function is a function of special attention in terms of specific hardware:

The interface of the keyboard drive and the upper layer is primarily the interface, the user, and keyboard derivation of the TTY, generally through the interface function of TTY.

1. KBD_INIT () - Keyboard Initialization Function: TTY Driver Initialization Function TTY_INIT () Call Keyboard Initialization Function KBD_INIT () function

2. PUT_QUEUE () or PUTS_QUEUE () function: Data buffer and TTY interface, keyboard drive (specifically the keyboard interrupt service function) stores the FLIP_BUFFER data buffer from the keyboard reading data, and the user calls Tty-driven Read The function (ie, read_chan ()) reads data from FLIP_BUFFER. 3. ../Linux-2.4.x/drivers/char/tty_ioctl.c file n_tty_iocTL () function calling place.

4. ../Linux-2.4.x/drivers/char/vt.c file VT_iocTL () wherever it is called.

(1) Void setledState (struct kbd_struct * kbd, unsigned int LED)

(2) Unsigned char GetLeDState (VOID)

(3) Int getKeycode (unsigned int scancode)

(4) Int setKeycode (unsigned int scalecode)

(5) Void Compute_shiftState (Void)

(6) static int pckbd_rate (struct kbd_repeat * rep)

5. ../Linux-2.4.x/drivers/chr/console.c file redraw_screen () call

(1) Void compute_shiftstate (void)

(2)

6. Different payables:

(1) static void kbd_bh (unsigned long dummy)

(2) Void PCKBD_LEDS (Unsigned Char LEDs)

7.

six.

转载请注明原文地址:https://www.9cbs.com/read-86796.html

New Post(0)