From 81df4702c424f91cca5570ab2554d1d4cbae534d Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Wed, 3 Mar 2021 22:43:17 -0500 Subject: 64kiB kernel area, ps/2 mouse support, signed decimals in knob format --- src/boot.asm | 4 +- src/kernel/idt.c | 6 +- src/kernel/isrs.asm | 17 ++++++ src/kernel/kbd.c | 84 ++++++++++++++++++++++++++-- src/kernel/paging.c | 4 ++ src/kernel/task.c | 6 +- src/kernel/window.c | 131 ++++++++++++++++++++++++++++++++------------ src/kernel/window.h | 3 + src/shared/include/winact.h | 12 +++- src/user/knob/format.c | 52 +++++++++++------- src/user/mdemo/main.c | 42 ++++++++++++++ 11 files changed, 292 insertions(+), 69 deletions(-) create mode 100644 src/user/mdemo/main.c (limited to 'src') diff --git a/src/boot.asm b/src/boot.asm index 74a3e5e..f56d6a6 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -1,7 +1,7 @@ bits 16 org 0x7c3e -kernel_sectors equ 64 +kernel_sectors equ 128 kernel_segment equ 0x3000 support_flags equ 0x4000 @@ -195,7 +195,7 @@ pmode: mov ds, ax mov es, ax mov ss, ax - mov esp, 0x00040000 + mov esp, 0x0002f000 xor ebp, ebp diff --git a/src/kernel/idt.c b/src/kernel/idt.c index 1a78da0..f07ef1d 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -219,6 +219,7 @@ extern isr_t quit_isr; extern isr_t yield_isr; extern isr_t kbd_isr; +extern isr_t mouse_isr; extern isr_t udf_isr; extern isr_t dfa_isr; @@ -325,6 +326,7 @@ void init_idt() { register_int(0x39, &yield_isr, 3); register_int(0x21, &kbd_isr, 0); + register_int(0x2c, &mouse_isr, 0); register_int(0x08, &udf_isr, 0); register_int(0x08, &dfa_isr, 0); @@ -346,8 +348,8 @@ void init_idt() { outb(PIC_MDATA, 0x01); outb(PIC_SDATA, 0x01); - outb(PIC_MDATA, 0xfd); - outb(PIC_SDATA, 0xff); + outb(PIC_MDATA, 0xf9); + outb(PIC_SDATA, 0xef); asm volatile ( "lidt %0" diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm index 1aba884..70bab19 100644 --- a/src/kernel/isrs.asm +++ b/src/kernel/isrs.asm @@ -5,6 +5,7 @@ global quit_isr global yield_isr global _start_user_mode global kbd_isr +global mouse_isr global udf_isr global dfa_isr @@ -133,6 +134,22 @@ _start_user_mode: sub esp, 4 jmp yield_isr.return_to_task +mouse_isr: + push eax + push ecx + push edx + + call on_kbd_isr + + mov al, 0x20 + out 0x00a0, al + out 0x0020, al + + pop edx + pop ecx + pop eax + iret + kbd_isr: push eax push ecx diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c index 47894cd..004706f 100644 --- a/src/kernel/kbd.c +++ b/src/kernel/kbd.c @@ -21,16 +21,36 @@ enum { enum { PS2C_READ_CONFIG = 0x20, PS2C_WRITE_CONFIG = 0x60, + PS2C_AUX_ENABLE = 0xa8, PS2C_DISABLE = 0xad, - PS2C_ENABLE = 0xae + PS2C_ENABLE = 0xae, + PS2C_SEND_AUX = 0xd4 }; enum { - PS2S_CODE_READY = 0x01 + PS2S_CODE_READY = 0x01, + PS2S_DONT_SEND = 0x02, + PS2S_FROM_MOUSE = 0x20 }; enum { - PS2G_XT_COMPAT = 0x40 + PS2G_KBD_IRQ = 0x01, + PS2G_MOUSE_IRQ = 0x02, + PS2G_KBD_OFF = 0x10, + PS2G_MOUSE_OFF = 0x20, + PS2G_XT_COMPAT = 0x40 +}; + +enum { + MFB_BUTTON_ONE = 0x01, + MFB_BUTTON_TWO = 0x02, + MFB_BUTTON_MID = 0x04, + MFB_X_SIGN = 0x10, + MFB_Y_SIGN = 0x20 +}; + +enum { + MC_ENABLE_REPORT = 0xf4 }; static uint32_t n_scantabs; @@ -55,7 +75,16 @@ void init_kbd() { outb(PS2_CMD, PS2C_READ_CONFIG); uint8_t config = inb(PS2_DATA); outb(PS2_CMD, PS2C_WRITE_CONFIG); - outb(PS2_DATA, config | PS2G_XT_COMPAT); + outb(PS2_DATA, (config | PS2G_XT_COMPAT | PS2G_MOUSE_IRQ | PS2G_KBD_IRQ) & ~(PS2G_MOUSE_OFF | PS2G_KBD_OFF)); + + outb(PS2_CMD, PS2C_SEND_AUX); + while (inb(PS2_CMD) & PS2S_DONT_SEND) + ; + outb(PS2_DATA, MC_ENABLE_REPORT); + while (!(inb(PS2_CMD) & PS2S_CODE_READY)) + ; + if (inb(PS2_DATA) != 0xfa) + PANIC("didn't get ACK after enabling mouse reporting"); uint32_t layout_len; if (!try_get_sz_setting("kbd-layout", scantab_path + SCANTAB_DIR_LEN, LAYOUT_NAME_MAX_LEN, &layout_len)) @@ -107,11 +136,54 @@ static inline uint8_t get_next_code_byte() { return cb; } +static inline uint8_t get_wait() { + for (uint32_t i = 0; i < 1000000; ++i) + ; + return inb(PS2_DATA); +} + static enum key_modifiers_t keymods = 0; +bool last_mouse_one = false; +bool last_mouse_two = false; +bool last_mouse_mid = false; + enum kbd_isr_result on_kbd_isr() { -//logf(LOG_INFO, "on_kbd_isr()"); - while (inb(PS2_CMD) & PS2S_CODE_READY) { + uint8_t code; + while ((code = inb(PS2_CMD)) & PS2S_CODE_READY) { + if (code & PS2S_FROM_MOUSE) { + const uint8_t first = get_wait(); + const uint8_t x = get_wait(); + const uint8_t y = get_wait(); + + if (x || y || (first & (MFB_X_SIGN | MFB_Y_SIGN))) + move_mouse_by((first & MFB_Y_SIGN) ? 256 - y : -y, + (first & MFB_X_SIGN) ? x - 256 : x); + + const bool mouse_one = first & MFB_BUTTON_ONE; + const bool mouse_two = first & MFB_BUTTON_TWO; + const bool mouse_mid = first & MFB_BUTTON_MID; + + if (mouse_one && !last_mouse_one) + mouse_button(LEFT, false); + if (mouse_two && !last_mouse_two) + mouse_button(RIGHT, false); + if (mouse_mid && !last_mouse_mid) + mouse_button(MIDDLE, false); + + if (!mouse_one && last_mouse_one) + mouse_button(LEFT, true); + if (!mouse_two && last_mouse_two) + mouse_button(RIGHT, true); + if (!mouse_mid && last_mouse_mid) + mouse_button(MIDDLE, true); + + last_mouse_one = mouse_one; + last_mouse_two = mouse_two; + last_mouse_mid = mouse_mid; + continue; + } + last_code_byte = 0; uint8_t code[256]; uint8_t code_i = 0; diff --git a/src/kernel/paging.c b/src/kernel/paging.c index 0432ab6..dc7ca27 100644 --- a/src/kernel/paging.c +++ b/src/kernel/paging.c @@ -115,11 +115,15 @@ void init_paging() { for (uint32_t i = 0; i < 1048576; ++i) KPAGE_TABLE_0[i] = (i * 4096) | PE_WRITABLE | PE_PRESENT; + KPAGE_TABLE_0[0x00020] &= ~PE_PRESENT; + KPAGE_TABLE_0[0x0002f] &= ~PE_PRESENT; for (uint16_t i = 0; i < 1024; ++i) KPAGE_DIR[i] = (uint32_t)(KPAGE_TABLE_0 + i * 1024) | PE_WRITABLE | PE_PRESENT; for (uint16_t i = 0; i < KERNEL_END / 4096; ++i) kmap[i] = (i * 4096) | PE_USER | PE_PRESENT; + kmap[0x00020] &= ~PE_PRESENT; + kmap[0x0002f] &= ~PE_PRESENT; asm volatile ( "mov $0x00005000, %%eax\n" diff --git a/src/kernel/task.c b/src/kernel/task.c index 93310bc..077eea6 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -62,11 +62,11 @@ uint32_t new_task(struct task_state state) { static void tmp_halt() { //logf(LOG_INFO, "scheduler halting"); - TSS->esp0 = 0x0003c000; + TSS->esp0 = 0x00028000; asm("sti\n" "hlt\n" "cli"); - TSS->esp0 = 0x00040000; + TSS->esp0 = 0x0002f000; //logf(LOG_INFO, "scheduler resumed"); } @@ -121,7 +121,7 @@ void init_tasks() { ipc_pipes[i].buffer = 0; TSS->ss0 = 0x18; - TSS->esp0 = 0x00040000; + TSS->esp0 = 0x0002f000; //TSS->cs = 0x13; //TSS->ds = 0x1b; //TSS->ss = 0x1b; diff --git a/src/kernel/window.c b/src/kernel/window.c index e7cf30d..bc36578 100644 --- a/src/kernel/window.c +++ b/src/kernel/window.c @@ -71,6 +71,49 @@ static void load_mode_params() { ); } +static inline void blit_pixel(uint32_t *into, struct pixel from) { + *into &= pix_clear_mask; + *into |= (from.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off; + *into |= (from.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off; + *into |= (from.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off; +} + +static uint16_t mouse_y; +static uint16_t mouse_x; + +#define MOUSE_WIDTH 8 +#define MOUSE_HEIGHT 8 + +#define B {.r = 0, .g = 0, .b = 0, .pad = 0} +#define W {.r = 255, .g = 255, .b = 255, .pad = 0} +#define T {.pad = 1} + +static const struct pixel mouse_image[] = { + W, W, W, W, W, W, T, T, + W, B, B, B, W, T, T, T, + W, B, B, B, W, W, T, T, + W, B, B, B, B, W, W, T, + W, W, W, B, B, B, W, T, + W, T, W, W, B, B, B, W, + T, T, T, W, W, B, W, W, + T, T, T, T, W, W, W, T +}; + +static void blit_mouse() { + uint16_t y_max = mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height - mouse_y : MOUSE_HEIGHT; + uint16_t x_max = mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width - mouse_x : MOUSE_WIDTH; + void *row = VBE_MODE_INFO->frame_buf + mouse_y * VBE_MODE_INFO->pitch + mouse_x * (VBE_MODE_INFO->bpp / 8); + for (uint16_t y = 0; y < y_max; ++y) { + uint32_t *out_pix = row; + for (uint16_t x = 0; x < x_max; ++x) { + if (!mouse_image[y * MOUSE_WIDTH + x].pad) + blit_pixel(out_pix, mouse_image[y * MOUSE_WIDTH + x]); + out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8); + } + row += VBE_MODE_INFO->pitch; + } +} + static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max) { void *row = VBE_MODE_INFO->frame_buf + y_min * VBE_MODE_INFO->pitch + x_min * (VBE_MODE_INFO->bpp / 8); const struct super_pixel *from_row = buffer + y_min * VBE_MODE_INFO->width + x_min; @@ -78,16 +121,17 @@ static void blit(uint16_t x_min, uint16_t x_max, uint16_t y_min, uint16_t y_max) uint32_t *out_pix = row; const struct super_pixel *from = from_row; for (uint16_t x = x_min; x < x_max; ++x) { - *out_pix &= pix_clear_mask; - *out_pix |= (from->p.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off; - *out_pix |= (from->p.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off; - *out_pix |= (from->p.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off; + blit_pixel(out_pix, from->p); out_pix = (uint32_t *)((void *)out_pix + VBE_MODE_INFO->bpp / 8); ++from; } row += VBE_MODE_INFO->pitch; from_row += VBE_MODE_INFO->width; } + + if ((y_min < mouse_y) && (y_max > mouse_y) && + (x_min < mouse_x) && (x_max > mouse_x)) + blit_mouse(); } #define POWER_OFF_MESSAGE_PITCH 45 @@ -343,8 +387,6 @@ static void send_action(struct window *w, struct window_action packet) { #define RUN_COMMAND_FILE "sys/winspace.rc" enum wm_action { - WM_SHUFFLE_UP, - WM_SHUFFLE_DOWN, WM_MOVE_LEFT, WM_MOVE_RIGHT, WM_MOVE_UP, @@ -355,8 +397,6 @@ enum wm_action { }; static struct key_packet keybinds[] = { - {.key_id = KEY_PAGE_DOWN, .modifiers = WINS}, - {.key_id = KEY_PAGE_UP, .modifiers = WINS}, {.key_id = KEY_LEFT_ARROW, .modifiers = WINS}, {.key_id = KEY_RIGHT_ARROW, .modifiers = WINS}, {.key_id = KEY_UP_ARROW, .modifiers = WINS}, @@ -393,6 +433,10 @@ void init_win() { paint_bg(); blit(0, VBE_MODE_INFO->width, 0, VBE_MODE_INFO->height); + mouse_x = (VBE_MODE_INFO->width - MOUSE_WIDTH) / 2; + mouse_y = (VBE_MODE_INFO->height - MOUSE_HEIGHT) / 2; + blit_mouse(); + const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE); if (!fid) PANIC("Couldn't open " RUN_COMMAND_FILE "."); @@ -425,34 +469,7 @@ void on_action(struct window_action packet) { for (uint8_t i = 0; i < N_WM_ACTIONS; ++i) if (fuzzy_key_match(keybinds[i], packet.as_key)) { switch_to_kernel_cr3(); - struct window *old_top, *old_bottom; switch (i) { - case WM_SHUFFLE_UP: - if (!top_window || !top_window->below) - break; - old_top = top_window; - old_bottom = bottom_window; - top_window = old_top->below; - top_window->above = 0; - old_top->below = 0; - old_top->above = old_bottom; - old_bottom->below = old_top; - bottom_window = old_top; - paint_and_above(bottom_window->above); - break; - case WM_SHUFFLE_DOWN: - if (!top_window || !top_window->below) - break; - old_top = top_window; - old_bottom = bottom_window; - bottom_window = old_bottom->above; - bottom_window->below = 0; - old_bottom->above = 0; - old_bottom->below = old_top; - old_top->above = old_bottom; - top_window = old_bottom; - paint_and_above(top_window); - break; case WM_MOVE_LEFT: if (top_window) { top_window->xpos -= MOVE_BY; @@ -487,4 +504,48 @@ void on_action(struct window_action packet) { if (top_window) send_action(top_window, packet); +} + +void move_mouse_by(int16_t y, int16_t x) { +//logf(LOG_INFO, "old mouse coords: (%d, %d)", mouse_x, mouse_y); + switch_to_kernel_cr3(); + blit(mouse_x, mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width ? VBE_MODE_INFO->width : mouse_x + MOUSE_WIDTH, + mouse_y, mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height ? VBE_MODE_INFO->height : mouse_y + MOUSE_HEIGHT); + mouse_y = (-y > mouse_y) ? 0 : (y + mouse_y + MOUSE_HEIGHT > VBE_MODE_INFO->height) ? VBE_MODE_INFO->height - MOUSE_HEIGHT : y + mouse_y; + mouse_x = (-x > mouse_x) ? 0 : (x + mouse_x + MOUSE_WIDTH > VBE_MODE_INFO->width) ? VBE_MODE_INFO->width - MOUSE_WIDTH : x + mouse_x; + blit_mouse(); + switch_to_task_cr3(); +//logf(LOG_INFO, "new mouse coords: (%d, %d)", mouse_x, mouse_y); +} + +static void focus(struct window *w) { + send_action(top_window, (struct window_action){.action_type = FOCUS_LEAVE}); + + if (w->below) + w->below->above = w->above; + else + bottom_window = w->above; + w->above->below = w->below; + w->above = 0; + w->below = top_window; + top_window->above = w; + top_window = w; + + send_action(w, (struct window_action){.action_type = FOCUS_ENTER}); +} + +void mouse_button(enum mouse_button which, bool up) { + if (!top_window) + return; + + struct window *const clicked_on = buffer[mouse_y * VBE_MODE_INFO->width + mouse_x].from_window; + if (!clicked_on) + return; + + if (clicked_on != top_window) { + focus(clicked_on); + paint_and_above(clicked_on); + } + + send_action(clicked_on, (struct window_action){.action_type = up ? MOUSE_UP : MOUSE_DOWN, .as_mouse = {.y = mouse_y - clicked_on->ypos, .x = mouse_x - clicked_on->xpos, .which = which}}); } \ No newline at end of file diff --git a/src/kernel/window.h b/src/kernel/window.h index 0a83845..a1f9716 100644 --- a/src/kernel/window.h +++ b/src/kernel/window.h @@ -33,4 +33,7 @@ void delete_any_windows_from(struct task_state *tstate); void show_shutdown(); +void move_mouse_by(int16_t y, int16_t x); +void mouse_button(enum mouse_button which, bool up); + #endif diff --git a/src/shared/include/winact.h b/src/shared/include/winact.h index bc18cb4..8b32d00 100644 --- a/src/shared/include/winact.h +++ b/src/shared/include/winact.h @@ -9,10 +9,20 @@ struct window_action { KEY_DOWN, KEY_UP, FOCUS_ENTER, - FOCUS_LEAVE + FOCUS_LEAVE, + MOUSE_DOWN, + MOUSE_UP } action_type; union { struct key_packet as_key; + struct { + //0, 0 is upper-left-most pixel not counting border + //packets are also sent for the border pixels, + // so this may be a negative value in those cases + int16_t y; + int16_t x; + enum mouse_button {LEFT, RIGHT, MIDDLE} which; + } as_mouse; }; } __attribute__ ((__packed__)); diff --git a/src/user/knob/format.c b/src/user/knob/format.c index c5d2447..cdc1687 100644 --- a/src/user/knob/format.c +++ b/src/user/knob/format.c @@ -42,8 +42,8 @@ struct format_spec { CHAR, STRING, UNSIGNED_DECIMAL, - HEXADECIMAL - //TODO: signed decimal + HEXADECIMAL, + SIGNED_DECIMAL } kind; }; @@ -73,6 +73,9 @@ static const char *get_format(const char *from, struct format_spec *format_out) case 'x': format_out->kind = HEXADECIMAL; break; + case 'd': + format_out->kind = SIGNED_DECIMAL; + break; default: format_out->kind = UNKNOWN; break; @@ -81,7 +84,17 @@ static const char *get_format(const char *from, struct format_spec *format_out) return from + 1; } -//char debug[] = "-- format_v: fmt = \" \"..."; +static uint8_t get_digits(uint32_t k) { + if (k >= 1000000000) + return 10; + uint8_t r = 1; + uint32_t n = 10; + while (k >= n) { + ++r; + n *= 10; + } + return r; +} //allocates new memory char *format_v(const char *fmt, va_list args) { @@ -92,11 +105,6 @@ char *format_v(const char *fmt, va_list args) { buf_i = buf; while (*fmt) { - //debug[20] = *fmt; - //debug[21] = fmt[1]; - //debug[22] = fmt[2]; - //_system_log(debug); - if (*fmt != '%') { ensure(1); *(buf_i++) = *(fmt++); @@ -137,20 +145,24 @@ char *format_v(const char *fmt, va_list args) { continue; uint32_t k; - case UNSIGNED_DECIMAL: + case SIGNED_DECIMAL: k = va_arg(args, uint32_t); - if (!form.len) { - if (k >= 1000000000) - form.len = 10; - else { - uint32_t n = 10; - ++form.len; - while (k >= n) { - ++form.len; - n *= 10; - } - } + bool is_neg = k & 0x80000000; + if (is_neg) { + ensure(1); + *(buf_i++) = '-'; + k = -k; } + if (!form.len) + form.len = get_digits(k); + else if (is_neg) + --form.len; + goto print_dec; + case UNSIGNED_DECIMAL: + k = va_arg(args, uint32_t); + if (!form.len) + form.len = get_digits(k); + print_dec: ensure(form.len); const uint32_t len_backup = form.len; while (form.len--) { diff --git a/src/user/mdemo/main.c b/src/user/mdemo/main.c new file mode 100644 index 0000000..fc7de80 --- /dev/null +++ b/src/user/mdemo/main.c @@ -0,0 +1,42 @@ +#include +#include + +#define TEXT_COLOR ((_pixel_t){.r = 0x00, .g = 0x00, .b = 0x00}) +#define BG_COLOR ((_pixel_t){.r = 0xbf, .g = 0xbf, .b = 0xbf}) + +static const char *const mb_names[] = { + "left", "right", "middle" +}; + +void main() { + struct popup main_win; + info_popup(&main_win, "Click me!", TEXT_COLOR, BG_COLOR); + + while (1) { + struct window_action winact; + _get_win_action(main_win.handle, &winact); + + switch (winact.action_type) { + struct popup modal; + case NOT_READY: + _wait_for_action(); + _yield_task(); + continue; + + case KEY_DOWN: + return; + + case MOUSE_DOWN: + info_popupf(&modal, + "Got %s click at (%d, %d)!", + TEXT_COLOR, BG_COLOR, + mb_names[winact.as_mouse.which], + winact.as_mouse.x, winact.as_mouse.y); + make_modal(&modal); + continue; + + default: + continue; + } + } +} \ No newline at end of file -- cgit v1.2.3