#include #include #include #include #include #include // Intenral functions static void wait_keyboard_event(void); static int check_special(struct keyboard_obj_s *keyboard, key_t key); static int check_signal(struct keyboard_obj_s *keyboard, key_t key); static void tty_buffer_display(struct keyboard_obj_s *keyboard); static int update_buffer(struct keyboard_obj_s *keyboard, key_t key); static int buffer_insert(struct keyboard_obj_s *keyboard, char n); static void cursor_callback(struct keyboard_obj_s *keyboard); //FIXME: this function is device-specifique !! ssize_t tty_read(void *inode, void *buffer, size_t count) { extern struct keycache_s *keylist; extern struct tty_s tty; struct keycache_s *keynode; struct keyboard_obj_s keyboard; int first_key; int timer_fd; // Check potential error. if (count < 2) return (0); // Initialize internal struc. memset(buffer, '\0', count); keyboard.buffer.addr = buffer; keyboard.buffer.size = count; keyboard.buffer.cursor = 0; keyboard.buffer.clen = 0; keyboard.mode = 0x00; keyboard.cvisible = 0; // save TTY informations. keyboard.saved.tty.cursor.x = tty.cursor.x; keyboard.saved.tty.cursor.y = tty.cursor.y; // Initialize timer for cursor. // FIXME: find real ticks value !! timer_fd = timer_install(&cursor_callback, &keyboard, 500 * 500 * 2, 1); if (timer_fd == -1) return (0); // Main Loop, wait [EXE] key. while ((keyboard.mode & 0x04) == 0) { // Wait user interruption. wait_keyboard_event(); // Start atomic operations and check // signal, special key then update // the buffer. atomic_start(); keynode = keylist; first_key = 0; while (keynode != NULL && (keynode->counter == 1 || (first_key == 0 && keynode->counter > 10 && (keynode->counter & 1) == 0))) { // Repeat key flags. first_key = 1; // Handle current key if (check_signal(&keyboard, keynode->keycode) == 0 && check_special(&keyboard, keynode->keycode) == 0) update_buffer(&keyboard, keynode->keycode); // Get next key. keynode = keynode->next; } atomic_stop(); // Display buffer on TTY. tty_buffer_display(&keyboard); } // uninstall cursor timer. timer_uninstall(timer_fd); // Return the number of input char. return (keyboard.buffer.clen); } //FIXME: function driver specific ! static void wait_keyboard_event(void) { extern volatile uint8_t keylist_isUpdate; // Wait key list update. // @note: // To ensure reentrace and avoid data corruption // we should wait kernel indication. // TODO: explain correctly x) while (keylist_isUpdate == 0) { __asm__ volatile ("sleep"); } keylist_isUpdate = 0; } static int check_signal(struct keyboard_obj_s *keyboard, key_t key) { //TODO (void)key; (void)keyboard; return (0); } static int check_special(struct keyboard_obj_s *keyboard, key_t key) { extern fx9860_context_t casio_context; extern fx9860_context_t vhex_context; unsigned int tmp; switch (key) { // Check MAJ. case KEY_ALPHA: { keyboard->mode = keyboard->mode ^ 0x02; return (1); } // Check Alpha / num mode. case KEY_SHIFT: { keyboard->mode = keyboard->mode ^ 0x01; return (1); } // Check DEL key. case KEY_DEL: { // Check potential error. if (keyboard->buffer.cursor <= 0) return (1); // Move seconde part. memcpy( &keyboard->buffer.addr[keyboard->buffer.cursor - 1], &keyboard->buffer.addr[keyboard->buffer.cursor], keyboard->buffer.clen - keyboard->buffer.cursor ); // Add null char and update clen. keyboard->buffer.clen = keyboard->buffer.clen - 1; keyboard->buffer.addr[keyboard->buffer.clen] = '\0'; keyboard->buffer.cursor = keyboard->buffer.cursor - 1; return (1); } // Check MENU key. // TODO: fix me ! case KEY_MENU: { // Save current Vhex context and restore Casio's context. atomic_start(); fx9860_context_save(&vhex_context); fx9860_context_restore(&casio_context); atomic_stop(); // Inject MENU key and call GetKey(). // TODO !!! //int row = 0; //int column = 0; //uint16_t keymatrix = 0x0308; //casio_Bkey_PutKeymatrix(&keymatrix); //casio_GetKeyWait(&row, &column, 0, 0, 0, &key); casio_GetKey(&key); // Save current Casio's context and restore Vhex's context. atomic_start(); fx9860_context_save(&casio_context); fx9860_context_restore(&vhex_context); atomic_stop(); return (1); } // Check EXE key. case KEY_EXE: { // Add new line character. keyboard->buffer.addr[keyboard->buffer.clen] = '\n'; keyboard->buffer.clen = keyboard->buffer.clen + 1; keyboard->buffer.addr[keyboard->buffer.clen] = '\0'; // indicate that the EXE has been pressed. keyboard->mode = keyboard->mode | 0x04; return (1); } // Check LEFT key. case KEY_LEFT: { // Check potential error. if (keyboard->buffer.cursor <= 0) return (1); // Move cursor. keyboard->buffer.cursor = keyboard->buffer.cursor - 1; return (1); } // Check RIGHT key. case KEY_RIGHT: { if (keyboard->buffer.cursor >= keyboard->buffer.clen) return (1); // Move cursor. keyboard->buffer.cursor = keyboard->buffer.cursor + 1; return (1); } default: break; } return (0); } static void tty_buffer_display(struct keyboard_obj_s *keyboard) { extern struct tty_s tty; size_t size; // Restore TTY X/Y axis positions. tty.cursor.x = keyboard->saved.tty.cursor.x; tty.cursor.y = keyboard->saved.tty.cursor.y; // Workaround for [EXE] key. size = ((keyboard->mode & 0x04) == 0) ? keyboard->buffer.clen + 1 : keyboard->buffer.clen; // Write buffer. tty_write(NULL, keyboard->buffer.addr, size); } static int update_buffer(struct keyboard_obj_s *keyboard, key_t key) { static const uint8_t keylist_alpha[] = { KEY_XOT, KEY_LOG, KEY_LN, KEY_SIN, KEY_COS, KEY_TAN, KEY_FRAC, KEY_FD, KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_ARROW, KEY_7, KEY_8, KEY_9, KEY_4, KEY_5, KEY_6, KEY_MUL, KEY_DIV, KEY_1, KEY_2, KEY_3, KEY_PLUS, KEY_MINUS, KEY_0, KEY_UNUSED }; static const uint8_t keylist_num[] = { KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_PLUS, KEY_MINUS, KEY_MUL, KEY_DIV, KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_POWER, KEY_DOT, KEY_FD, KEY_ARROW, KEY_UNUSED }; static const char keylist_num_char[] = "0123456789+-x/(),^.|_"; const uint8_t *keycode_list; char character; int i; // Get the appropriate key list. keycode_list = ((keyboard->mode & 1) == 0) ? keylist_alpha : keylist_num; // Try to find the pressed key. i = -1; while (keycode_list[++i] != KEY_UNUSED && keycode_list[i] != key); if (keycode_list[i] != key) return (0); // If the key match, update buffer. // Get the char to be written if ((keyboard->mode & 1) == 0) character = (keyboard->mode & 2) ? 'A' + i : 'a' + i; else character = keylist_num_char[i]; // Insert new character if possible. buffer_insert(keyboard, character); return (1); } static int buffer_insert(struct keyboard_obj_s *keyboard, char n) { // Check if the buffer is full. if (keyboard->buffer.clen + 1 >= keyboard->buffer.size) return (1); // Move the seconds par of the buffer is needed if (keyboard->buffer.cursor < keyboard->buffer.clen) { int i = keyboard->buffer.clen + 1; while (--i >= (int)keyboard->buffer.cursor) keyboard->buffer.addr[i] = keyboard->buffer.addr[i - 1]; } // Add the new character. keyboard->buffer.addr[keyboard->buffer.cursor] = n; // Update cursor and character len. keyboard->buffer.cursor = keyboard->buffer.cursor + 1; keyboard->buffer.clen = keyboard->buffer.clen + 1; return (0); } static void cursor_callback(struct keyboard_obj_s *keyboard) { extern struct tty_s tty; int x; int y; // Draw cursor if needed if (keyboard->cvisible == 0) { // Geneate TTY buffer cursor position. x = keyboard->buffer.cursor + keyboard->saved.tty.cursor.x; y = x / tty.cursor.max.x; x = x - (y * tty.cursor.max.x); y = y + keyboard->saved.tty.cursor.y; // Save current cursor position and // resotre saved position. int sttyx = tty.cursor.x; int sttyy = tty.cursor.x; tty.cursor.x = x; tty.cursor.y = y; // Get Display X and Y position. tty_ioctl(NULL, TTY_IOCTL_GETDX, &x); tty_ioctl(NULL, TTY_IOCTL_GETDY, &y); // Display cursor. kvram_reverse(x, y, (KERNEL_FONT_REAL_WIDTH + 1), (KERNEL_FONT_REAL_HEIGHT + 1)); kvram_display(); // Restore TTY cursor position tty.cursor.x = sttyx; tty.cursor.y = sttyy; } // Update cursor status. keyboard->cvisible = keyboard->cvisible ^ 1; }