Changeset 925a21e in mainline for uspace/srv/hid
- Timestamp:
- 2011-09-24T14:20:29Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5bf76c1
- Parents:
- 867e2555 (diff), 1ab4aca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/srv/hid
- Files:
-
- 18 added
- 19 deleted
- 19 edited
- 10 moved
-
console/Makefile (modified) (1 diff)
-
console/console.c (modified) (10 diffs)
-
console/console.h (modified) (1 diff)
-
console/gcons.c (deleted)
-
console/gfx/anim_1.ppm (deleted)
-
console/gfx/anim_1.tga (added)
-
console/gfx/anim_2.ppm (deleted)
-
console/gfx/anim_2.tga (added)
-
console/gfx/anim_3.ppm (deleted)
-
console/gfx/anim_3.tga (added)
-
console/gfx/anim_4.ppm (deleted)
-
console/gfx/anim_4.tga (added)
-
console/gfx/cons_data.tga (added)
-
console/gfx/cons_dis.tga (added)
-
console/gfx/cons_dis_sel.tga (added)
-
console/gfx/cons_has_data.ppm (deleted)
-
console/gfx/cons_idle.ppm (deleted)
-
console/gfx/cons_idle.tga (added)
-
console/gfx/cons_kernel.ppm (deleted)
-
console/gfx/cons_kernel.tga (added)
-
console/gfx/cons_sel.tga (added)
-
console/gfx/cons_selected.ppm (deleted)
-
console/gfx/helenos.ppm (deleted)
-
console/gfx/helenos.tga (added)
-
console/gfx/nameic.ppm (deleted)
-
console/gfx/nameic.tga (added)
-
console/keybuffer.c (deleted)
-
fb/Makefile (modified) (1 diff)
-
fb/ctl/serial.c (added)
-
fb/ctl/serial.h (moved) (moved from uspace/srv/hid/fb/msim.h ) (2 diffs)
-
fb/ega.c (deleted)
-
fb/fb.c (modified) (2 diffs)
-
fb/fb.h (modified) (2 diffs)
-
fb/gfx/font-8x16.c (moved) (moved from uspace/srv/hid/fb/font-8x16.c ) (1 diff)
-
fb/gfx/font-8x16.h (moved) (moved from uspace/srv/hid/fb/font-8x16.h ) (1 diff)
-
fb/main.c (deleted)
-
fb/pointer.xbm (deleted)
-
fb/pointer_mask.xbm (deleted)
-
fb/port/ega.c (added)
-
fb/port/ega.h (moved) (moved from uspace/srv/hid/fb/ega.h ) (1 diff)
-
fb/port/kchar.c (moved) (moved from uspace/srv/hid/fb/msim.c ) (1 diff)
-
fb/port/kchar.h (moved) (moved from uspace/srv/hid/fb/main.h ) (2 diffs)
-
fb/port/kfb.c (added)
-
fb/port/kfb.h (added)
-
fb/port/niagara.c (moved) (moved from uspace/srv/hid/fb/niagara.c ) (1 diff)
-
fb/port/niagara.h (moved) (moved from uspace/srv/hid/fb/niagara.h ) (1 diff)
-
fb/port/ski.c (moved) (moved from uspace/srv/hid/fb/ski.c ) (3 diffs)
-
fb/port/ski.h (moved) (moved from uspace/srv/hid/fb/ski.h ) (2 diffs)
-
fb/ppm.c (deleted)
-
fb/ppm.h (deleted)
-
fb/proto/vt100.c (added)
-
fb/proto/vt100.h (added)
-
fb/serial_console.c (deleted)
-
input/ctl/kbdev.c (modified) (7 diffs)
-
input/generic/input.c (modified) (20 diffs)
-
input/include/input.h (modified) (2 diffs)
-
input/include/kbd.h (modified) (2 diffs)
-
input/include/mouse.h (modified) (2 diffs)
-
input/port/adb.c (modified) (3 diffs)
-
input/port/adb_mouse.c (modified) (2 diffs)
-
input/port/chardev.c (modified) (4 diffs)
-
input/port/chardev_mouse.c (modified) (4 diffs)
-
input/port/ns16550.c (modified) (2 diffs)
-
input/proto/mousedev.c (modified) (7 diffs)
-
s3c24xx_ts/s3c24xx_ts.c (modified) (8 diffs)
-
s3c24xx_ts/s3c24xx_ts.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/console/Makefile
r867e2555 r925a21e 29 29 30 30 USPACE_PREFIX = ../../.. 31 LIBS = $(LIBFB_PREFIX)/libfb.a 32 EXTRA_CFLAGS += -I$(LIBFB_PREFIX) 31 33 BINARY = console 32 34 33 GENERIC_SOURCES = \35 SOURCES = \ 34 36 console.c \ 35 keybuffer.c \ 36 gcons.c 37 images.c 37 38 38 39 IMAGES = \ 39 gfx/helenos.ppm \ 40 gfx/nameic.ppm \ 41 gfx/cons_selected.ppm \ 42 gfx/cons_idle.ppm \ 43 gfx/cons_has_data.ppm \ 44 gfx/cons_kernel.ppm \ 45 gfx/anim_1.ppm \ 46 gfx/anim_2.ppm \ 47 gfx/anim_3.ppm \ 48 gfx/anim_4.ppm 40 gfx/helenos.tga \ 41 gfx/nameic.tga \ 42 gfx/cons_data.tga \ 43 gfx/cons_dis.tga \ 44 gfx/cons_dis_sel.tga \ 45 gfx/cons_idle.tga \ 46 gfx/cons_sel.tga \ 47 gfx/cons_kernel.tga \ 48 gfx/anim_1.tga \ 49 gfx/anim_2.tga \ 50 gfx/anim_3.tga \ 51 gfx/anim_4.tga 49 52 50 SOURCES = \ 51 $(GENERIC_SOURCES) \ 52 $(IMAGES) 53 PRE_DEPEND = images.c images.h 54 EXTRA_CLEAN = images.c images.h 53 55 54 56 include $(USPACE_PREFIX)/Makefile.common 55 57 56 %.o: %.ppm 57 $( OBJCOPY) -I binary -O $(BFD_NAME) -B $(BFD_ARCH) $< $@58 images.c images.h: $(IMAGES) 59 $(ROOT_PATH)/tools/mkarray.py images CONSOLE_IMAGES $^ -
uspace/srv/hid/console/console.c
r867e2555 r925a21e 1 1 /* 2 * Copyright (c) 2006 Josef Cejka 3 * Copyright (c) 2011 Jiri Svoboda 2 * Copyright (c) 2011 Martin Decky 4 3 * All rights reserved. 5 4 * … … 34 33 */ 35 34 36 #include <libc.h> 35 #include <async.h> 36 #include <stdio.h> 37 #include <adt/prodcons.h> 37 38 #include <ipc/input.h> 38 #include <io/keycode.h> 39 #include <ipc/fb.h> 40 #include <ipc/services.h> 41 #include <ns.h> 42 #include <ns_obsolete.h> 39 #include <ipc/console.h> 40 #include <ipc/vfs.h> 43 41 #include <errno.h> 44 42 #include <str_error.h> 45 #include <ipc/console.h> 46 #include <unistd.h> 47 #include <async.h> 48 #include <async_obsolete.h> 49 #include <adt/fifo.h> 50 #include <sys/mman.h> 51 #include <stdio.h> 52 #include <str.h> 53 #include <sysinfo.h> 43 #include <loc.h> 54 44 #include <event.h> 55 #include <devmap.h> 56 #include <fcntl.h> 57 #include <vfs/vfs.h> 45 #include <io/keycode.h> 46 #include <screenbuffer.h> 47 #include <fb.h> 48 #include <imgmap.h> 49 #include <align.h> 50 #include <malloc.h> 51 #include <as.h> 58 52 #include <fibril_synch.h> 59 #include <io/style.h> 60 #include <io/screenbuffer.h> 61 53 #include "images.h" 62 54 #include "console.h" 63 #include "gcons.h"64 #include "keybuffer.h"65 55 66 56 #define NAME "console" 67 57 #define NAMESPACE "term" 68 58 69 /** Session with the input server. */ 59 #define CONSOLE_TOP 66 60 #define CONSOLE_MARGIN 12 61 62 #define STATE_START 100 63 #define STATE_TOP 8 64 #define STATE_SPACE 4 65 #define STATE_WIDTH 48 66 #define STATE_HEIGHT 48 67 68 typedef enum { 69 CONS_DISCONNECTED = 0, 70 CONS_DISCONNECTED_SELECTED, 71 CONS_SELECTED, 72 CONS_IDLE, 73 CONS_DATA, 74 CONS_KERNEL, 75 CONS_LAST 76 } console_state_t; 77 78 typedef struct { 79 atomic_t refcnt; /**< Connection reference count */ 80 prodcons_t input_pc; /**< Incoming keyboard events */ 81 82 fibril_mutex_t mtx; /**< Lock protecting mutable fields */ 83 84 size_t index; /**< Console index */ 85 console_state_t state; /**< Console state */ 86 service_id_t dsid; /**< Service handle */ 87 88 vp_handle_t state_vp; /**< State icon viewport */ 89 sysarg_t cols; /**< Number of columns */ 90 sysarg_t rows; /**< Number of rows */ 91 console_caps_t ccaps; /**< Console capabilities */ 92 93 screenbuffer_t *frontbuf; /**< Front buffer */ 94 frontbuf_handle_t fbid; /**< Front buffer handle */ 95 } console_t; 96 97 typedef enum { 98 GRAPHICS_NONE = 0, 99 GRAPHICS_BASIC = 1, 100 GRAPHICS_FULL = 2 101 } graphics_state_t; 102 103 /** Current console state */ 104 static graphics_state_t graphics_state = GRAPHICS_NONE; 105 106 /** State icons */ 107 static imagemap_handle_t state_icons[CONS_LAST]; 108 109 /** Session to the input server */ 70 110 static async_sess_t *input_sess; 71 111 72 /** Information about framebuffer */ 73 struct { 74 int phone; /**< Framebuffer phone */ 75 sysarg_t cols; /**< Framebuffer columns */ 76 sysarg_t rows; /**< Framebuffer rows */ 77 sysarg_t color_cap; /**< Color capabilities (FB_CCAP_xxx) */ 78 } fb_info; 79 80 typedef struct { 81 size_t index; /**< Console index */ 82 size_t refcount; /**< Connection reference count */ 83 devmap_handle_t devmap_handle; /**< Device handle */ 84 keybuffer_t keybuffer; /**< Buffer for incoming keys. */ 85 screenbuffer_t scr; /**< Screenbuffer for saving screen 86 contents and related settings. */ 87 } console_t; 112 /** Session to the framebuffer server */ 113 static async_sess_t *fb_sess; 114 115 /** Framebuffer resolution */ 116 static sysarg_t xres; 117 static sysarg_t yres; 88 118 89 119 /** Array of data for virtual consoles */ 90 120 static console_t consoles[CONSOLE_COUNT]; 91 121 122 /** Mutex for console switching */ 123 static FIBRIL_MUTEX_INITIALIZE(switch_mtx); 124 125 static console_t *prev_console = &consoles[0]; 92 126 static console_t *active_console = &consoles[0]; 93 static console_t *prev_console = &consoles[0];94 127 static console_t *kernel_console = &consoles[KERNEL_CONSOLE]; 95 128 96 /** Pointer to memory shared with framebufer used for 97 faster virtual console switching */ 98 static keyfield_t *interbuffer = NULL; 99 100 /** Information on row-span yet unsent to FB driver. */ 129 static imgmap_t *logo_img; 130 static imgmap_t *nameic_img; 131 132 static imgmap_t *anim_1_img; 133 static imgmap_t *anim_2_img; 134 static imgmap_t *anim_3_img; 135 static imgmap_t *anim_4_img; 136 137 static imagemap_handle_t anim_1; 138 static imagemap_handle_t anim_2; 139 static imagemap_handle_t anim_3; 140 static imagemap_handle_t anim_4; 141 142 static sequence_handle_t anim_seq; 143 144 static imgmap_t *cons_data_img; 145 static imgmap_t *cons_dis_img; 146 static imgmap_t *cons_dis_sel_img; 147 static imgmap_t *cons_idle_img; 148 static imgmap_t *cons_kernel_img; 149 static imgmap_t *cons_sel_img; 150 151 static vp_handle_t logo_vp; 152 static imagemap_handle_t logo_handle; 153 154 static vp_handle_t nameic_vp; 155 static imagemap_handle_t nameic_handle; 156 157 static vp_handle_t screen_vp; 158 static vp_handle_t console_vp; 159 101 160 struct { 102 sysarg_t col; /**< Leftmost column of the span. */ 103 sysarg_t row; /**< Row where the span lies. */ 104 sysarg_t cnt; /**< Width of the span. */ 105 } fb_pending; 106 107 static FIBRIL_MUTEX_INITIALIZE(input_mutex); 108 static FIBRIL_CONDVAR_INITIALIZE(input_cv); 109 110 static FIBRIL_MUTEX_INITIALIZE(big_console_lock); 111 112 static void console_serialize_start(void) 113 { 114 fibril_mutex_lock(&big_console_lock); 115 } 116 117 static void console_serialize_end(void) 118 { 119 fibril_mutex_unlock(&big_console_lock); 120 } 121 122 static void curs_visibility(bool visible) 123 { 124 async_obsolete_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible); 125 } 126 127 static void curs_hide_sync(void) 128 { 129 async_obsolete_req_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false); 130 } 131 132 static void curs_goto(sysarg_t x, sysarg_t y) 133 { 134 async_obsolete_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y); 135 } 136 137 static void screen_clear(void) 138 { 139 async_obsolete_msg_0(fb_info.phone, FB_CLEAR); 140 } 141 142 static void screen_yield(void) 143 { 144 async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_YIELD); 145 } 146 147 static void screen_reclaim(void) 148 { 149 async_obsolete_req_0_0(fb_info.phone, FB_SCREEN_RECLAIM); 150 } 151 152 static void input_yield(void) 153 { 154 async_exch_t *exch = async_exchange_begin(input_sess); 155 if (exch == NULL) { 156 printf("%s: Failed starting exchange with input device.\n", 157 NAME); 161 sysarg_t x; 162 sysarg_t y; 163 164 sysarg_t btn_x; 165 sysarg_t btn_y; 166 167 bool pressed; 168 } mouse; 169 170 static void cons_redraw_state(console_t *cons) 171 { 172 if (graphics_state == GRAPHICS_FULL) { 173 fibril_mutex_lock(&cons->mtx); 174 175 fb_vp_imagemap_damage(fb_sess, cons->state_vp, 176 state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT); 177 178 if ((cons->state != CONS_DISCONNECTED) && 179 (cons->state != CONS_KERNEL) && 180 (cons->state != CONS_DISCONNECTED_SELECTED)) { 181 char data[5]; 182 snprintf(data, 5, "%zu", cons->index + 1); 183 184 for (size_t i = 0; data[i] != 0; i++) 185 fb_vp_putchar(fb_sess, cons->state_vp, i + 2, 1, data[i]); 186 } 187 188 fibril_mutex_unlock(&cons->mtx); 189 } 190 } 191 192 static void cons_kernel_sequence_start(console_t *cons) 193 { 194 if (graphics_state == GRAPHICS_FULL) { 195 fibril_mutex_lock(&cons->mtx); 196 197 fb_vp_sequence_start(fb_sess, cons->state_vp, anim_seq); 198 fb_vp_imagemap_damage(fb_sess, cons->state_vp, 199 state_icons[cons->state], 0, 0, STATE_WIDTH, STATE_HEIGHT); 200 201 fibril_mutex_unlock(&cons->mtx); 202 } 203 } 204 205 static void cons_update_state(console_t *cons, console_state_t state) 206 { 207 bool update = false; 208 209 fibril_mutex_lock(&cons->mtx); 210 211 if (cons->state != state) { 212 cons->state = state; 213 update = true; 214 } 215 216 fibril_mutex_unlock(&cons->mtx); 217 218 if (update) 219 cons_redraw_state(cons); 220 } 221 222 static void cons_notify_data(console_t *cons) 223 { 224 fibril_mutex_lock(&switch_mtx); 225 226 if (cons != active_console) 227 cons_update_state(cons, CONS_DATA); 228 229 fibril_mutex_unlock(&switch_mtx); 230 } 231 232 static void cons_notify_connect(console_t *cons) 233 { 234 fibril_mutex_lock(&switch_mtx); 235 236 if (cons == active_console) 237 cons_update_state(cons, CONS_SELECTED); 238 else 239 cons_update_state(cons, CONS_IDLE); 240 241 fibril_mutex_unlock(&switch_mtx); 242 } 243 244 static void cons_notify_disconnect(console_t *cons) 245 { 246 fibril_mutex_lock(&switch_mtx); 247 248 if (cons == active_console) 249 cons_update_state(cons, CONS_DISCONNECTED_SELECTED); 250 else 251 cons_update_state(cons, CONS_DISCONNECTED); 252 253 fibril_mutex_unlock(&switch_mtx); 254 } 255 256 static void cons_update(console_t *cons) 257 { 258 fibril_mutex_lock(&switch_mtx); 259 fibril_mutex_lock(&cons->mtx); 260 261 if ((cons == active_console) && (active_console != kernel_console)) { 262 fb_vp_update(fb_sess, console_vp, cons->fbid); 263 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 264 } 265 266 fibril_mutex_unlock(&cons->mtx); 267 fibril_mutex_unlock(&switch_mtx); 268 } 269 270 static void cons_update_cursor(console_t *cons) 271 { 272 fibril_mutex_lock(&switch_mtx); 273 fibril_mutex_lock(&cons->mtx); 274 275 if ((cons == active_console) && (active_console != kernel_console)) 276 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 277 278 fibril_mutex_unlock(&cons->mtx); 279 fibril_mutex_unlock(&switch_mtx); 280 } 281 282 static void cons_clear(console_t *cons) 283 { 284 fibril_mutex_lock(&cons->mtx); 285 screenbuffer_clear(cons->frontbuf); 286 fibril_mutex_unlock(&cons->mtx); 287 288 cons_update(cons); 289 } 290 291 static void cons_damage_all(console_t *cons) 292 { 293 fibril_mutex_lock(&switch_mtx); 294 fibril_mutex_lock(&cons->mtx); 295 296 if ((cons == active_console) && (active_console != kernel_console)) { 297 fb_vp_damage(fb_sess, console_vp, cons->fbid, 0, 0, cons->cols, 298 cons->rows); 299 fb_vp_cursor_update(fb_sess, console_vp, cons->fbid); 300 } 301 302 fibril_mutex_unlock(&cons->mtx); 303 fibril_mutex_unlock(&switch_mtx); 304 } 305 306 static void cons_switch(console_t *cons) 307 { 308 fibril_mutex_lock(&switch_mtx); 309 310 if (cons == active_console) { 311 fibril_mutex_unlock(&switch_mtx); 158 312 return; 159 313 } 160 314 161 async_req_0_0(exch, INPUT_YIELD); 162 async_exchange_end(exch); 163 } 164 165 static void input_reclaim(void) 166 { 167 async_exch_t *exch = async_exchange_begin(input_sess); 168 if (exch == NULL) { 169 printf("%s: Failed starting exchange with input device.\n", 170 NAME); 171 return; 172 } 173 174 async_req_0_0(exch, INPUT_RECLAIM); 175 async_exchange_end(exch); 176 } 177 178 static void set_style(uint8_t style) 179 { 180 async_obsolete_msg_1(fb_info.phone, FB_SET_STYLE, style); 181 } 182 183 static void set_color(uint8_t fgcolor, uint8_t bgcolor, uint8_t flags) 184 { 185 async_obsolete_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags); 186 } 187 188 static void set_rgb_color(uint32_t fgcolor, uint32_t bgcolor) 189 { 190 async_obsolete_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor); 191 } 192 193 static void set_attrs(attrs_t *attrs) 194 { 195 switch (attrs->t) { 196 case at_style: 197 set_style(attrs->a.s.style); 198 break; 199 case at_idx: 200 set_color(attrs->a.i.fg_color, attrs->a.i.bg_color, 201 attrs->a.i.flags); 202 break; 203 case at_rgb: 204 set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color); 205 break; 206 } 207 } 208 209 static int ccap_fb_to_con(sysarg_t ccap_fb, sysarg_t *ccap_con) 210 { 211 switch (ccap_fb) { 212 case FB_CCAP_NONE: 213 *ccap_con = CONSOLE_CCAP_NONE; 214 break; 215 case FB_CCAP_STYLE: 216 *ccap_con = CONSOLE_CCAP_STYLE; 217 break; 218 case FB_CCAP_INDEXED: 219 *ccap_con = CONSOLE_CCAP_INDEXED; 220 break; 221 case FB_CCAP_RGB: 222 *ccap_con = CONSOLE_CCAP_RGB; 223 break; 224 default: 225 return EINVAL; 226 } 227 228 return EOK; 229 } 230 231 /** Send an area of screenbuffer to the FB driver. */ 232 static void fb_update_area(console_t *cons, sysarg_t x0, sysarg_t y0, sysarg_t width, sysarg_t height) 233 { 234 if (interbuffer) { 235 sysarg_t x; 236 sysarg_t y; 237 238 for (y = 0; y < height; y++) { 239 for (x = 0; x < width; x++) { 240 interbuffer[y * width + x] = 241 *get_field_at(&cons->scr, x0 + x, y0 + y); 242 } 243 } 244 245 async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 246 x0, y0, width, height); 247 } 248 } 249 250 /** Flush pending cells to FB. */ 251 static void fb_pending_flush(void) 252 { 253 if (fb_pending.cnt > 0) { 254 fb_update_area(active_console, fb_pending.col, 255 fb_pending.row, fb_pending.cnt, 1); 256 fb_pending.cnt = 0; 257 } 258 } 259 260 /** Mark a character cell as changed. 315 if (cons == kernel_console) { 316 fb_yield(fb_sess); 317 if (!console_kcon()) { 318 fb_claim(fb_sess); 319 fibril_mutex_unlock(&switch_mtx); 320 return; 321 } 322 } 323 324 if (active_console == kernel_console) 325 fb_claim(fb_sess); 326 327 prev_console = active_console; 328 active_console = cons; 329 330 if (prev_console->state == CONS_DISCONNECTED_SELECTED) 331 cons_update_state(prev_console, CONS_DISCONNECTED); 332 else 333 cons_update_state(prev_console, CONS_IDLE); 334 335 if ((cons->state == CONS_DISCONNECTED) || 336 (cons->state == CONS_DISCONNECTED_SELECTED)) 337 cons_update_state(cons, CONS_DISCONNECTED_SELECTED); 338 else 339 cons_update_state(cons, CONS_SELECTED); 340 341 fibril_mutex_unlock(&switch_mtx); 342 343 cons_damage_all(cons); 344 } 345 346 static ssize_t limit(ssize_t val, ssize_t lo, ssize_t hi) 347 { 348 if (val > hi) 349 return hi; 350 351 if (val < lo) 352 return lo; 353 354 return val; 355 } 356 357 static void cons_mouse_move(sysarg_t dx, sysarg_t dy) 358 { 359 ssize_t sx = (ssize_t) dx; 360 ssize_t sy = (ssize_t) dy; 361 362 mouse.x = limit(mouse.x + sx, 0, xres); 363 mouse.y = limit(mouse.y + sy, 0, yres); 364 365 fb_pointer_update(fb_sess, mouse.x, mouse.y, true); 366 } 367 368 static console_t *cons_find_icon(sysarg_t x, sysarg_t y) 369 { 370 sysarg_t status_start = 371 STATE_START + (xres - 800) / 2 + CONSOLE_MARGIN; 372 373 if ((y < STATE_TOP) || (y >= STATE_TOP + STATE_HEIGHT)) 374 return NULL; 375 376 if (x < status_start) 377 return NULL; 378 379 if (x >= status_start + (STATE_WIDTH + STATE_SPACE) * CONSOLE_COUNT) 380 return NULL; 381 382 if (((x - status_start) % (STATE_WIDTH + STATE_SPACE)) >= STATE_WIDTH) 383 return NULL; 384 385 sysarg_t btn = (x - status_start) / (STATE_WIDTH + STATE_SPACE); 386 387 if (btn < CONSOLE_COUNT) 388 return consoles + btn; 389 390 return NULL; 391 } 392 393 /** Handle mouse click 261 394 * 262 * This adds the cell to the pending rowspan if possible. Otherwise 263 * the old span is flushed first. 395 * @param state Button state (true - pressed, false - depressed) 264 396 * 265 397 */ 266 static void cell_mark_changed(sysarg_t col, sysarg_t row) 267 { 268 if (fb_pending.cnt != 0) { 269 if ((col != fb_pending.col + fb_pending.cnt) 270 || (row != fb_pending.row)) { 271 fb_pending_flush(); 272 } 273 } 274 275 if (fb_pending.cnt == 0) { 276 fb_pending.col = col; 277 fb_pending.row = row; 278 } 279 280 fb_pending.cnt++; 281 } 282 283 /** Print a character to the active VC with buffering. */ 284 static void fb_putchar(wchar_t c, sysarg_t col, sysarg_t row) 285 { 286 async_obsolete_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row); 398 static console_t *cons_mouse_button(bool state) 399 { 400 if (graphics_state != GRAPHICS_FULL) 401 return NULL; 402 403 if (state) { 404 console_t *cons = cons_find_icon(mouse.x, mouse.y); 405 if (cons != NULL) { 406 mouse.btn_x = mouse.x; 407 mouse.btn_y = mouse.y; 408 mouse.pressed = true; 409 } 410 411 return NULL; 412 } 413 414 if ((!state) && (!mouse.pressed)) 415 return NULL; 416 417 console_t *cons = cons_find_icon(mouse.x, mouse.y); 418 if (cons == cons_find_icon(mouse.btn_x, mouse.btn_y)) 419 return cons; 420 421 mouse.pressed = false; 422 return NULL; 423 } 424 425 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg) 426 { 427 /* Ignore parameters, the connection is already opened */ 428 while (true) { 429 ipc_call_t call; 430 ipc_callid_t callid = async_get_call(&call); 431 432 if (!IPC_GET_IMETHOD(call)) { 433 /* TODO: Handle hangup */ 434 async_hangup(input_sess); 435 return; 436 } 437 438 kbd_event_type_t type; 439 keycode_t key; 440 keymod_t mods; 441 wchar_t c; 442 443 switch (IPC_GET_IMETHOD(call)) { 444 case INPUT_EVENT_KEY: 445 type = IPC_GET_ARG1(call); 446 key = IPC_GET_ARG2(call); 447 mods = IPC_GET_ARG3(call); 448 c = IPC_GET_ARG4(call); 449 450 if ((key >= KC_F1) && (key < KC_F1 + CONSOLE_COUNT) && 451 ((mods & KM_CTRL) == 0)) 452 cons_switch(&consoles[key - KC_F1]); 453 else { 454 /* Got key press/release event */ 455 kbd_event_t *event = 456 (kbd_event_t *) malloc(sizeof(kbd_event_t)); 457 if (event == NULL) { 458 async_answer_0(callid, ENOMEM); 459 break; 460 } 461 462 link_initialize(&event->link); 463 event->type = type; 464 event->key = key; 465 event->mods = mods; 466 event->c = c; 467 468 prodcons_produce(&active_console->input_pc, &event->link); 469 } 470 471 async_answer_0(callid, EOK); 472 break; 473 case INPUT_EVENT_MOVE: 474 cons_mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 475 async_answer_0(callid, EOK); 476 break; 477 case INPUT_EVENT_BUTTON: 478 /* Got pointer button press/release event */ 479 if (IPC_GET_ARG1(call) == 1) { 480 console_t *cons = 481 cons_mouse_button((bool) IPC_GET_ARG2(call)); 482 if (cons != NULL) 483 cons_switch(cons); 484 } 485 async_answer_0(callid, EOK); 486 break; 487 default: 488 async_answer_0(callid, EINVAL); 489 } 490 } 287 491 } 288 492 289 493 /** Process a character from the client (TTY emulation). */ 290 static void write_char(console_t *cons, wchar_t ch) 291 { 292 bool flush_cursor = false; 494 static void cons_write_char(console_t *cons, wchar_t ch) 495 { 496 sysarg_t updated = 0; 497 498 fibril_mutex_lock(&cons->mtx); 293 499 294 500 switch (ch) { 295 501 case '\n': 296 fb_pending_flush(); 297 flush_cursor = true; 298 cons->scr.position_y++; 299 cons->scr.position_x = 0; 502 updated = screenbuffer_newline(cons->frontbuf); 300 503 break; 301 504 case '\r': 302 505 break; 303 506 case '\t': 304 cons->scr.position_x += 8; 305 cons->scr.position_x -= cons->scr.position_x % 8; 507 updated = screenbuffer_tabstop(cons->frontbuf, 8); 306 508 break; 307 509 case '\b': 308 if (cons->scr.position_x == 0) 309 break; 310 cons->scr.position_x--; 311 if (cons == active_console) 312 cell_mark_changed(cons->scr.position_x, cons->scr.position_y); 313 screenbuffer_putchar(&cons->scr, ' '); 510 updated = screenbuffer_backspace(cons->frontbuf); 314 511 break; 315 512 default: 316 if (cons == active_console) 317 cell_mark_changed(cons->scr.position_x, cons->scr.position_y); 318 319 screenbuffer_putchar(&cons->scr, ch); 320 cons->scr.position_x++; 321 } 322 323 if (cons->scr.position_x >= cons->scr.size_x) { 324 flush_cursor = true; 325 cons->scr.position_y++; 326 } 327 328 if (cons->scr.position_y >= cons->scr.size_y) { 329 fb_pending_flush(); 330 cons->scr.position_y = cons->scr.size_y - 1; 331 screenbuffer_clear_line(&cons->scr, cons->scr.top_line); 332 cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y; 333 334 if (cons == active_console) 335 async_obsolete_msg_1(fb_info.phone, FB_SCROLL, 1); 336 } 337 338 if (cons == active_console && flush_cursor) 339 curs_goto(cons->scr.position_x, cons->scr.position_y); 340 cons->scr.position_x = cons->scr.position_x % cons->scr.size_x; 341 } 342 343 /** Switch to new console */ 344 static void change_console(console_t *cons) 345 { 346 if (cons == active_console) 347 return; 348 349 fb_pending_flush(); 350 351 if (cons == kernel_console) { 352 console_serialize_start(); 353 curs_hide_sync(); 354 gcons_in_kernel(); 355 screen_yield(); 356 input_yield(); 357 console_serialize_end(); 358 359 if (console_kcon()) { 360 prev_console = active_console; 361 active_console = kernel_console; 362 } else 363 cons = active_console; 364 } 365 366 if (cons != kernel_console) { 367 console_serialize_start(); 368 369 if (active_console == kernel_console) { 370 screen_reclaim(); 371 input_reclaim(); 372 gcons_redraw_console(); 373 } 374 375 active_console = cons; 376 gcons_change_console(cons->index); 377 378 set_attrs(&cons->scr.attrs); 379 curs_visibility(false); 380 381 sysarg_t x; 382 sysarg_t y; 383 int rc = 0; 384 385 if (interbuffer) { 386 for (y = 0; y < cons->scr.size_y; y++) { 387 for (x = 0; x < cons->scr.size_x; x++) { 388 interbuffer[y * cons->scr.size_x + x] = 389 *get_field_at(&cons->scr, x, y); 390 } 391 } 392 393 /* This call can preempt, but we are already at the end */ 394 rc = async_obsolete_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA, 395 0, 0, cons->scr.size_x, 396 cons->scr.size_y); 397 } 398 399 if ((!interbuffer) || (rc != 0)) { 400 set_attrs(&cons->scr.attrs); 401 screen_clear(); 402 403 for (y = 0; y < cons->scr.size_y; y++) 404 for (x = 0; x < cons->scr.size_x; x++) { 405 keyfield_t *field = get_field_at(&cons->scr, x, y); 406 407 if (!attrs_same(cons->scr.attrs, field->attrs)) 408 set_attrs(&field->attrs); 409 410 cons->scr.attrs = field->attrs; 411 if ((field->character == ' ') && 412 (attrs_same(field->attrs, cons->scr.attrs))) 413 continue; 414 415 fb_putchar(field->character, x, y); 416 } 417 } 418 419 curs_goto(cons->scr.position_x, cons->scr.position_y); 420 curs_visibility(cons->scr.is_cursor_visible); 421 422 console_serialize_end(); 423 } 424 } 425 426 /** Handler for input events */ 427 static void input_events(ipc_callid_t iid, ipc_call_t *icall, void *arg) 428 { 429 /* Ignore parameters, the connection is already opened */ 430 while (true) { 431 ipc_call_t call; 432 ipc_callid_t callid = async_get_call(&call); 433 434 int retval; 435 kbd_event_t ev; 436 437 if (!IPC_GET_IMETHOD(call)) { 438 /* TODO: Handle hangup */ 439 async_hangup(input_sess); 440 return; 441 } 442 443 switch (IPC_GET_IMETHOD(call)) { 444 case INPUT_EVENT_KEY: 445 /* Got key press/release event */ 446 retval = 0; 447 ev.type = IPC_GET_ARG1(call); 448 ev.key = IPC_GET_ARG2(call); 449 ev.mods = IPC_GET_ARG3(call); 450 ev.c = IPC_GET_ARG4(call); 451 452 if ((ev.key >= KC_F1) && (ev.key < KC_F1 + 453 CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) { 454 if (ev.key == KC_F1 + KERNEL_CONSOLE) 455 change_console(kernel_console); 456 else 457 change_console(&consoles[ev.key - KC_F1]); 458 break; 459 } 460 461 fibril_mutex_lock(&input_mutex); 462 keybuffer_push(&active_console->keybuffer, &ev); 463 fibril_condvar_broadcast(&input_cv); 464 fibril_mutex_unlock(&input_mutex); 465 break; 466 case INPUT_EVENT_MOVE: 467 /* Got pointer move event */ 468 gcons_mouse_move((int) IPC_GET_ARG1(call), 469 (int) IPC_GET_ARG2(call)); 470 retval = 0; 471 break; 472 case INPUT_EVENT_BUTTON: 473 /* Got pointer button press/release event */ 474 if (IPC_GET_ARG1(call) == 1) { 475 int newcon = gcons_mouse_btn((bool) IPC_GET_ARG2(call)); 476 if (newcon != -1) 477 change_console(&consoles[newcon]); 478 } 479 retval = 0; 480 break; 481 default: 482 retval = ENOENT; 483 } 484 485 async_answer_0(callid, retval); 486 } 487 } 488 489 static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 513 updated = screenbuffer_putchar(cons->frontbuf, ch, true); 514 } 515 516 fibril_mutex_unlock(&cons->mtx); 517 518 if (updated > 1) 519 cons_update(cons); 520 } 521 522 static void cons_set_cursor(console_t *cons, sysarg_t col, sysarg_t row) 523 { 524 fibril_mutex_lock(&cons->mtx); 525 screenbuffer_set_cursor(cons->frontbuf, col, row); 526 fibril_mutex_unlock(&cons->mtx); 527 528 cons_update_cursor(cons); 529 } 530 531 static void cons_set_cursor_visibility(console_t *cons, bool visible) 532 { 533 fibril_mutex_lock(&cons->mtx); 534 screenbuffer_set_cursor_visibility(cons->frontbuf, visible); 535 fibril_mutex_unlock(&cons->mtx); 536 537 cons_update_cursor(cons); 538 } 539 540 static void cons_get_cursor(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 541 { 542 sysarg_t col; 543 sysarg_t row; 544 545 fibril_mutex_lock(&cons->mtx); 546 screenbuffer_get_cursor(cons->frontbuf, &col, &row); 547 fibril_mutex_unlock(&cons->mtx); 548 549 async_answer_2(iid, EOK, col, row); 550 } 551 552 static void cons_write(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 490 553 { 491 554 void *buf; … … 494 557 495 558 if (rc != EOK) { 496 async_answer_0( rid, rc);559 async_answer_0(iid, rc); 497 560 return; 498 561 } 499 562 500 console_serialize_start();501 502 563 size_t off = 0; 503 while (off < size) { 504 wchar_t ch = str_decode(buf, &off, size); 505 write_char(cons, ch); 506 } 507 508 console_serialize_end(); 509 510 gcons_notify_char(cons->index); 511 async_answer_1(rid, EOK, size); 512 564 while (off < size) 565 cons_write_char(cons, str_decode(buf, &off, size)); 566 567 async_answer_1(iid, EOK, size); 513 568 free(buf); 514 } 515 516 static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 569 570 cons_notify_data(cons); 571 } 572 573 static void cons_read(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 517 574 { 518 575 ipc_callid_t callid; … … 520 577 if (!async_data_read_receive(&callid, &size)) { 521 578 async_answer_0(callid, EINVAL); 522 async_answer_0( rid, EINVAL);579 async_answer_0(iid, EINVAL); 523 580 return; 524 581 } … … 527 584 if (buf == NULL) { 528 585 async_answer_0(callid, ENOMEM); 529 async_answer_0( rid, ENOMEM);586 async_answer_0(iid, ENOMEM); 530 587 return; 531 588 } 532 589 533 590 size_t pos = 0; 534 kbd_event_t ev; 535 fibril_mutex_lock(&input_mutex); 536 537 recheck: 538 while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) { 539 if (ev.type == KEY_PRESS) { 540 buf[pos] = ev.c; 591 while (pos < size) { 592 link_t *link = prodcons_consume(&cons->input_pc); 593 kbd_event_t *event = list_get_instance(link, kbd_event_t, link); 594 595 if (event->type == KEY_PRESS) { 596 buf[pos] = event->c; 541 597 pos++; 542 598 } 543 } 544 545 if (pos == size) { 546 (void) async_data_read_finalize(callid, buf, size); 547 async_answer_1(rid, EOK, size); 548 free(buf); 549 } else { 550 fibril_condvar_wait(&input_cv, &input_mutex); 551 goto recheck; 552 } 553 554 fibril_mutex_unlock(&input_mutex); 555 } 556 557 static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request) 558 { 559 kbd_event_t ev; 560 561 fibril_mutex_lock(&input_mutex); 562 563 recheck: 564 if (keybuffer_pop(&cons->keybuffer, &ev)) { 565 async_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c); 566 } else { 567 fibril_condvar_wait(&input_cv, &input_mutex); 568 goto recheck; 569 } 570 571 fibril_mutex_unlock(&input_mutex); 572 } 573 574 /** Default thread for new connections */ 599 600 free(event); 601 } 602 603 (void) async_data_read_finalize(callid, buf, size); 604 async_answer_1(iid, EOK, size); 605 free(buf); 606 } 607 608 static void cons_set_style(console_t *cons, console_style_t style) 609 { 610 fibril_mutex_lock(&cons->mtx); 611 screenbuffer_set_style(cons->frontbuf, style); 612 fibril_mutex_unlock(&cons->mtx); 613 } 614 615 static void cons_set_color(console_t *cons, console_color_t bgcolor, 616 console_color_t fgcolor, console_color_attr_t attr) 617 { 618 fibril_mutex_lock(&cons->mtx); 619 screenbuffer_set_color(cons->frontbuf, bgcolor, fgcolor, attr); 620 fibril_mutex_unlock(&cons->mtx); 621 } 622 623 static void cons_set_rgb_color(console_t *cons, pixel_t bgcolor, 624 pixel_t fgcolor) 625 { 626 fibril_mutex_lock(&cons->mtx); 627 screenbuffer_set_rgb_color(cons->frontbuf, bgcolor, fgcolor); 628 fibril_mutex_unlock(&cons->mtx); 629 } 630 631 static void cons_get_event(console_t *cons, ipc_callid_t iid, ipc_call_t *icall) 632 { 633 link_t *link = prodcons_consume(&cons->input_pc); 634 kbd_event_t *event = list_get_instance(link, kbd_event_t, link); 635 636 async_answer_4(iid, EOK, event->type, event->key, event->mods, event->c); 637 free(event); 638 } 639 575 640 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 576 641 { 577 642 console_t *cons = NULL; 578 643 579 size_t i; 580 for (i = 0; i < CONSOLE_COUNT; i++) { 644 for (size_t i = 0; i < CONSOLE_COUNT; i++) { 581 645 if (i == KERNEL_CONSOLE) 582 646 continue; 583 647 584 if (consoles[i].d evmap_handle == (devmap_handle_t) IPC_GET_ARG1(*icall)) {648 if (consoles[i].dsid == (service_id_t) IPC_GET_ARG1(*icall)) { 585 649 cons = &consoles[i]; 586 650 break; … … 593 657 } 594 658 595 ipc_callid_t callid; 596 ipc_call_t call; 597 sysarg_t arg1; 598 sysarg_t arg2; 599 sysarg_t arg3; 600 601 int rc; 602 603 console_serialize_start(); 604 if (cons->refcount == 0) 605 gcons_notify_connect(cons->index); 606 607 cons->refcount++; 659 if (atomic_postinc(&cons->refcnt) == 0) { 660 cons_set_cursor_visibility(cons, true); 661 cons_notify_connect(cons); 662 } 608 663 609 664 /* Accept the connection */ … … 611 666 612 667 while (true) { 613 console_serialize_end(); 614 callid = async_get_call(&call); 615 console_serialize_start(); 616 617 arg1 = 0; 618 arg2 = 0; 619 arg3 = 0; 668 ipc_call_t call; 669 ipc_callid_t callid = async_get_call(&call); 620 670 621 671 if (!IPC_GET_IMETHOD(call)) { 622 cons->refcount--; 623 if (cons->refcount == 0) 624 gcons_notify_disconnect(cons->index); 625 console_serialize_end(); 672 if (atomic_postdec(&cons->refcnt) == 1) 673 cons_notify_disconnect(cons); 674 626 675 return; 627 676 } … … 629 678 switch (IPC_GET_IMETHOD(call)) { 630 679 case VFS_OUT_READ: 631 console_serialize_end();632 680 cons_read(cons, callid, &call); 633 console_serialize_start(); 634 continue; 681 break; 635 682 case VFS_OUT_WRITE: 636 console_serialize_end();637 683 cons_write(cons, callid, &call); 638 console_serialize_start(); 639 continue; 684 break; 640 685 case VFS_OUT_SYNC: 641 fb_pending_flush(); 642 if (cons == active_console) { 643 async_obsolete_req_0_0(fb_info.phone, FB_FLUSH); 644 curs_goto(cons->scr.position_x, cons->scr.position_y); 645 } 686 cons_update(cons); 687 async_answer_0(callid, EOK); 646 688 break; 647 689 case CONSOLE_CLEAR: 648 /* Send message to fb */ 649 if (cons == active_console) 650 async_obsolete_msg_0(fb_info.phone, FB_CLEAR); 651 652 screenbuffer_clear(&cons->scr); 653 690 cons_clear(cons); 691 async_answer_0(callid, EOK); 654 692 break; 655 693 case CONSOLE_GOTO: 656 screenbuffer_goto(&cons->scr, 657 IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 658 if (cons == active_console) 659 curs_goto(IPC_GET_ARG1(call), 660 IPC_GET_ARG2(call)); 694 cons_set_cursor(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 695 async_answer_0(callid, EOK); 661 696 break; 662 697 case CONSOLE_GET_POS: 663 arg1 = cons->scr.position_x; 664 arg2 = cons->scr.position_y; 698 cons_get_cursor(cons, callid, &call); 665 699 break; 666 700 case CONSOLE_GET_SIZE: 667 arg1 = fb_info.cols; 668 arg2 = fb_info.rows; 701 async_answer_2(callid, EOK, cons->cols, cons->rows); 669 702 break; 670 703 case CONSOLE_GET_COLOR_CAP: 671 rc = ccap_fb_to_con(fb_info.color_cap, &arg1); 672 if (rc != EOK) { 673 async_answer_0(callid, rc); 674 continue; 675 } 704 async_answer_1(callid, EOK, cons->ccaps); 676 705 break; 677 706 case CONSOLE_SET_STYLE: 678 fb_pending_flush(); 679 arg1 = IPC_GET_ARG1(call); 680 screenbuffer_set_style(&cons->scr, arg1); 681 if (cons == active_console) 682 set_style(arg1); 707 cons_set_style(cons, IPC_GET_ARG1(call)); 708 async_answer_0(callid, EOK); 683 709 break; 684 710 case CONSOLE_SET_COLOR: 685 fb_pending_flush(); 686 arg1 = IPC_GET_ARG1(call); 687 arg2 = IPC_GET_ARG2(call); 688 arg3 = IPC_GET_ARG3(call); 689 screenbuffer_set_color(&cons->scr, arg1, arg2, arg3); 690 if (cons == active_console) 691 set_color(arg1, arg2, arg3); 711 cons_set_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call), 712 IPC_GET_ARG3(call)); 713 async_answer_0(callid, EOK); 692 714 break; 693 715 case CONSOLE_SET_RGB_COLOR: 694 fb_pending_flush(); 695 arg1 = IPC_GET_ARG1(call); 696 arg2 = IPC_GET_ARG2(call); 697 screenbuffer_set_rgb_color(&cons->scr, arg1, arg2); 698 if (cons == active_console) 699 set_rgb_color(arg1, arg2); 716 cons_set_rgb_color(cons, IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 717 async_answer_0(callid, EOK); 700 718 break; 701 719 case CONSOLE_CURSOR_VISIBILITY: 702 fb_pending_flush(); 703 arg1 = IPC_GET_ARG1(call); 704 cons->scr.is_cursor_visible = arg1; 705 if (cons == active_console) 706 curs_visibility(arg1); 720 cons_set_cursor_visibility(cons, IPC_GET_ARG1(call)); 721 async_answer_0(callid, EOK); 707 722 break; 708 723 case CONSOLE_GET_EVENT: 709 console_serialize_end();710 724 cons_get_event(cons, callid, &call); 711 console_serialize_start(); 712 continue; 713 } 714 async_answer_3(callid, EOK, arg1, arg2, arg3); 715 } 716 } 717 718 static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) 719 { 720 change_console(prev_console); 721 } 722 723 static async_sess_t *connect_input(const char *dev_path) 725 break; 726 default: 727 async_answer_0(callid, EINVAL); 728 } 729 } 730 } 731 732 static async_sess_t *input_connect(const char *svc) 724 733 { 725 734 async_sess_t *sess; 726 async_exch_t *exch; 727 devmap_handle_t handle; 728 729 int rc = devmap_device_get_handle(dev_path, &handle, 0); 735 service_id_t dsid; 736 737 int rc = loc_service_get_id(svc, &dsid, 0); 730 738 if (rc == EOK) { 731 sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);739 sess = loc_service_connect(EXCHANGE_ATOMIC, dsid, 0); 732 740 if (sess == NULL) { 733 printf("%s: Failed to connect to input server\n", NAME); 741 printf("%s: Unable to connect to input service %s\n", NAME, 742 svc); 734 743 return NULL; 735 744 } 736 } else {745 } else 737 746 return NULL; 738 } 739 740 exch = async_exchange_begin(sess); 741 if (exch == NULL) { 742 printf("%s: Failed to create callback from input server.\n", NAME); 743 return NULL; 744 } 745 746 /* NB: The callback connection is slotted for removal */ 747 748 async_exch_t *exch = async_exchange_begin(sess); 747 749 rc = async_connect_to_me(exch, 0, 0, 0, input_events, NULL); 748 749 750 async_exchange_end(exch); 750 751 751 752 if (rc != EOK) { 752 753 async_hangup(sess); 753 printf("%s: Failed to create callback from input server (%s).\n",754 NAME, s tr_error(rc));754 printf("%s: Unable to create callback connection to service %s (%s)\n", 755 NAME, svc, str_error(rc)); 755 756 return NULL; 756 757 } … … 759 760 } 760 761 761 static bool console_srv_init(char *input_dev) 762 { 763 /* Connect to input server */ 764 input_sess = connect_input(input_dev); 762 static void interrupt_received(ipc_callid_t callid, ipc_call_t *call) 763 { 764 cons_switch(prev_console); 765 } 766 767 static async_sess_t *fb_connect(const char *svc) 768 { 769 async_sess_t *sess; 770 service_id_t dsid; 771 772 int rc = loc_service_get_id(svc, &dsid, 0); 773 if (rc == EOK) { 774 sess = loc_service_connect(EXCHANGE_SERIALIZE, dsid, 0); 775 if (sess == NULL) { 776 printf("%s: Unable to connect to framebuffer service %s\n", 777 NAME, svc); 778 return NULL; 779 } 780 } else 781 return NULL; 782 783 return sess; 784 } 785 786 static bool console_srv_init(char *input_svc, char *fb_svc) 787 { 788 /* Avoid double initialization */ 789 if (graphics_state != GRAPHICS_NONE) 790 return false; 791 792 /* Connect to input service */ 793 input_sess = input_connect(input_svc); 765 794 if (input_sess == NULL) 766 795 return false; 767 796 768 /* Connect to framebuffer driver */ 769 fb_info.phone = service_obsolete_connect_blocking(SERVICE_VIDEO, 0, 0); 770 if (fb_info.phone < 0) { 771 printf("%s: Failed to connect to video service\n", NAME); 797 /* Connect to framebuffer service */ 798 fb_sess = fb_connect(fb_svc); 799 if (fb_sess == NULL) 772 800 return false; 773 } 774 775 /* Register driver */ 776 int rc = devmap_driver_register(NAME, client_connection); 801 802 /* Register server */ 803 int rc = loc_server_register(NAME, client_connection); 777 804 if (rc < 0) { 778 printf("%s: Unable to register driver (%d)\n", NAME, rc); 805 printf("%s: Unable to register server (%s)\n", NAME, 806 str_error(rc)); 779 807 return false; 780 808 } 781 809 782 /* Initialize gcons */ 783 gcons_init(fb_info.phone); 784 785 /* Synchronize, the gcons could put something in queue */ 786 async_obsolete_req_0_0(fb_info.phone, FB_FLUSH); 787 async_obsolete_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows); 788 async_obsolete_req_0_1(fb_info.phone, FB_GET_COLOR_CAP, &fb_info.color_cap); 789 790 /* Set up shared memory buffer. */ 791 size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows; 792 interbuffer = as_get_mappable_page(ib_size); 793 794 if (as_area_create(interbuffer, ib_size, AS_AREA_READ | 795 AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) 796 interbuffer = NULL; 797 798 if (interbuffer) { 799 if (async_obsolete_share_out_start(fb_info.phone, interbuffer, 800 AS_AREA_READ) != EOK) { 801 as_area_destroy(interbuffer); 802 interbuffer = NULL; 803 } 804 } 805 806 fb_pending.cnt = 0; 810 fb_get_resolution(fb_sess, &xres, &yres); 811 812 /* Initialize the screen */ 813 screen_vp = fb_vp_create(fb_sess, 0, 0, xres, yres); 814 815 if ((xres >= 800) && (yres >= 600)) { 816 logo_vp = fb_vp_create(fb_sess, xres - 66, 2, 64, 60); 817 logo_img = imgmap_decode_tga((void *) helenos_tga, 818 helenos_tga_size, IMGMAP_FLAG_SHARED); 819 logo_handle = fb_imagemap_create(fb_sess, logo_img); 820 821 nameic_vp = fb_vp_create(fb_sess, 5, 17, 100, 26); 822 nameic_img = imgmap_decode_tga((void *) nameic_tga, 823 nameic_tga_size, IMGMAP_FLAG_SHARED); 824 nameic_handle = fb_imagemap_create(fb_sess, nameic_img); 825 826 cons_data_img = imgmap_decode_tga((void *) cons_data_tga, 827 cons_data_tga_size, IMGMAP_FLAG_SHARED); 828 cons_dis_img = imgmap_decode_tga((void *) cons_dis_tga, 829 cons_dis_tga_size, IMGMAP_FLAG_SHARED); 830 cons_dis_sel_img = imgmap_decode_tga((void *) cons_dis_sel_tga, 831 cons_dis_sel_tga_size, IMGMAP_FLAG_SHARED); 832 cons_idle_img = imgmap_decode_tga((void *) cons_idle_tga, 833 cons_idle_tga_size, IMGMAP_FLAG_SHARED); 834 cons_kernel_img = imgmap_decode_tga((void *) cons_kernel_tga, 835 cons_kernel_tga_size, IMGMAP_FLAG_SHARED); 836 cons_sel_img = imgmap_decode_tga((void *) cons_sel_tga, 837 cons_sel_tga_size, IMGMAP_FLAG_SHARED); 838 839 state_icons[CONS_DISCONNECTED] = 840 fb_imagemap_create(fb_sess, cons_dis_img); 841 state_icons[CONS_DISCONNECTED_SELECTED] = 842 fb_imagemap_create(fb_sess, cons_dis_sel_img); 843 state_icons[CONS_SELECTED] = 844 fb_imagemap_create(fb_sess, cons_sel_img); 845 state_icons[CONS_IDLE] = 846 fb_imagemap_create(fb_sess, cons_idle_img); 847 state_icons[CONS_DATA] = 848 fb_imagemap_create(fb_sess, cons_data_img); 849 state_icons[CONS_KERNEL] = 850 fb_imagemap_create(fb_sess, cons_kernel_img); 851 852 anim_1_img = imgmap_decode_tga((void *) anim_1_tga, 853 anim_1_tga_size, IMGMAP_FLAG_SHARED); 854 anim_2_img = imgmap_decode_tga((void *) anim_2_tga, 855 anim_2_tga_size, IMGMAP_FLAG_SHARED); 856 anim_3_img = imgmap_decode_tga((void *) anim_3_tga, 857 anim_3_tga_size, IMGMAP_FLAG_SHARED); 858 anim_4_img = imgmap_decode_tga((void *) anim_4_tga, 859 anim_4_tga_size, IMGMAP_FLAG_SHARED); 860 861 anim_1 = fb_imagemap_create(fb_sess, anim_1_img); 862 anim_2 = fb_imagemap_create(fb_sess, anim_2_img); 863 anim_3 = fb_imagemap_create(fb_sess, anim_3_img); 864 anim_4 = fb_imagemap_create(fb_sess, anim_4_img); 865 866 anim_seq = fb_sequence_create(fb_sess); 867 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_1); 868 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_2); 869 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_3); 870 fb_sequence_add_imagemap(fb_sess, anim_seq, anim_4); 871 872 console_vp = fb_vp_create(fb_sess, CONSOLE_MARGIN, CONSOLE_TOP, 873 xres - 2 * CONSOLE_MARGIN, yres - (CONSOLE_TOP + CONSOLE_MARGIN)); 874 875 fb_vp_clear(fb_sess, screen_vp); 876 fb_vp_imagemap_damage(fb_sess, logo_vp, logo_handle, 877 0, 0, 64, 60); 878 fb_vp_imagemap_damage(fb_sess, nameic_vp, nameic_handle, 879 0, 0, 100, 26); 880 881 graphics_state = GRAPHICS_FULL; 882 } else { 883 console_vp = screen_vp; 884 graphics_state = GRAPHICS_BASIC; 885 } 886 887 fb_vp_set_style(fb_sess, console_vp, STYLE_NORMAL); 888 fb_vp_clear(fb_sess, console_vp); 889 890 sysarg_t cols; 891 sysarg_t rows; 892 fb_vp_get_dimensions(fb_sess, console_vp, &cols, &rows); 893 894 console_caps_t ccaps; 895 fb_vp_get_caps(fb_sess, console_vp, &ccaps); 896 897 mouse.x = xres / 2; 898 mouse.y = yres / 2; 899 mouse.pressed = false; 807 900 808 901 /* Inititalize consoles */ 809 size_t i; 810 for (i = 0; i < CONSOLE_COUNT; i++) { 811 if (i != KERNEL_CONSOLE) { 812 if (screenbuffer_init(&consoles[i].scr, 813 fb_info.cols, fb_info.rows) == NULL) { 814 printf("%s: Unable to allocate screen buffer %zu\n", NAME, i); 815 return false; 816 } 817 screenbuffer_clear(&consoles[i].scr); 818 keybuffer_init(&consoles[i].keybuffer); 819 consoles[i].index = i; 820 consoles[i].refcount = 0; 821 822 char vc[DEVMAP_NAME_MAXLEN + 1]; 823 snprintf(vc, DEVMAP_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i); 824 825 if (devmap_device_register(vc, &consoles[i].devmap_handle) != EOK) { 826 printf("%s: Unable to register device %s\n", NAME, vc); 827 return false; 828 } 829 } 830 } 831 832 /* Initialize the screen */ 833 console_serialize_start(); 834 gcons_redraw_console(); 835 set_style(STYLE_NORMAL); 836 screen_clear(); 837 curs_goto(0, 0); 838 curs_visibility(active_console->scr.is_cursor_visible); 839 console_serialize_end(); 902 for (size_t i = 0; i < CONSOLE_COUNT; i++) { 903 consoles[i].index = i; 904 atomic_set(&consoles[i].refcnt, 0); 905 fibril_mutex_initialize(&consoles[i].mtx); 906 907 if (graphics_state == GRAPHICS_FULL) { 908 /* Create state buttons */ 909 consoles[i].state_vp = 910 fb_vp_create(fb_sess, STATE_START + (xres - 800) / 2 + 911 CONSOLE_MARGIN + i * (STATE_WIDTH + STATE_SPACE), 912 STATE_TOP, STATE_WIDTH, STATE_HEIGHT); 913 } 914 915 if (i == KERNEL_CONSOLE) { 916 consoles[i].state = CONS_KERNEL; 917 cons_redraw_state(&consoles[i]); 918 cons_kernel_sequence_start(&consoles[i]); 919 continue; 920 } 921 922 if (i == 0) 923 consoles[i].state = CONS_DISCONNECTED_SELECTED; 924 else 925 consoles[i].state = CONS_DISCONNECTED; 926 927 consoles[i].cols = cols; 928 consoles[i].rows = rows; 929 consoles[i].ccaps = ccaps; 930 consoles[i].frontbuf = 931 screenbuffer_create(cols, rows, SCREENBUFFER_FLAG_SHARED); 932 933 if (consoles[i].frontbuf == NULL) { 934 printf("%s: Unable to allocate frontbuffer %zu\n", NAME, i); 935 return false; 936 } 937 938 consoles[i].fbid = fb_frontbuf_create(fb_sess, consoles[i].frontbuf); 939 if (consoles[i].fbid == 0) { 940 printf("%s: Unable to create frontbuffer %zu\n", NAME, i); 941 return false; 942 } 943 944 prodcons_initialize(&consoles[i].input_pc); 945 cons_redraw_state(&consoles[i]); 946 947 char vc[LOC_NAME_MAXLEN + 1]; 948 snprintf(vc, LOC_NAME_MAXLEN, "%s/vc%zu", NAMESPACE, i); 949 950 if (loc_service_register(vc, &consoles[i].dsid) != EOK) { 951 printf("%s: Unable to register device %s\n", NAME, vc); 952 return false; 953 } 954 } 840 955 841 956 /* Receive kernel notifications */ 842 957 async_set_interrupt_received(interrupt_received); 843 if (event_subscribe(EVENT_KCONSOLE, 0) != EOK) 844 printf("%s: Error registering kconsole notifications\n", NAME); 958 rc = event_subscribe(EVENT_KCONSOLE, 0); 959 if (rc != EOK) 960 printf("%s: Failed to register kconsole notifications (%s)\n", 961 NAME, str_error(rc)); 845 962 846 963 return true; … … 849 966 static void usage(void) 850 967 { 851 printf("Usage: console <input_dev> \n");968 printf("Usage: console <input_dev> <framebuffer_dev>\n"); 852 969 } 853 970 854 971 int main(int argc, char *argv[]) 855 972 { 856 if (argc < 2) {973 if (argc < 3) { 857 974 usage(); 858 975 return -1; 859 976 } 860 977 861 printf( NAME ": HelenOS Console service\n");862 863 if (!console_srv_init(argv[1] ))978 printf("%s: HelenOS Console service\n", NAME); 979 980 if (!console_srv_init(argv[1], argv[2])) 864 981 return -1; 865 982 866 printf(NAME ": Accepting connections\n"); 983 printf("%s: Accepting connections\n", NAME); 984 task_retval(0); 867 985 async_manager(); 868 986 -
uspace/srv/hid/console/console.h
r867e2555 r925a21e 33 33 */ 34 34 35 #ifndef __CONSOLE_H__36 #define __CONSOLE_H__35 #ifndef CONSOLE_CONSOLE_H__ 36 #define CONSOLE_CONSOLE_H__ 37 37 38 38 #define CONSOLE_COUNT 12 -
uspace/srv/hid/fb/Makefile
r867e2555 r925a21e 29 29 30 30 USPACE_PREFIX = ../../.. 31 ROOT_PATH = $(USPACE_PREFIX)/.. 32 33 COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common 34 CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config 35 31 LIBS = $(LIBFB_PREFIX)/libfb.a 32 EXTRA_CFLAGS += -I$(LIBFB_PREFIX) 36 33 BINARY = fb 37 34 38 -include $(COMMON_MAKEFILE)39 -include $(CONFIG_MAKEFILE)40 41 35 SOURCES = \ 42 main.c \ 43 ppm.c 44 45 ifneq ($(UARCH),ia64) 46 SOURCES += \ 47 fb.c \ 48 font-8x16.c 49 EXTRA_CFLAGS += -DFB_ENABLED 50 endif 51 52 ifeq ($(UARCH),ia32) 53 SOURCES += \ 54 ega.c 55 EXTRA_CFLAGS += -DEGA_ENABLED 56 endif 57 58 ifeq ($(UARCH),ia64) 59 SOURCES += \ 60 ega.c \ 61 ski.c \ 62 serial_console.c 63 EXTRA_CFLAGS += -DSKI_ENABLED -DEGA_ENABLED 64 endif 65 66 ifeq ($(UARCH),amd64) 67 SOURCES += \ 68 ega.c 69 EXTRA_CFLAGS += -DEGA_ENABLED 70 endif 71 72 ifeq ($(UARCH),mips32) 73 SOURCES += \ 74 msim.c \ 75 serial_console.c 76 EXTRA_CFLAGS += -DMSIM_ENABLED 77 endif 78 79 ifeq ($(UARCH),sparc64) 80 ifeq ($(PROCESSOR),sun4v) 81 SOURCES += \ 82 niagara.c \ 83 serial_console.c 84 EXTRA_CFLAGS += -DNIAGARA_ENABLED 85 endif 86 endif 87 88 EXTRA_CFLAGS += -D$(UARCH) 36 gfx/font-8x16.c \ 37 ctl/serial.c \ 38 port/ega.c \ 39 port/kfb.c \ 40 port/kchar.c \ 41 port/niagara.c \ 42 port/ski.c \ 43 proto/vt100.c \ 44 fb.c 89 45 90 46 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/hid/fb/ctl/serial.h
r867e2555 r925a21e 28 28 */ 29 29 30 /** @addtogroup msimfb31 * @brief HelenOS MSIM text console.32 * @ingroup fbs33 * @{34 */35 30 /** @file 36 31 */ 37 32 38 #ifndef FB_ MSIM_H_39 #define FB_ MSIM_H_33 #ifndef FB_CTL_SERIAL_H_ 34 #define FB_CTL_SERIAL_H_ 40 35 41 extern int msim_init(void); 36 #include "../proto/vt100.h" 37 38 extern int serial_init(vt100_putchar_t, vt100_control_puts_t); 42 39 43 40 #endif … … 45 42 /** @} 46 43 */ 47 -
uspace/srv/hid/fb/fb.c
r867e2555 r925a21e 1 1 /* 2 * Copyright (c) 2008 Martin Decky 3 * Copyright (c) 2006 Jakub Vana 4 * Copyright (c) 2006 Ondrej Palkovsky 2 * Copyright (c) 2011 Martin Decky 5 3 * All rights reserved. 6 4 * … … 29 27 */ 30 28 31 /** 32 * @defgroup fb Graphical framebuffer 33 * @brief HelenOS graphical framebuffer. 34 * @ingroup fbs 35 * @{ 36 */ 37 38 /** @file 39 */ 40 41 #include <stdlib.h> 42 #include <unistd.h> 43 #include <str.h> 44 #include <ddi.h> 45 #include <sysinfo.h> 46 #include <align.h> 29 #include <sys/types.h> 30 #include <bool.h> 31 #include <loc.h> 32 #include <errno.h> 33 #include <stdio.h> 34 #include <malloc.h> 35 #include <inttypes.h> 47 36 #include <as.h> 48 #include <ipc/fb.h> 49 #include <ipc/ns.h> 50 #include <ipc/services.h> 51 #include <kernel/errno.h> 52 #include <kernel/genarch/fb/visuals.h> 53 #include <io/color.h> 54 #include <io/style.h> 55 #include <async.h> 56 #include <fibril.h> 57 #include <bool.h> 58 #include <stdio.h> 59 #include <byteorder.h> 60 #include <io/screenbuffer.h> 61 #include "font-8x16.h" 37 #include <fb.h> 38 #include <screenbuffer.h> 39 #include "port/ega.h" 40 #include "port/kchar.h" 41 #include "port/kfb.h" 42 #include "port/niagara.h" 43 #include "port/ski.h" 62 44 #include "fb.h" 63 #include "main.h" 64 #include "ppm.h" 65 #include "pointer.xbm" 66 #include "pointer_mask.xbm" 67 68 // FIXME: remove this header 69 #include <kernel/ipc/ipc_methods.h> 70 71 #define DEFAULT_BGCOLOR 0xf0f0f0 72 #define DEFAULT_FGCOLOR 0x000000 73 74 #define GLYPH_UNAVAIL '?' 75 76 #define MAX_ANIM_LEN 8 77 #define MAX_ANIMATIONS 4 78 #define MAX_PIXMAPS 256 /**< Maximum number of saved pixmaps */ 79 #define MAX_VIEWPORTS 128 /**< Viewport is a rectangular area on the screen */ 80 81 /** Function to render a pixel from a RGB value. */ 82 typedef void (*rgb_conv_t)(void *, uint32_t); 83 84 /** Function to render a bit mask. */ 85 typedef void (*mask_conv_t)(void *, bool); 86 87 /** Function to draw a glyph. */ 88 typedef void (*dg_t)(unsigned int x, unsigned int y, bool cursor, 89 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); 90 91 struct { 92 uint8_t *fb_addr; 93 94 unsigned int xres; 95 unsigned int yres; 96 97 unsigned int scanline; 98 unsigned int glyphscanline; 99 100 unsigned int pixelbytes; 101 unsigned int glyphbytes; 102 103 /** Pre-rendered mask for rendering glyphs. Specific for the visual. */ 104 uint8_t *glyphs; 105 106 rgb_conv_t rgb_conv; 107 mask_conv_t mask_conv; 108 } screen; 109 110 /** Backbuffer character cell. */ 111 typedef struct { 112 uint32_t glyph; 113 uint32_t fg_color; 114 uint32_t bg_color; 115 } bb_cell_t; 116 117 typedef struct { 118 bool initialized; 119 unsigned int x; 120 unsigned int y; 121 unsigned int width; 122 unsigned int height; 123 124 /* Text support in window */ 125 unsigned int cols; 126 unsigned int rows; 45 46 #define NAME "fb" 47 #define NAMESPACE "hid" 48 49 #define TICK_INTERVAL 250000 50 51 static LIST_INITIALIZE(fbdevs); 52 53 fbdev_t *fbdev_register(fbdev_ops_t *ops, void *data) 54 { 55 sysarg_t index = 0; 56 57 if (!list_empty(&fbdevs)) { 58 list_foreach(fbdevs, link) { 59 fbdev_t *dev = list_get_instance(link, fbdev_t, link); 60 if (index <= dev->index) 61 index = dev->index + 1; 62 } 63 } 64 65 fbdev_t *dev = (fbdev_t *) malloc(sizeof(fbdev_t)); 66 if (dev == NULL) 67 return NULL; 68 69 link_initialize(&dev->link); 70 atomic_set(&dev->refcnt, 0); 71 dev->claimed = false; 72 dev->index = index; 73 list_initialize(&dev->vps); 74 list_initialize(&dev->frontbufs); 75 list_initialize(&dev->imagemaps); 76 list_initialize(&dev->sequences); 77 78 dev->ops = *ops; 79 dev->data = data; 80 81 char node[LOC_NAME_MAXLEN + 1]; 82 snprintf(node, LOC_NAME_MAXLEN, "%s/%s%" PRIun, NAMESPACE, NAME, 83 index); 84 85 if (loc_service_register(node, &dev->dsid) != EOK) { 86 printf("%s: Unable to register device %s\n", NAME, node); 87 free(dev); 88 return NULL; 89 } 90 91 list_append(&dev->link, &fbdevs); 92 return dev; 93 } 94 95 static void fbsrv_yield(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 96 { 97 assert(dev->ops.yield); 98 99 if (dev->claimed) { 100 int rc = dev->ops.yield(dev); 101 if (rc == EOK) 102 dev->claimed = false; 103 104 async_answer_0(iid, rc); 105 } else 106 async_answer_0(iid, ENOENT); 107 } 108 109 static void fbsrv_claim(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 110 { 111 assert(dev->ops.claim); 112 113 if (!dev->claimed) { 114 int rc = dev->ops.claim(dev); 115 if (rc == EOK) 116 dev->claimed = true; 117 118 async_answer_0(iid, rc); 119 } else 120 async_answer_0(iid, ENOENT); 121 } 122 123 static void fbsrv_get_resolution(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 124 { 125 assert(dev->ops.get_resolution); 126 127 sysarg_t width; 128 sysarg_t height; 129 int rc = dev->ops.get_resolution(dev, &width, &height); 130 131 async_answer_2(iid, rc, width, height); 132 } 133 134 static void fbsrv_pointer_update(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 135 { 136 if ((dev->claimed) && (dev->ops.pointer_update)) { 137 dev->ops.pointer_update(dev, IPC_GET_ARG1(*icall), 138 IPC_GET_ARG2(*icall), IPC_GET_ARG3(*icall)); 139 async_answer_0(iid, EOK); 140 } else 141 async_answer_0(iid, ENOTSUP); 142 } 143 144 static fbvp_t *resolve_vp(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid) 145 { 146 fbvp_t *vp = NULL; 147 list_foreach(dev->vps, link) { 148 fbvp_t *cur = list_get_instance(link, fbvp_t, link); 149 if (cur == (fbvp_t *) handle) { 150 vp = cur; 151 break; 152 } 153 } 154 155 if (vp == NULL) { 156 async_answer_0(iid, ENOENT); 157 return NULL; 158 } 159 160 return vp; 161 } 162 163 static frontbuf_t *resolve_frontbuf(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid) 164 { 165 frontbuf_t *frontbuf = NULL; 166 list_foreach(dev->frontbufs, link) { 167 frontbuf_t *cur = list_get_instance(link, frontbuf_t, link); 168 if (cur == (frontbuf_t *) handle) { 169 frontbuf = cur; 170 break; 171 } 172 } 173 174 if (frontbuf == NULL) { 175 async_answer_0(iid, ENOENT); 176 return NULL; 177 } 178 179 return frontbuf; 180 } 181 182 static imagemap_t *resolve_imagemap(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid) 183 { 184 imagemap_t *imagemap = NULL; 185 list_foreach(dev->imagemaps, link) { 186 imagemap_t *cur = list_get_instance(link, imagemap_t, link); 187 if (cur == (imagemap_t *) handle) { 188 imagemap = cur; 189 break; 190 } 191 } 192 193 if (imagemap == NULL) { 194 async_answer_0(iid, ENOENT); 195 return NULL; 196 } 197 198 return imagemap; 199 } 200 201 static sequence_t *resolve_sequence(fbdev_t *dev, sysarg_t handle, ipc_callid_t iid) 202 { 203 sequence_t *sequence = NULL; 204 list_foreach(dev->sequences, link) { 205 sequence_t *cur = list_get_instance(link, sequence_t, link); 206 if (cur == (sequence_t *) handle) { 207 sequence = cur; 208 break; 209 } 210 } 211 212 if (sequence == NULL) { 213 async_answer_0(iid, ENOENT); 214 return NULL; 215 } 216 217 return sequence; 218 } 219 220 static void fbsrv_vp_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 221 { 222 assert(dev->ops.font_metrics); 223 assert(dev->ops.vp_create); 224 225 fbvp_t *vp = (fbvp_t *) malloc(sizeof(fbvp_t)); 226 if (vp == NULL) { 227 async_answer_0(iid, ENOMEM); 228 return; 229 } 230 231 link_initialize(&vp->link); 232 233 vp->x = IPC_GET_ARG1(*icall); 234 vp->y = IPC_GET_ARG2(*icall); 235 vp->width = IPC_GET_ARG3(*icall); 236 vp->height = IPC_GET_ARG4(*icall); 237 238 dev->ops.font_metrics(dev, vp->width, vp->height, &vp->cols, &vp->rows); 239 240 vp->cursor_active = false; 241 vp->cursor_flash = false; 242 243 list_initialize(&vp->sequences); 244 245 vp->backbuf = screenbuffer_create(vp->cols, vp->rows, 246 SCREENBUFFER_FLAG_NONE); 247 if (vp->backbuf == NULL) { 248 free(vp); 249 async_answer_0(iid, ENOMEM); 250 return; 251 } 252 253 vp->top_row = 0; 254 255 int rc = dev->ops.vp_create(dev, vp); 256 if (rc != EOK) { 257 free(vp); 258 async_answer_0(iid, ENOMEM); 259 return; 260 } 261 262 list_append(&vp->link, &dev->vps); 263 async_answer_1(iid, EOK, (sysarg_t) vp); 264 } 265 266 static void fbsrv_vp_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 267 { 268 assert(dev->ops.vp_destroy); 269 270 fbvp_t *vp = resolve_vp(dev, IPC_GET_ARG1(*icall), iid); 271 if (vp == NULL) 272 return; 273 274 if (dev->active_vp == vp) { 275 async_answer_0(iid, EPERM); 276 return; 277 } 278 279 dev->ops.vp_destroy(dev, vp); 280 281 list_remove(&vp->link); 282 free(vp->backbuf); 283 free(vp); 284 285 async_answer_0(iid, EOK); 286 } 287 288 static void fbsrv_frontbuf_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 289 { 290 frontbuf_t *frontbuf = (frontbuf_t *) malloc(sizeof(frontbuf_t)); 291 if (frontbuf == NULL) { 292 async_answer_0(iid, ENOMEM); 293 return; 294 } 295 296 link_initialize(&frontbuf->link); 297 298 ipc_callid_t callid; 299 if (!async_share_out_receive(&callid, &frontbuf->size, 300 &frontbuf->flags)) { 301 free(frontbuf); 302 async_answer_0(iid, EINVAL); 303 return; 304 } 305 306 frontbuf->data = as_get_mappable_page(frontbuf->size); 307 int rc = async_answer_1(callid, EOK, (sysarg_t) frontbuf->data); 308 if (rc != EOK) { 309 free(frontbuf); 310 async_answer_0(iid, ENOMEM); 311 return; 312 } 313 314 list_append(&frontbuf->link, &dev->frontbufs); 315 async_answer_1(iid, EOK, (sysarg_t) frontbuf); 316 } 317 318 static void fbsrv_frontbuf_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 319 { 320 frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid); 321 if (frontbuf == NULL) 322 return; 323 324 list_remove(&frontbuf->link); 325 as_area_destroy(frontbuf->data); 326 free(frontbuf); 327 328 async_answer_0(iid, EOK); 329 } 330 331 static void fbsrv_imagemap_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 332 { 333 imagemap_t *imagemap = (imagemap_t *) malloc(sizeof(imagemap_t)); 334 if (imagemap == NULL) { 335 async_answer_0(iid, ENOMEM); 336 return; 337 } 338 339 link_initialize(&imagemap->link); 340 link_initialize(&imagemap->seq_link); 341 342 ipc_callid_t callid; 343 if (!async_share_out_receive(&callid, &imagemap->size, 344 &imagemap->flags)) { 345 free(imagemap); 346 async_answer_0(iid, EINVAL); 347 return; 348 } 349 350 imagemap->data = as_get_mappable_page(imagemap->size); 351 int rc = async_answer_1(callid, EOK, (sysarg_t) imagemap->data); 352 if (rc != EOK) { 353 free(imagemap); 354 async_answer_0(iid, ENOMEM); 355 return; 356 } 357 358 list_append(&imagemap->link, &dev->imagemaps); 359 async_answer_1(iid, EOK, (sysarg_t) imagemap); 360 } 361 362 static void fbsrv_imagemap_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 363 { 364 imagemap_t *imagemap = resolve_imagemap(dev, IPC_GET_ARG1(*icall), iid); 365 if (imagemap == NULL) 366 return; 367 368 list_remove(&imagemap->link); 369 list_remove(&imagemap->seq_link); 370 as_area_destroy(imagemap->data); 371 free(imagemap); 372 373 async_answer_0(iid, EOK); 374 } 375 376 static void fbsrv_sequence_create(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 377 { 378 sequence_t *sequence = (sequence_t *) malloc(sizeof(sequence_t)); 379 if (sequence == NULL) { 380 async_answer_0(iid, ENOMEM); 381 return; 382 } 383 384 link_initialize(&sequence->link); 385 list_initialize(&sequence->imagemaps); 386 sequence->count = 0; 387 388 list_append(&sequence->link, &dev->sequences); 389 async_answer_1(iid, EOK, (sysarg_t) sequence); 390 } 391 392 static void fbsrv_sequence_destroy(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 393 { 394 sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid); 395 if (sequence == NULL) 396 return; 397 398 list_remove(&sequence->link); 399 free(sequence); 400 401 async_answer_0(iid, EOK); 402 } 403 404 static void fbsrv_sequence_add_imagemap(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 405 { 406 sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid); 407 if (sequence == NULL) 408 return; 409 410 imagemap_t *imagemap = resolve_imagemap(dev, IPC_GET_ARG2(*icall), iid); 411 if (imagemap == NULL) 412 return; 413 414 if (list_member(&imagemap->seq_link, &sequence->imagemaps)) { 415 async_answer_0(iid, EEXISTS); 416 return; 417 } 418 419 list_append(&imagemap->seq_link, &sequence->imagemaps); 420 sequence->count++; 421 422 async_answer_0(iid, EOK); 423 } 424 425 static void fbsrv_vp_focus(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 426 { 427 fbvp_t *vp = resolve_vp(dev, IPC_GET_ARG1(*icall), iid); 428 if (vp == NULL) 429 return; 430 431 if (dev->active_vp != vp) 432 dev->active_vp = vp; 433 434 async_answer_0(iid, EOK); 435 } 436 437 static void fbsrv_vp_clear(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 438 { 439 assert(dev->ops.vp_clear); 440 441 if ((dev->claimed) && (dev->active_vp)) { 442 screenbuffer_set_cursor_visibility(dev->active_vp->backbuf, false); 443 dev->ops.vp_clear(dev, dev->active_vp); 444 async_answer_0(iid, EOK); 445 } else 446 async_answer_0(iid, ENOENT); 447 } 448 449 static void fbsrv_vp_get_dimensions(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 450 { 451 if (dev->active_vp) 452 async_answer_2(iid, EOK, dev->active_vp->cols, dev->active_vp->rows); 453 else 454 async_answer_0(iid, ENOENT); 455 } 456 457 static void fbsrv_vp_get_caps(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 458 { 459 assert(dev->ops.vp_get_caps); 460 461 if (dev->active_vp) 462 async_answer_1(iid, EOK, 463 (sysarg_t) dev->ops.vp_get_caps(dev, dev->active_vp)); 464 else 465 async_answer_0(iid, ENOENT); 466 } 467 468 static void fbsrv_vp_cursor_update(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 469 { 470 assert(dev->ops.vp_cursor_update); 471 472 frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid); 473 if (frontbuf == NULL) 474 return; 475 476 if ((dev->claimed) && (dev->active_vp)) { 477 screenbuffer_t *screenbuf = (screenbuffer_t *) frontbuf->data; 478 479 sysarg_t prev_col; 480 sysarg_t prev_row; 481 sysarg_t col; 482 sysarg_t row; 483 484 screenbuffer_get_cursor(dev->active_vp->backbuf, 485 &prev_col, &prev_row); 486 screenbuffer_get_cursor(screenbuf, &col, &row); 487 screenbuffer_set_cursor(dev->active_vp->backbuf, col, row); 488 489 bool visible = screenbuffer_get_cursor_visibility(screenbuf); 490 screenbuffer_set_cursor_visibility(dev->active_vp->backbuf, visible); 491 492 if (visible) 493 dev->active_vp->cursor_active = true; 494 495 dev->ops.vp_cursor_update(dev, dev->active_vp, prev_col, prev_row, 496 col, row, visible); 497 async_answer_0(iid, EOK); 498 } else 499 async_answer_0(iid, ENOENT); 500 } 501 502 static void fbsrv_vp_cursor_flash(fbdev_t *dev) 503 { 504 if ((dev->claimed) && (dev->ops.vp_cursor_flash)) { 505 list_foreach (dev->vps, link) { 506 fbvp_t *vp = list_get_instance(link, fbvp_t, link); 507 508 if (vp->cursor_active) { 509 sysarg_t col; 510 sysarg_t row; 511 512 screenbuffer_get_cursor(vp->backbuf, &col, &row); 513 vp->cursor_flash = !vp->cursor_flash; 514 dev->ops.vp_cursor_flash(dev, vp, col, row); 515 } 516 } 517 } 518 } 519 520 static void fbsrv_sequences_update(fbdev_t *dev) 521 { 522 if ((dev->claimed) && (dev->ops.vp_imgmap_damage)) { 523 list_foreach (dev->vps, vp_link) { 524 fbvp_t *vp = list_get_instance(vp_link, fbvp_t, link); 525 526 list_foreach (vp->sequences, seq_vp_link) { 527 sequence_vp_t *seq_vp = 528 list_get_instance(seq_vp_link, sequence_vp_t, link); 529 530 seq_vp->current++; 531 if (seq_vp->current >= seq_vp->seq->count) 532 seq_vp->current = 0; 533 534 link_t *link = 535 list_nth(&seq_vp->seq->imagemaps, seq_vp->current); 536 if (link != NULL) { 537 imagemap_t *imagemap = 538 list_get_instance(link, imagemap_t, seq_link); 539 540 imgmap_t *imgmap = (imgmap_t *) imagemap->data; 541 sysarg_t width; 542 sysarg_t height; 543 544 imgmap_get_resolution(imgmap, &width, &height); 545 dev->ops.vp_imgmap_damage(dev, vp, imgmap, 546 0, 0, width, height); 547 } 548 } 549 } 550 } 551 } 552 553 static void fbsrv_vp_set_style(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 554 { 555 if (dev->active_vp) { 556 dev->active_vp->attrs.type = CHAR_ATTR_STYLE; 557 dev->active_vp->attrs.val.style = 558 (console_style_t) IPC_GET_ARG1(*icall); 559 async_answer_0(iid, EOK); 560 } else 561 async_answer_0(iid, ENOENT); 562 } 563 564 static void fbsrv_vp_set_color(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 565 { 566 if (dev->active_vp) { 567 dev->active_vp->attrs.type = CHAR_ATTR_INDEX; 568 dev->active_vp->attrs.val.index.bgcolor = 569 (console_color_t) IPC_GET_ARG1(*icall); 570 dev->active_vp->attrs.val.index.fgcolor = 571 (console_color_t) IPC_GET_ARG2(*icall); 572 dev->active_vp->attrs.val.index.attr = 573 (console_color_attr_t) IPC_GET_ARG3(*icall); 574 async_answer_0(iid, EOK); 575 } else 576 async_answer_0(iid, ENOENT); 577 } 578 579 static void fbsrv_vp_set_rgb_color(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 580 { 581 if (dev->active_vp) { 582 dev->active_vp->attrs.type = CHAR_ATTR_RGB; 583 dev->active_vp->attrs.val.rgb.bgcolor = IPC_GET_ARG1(*icall); 584 dev->active_vp->attrs.val.rgb.fgcolor = IPC_GET_ARG2(*icall); 585 async_answer_0(iid, EOK); 586 } else 587 async_answer_0(iid, ENOENT); 588 } 589 590 static void fbsrv_vp_putchar(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 591 { 592 assert(dev->ops.vp_char_update); 593 594 if ((dev->claimed) && (dev->active_vp)) { 595 charfield_t *field = screenbuffer_field_at(dev->active_vp->backbuf, 596 IPC_GET_ARG1(*icall), IPC_GET_ARG2(*icall)); 597 598 field->ch = IPC_GET_ARG3(*icall); 599 600 dev->ops.vp_char_update(dev, dev->active_vp, IPC_GET_ARG1(*icall), 601 IPC_GET_ARG2(*icall)); 602 async_answer_0(iid, EOK); 603 } else 604 async_answer_0(iid, ENOENT); 605 } 606 607 static bool fbsrv_vp_update_scroll(fbdev_t *dev, fbvp_t *vp, 608 screenbuffer_t *frontbuf) 609 { 610 assert(dev->ops.vp_char_update); 611 612 sysarg_t top_row = screenbuffer_get_top_row(frontbuf); 613 614 if (vp->top_row == top_row) 615 return false; 616 617 vp->top_row = top_row; 618 619 for (sysarg_t y = 0; y < vp->rows; y++) { 620 for (sysarg_t x = 0; x < vp->cols; x++) { 621 charfield_t *front_field = 622 screenbuffer_field_at(frontbuf, x, y); 623 charfield_t *back_field = 624 screenbuffer_field_at(vp->backbuf, x, y); 625 bool update = false; 626 627 if (front_field->ch != back_field->ch) { 628 back_field->ch = front_field->ch; 629 update = true; 630 } 631 632 if (!attrs_same(front_field->attrs, back_field->attrs)) { 633 back_field->attrs = front_field->attrs; 634 update = true; 635 } 636 637 front_field->flags &= ~CHAR_FLAG_DIRTY; 638 639 if (update) 640 dev->ops.vp_char_update(dev, vp, x, y); 641 } 642 } 643 644 return true; 645 } 646 647 static void fbsrv_vp_update(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 648 { 649 assert(dev->ops.vp_char_update); 650 651 frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid); 652 if (frontbuf == NULL) 653 return; 654 655 if ((dev->claimed) && (dev->active_vp)) { 656 fbvp_t *vp = dev->active_vp; 657 screenbuffer_t *screenbuf = (screenbuffer_t *) frontbuf->data; 658 659 if (fbsrv_vp_update_scroll(dev, vp, screenbuf)) { 660 async_answer_0(iid, EOK); 661 return; 662 } 663 664 for (sysarg_t y = 0; y < vp->rows; y++) { 665 for (sysarg_t x = 0; x < vp->cols; x++) { 666 charfield_t *front_field = 667 screenbuffer_field_at(screenbuf, x, y); 668 charfield_t *back_field = 669 screenbuffer_field_at(vp->backbuf, x, y); 670 bool update = false; 671 672 if ((front_field->flags & CHAR_FLAG_DIRTY) == CHAR_FLAG_DIRTY) { 673 if (front_field->ch != back_field->ch) { 674 back_field->ch = front_field->ch; 675 update = true; 676 } 677 678 if (!attrs_same(front_field->attrs, back_field->attrs)) { 679 back_field->attrs = front_field->attrs; 680 update = true; 681 } 682 683 front_field->flags &= ~CHAR_FLAG_DIRTY; 684 } 685 686 if (update) 687 dev->ops.vp_char_update(dev, vp, x, y); 688 } 689 } 690 691 async_answer_0(iid, EOK); 692 } else 693 async_answer_0(iid, ENOENT); 694 } 695 696 static void fbsrv_vp_damage(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 697 { 698 assert(dev->ops.vp_char_update); 699 700 frontbuf_t *frontbuf = resolve_frontbuf(dev, IPC_GET_ARG1(*icall), iid); 701 if (frontbuf == NULL) 702 return; 703 704 if ((dev->claimed) && (dev->active_vp)) { 705 fbvp_t *vp = dev->active_vp; 706 screenbuffer_t *screenbuf = (screenbuffer_t *) frontbuf->data; 707 708 if (fbsrv_vp_update_scroll(dev, vp, screenbuf)) { 709 async_answer_0(iid, EOK); 710 return; 711 } 712 713 sysarg_t col = IPC_GET_ARG2(*icall); 714 sysarg_t row = IPC_GET_ARG3(*icall); 715 716 sysarg_t cols = IPC_GET_ARG4(*icall); 717 sysarg_t rows = IPC_GET_ARG5(*icall); 718 719 for (sysarg_t y = 0; y < rows; y++) { 720 for (sysarg_t x = 0; x < cols; x++) { 721 charfield_t *front_field = 722 screenbuffer_field_at(screenbuf, col + x, row + y); 723 charfield_t *back_field = 724 screenbuffer_field_at(vp->backbuf, col + x, row + y); 725 bool update = false; 726 727 if (front_field->ch != back_field->ch) { 728 back_field->ch = front_field->ch; 729 update = true; 730 } 731 732 if (!attrs_same(front_field->attrs, back_field->attrs)) { 733 back_field->attrs = front_field->attrs; 734 update = true; 735 } 736 737 front_field->flags &= ~CHAR_FLAG_DIRTY; 738 739 if (update) 740 dev->ops.vp_char_update(dev, vp, col + x, row + y); 741 } 742 } 743 744 async_answer_0(iid, EOK); 745 } else 746 async_answer_0(iid, ENOENT); 747 } 748 749 static void fbsrv_vp_imagemap_damage(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 750 { 751 imagemap_t *imagemap = resolve_imagemap(dev, IPC_GET_ARG1(*icall), iid); 752 if (imagemap == NULL) 753 return; 754 755 if ((dev->claimed) && (dev->ops.vp_imgmap_damage)) { 756 if (dev->active_vp) { 757 dev->ops.vp_imgmap_damage(dev, dev->active_vp, 758 (imgmap_t *) imagemap->data, 759 IPC_GET_ARG2(*icall), IPC_GET_ARG3(*icall), 760 IPC_GET_ARG4(*icall), IPC_GET_ARG5(*icall)); 761 async_answer_0(iid, EOK); 762 } else 763 async_answer_0(iid, ENOENT); 764 } else 765 async_answer_0(iid, ENOTSUP); 766 } 767 768 static void fbsrv_vp_sequence_start(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 769 { 770 sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid); 771 if (sequence == NULL) 772 return; 773 774 if (dev->active_vp) { 775 /* Check if the sequence is not already started */ 776 list_foreach(dev->active_vp->sequences, link) { 777 sequence_vp_t *seq_vp = 778 list_get_instance(link, sequence_vp_t, link); 779 780 if (seq_vp->seq == sequence) { 781 async_answer_0(iid, EEXISTS); 782 return; 783 } 784 } 785 786 sequence_vp_t *seq_vp = 787 (sequence_vp_t *) malloc(sizeof(sequence_vp_t)); 788 789 if (seq_vp != NULL) { 790 link_initialize(&seq_vp->link); 791 seq_vp->seq = sequence; 792 seq_vp->current = 0; 793 794 list_append(&seq_vp->link, &dev->active_vp->sequences); 795 async_answer_0(iid, EOK); 796 } else 797 async_answer_0(iid, ENOMEM); 798 } else 799 async_answer_0(iid, ENOENT); 800 } 801 802 static void fbsrv_vp_sequence_stop(fbdev_t *dev, ipc_callid_t iid, ipc_call_t *icall) 803 { 804 sequence_t *sequence = resolve_sequence(dev, IPC_GET_ARG1(*icall), iid); 805 if (sequence == NULL) 806 return; 807 808 if (dev->active_vp) { 809 list_foreach(dev->active_vp->sequences, link) { 810 sequence_vp_t *seq_vp = 811 list_get_instance(link, sequence_vp_t, link); 812 813 if (seq_vp->seq == sequence) { 814 list_remove(&seq_vp->link); 815 free(seq_vp); 816 817 async_answer_0(iid, EOK); 818 return; 819 } 820 } 821 822 async_answer_0(iid, ENOENT); 823 } else 824 async_answer_0(iid, ENOENT); 825 } 826 827 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 828 { 829 fbdev_t *dev = NULL; 830 service_id_t dsid = (service_id_t) IPC_GET_ARG1(*icall); 831 832 list_foreach(fbdevs, link) { 833 fbdev_t *fbdev = list_get_instance(link, fbdev_t, link); 834 if (fbdev->dsid == dsid) { 835 dev = fbdev; 836 break; 837 } 838 } 839 840 if (dev == NULL) { 841 async_answer_0(iid, ENOENT); 842 return; 843 } 844 845 if (atomic_get(&dev->refcnt) > 0) { 846 async_answer_0(iid, ELIMIT); 847 return; 848 } 127 849 128 850 /* 129 * Style and glyphs for text printing851 * Accept the connection 130 852 */ 131 853 132 /** Current attributes. */ 133 attr_rgb_t attr; 134 135 uint8_t *bgpixel; 136 137 /** 138 * Glyph drawing function for this viewport. Different viewports 139 * might use different drawing functions depending on whether their 140 * scanlines are aligned on a word boundary. 141 */ 142 dg_t dglyph; 143 144 /* Auto-cursor position */ 145 bool cursor_active; 146 unsigned int cur_col; 147 unsigned int cur_row; 148 bool cursor_shown; 149 150 /* Back buffer */ 151 bb_cell_t *backbuf; 152 unsigned int bbsize; 153 } viewport_t; 154 155 typedef struct { 156 bool initialized; 157 bool enabled; 158 unsigned int vp; 159 160 unsigned int pos; 161 unsigned int animlen; 162 unsigned int pixmaps[MAX_ANIM_LEN]; 163 } animation_t; 164 165 static animation_t animations[MAX_ANIMATIONS]; 166 static bool anims_enabled; 167 168 typedef struct { 169 unsigned int width; 170 unsigned int height; 171 uint8_t *data; 172 } pixmap_t; 173 174 static pixmap_t pixmaps[MAX_PIXMAPS]; 175 static viewport_t viewports[128]; 176 177 static bool client_connected = false; /**< Allow only 1 connection */ 178 179 static uint32_t color_table[16] = { 180 [COLOR_BLACK] = 0x000000, 181 [COLOR_BLUE] = 0x0000f0, 182 [COLOR_GREEN] = 0x00f000, 183 [COLOR_CYAN] = 0x00f0f0, 184 [COLOR_RED] = 0xf00000, 185 [COLOR_MAGENTA] = 0xf000f0, 186 [COLOR_YELLOW] = 0xf0f000, 187 [COLOR_WHITE] = 0xf0f0f0, 188 189 [8 + COLOR_BLACK] = 0x000000, 190 [8 + COLOR_BLUE] = 0x0000ff, 191 [8 + COLOR_GREEN] = 0x00ff00, 192 [8 + COLOR_CYAN] = 0x00ffff, 193 [8 + COLOR_RED] = 0xff0000, 194 [8 + COLOR_MAGENTA] = 0xff00ff, 195 [8 + COLOR_YELLOW] = 0xffff00, 196 [8 + COLOR_WHITE] = 0xffffff, 197 }; 198 199 static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a); 200 static int rgb_from_style(attr_rgb_t *rgb, int style); 201 static int rgb_from_idx(attr_rgb_t *rgb, sysarg_t fg_color, 202 sysarg_t bg_color, sysarg_t flags); 203 204 static int fb_set_color(viewport_t *vport, sysarg_t fg_color, 205 sysarg_t bg_color, sysarg_t attr); 206 207 static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor, 208 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); 209 static void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor, 210 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color); 211 212 static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col, 213 unsigned int row); 214 215 216 #define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1)) 217 #define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1)) 218 #define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1)) 219 220 #define COL2X(col) ((col) * FONT_WIDTH) 221 #define ROW2Y(row) ((row) * FONT_SCANLINES) 222 223 #define X2COL(x) ((x) / FONT_WIDTH) 224 #define Y2ROW(y) ((y) / FONT_SCANLINES) 225 226 #define FB_POS(x, y) ((y) * screen.scanline + (x) * screen.pixelbytes) 227 #define BB_POS(vport, col, row) ((row) * vport->cols + (col)) 228 #define GLYPH_POS(glyph, y, cursor) (((glyph) + (cursor) * FONT_GLYPHS) * screen.glyphbytes + (y) * screen.glyphscanline) 229 230 /* 231 * RGB conversion and mask functions. 232 * 233 * These functions write an RGB value to some memory in some predefined format. 234 * The naming convention corresponds to the format created by these functions. 235 * The functions use the so called network order (i.e. big endian) with respect 236 * to their names. 237 */ 238 239 static void rgb_0888(void *dst, uint32_t rgb) 240 { 241 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) | 242 (RED(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (BLUE(rgb, 8))); 243 } 244 245 static void bgr_0888(void *dst, uint32_t rgb) 246 { 247 *((uint32_t *) dst) = host2uint32_t_be((0 << 24) | 248 (BLUE(rgb, 8) << 16) | (GREEN(rgb, 8) << 8) | (RED(rgb, 8))); 249 } 250 251 static void mask_0888(void *dst, bool mask) 252 { 253 bgr_0888(dst, mask ? 0xffffff : 0); 254 } 255 256 static void rgb_8880(void *dst, uint32_t rgb) 257 { 258 *((uint32_t *) dst) = host2uint32_t_be((RED(rgb, 8) << 24) | 259 (GREEN(rgb, 8) << 16) | (BLUE(rgb, 8) << 8) | 0); 260 } 261 262 static void bgr_8880(void *dst, uint32_t rgb) 263 { 264 *((uint32_t *) dst) = host2uint32_t_be((BLUE(rgb, 8) << 24) | 265 (GREEN(rgb, 8) << 16) | (RED(rgb, 8) << 8) | 0); 266 } 267 268 static void mask_8880(void *dst, bool mask) 269 { 270 bgr_8880(dst, mask ? 0xffffff : 0); 271 } 272 273 static void rgb_888(void *dst, uint32_t rgb) 274 { 275 ((uint8_t *) dst)[0] = RED(rgb, 8); 276 ((uint8_t *) dst)[1] = GREEN(rgb, 8); 277 ((uint8_t *) dst)[2] = BLUE(rgb, 8); 278 } 279 280 static void bgr_888(void *dst, uint32_t rgb) 281 { 282 ((uint8_t *) dst)[0] = BLUE(rgb, 8); 283 ((uint8_t *) dst)[1] = GREEN(rgb, 8); 284 ((uint8_t *) dst)[2] = RED(rgb, 8); 285 } 286 287 static void mask_888(void *dst, bool mask) 288 { 289 bgr_888(dst, mask ? 0xffffff : 0); 290 } 291 292 static void rgb_555_be(void *dst, uint32_t rgb) 293 { 294 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 10 | 295 GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); 296 } 297 298 static void rgb_555_le(void *dst, uint32_t rgb) 299 { 300 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 10 | 301 GREEN(rgb, 5) << 5 | BLUE(rgb, 5)); 302 } 303 304 static void rgb_565_be(void *dst, uint32_t rgb) 305 { 306 *((uint16_t *) dst) = host2uint16_t_be(RED(rgb, 5) << 11 | 307 GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); 308 } 309 310 static void rgb_565_le(void *dst, uint32_t rgb) 311 { 312 *((uint16_t *) dst) = host2uint16_t_le(RED(rgb, 5) << 11 | 313 GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); 314 } 315 316 static void mask_555(void *dst, bool mask) 317 { 318 rgb_555_be(dst, mask ? 0xffffff : 0); 319 } 320 321 static void mask_565(void *dst, bool mask) 322 { 323 rgb_565_be(dst, mask ? 0xffffff : 0); 324 } 325 326 static void bgr_323(void *dst, uint32_t rgb) 327 { 328 *((uint8_t *) dst) 329 = ~((RED(rgb, 3) << 5) | (GREEN(rgb, 2) << 3) | BLUE(rgb, 3)); 330 } 331 332 static void mask_323(void *dst, bool mask) 333 { 334 bgr_323(dst, mask ? 0x0 : ~0x0); 335 } 336 337 /** Draw a filled rectangle. 338 * 339 * @note Need real implementation that does not access VRAM twice. 340 * 341 */ 342 static void draw_filled_rect(unsigned int x0, unsigned int y0, unsigned int x1, 343 unsigned int y1, uint32_t color) 344 { 345 unsigned int x; 346 unsigned int y; 347 unsigned int copy_bytes; 348 349 uint8_t *sp; 350 uint8_t *dp; 351 uint8_t cbuf[4]; 352 353 if ((y0 >= y1) || (x0 >= x1)) 354 return; 355 356 screen.rgb_conv(cbuf, color); 357 358 sp = &screen.fb_addr[FB_POS(x0, y0)]; 359 dp = sp; 360 361 /* Draw the first line. */ 362 for (x = x0; x < x1; x++) { 363 memcpy(dp, cbuf, screen.pixelbytes); 364 dp += screen.pixelbytes; 365 } 366 367 dp = sp + screen.scanline; 368 copy_bytes = (x1 - x0) * screen.pixelbytes; 369 370 /* Draw the remaining lines by copying. */ 371 for (y = y0 + 1; y < y1; y++) { 372 memcpy(dp, sp, copy_bytes); 373 dp += screen.scanline; 374 } 375 } 376 377 /** Redraw viewport. 378 * 379 * @param vport Viewport to redraw 380 * 381 */ 382 static void vport_redraw(viewport_t *vport) 383 { 384 unsigned int col; 385 unsigned int row; 386 387 for (row = 0; row < vport->rows; row++) { 388 for (col = 0; col < vport->cols; col++) { 389 draw_vp_glyph(vport, false, col, row); 390 } 391 } 392 393 if (COL2X(vport->cols) < vport->width) { 394 draw_filled_rect( 395 vport->x + COL2X(vport->cols), vport->y, 396 vport->x + vport->width, vport->y + vport->height, 397 vport->attr.bg_color); 398 } 399 400 if (ROW2Y(vport->rows) < vport->height) { 401 draw_filled_rect( 402 vport->x, vport->y + ROW2Y(vport->rows), 403 vport->x + vport->width, vport->y + vport->height, 404 vport->attr.bg_color); 405 } 406 } 407 408 static void backbuf_clear(bb_cell_t *backbuf, size_t len, uint32_t fg_color, 409 uint32_t bg_color) 410 { 411 size_t i; 412 413 for (i = 0; i < len; i++) { 414 backbuf[i].glyph = 0; 415 backbuf[i].fg_color = fg_color; 416 backbuf[i].bg_color = bg_color; 417 } 418 } 419 420 /** Clear viewport. 421 * 422 * @param vport Viewport to clear 423 * 424 */ 425 static void vport_clear(viewport_t *vport) 426 { 427 backbuf_clear(vport->backbuf, vport->cols * vport->rows, 428 vport->attr.fg_color, vport->attr.bg_color); 429 vport_redraw(vport); 430 } 431 432 /** Scroll viewport by the specified number of lines. 433 * 434 * @param vport Viewport to scroll 435 * @param lines Number of lines to scroll 436 * 437 */ 438 static void vport_scroll(viewport_t *vport, int lines) 439 { 440 unsigned int col; 441 unsigned int row; 442 unsigned int x; 443 unsigned int y; 444 uint32_t glyph; 445 uint32_t fg_color; 446 uint32_t bg_color; 447 bb_cell_t *bbp; 448 bb_cell_t *xbp; 449 450 /* 451 * Redraw. 452 */ 453 454 y = vport->y; 455 for (row = 0; row < vport->rows; row++) { 456 x = vport->x; 457 for (col = 0; col < vport->cols; col++) { 458 if (((int) row + lines >= 0) && 459 ((int) row + lines < (int) vport->rows)) { 460 xbp = &vport->backbuf[BB_POS(vport, col, row + lines)]; 461 bbp = &vport->backbuf[BB_POS(vport, col, row)]; 462 463 glyph = xbp->glyph; 464 fg_color = xbp->fg_color; 465 bg_color = xbp->bg_color; 466 467 if ((bbp->glyph == glyph) 468 && (bbp->fg_color == xbp->fg_color) 469 && (bbp->bg_color == xbp->bg_color)) { 470 x += FONT_WIDTH; 471 continue; 472 } 473 } else { 474 glyph = 0; 475 fg_color = vport->attr.fg_color; 476 bg_color = vport->attr.bg_color; 477 } 478 479 (*vport->dglyph)(x, y, false, screen.glyphs, glyph, 480 fg_color, bg_color); 481 x += FONT_WIDTH; 482 } 483 y += FONT_SCANLINES; 484 } 485 486 /* 487 * Scroll backbuffer. 488 */ 489 490 if (lines > 0) { 491 memmove(vport->backbuf, vport->backbuf + vport->cols * lines, 492 vport->cols * (vport->rows - lines) * sizeof(bb_cell_t)); 493 backbuf_clear(&vport->backbuf[BB_POS(vport, 0, vport->rows - lines)], 494 vport->cols * lines, vport->attr.fg_color, vport->attr.bg_color); 495 } else { 496 memmove(vport->backbuf - vport->cols * lines, vport->backbuf, 497 vport->cols * (vport->rows + lines) * sizeof(bb_cell_t)); 498 backbuf_clear(vport->backbuf, - vport->cols * lines, 499 vport->attr.fg_color, vport->attr.bg_color); 500 } 501 } 502 503 /** Render glyphs 504 * 505 * Convert glyphs from device independent font 506 * description to current visual representation. 507 * 508 */ 509 static void render_glyphs(void) 510 { 511 unsigned int glyph; 512 513 for (glyph = 0; glyph < FONT_GLYPHS; glyph++) { 514 unsigned int y; 515 516 for (y = 0; y < FONT_SCANLINES; y++) { 517 unsigned int x; 518 519 for (x = 0; x < FONT_WIDTH; x++) { 520 screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, false) + x * screen.pixelbytes], 521 (fb_font[glyph][y] & (1 << (7 - x))) ? true : false); 522 523 screen.mask_conv(&screen.glyphs[GLYPH_POS(glyph, y, true) + x * screen.pixelbytes], 524 (fb_font[glyph][y] & (1 << (7 - x))) ? false : true); 525 } 526 } 527 } 528 } 529 530 /** Create new viewport 531 * 532 * @param x Origin of the viewport (x). 533 * @param y Origin of the viewport (y). 534 * @param width Width of the viewport. 535 * @param height Height of the viewport. 536 * 537 * @return New viewport number. 538 * 539 */ 540 static int vport_create(unsigned int x, unsigned int y, 541 unsigned int width, unsigned int height) 542 { 543 unsigned int i; 544 545 for (i = 0; i < MAX_VIEWPORTS; i++) { 546 if (!viewports[i].initialized) 854 atomic_inc(&dev->refcnt); 855 dev->claimed = true; 856 async_answer_0(iid, EOK); 857 858 while (true) { 859 ipc_call_t call; 860 ipc_callid_t callid = 861 async_get_call_timeout(&call, TICK_INTERVAL); 862 863 if (!callid) { 864 fbsrv_vp_cursor_flash(dev); 865 fbsrv_sequences_update(dev); 866 continue; 867 } 868 869 if (!IPC_GET_IMETHOD(call)) { 870 dev->claimed = false; 871 atomic_dec(&dev->refcnt); 872 async_answer_0(callid, EOK); 547 873 break; 548 }549 550 if (i == MAX_VIEWPORTS)551 return ELIMIT;552 553 unsigned int cols = width / FONT_WIDTH;554 unsigned int rows = height / FONT_SCANLINES;555 unsigned int bbsize = cols * rows * sizeof(bb_cell_t);556 unsigned int word_size = sizeof(unsigned long);557 558 bb_cell_t *backbuf = (bb_cell_t *) malloc(bbsize);559 if (!backbuf)560 return ENOMEM;561 562 uint8_t *bgpixel = (uint8_t *) malloc(screen.pixelbytes);563 if (!bgpixel) {564 free(backbuf);565 return ENOMEM;566 }567 568 backbuf_clear(backbuf, cols * rows, DEFAULT_FGCOLOR, DEFAULT_BGCOLOR);569 memset(bgpixel, 0, screen.pixelbytes);570 571 viewports[i].x = x;572 viewports[i].y = y;573 viewports[i].width = width;574 viewports[i].height = height;575 576 viewports[i].cols = cols;577 viewports[i].rows = rows;578 579 viewports[i].attr.bg_color = DEFAULT_BGCOLOR;580 viewports[i].attr.fg_color = DEFAULT_FGCOLOR;581 582 viewports[i].bgpixel = bgpixel;583 584 /*585 * Conditions necessary to select aligned version:586 * - word size is divisible by pixelbytes587 * - cell scanline size is divisible by word size588 * - cell scanlines are word-aligned589 *590 */591 if (((word_size % screen.pixelbytes) == 0)592 && ((FONT_WIDTH * screen.pixelbytes) % word_size == 0)593 && ((x * screen.pixelbytes) % word_size == 0)594 && (screen.scanline % word_size == 0)) {595 viewports[i].dglyph = draw_glyph_aligned;596 } else {597 viewports[i].dglyph = draw_glyph_fallback;598 }599 600 viewports[i].cur_col = 0;601 viewports[i].cur_row = 0;602 viewports[i].cursor_active = false;603 viewports[i].cursor_shown = false;604 605 viewports[i].bbsize = bbsize;606 viewports[i].backbuf = backbuf;607 608 viewports[i].initialized = true;609 610 screen.rgb_conv(viewports[i].bgpixel, viewports[i].attr.bg_color);611 612 return i;613 }614 615 616 /** Initialize framebuffer as a chardev output device617 *618 * @param addr Address of the framebuffer619 * @param xres Screen width in pixels620 * @param yres Screen height in pixels621 * @param visual Bits per pixel (8, 16, 24, 32)622 * @param scan Bytes per one scanline623 *624 */625 static bool screen_init(void *addr, unsigned int xres, unsigned int yres,626 unsigned int scan, unsigned int visual)627 {628 switch (visual) {629 case VISUAL_INDIRECT_8:630 screen.rgb_conv = bgr_323;631 screen.mask_conv = mask_323;632 screen.pixelbytes = 1;633 break;634 case VISUAL_RGB_5_5_5_LE:635 screen.rgb_conv = rgb_555_le;636 screen.mask_conv = mask_555;637 screen.pixelbytes = 2;638 break;639 case VISUAL_RGB_5_5_5_BE:640 screen.rgb_conv = rgb_555_be;641 screen.mask_conv = mask_555;642 screen.pixelbytes = 2;643 break;644 case VISUAL_RGB_5_6_5_LE:645 screen.rgb_conv = rgb_565_le;646 screen.mask_conv = mask_565;647 screen.pixelbytes = 2;648 break;649 case VISUAL_RGB_5_6_5_BE:650 screen.rgb_conv = rgb_565_be;651 screen.mask_conv = mask_565;652 screen.pixelbytes = 2;653 break;654 case VISUAL_RGB_8_8_8:655 screen.rgb_conv = rgb_888;656 screen.mask_conv = mask_888;657 screen.pixelbytes = 3;658 break;659 case VISUAL_BGR_8_8_8:660 screen.rgb_conv = bgr_888;661 screen.mask_conv = mask_888;662 screen.pixelbytes = 3;663 break;664 case VISUAL_RGB_8_8_8_0:665 screen.rgb_conv = rgb_8880;666 screen.mask_conv = mask_8880;667 screen.pixelbytes = 4;668 break;669 case VISUAL_RGB_0_8_8_8:670 screen.rgb_conv = rgb_0888;671 screen.mask_conv = mask_0888;672 screen.pixelbytes = 4;673 break;674 case VISUAL_BGR_0_8_8_8:675 screen.rgb_conv = bgr_0888;676 screen.mask_conv = mask_0888;677 screen.pixelbytes = 4;678 break;679 case VISUAL_BGR_8_8_8_0:680 screen.rgb_conv = bgr_8880;681 screen.mask_conv = mask_8880;682 screen.pixelbytes = 4;683 break;684 default:685 return false;686 }687 688 screen.fb_addr = (unsigned char *) addr;689 screen.xres = xres;690 screen.yres = yres;691 screen.scanline = scan;692 693 screen.glyphscanline = FONT_WIDTH * screen.pixelbytes;694 screen.glyphbytes = screen.glyphscanline * FONT_SCANLINES;695 696 size_t glyphsize = 2 * FONT_GLYPHS * screen.glyphbytes;697 uint8_t *glyphs = (uint8_t *) malloc(glyphsize);698 if (!glyphs)699 return false;700 701 memset(glyphs, 0, glyphsize);702 screen.glyphs = glyphs;703 704 render_glyphs();705 706 /* Create first viewport */707 vport_create(0, 0, xres, yres);708 709 return true;710 }711 712 713 /** Draw a glyph, takes advantage of alignment.714 *715 * This version can only be used if the following conditions are met:716 *717 * - word size is divisible by pixelbytes718 * - cell scanline size is divisible by word size719 * - cell scanlines are word-aligned720 *721 * It makes use of the pre-rendered mask to process (possibly) several722 * pixels at once (word size / pixelbytes pixels at a time are processed)723 * making it very fast. Most notably this version is not applicable at 24 bits724 * per pixel.725 *726 * @param x x coordinate of top-left corner on screen.727 * @param y y coordinate of top-left corner on screen.728 * @param cursor Draw glyph with cursor729 * @param glyphs Pointer to font bitmap.730 * @param glyph Code of the glyph to draw.731 * @param fg_color Foreground color.732 * @param bg_color Backgroudn color.733 *734 */735 static void draw_glyph_aligned(unsigned int x, unsigned int y, bool cursor,736 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color)737 {738 unsigned int i;739 unsigned int yd;740 unsigned long fg_buf;741 unsigned long bg_buf;742 unsigned long mask;743 744 /*745 * Prepare a pair of words, one filled with foreground-color746 * pattern and the other filled with background-color pattern.747 */748 for (i = 0; i < sizeof(unsigned long) / screen.pixelbytes; i++) {749 screen.rgb_conv(&((uint8_t *) &fg_buf)[i * screen.pixelbytes],750 fg_color);751 screen.rgb_conv(&((uint8_t *) &bg_buf)[i * screen.pixelbytes],752 bg_color);753 }754 755 /* Pointer to the current position in the mask. */756 unsigned long *maskp = (unsigned long *) &glyphs[GLYPH_POS(glyph, 0, cursor)];757 758 /* Pointer to the current position on the screen. */759 unsigned long *dp = (unsigned long *) &screen.fb_addr[FB_POS(x, y)];760 761 /* Width of the character cell in words. */762 unsigned int ww = FONT_WIDTH * screen.pixelbytes / sizeof(unsigned long);763 764 /* Offset to add when moving to another screen scanline. */765 unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;766 767 for (yd = 0; yd < FONT_SCANLINES; yd++) {768 /*769 * Now process the cell scanline, combining foreground770 * and background color patters using the pre-rendered mask.771 */772 for (i = 0; i < ww; i++) {773 mask = *maskp++;774 *dp++ = (fg_buf & mask) | (bg_buf & ~mask);775 }776 777 /* Move to the beginning of the next scanline of the cell. */778 dp = (unsigned long *) ((uint8_t *) dp + d_add);779 }780 }781 782 /** Draw a glyph, fallback version.783 *784 * This version does not make use of the pre-rendered mask, it uses785 * the font bitmap directly. It works always, but it is slower.786 *787 * @param x x coordinate of top-left corner on screen.788 * @param y y coordinate of top-left corner on screen.789 * @param cursor Draw glyph with cursor790 * @param glyphs Pointer to font bitmap.791 * @param glyph Code of the glyph to draw.792 * @param fg_color Foreground color.793 * @param bg_color Backgroudn color.794 *795 */796 void draw_glyph_fallback(unsigned int x, unsigned int y, bool cursor,797 uint8_t *glyphs, uint32_t glyph, uint32_t fg_color, uint32_t bg_color)798 {799 unsigned int i;800 unsigned int j;801 unsigned int yd;802 uint8_t fg_buf[4];803 uint8_t bg_buf[4];804 uint8_t *sp;805 uint8_t b;806 807 /* Pre-render 1x the foreground and background color pixels. */808 if (cursor) {809 screen.rgb_conv(fg_buf, bg_color);810 screen.rgb_conv(bg_buf, fg_color);811 } else {812 screen.rgb_conv(fg_buf, fg_color);813 screen.rgb_conv(bg_buf, bg_color);814 }815 816 /* Pointer to the current position on the screen. */817 uint8_t *dp = (uint8_t *) &screen.fb_addr[FB_POS(x, y)];818 819 /* Offset to add when moving to another screen scanline. */820 unsigned int d_add = screen.scanline - FONT_WIDTH * screen.pixelbytes;821 822 for (yd = 0; yd < FONT_SCANLINES; yd++) {823 /* Byte containing bits of the glyph scanline. */824 b = fb_font[glyph][yd];825 826 for (i = 0; i < FONT_WIDTH; i++) {827 /* Choose color based on the current bit. */828 sp = (b & 0x80) ? fg_buf : bg_buf;829 830 /* Copy the pixel. */831 for (j = 0; j < screen.pixelbytes; j++) {832 *dp++ = *sp++;833 }834 835 /* Move to the next bit. */836 b = b << 1;837 }838 839 /* Move to the beginning of the next scanline of the cell. */840 dp += d_add;841 }842 }843 844 /** Draw glyph at specified position in viewport.845 *846 * @param vport Viewport identification847 * @param cursor Draw glyph with cursor848 * @param col Screen position relative to viewport849 * @param row Screen position relative to viewport850 *851 */852 static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,853 unsigned int row)854 {855 unsigned int x = vport->x + COL2X(col);856 unsigned int y = vport->y + ROW2Y(row);857 858 uint32_t glyph = vport->backbuf[BB_POS(vport, col, row)].glyph;859 uint32_t fg_color = vport->backbuf[BB_POS(vport, col, row)].fg_color;860 uint32_t bg_color = vport->backbuf[BB_POS(vport, col, row)].bg_color;861 862 (*vport->dglyph)(x, y, cursor, screen.glyphs, glyph,863 fg_color, bg_color);864 }865 866 /** Hide cursor if it is shown867 *868 */869 static void cursor_hide(viewport_t *vport)870 {871 if ((vport->cursor_active) && (vport->cursor_shown)) {872 draw_vp_glyph(vport, false, vport->cur_col, vport->cur_row);873 vport->cursor_shown = false;874 }875 }876 877 878 /** Show cursor if cursor showing is enabled879 *880 */881 static void cursor_show(viewport_t *vport)882 {883 /* Do not check for cursor_shown */884 if (vport->cursor_active) {885 draw_vp_glyph(vport, true, vport->cur_col, vport->cur_row);886 vport->cursor_shown = true;887 }888 }889 890 891 /** Invert cursor, if it is enabled892 *893 */894 static void cursor_blink(viewport_t *vport)895 {896 if (vport->cursor_shown)897 cursor_hide(vport);898 else899 cursor_show(vport);900 }901 902 903 /** Draw character at given position relative to viewport904 *905 * @param vport Viewport identification906 * @param c Character to draw907 * @param col Screen position relative to viewport908 * @param row Screen position relative to viewport909 *910 */911 static void draw_char(viewport_t *vport, wchar_t c, unsigned int col, unsigned int row)912 {913 bb_cell_t *bbp;914 915 /* Do not hide cursor if we are going to overwrite it */916 if ((vport->cursor_active) && (vport->cursor_shown) &&917 ((vport->cur_col != col) || (vport->cur_row != row)))918 cursor_hide(vport);919 920 bbp = &vport->backbuf[BB_POS(vport, col, row)];921 bbp->glyph = fb_font_glyph(c);922 bbp->fg_color = vport->attr.fg_color;923 bbp->bg_color = vport->attr.bg_color;924 925 draw_vp_glyph(vport, false, col, row);926 927 vport->cur_col = col;928 vport->cur_row = row;929 930 vport->cur_col++;931 if (vport->cur_col >= vport->cols) {932 vport->cur_col = 0;933 vport->cur_row++;934 if (vport->cur_row >= vport->rows)935 vport->cur_row--;936 }937 938 cursor_show(vport);939 }940 941 /** Draw text data to viewport.942 *943 * @param vport Viewport id944 * @param data Text data.945 * @param x Leftmost column of the area.946 * @param y Topmost row of the area.947 * @param w Number of rows.948 * @param h Number of columns.949 *950 */951 static void draw_text_data(viewport_t *vport, keyfield_t *data, unsigned int x,952 unsigned int y, unsigned int w, unsigned int h)953 {954 unsigned int i;955 unsigned int j;956 bb_cell_t *bbp;957 attrs_t *a;958 959 for (j = 0; j < h; j++) {960 for (i = 0; i < w; i++) {961 unsigned int col = x + i;962 unsigned int row = y + j;963 964 bbp = &vport->backbuf[BB_POS(vport, col, row)];965 966 a = &data[j * w + i].attrs;967 968 attr_rgb_t rgb;969 rgb.fg_color = 0;970 rgb.bg_color = 0;971 rgb_from_attr(&rgb, a);972 973 bbp->glyph = fb_font_glyph(data[j * w + i].character);974 bbp->fg_color = rgb.fg_color;975 bbp->bg_color = rgb.bg_color;976 977 draw_vp_glyph(vport, false, col, row);978 }979 }980 cursor_show(vport);981 }982 983 984 static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)985 {986 int pm = *((int *) data);987 pixmap_t *pmap = &pixmaps[pm];988 unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;989 990 screen.rgb_conv(&pmap->data[pos], color);991 }992 993 994 static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)995 {996 viewport_t *vport = (viewport_t *) data;997 unsigned int dx = vport->x + x;998 unsigned int dy = vport->y + y;999 1000 screen.rgb_conv(&screen.fb_addr[FB_POS(dx, dy)], color);1001 }1002 1003 1004 /** Return first free pixmap1005 *1006 */1007 static int find_free_pixmap(void)1008 {1009 unsigned int i;1010 1011 for (i = 0; i < MAX_PIXMAPS; i++)1012 if (!pixmaps[i].data)1013 return i;1014 1015 return -1;1016 }1017 1018 1019 /** Create a new pixmap and return appropriate ID1020 *1021 */1022 static int shm2pixmap(unsigned char *shm, size_t size)1023 {1024 int pm;1025 pixmap_t *pmap;1026 1027 pm = find_free_pixmap();1028 if (pm == -1)1029 return ELIMIT;1030 1031 pmap = &pixmaps[pm];1032 1033 if (ppm_get_data(shm, size, &pmap->width, &pmap->height))1034 return EINVAL;1035 1036 pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);1037 if (!pmap->data)1038 return ENOMEM;1039 1040 ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);1041 1042 return pm;1043 }1044 1045 1046 /** Handle shared memory communication calls1047 *1048 * Protocol for drawing pixmaps:1049 * - FB_PREPARE_SHM(client shm identification)1050 * - IPC_M_AS_AREA_SEND1051 * - FB_DRAW_PPM(startx, starty)1052 * - FB_DROP_SHM1053 *1054 * Protocol for text drawing1055 * - IPC_M_AS_AREA_SEND1056 * - FB_DRAW_TEXT_DATA1057 *1058 * @param callid Callid of the current call1059 * @param call Current call data1060 * @param vp Active viewport1061 *1062 * @return false if the call was not handled byt this function, true otherwise1063 *1064 * Note: this function is not thread-safe, you would have1065 * to redefine static variables with fibril_local.1066 *1067 */1068 static bool shm_handle(ipc_callid_t callid, ipc_call_t *call, int vp)1069 {1070 static keyfield_t *interbuffer = NULL;1071 static size_t intersize = 0;1072 1073 static unsigned char *shm = NULL;1074 static sysarg_t shm_id = 0;1075 static size_t shm_size;1076 1077 bool handled = true;1078 int retval = EOK;1079 viewport_t *vport = &viewports[vp];1080 unsigned int x;1081 unsigned int y;1082 unsigned int w;1083 unsigned int h;1084 1085 switch (IPC_GET_IMETHOD(*call)) {1086 case IPC_M_SHARE_OUT:1087 /* We accept one area for data interchange */1088 if (IPC_GET_ARG1(*call) == shm_id) {1089 void *dest = as_get_mappable_page(IPC_GET_ARG2(*call));1090 shm_size = IPC_GET_ARG2(*call);1091 if (async_answer_1(callid, EOK, (sysarg_t) dest)) {1092 shm_id = 0;1093 return false;1094 }1095 shm = dest;1096 1097 if (shm[0] != 'P')1098 return false;1099 1100 return true;1101 } else {1102 intersize = IPC_GET_ARG2(*call);1103 receive_comm_area(callid, call, (void *) &interbuffer);1104 }1105 return true;1106 case FB_PREPARE_SHM:1107 if (shm_id)1108 retval = EBUSY;1109 else1110 shm_id = IPC_GET_ARG1(*call);1111 break;1112 1113 case FB_DROP_SHM:1114 if (shm) {1115 as_area_destroy(shm);1116 shm = NULL;1117 }1118 shm_id = 0;1119 break;1120 1121 case FB_SHM2PIXMAP:1122 if (!shm) {1123 retval = EINVAL;1124 break;1125 }1126 retval = shm2pixmap(shm, shm_size);1127 break;1128 case FB_DRAW_PPM:1129 if (!shm) {1130 retval = EINVAL;1131 break;1132 }1133 x = IPC_GET_ARG1(*call);1134 y = IPC_GET_ARG2(*call);1135 1136 if ((x > vport->width) || (y > vport->height)) {1137 retval = EINVAL;1138 break;1139 }1140 1141 ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),1142 IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);1143 break;1144 case FB_DRAW_TEXT_DATA:1145 x = IPC_GET_ARG1(*call);1146 y = IPC_GET_ARG2(*call);1147 w = IPC_GET_ARG3(*call);1148 h = IPC_GET_ARG4(*call);1149 if (!interbuffer) {1150 retval = EINVAL;1151 break;1152 }1153 if (x + w > vport->cols || y + h > vport->rows) {1154 retval = EINVAL;1155 break;1156 }1157 if (intersize < w * h * sizeof(*interbuffer)) {1158 retval = EINVAL;1159 break;1160 }1161 draw_text_data(vport, interbuffer, x, y, w, h);1162 break;1163 default:1164 handled = false;1165 }1166 1167 if (handled)1168 async_answer_0(callid, retval);1169 return handled;1170 }1171 1172 1173 static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)1174 {1175 unsigned int width = vport->width;1176 unsigned int height = vport->height;1177 1178 if (width + vport->x > screen.xres)1179 width = screen.xres - vport->x;1180 if (height + vport->y > screen.yres)1181 height = screen.yres - vport->y;1182 1183 unsigned int realwidth = pmap->width <= width ? pmap->width : width;1184 unsigned int realheight = pmap->height <= height ? pmap->height : height;1185 1186 unsigned int srcrowsize = vport->width * screen.pixelbytes;1187 unsigned int realrowsize = realwidth * screen.pixelbytes;1188 1189 unsigned int y;1190 for (y = 0; y < realheight; y++) {1191 unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;1192 memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);1193 }1194 }1195 1196 1197 /** Save viewport to pixmap1198 *1199 */1200 static int save_vp_to_pixmap(viewport_t *vport)1201 {1202 int pm;1203 pixmap_t *pmap;1204 1205 pm = find_free_pixmap();1206 if (pm == -1)1207 return ELIMIT;1208 1209 pmap = &pixmaps[pm];1210 pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);1211 if (!pmap->data)1212 return ENOMEM;1213 1214 pmap->width = vport->width;1215 pmap->height = vport->height;1216 1217 copy_vp_to_pixmap(vport, pmap);1218 1219 return pm;1220 }1221 1222 1223 /** Draw pixmap on screen1224 *1225 * @param vp Viewport to draw on1226 * @param pm Pixmap identifier1227 *1228 */1229 static int draw_pixmap(int vp, int pm)1230 {1231 pixmap_t *pmap = &pixmaps[pm];1232 viewport_t *vport = &viewports[vp];1233 1234 unsigned int width = vport->width;1235 unsigned int height = vport->height;1236 1237 if (width + vport->x > screen.xres)1238 width = screen.xres - vport->x;1239 if (height + vport->y > screen.yres)1240 height = screen.yres - vport->y;1241 1242 if (!pmap->data)1243 return EINVAL;1244 1245 unsigned int realwidth = pmap->width <= width ? pmap->width : width;1246 unsigned int realheight = pmap->height <= height ? pmap->height : height;1247 1248 unsigned int srcrowsize = vport->width * screen.pixelbytes;1249 unsigned int realrowsize = realwidth * screen.pixelbytes;1250 1251 unsigned int y;1252 for (y = 0; y < realheight; y++) {1253 unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;1254 memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);1255 }1256 1257 return EOK;1258 }1259 1260 1261 /** Tick animation one step forward1262 *1263 */1264 static void anims_tick(void)1265 {1266 unsigned int i;1267 static int counts = 0;1268 1269 /* Limit redrawing */1270 counts = (counts + 1) % 8;1271 if (counts)1272 return;1273 1274 for (i = 0; i < MAX_ANIMATIONS; i++) {1275 if ((!animations[i].animlen) || (!animations[i].initialized) ||1276 (!animations[i].enabled))1277 continue;1278 1279 draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);1280 animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;1281 }1282 }1283 1284 1285 static unsigned int pointer_x;1286 static unsigned int pointer_y;1287 static bool pointer_shown, pointer_enabled;1288 static int pointer_vport = -1;1289 static int pointer_pixmap = -1;1290 1291 1292 static void mouse_show(void)1293 {1294 int i, j;1295 int visibility;1296 int color;1297 int bytepos;1298 1299 if ((pointer_shown) || (!pointer_enabled))1300 return;1301 1302 /* Save image under the pointer. */1303 if (pointer_vport == -1) {1304 pointer_vport = vport_create(pointer_x, pointer_y, pointer_width, pointer_height);1305 if (pointer_vport < 0)1306 return;1307 } else {1308 viewports[pointer_vport].x = pointer_x;1309 viewports[pointer_vport].y = pointer_y;1310 }1311 1312 if (pointer_pixmap == -1)1313 pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);1314 else1315 copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);1316 1317 /* Draw mouse pointer. */1318 for (i = 0; i < pointer_height; i++)1319 for (j = 0; j < pointer_width; j++) {1320 bytepos = i * ((pointer_width - 1) / 8 + 1) + j / 8;1321 visibility = pointer_mask_bits[bytepos] &1322 (1 << (j % 8));1323 if (visibility) {1324 color = pointer_bits[bytepos] &1325 (1 << (j % 8)) ? 0 : 0xffffff;1326 if (pointer_x + j < screen.xres && pointer_y +1327 i < screen.yres)1328 putpixel(&viewports[0], pointer_x + j,1329 pointer_y + i, color);1330 }1331 }1332 pointer_shown = 1;1333 }1334 1335 1336 static void mouse_hide(void)1337 {1338 /* Restore image under the pointer. */1339 if (pointer_shown) {1340 draw_pixmap(pointer_vport, pointer_pixmap);1341 pointer_shown = 0;1342 }1343 }1344 1345 1346 static void mouse_move(unsigned int x, unsigned int y)1347 {1348 mouse_hide();1349 pointer_x = x % screen.xres;1350 pointer_y = y % screen.yres;1351 mouse_show();1352 }1353 1354 1355 static int anim_handle(ipc_callid_t callid, ipc_call_t *call, int vp)1356 {1357 bool handled = true;1358 int retval = EOK;1359 int i, nvp;1360 int newval;1361 1362 switch (IPC_GET_IMETHOD(*call)) {1363 case FB_ANIM_CREATE:1364 nvp = IPC_GET_ARG1(*call);1365 if (nvp == -1)1366 nvp = vp;1367 if (nvp >= MAX_VIEWPORTS || nvp < 0 ||1368 !viewports[nvp].initialized) {1369 retval = EINVAL;1370 break;1371 }1372 for (i = 0; i < MAX_ANIMATIONS; i++) {1373 if (!animations[i].initialized)1374 break;1375 }1376 if (i == MAX_ANIMATIONS) {1377 retval = ELIMIT;1378 break;1379 }1380 animations[i].initialized = 1;1381 animations[i].animlen = 0;1382 animations[i].pos = 0;1383 animations[i].enabled = 0;1384 animations[i].vp = nvp;1385 retval = i;1386 break;1387 case FB_ANIM_DROP:1388 i = IPC_GET_ARG1(*call);1389 if (i >= MAX_ANIMATIONS || i < 0) {1390 retval = EINVAL;1391 break;1392 }1393 animations[i].initialized = 0;1394 break;1395 case FB_ANIM_ADDPIXMAP:1396 i = IPC_GET_ARG1(*call);1397 if (i >= MAX_ANIMATIONS || i < 0 ||1398 !animations[i].initialized) {1399 retval = EINVAL;1400 break;1401 }1402 if (animations[i].animlen == MAX_ANIM_LEN) {1403 retval = ELIMIT;1404 break;1405 }1406 newval = IPC_GET_ARG2(*call);1407 if (newval < 0 || newval > MAX_PIXMAPS ||1408 !pixmaps[newval].data) {1409 retval = EINVAL;1410 break;1411 }1412 animations[i].pixmaps[animations[i].animlen++] = newval;1413 break;1414 case FB_ANIM_CHGVP:1415 i = IPC_GET_ARG1(*call);1416 if (i >= MAX_ANIMATIONS || i < 0) {1417 retval = EINVAL;1418 break;1419 }1420 nvp = IPC_GET_ARG2(*call);1421 if (nvp == -1)1422 nvp = vp;1423 if (nvp >= MAX_VIEWPORTS || nvp < 0 ||1424 !viewports[nvp].initialized) {1425 retval = EINVAL;1426 break;1427 }1428 animations[i].vp = nvp;1429 break;1430 case FB_ANIM_START:1431 case FB_ANIM_STOP:1432 i = IPC_GET_ARG1(*call);1433 if (i >= MAX_ANIMATIONS || i < 0) {1434 retval = EINVAL;1435 break;1436 }1437 newval = (IPC_GET_IMETHOD(*call) == FB_ANIM_START);1438 if (newval ^ animations[i].enabled) {1439 animations[i].enabled = newval;1440 anims_enabled += newval ? 1 : -1;1441 }1442 break;1443 default:1444 handled = 0;1445 }1446 if (handled)1447 async_answer_0(callid, retval);1448 return handled;1449 }1450 1451 1452 /** Handler for messages concerning pixmap handling1453 *1454 */1455 static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)1456 {1457 bool handled = true;1458 int retval = EOK;1459 int i, nvp;1460 1461 switch (IPC_GET_IMETHOD(*call)) {1462 case FB_VP_DRAW_PIXMAP:1463 nvp = IPC_GET_ARG1(*call);1464 if (nvp == -1)1465 nvp = vp;1466 if (nvp < 0 || nvp >= MAX_VIEWPORTS ||1467 !viewports[nvp].initialized) {1468 retval = EINVAL;1469 break;1470 }1471 i = IPC_GET_ARG2(*call);1472 retval = draw_pixmap(nvp, i);1473 break;1474 case FB_VP2PIXMAP:1475 nvp = IPC_GET_ARG1(*call);1476 if (nvp == -1)1477 nvp = vp;1478 if (nvp < 0 || nvp >= MAX_VIEWPORTS ||1479 !viewports[nvp].initialized)1480 retval = EINVAL;1481 else1482 retval = save_vp_to_pixmap(&viewports[nvp]);1483 break;1484 case FB_DROP_PIXMAP:1485 i = IPC_GET_ARG1(*call);1486 if (i >= MAX_PIXMAPS) {1487 retval = EINVAL;1488 break;1489 }1490 if (pixmaps[i].data) {1491 free(pixmaps[i].data);1492 pixmaps[i].data = NULL;1493 }1494 break;1495 default:1496 handled = 0;1497 }1498 1499 if (handled)1500 async_answer_0(callid, retval);1501 return handled;1502 1503 }1504 1505 static int rgb_from_style(attr_rgb_t *rgb, int style)1506 {1507 switch (style) {1508 case STYLE_NORMAL:1509 rgb->fg_color = color_table[COLOR_BLACK];1510 rgb->bg_color = color_table[COLOR_WHITE];1511 break;1512 case STYLE_EMPHASIS:1513 rgb->fg_color = color_table[COLOR_RED];1514 rgb->bg_color = color_table[COLOR_WHITE];1515 break;1516 case STYLE_INVERTED:1517 rgb->fg_color = color_table[COLOR_WHITE];1518 rgb->bg_color = color_table[COLOR_BLACK];1519 break;1520 case STYLE_SELECTED:1521 rgb->fg_color = color_table[COLOR_WHITE];1522 rgb->bg_color = color_table[COLOR_RED];1523 break;1524 default:1525 return EINVAL;1526 }1527 1528 return EOK;1529 }1530 1531 static int rgb_from_idx(attr_rgb_t *rgb, sysarg_t fg_color,1532 sysarg_t bg_color, sysarg_t flags)1533 {1534 fg_color = (fg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);1535 bg_color = (bg_color & 7) | ((flags & CATTR_BRIGHT) ? 8 : 0);1536 1537 rgb->fg_color = color_table[fg_color];1538 rgb->bg_color = color_table[bg_color];1539 1540 return EOK;1541 }1542 1543 static int rgb_from_attr(attr_rgb_t *rgb, const attrs_t *a)1544 {1545 int rc;1546 1547 switch (a->t) {1548 case at_style:1549 rc = rgb_from_style(rgb, a->a.s.style);1550 break;1551 case at_idx:1552 rc = rgb_from_idx(rgb, a->a.i.fg_color,1553 a->a.i.bg_color, a->a.i.flags);1554 break;1555 case at_rgb:1556 *rgb = a->a.r;1557 rc = EOK;1558 break;1559 }1560 1561 return rc;1562 }1563 1564 static int fb_set_style(viewport_t *vport, sysarg_t style)1565 {1566 return rgb_from_style(&vport->attr, (int) style);1567 }1568 1569 static int fb_set_color(viewport_t *vport, sysarg_t fg_color,1570 sysarg_t bg_color, sysarg_t flags)1571 {1572 return rgb_from_idx(&vport->attr, fg_color, bg_color, flags);1573 }1574 1575 /** Function for handling connections to FB1576 *1577 */1578 static void fb_client_connection(ipc_callid_t iid, ipc_call_t *icall,1579 void *arg)1580 {1581 unsigned int vp = 0;1582 viewport_t *vport = &viewports[vp];1583 1584 if (client_connected) {1585 async_answer_0(iid, ELIMIT);1586 return;1587 }1588 1589 /* Accept connection */1590 client_connected = true;1591 async_answer_0(iid, EOK);1592 1593 while (true) {1594 ipc_callid_t callid;1595 ipc_call_t call;1596 int retval;1597 unsigned int i;1598 int scroll;1599 wchar_t ch;1600 unsigned int col, row;1601 1602 if ((vport->cursor_active) || (anims_enabled))1603 callid = async_get_call_timeout(&call, 250000);1604 else1605 callid = async_get_call(&call);1606 1607 mouse_hide();1608 if (!callid) {1609 cursor_blink(vport);1610 anims_tick();1611 mouse_show();1612 continue;1613 }1614 1615 if (shm_handle(callid, &call, vp))1616 continue;1617 1618 if (pixmap_handle(callid, &call, vp))1619 continue;1620 1621 if (anim_handle(callid, &call, vp))1622 continue;1623 1624 if (!IPC_GET_IMETHOD(call)) {1625 client_connected = false;1626 1627 /* Cleanup other viewports */1628 for (i = 1; i < MAX_VIEWPORTS; i++)1629 vport->initialized = false;1630 1631 /* Exit thread */1632 return;1633 874 } 1634 875 1635 876 switch (IPC_GET_IMETHOD(call)) { 1636 case FB_PUTCHAR: 1637 ch = IPC_GET_ARG1(call); 1638 col = IPC_GET_ARG2(call); 1639 row = IPC_GET_ARG3(call); 1640 1641 if ((col >= vport->cols) || (row >= vport->rows)) { 1642 retval = EINVAL; 1643 break; 1644 } 1645 async_answer_0(callid, EOK); 1646 1647 draw_char(vport, ch, col, row); 1648 1649 /* Message already answered */ 1650 continue; 1651 case FB_CLEAR: 1652 vport_clear(vport); 1653 cursor_show(vport); 1654 retval = EOK; 1655 break; 1656 case FB_CURSOR_GOTO: 1657 col = IPC_GET_ARG1(call); 1658 row = IPC_GET_ARG2(call); 1659 1660 if ((col >= vport->cols) || (row >= vport->rows)) { 1661 retval = EINVAL; 1662 break; 1663 } 1664 retval = EOK; 1665 1666 cursor_hide(vport); 1667 vport->cur_col = col; 1668 vport->cur_row = row; 1669 cursor_show(vport); 1670 break; 1671 case FB_CURSOR_VISIBILITY: 1672 cursor_hide(vport); 1673 vport->cursor_active = IPC_GET_ARG1(call); 1674 cursor_show(vport); 1675 retval = EOK; 1676 break; 1677 case FB_GET_CSIZE: 1678 async_answer_2(callid, EOK, vport->cols, vport->rows); 1679 continue; 1680 case FB_GET_COLOR_CAP: 1681 async_answer_1(callid, EOK, FB_CCAP_RGB); 1682 continue; 1683 case FB_SCROLL: 1684 scroll = IPC_GET_ARG1(call); 1685 if ((scroll > (int) vport->rows) || (scroll < (-(int) vport->rows))) { 1686 retval = EINVAL; 1687 break; 1688 } 1689 cursor_hide(vport); 1690 vport_scroll(vport, scroll); 1691 cursor_show(vport); 1692 retval = EOK; 1693 break; 1694 case FB_VIEWPORT_SWITCH: 1695 i = IPC_GET_ARG1(call); 1696 if (i >= MAX_VIEWPORTS) { 1697 retval = EINVAL; 1698 break; 1699 } 1700 if (!viewports[i].initialized) { 1701 retval = EADDRNOTAVAIL; 1702 break; 1703 } 1704 cursor_hide(vport); 1705 vp = i; 1706 vport = &viewports[vp]; 1707 cursor_show(vport); 1708 retval = EOK; 1709 break; 1710 case FB_VIEWPORT_CREATE: 1711 retval = vport_create(IPC_GET_ARG1(call) >> 16, 1712 IPC_GET_ARG1(call) & 0xffff, 1713 IPC_GET_ARG2(call) >> 16, 1714 IPC_GET_ARG2(call) & 0xffff); 1715 break; 1716 case FB_VIEWPORT_DELETE: 1717 i = IPC_GET_ARG1(call); 1718 if (i >= MAX_VIEWPORTS) { 1719 retval = EINVAL; 1720 break; 1721 } 1722 if (!viewports[i].initialized) { 1723 retval = EADDRNOTAVAIL; 1724 break; 1725 } 1726 viewports[i].initialized = false; 1727 if (viewports[i].bgpixel) 1728 free(viewports[i].bgpixel); 1729 if (viewports[i].backbuf) 1730 free(viewports[i].backbuf); 1731 retval = EOK; 1732 break; 1733 case FB_SET_STYLE: 1734 retval = fb_set_style(vport, IPC_GET_ARG1(call)); 1735 break; 1736 case FB_SET_COLOR: 1737 retval = fb_set_color(vport, IPC_GET_ARG1(call), 1738 IPC_GET_ARG2(call), IPC_GET_ARG3(call)); 1739 break; 1740 case FB_SET_RGB_COLOR: 1741 vport->attr.fg_color = IPC_GET_ARG1(call); 1742 vport->attr.bg_color = IPC_GET_ARG2(call); 1743 retval = EOK; 1744 break; 1745 case FB_GET_RESOLUTION: 1746 async_answer_2(callid, EOK, screen.xres, screen.yres); 1747 continue; 1748 case FB_POINTER_MOVE: 1749 pointer_enabled = true; 1750 mouse_move(IPC_GET_ARG1(call), IPC_GET_ARG2(call)); 1751 retval = EOK; 1752 break; 1753 case FB_SCREEN_YIELD: 1754 case FB_SCREEN_RECLAIM: 1755 retval = EOK; 1756 break; 1757 default: 1758 retval = ENOENT; 1759 } 1760 async_answer_0(callid, retval); 1761 } 1762 } 1763 1764 /** Initialization of framebuffer 1765 * 1766 */ 1767 int fb_init(void) 1768 { 1769 async_set_client_connection(fb_client_connection); 1770 1771 sysarg_t fb_ph_addr; 1772 if (sysinfo_get_value("fb.address.physical", &fb_ph_addr) != EOK) 1773 return -1; 1774 1775 sysarg_t fb_offset; 1776 if (sysinfo_get_value("fb.offset", &fb_offset) != EOK) 1777 fb_offset = 0; 1778 1779 sysarg_t fb_width; 1780 if (sysinfo_get_value("fb.width", &fb_width) != EOK) 1781 return -1; 1782 1783 sysarg_t fb_height; 1784 if (sysinfo_get_value("fb.height", &fb_height) != EOK) 1785 return -1; 1786 1787 sysarg_t fb_scanline; 1788 if (sysinfo_get_value("fb.scanline", &fb_scanline) != EOK) 1789 return -1; 1790 1791 sysarg_t fb_visual; 1792 if (sysinfo_get_value("fb.visual", &fb_visual) != EOK) 1793 return -1; 1794 1795 sysarg_t fbsize = fb_scanline * fb_height; 1796 void *fb_addr = as_get_mappable_page(fbsize); 1797 1798 if (physmem_map((void *) fb_ph_addr + fb_offset, fb_addr, 1799 ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0) 1800 return -1; 1801 1802 if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual)) 1803 return 0; 1804 1805 return -1; 1806 } 1807 1808 /** 1809 * @} 1810 */ 877 878 /* Screen methods */ 879 880 case FB_GET_RESOLUTION: 881 fbsrv_get_resolution(dev, callid, &call); 882 break; 883 case FB_YIELD: 884 fbsrv_yield(dev, callid, &call); 885 break; 886 case FB_CLAIM: 887 fbsrv_claim(dev, callid, &call); 888 break; 889 case FB_POINTER_UPDATE: 890 fbsrv_pointer_update(dev, callid, &call); 891 break; 892 893 /* Object methods */ 894 895 case FB_VP_CREATE: 896 fbsrv_vp_create(dev, callid, &call); 897 break; 898 case FB_VP_DESTROY: 899 fbsrv_vp_destroy(dev, callid, &call); 900 break; 901 case FB_FRONTBUF_CREATE: 902 fbsrv_frontbuf_create(dev, callid, &call); 903 break; 904 case FB_FRONTBUF_DESTROY: 905 fbsrv_frontbuf_destroy(dev, callid, &call); 906 break; 907 case FB_IMAGEMAP_CREATE: 908 fbsrv_imagemap_create(dev, callid, &call); 909 break; 910 case FB_IMAGEMAP_DESTROY: 911 fbsrv_imagemap_destroy(dev, callid, &call); 912 break; 913 case FB_SEQUENCE_CREATE: 914 fbsrv_sequence_create(dev, callid, &call); 915 break; 916 case FB_SEQUENCE_DESTROY: 917 fbsrv_sequence_destroy(dev, callid, &call); 918 break; 919 case FB_SEQUENCE_ADD_IMAGEMAP: 920 fbsrv_sequence_add_imagemap(dev, callid, &call); 921 break; 922 923 /* Viewport stateful methods */ 924 925 case FB_VP_FOCUS: 926 fbsrv_vp_focus(dev, callid, &call); 927 break; 928 case FB_VP_CLEAR: 929 fbsrv_vp_clear(dev, callid, &call); 930 break; 931 case FB_VP_GET_DIMENSIONS: 932 fbsrv_vp_get_dimensions(dev, callid, &call); 933 break; 934 case FB_VP_GET_CAPS: 935 fbsrv_vp_get_caps(dev, callid, &call); 936 break; 937 938 /* Style methods (viewport specific) */ 939 940 case FB_VP_CURSOR_UPDATE: 941 fbsrv_vp_cursor_update(dev, callid, &call); 942 break; 943 case FB_VP_SET_STYLE: 944 fbsrv_vp_set_style(dev, callid, &call); 945 break; 946 case FB_VP_SET_COLOR: 947 fbsrv_vp_set_color(dev, callid, &call); 948 break; 949 case FB_VP_SET_RGB_COLOR: 950 fbsrv_vp_set_rgb_color(dev, callid, &call); 951 break; 952 953 /* Text output methods (viewport specific) */ 954 955 case FB_VP_PUTCHAR: 956 fbsrv_vp_putchar(dev, callid, &call); 957 break; 958 case FB_VP_UPDATE: 959 fbsrv_vp_update(dev, callid, &call); 960 break; 961 case FB_VP_DAMAGE: 962 fbsrv_vp_damage(dev, callid, &call); 963 break; 964 965 /* Image map methods (viewport specific) */ 966 967 case FB_VP_IMAGEMAP_DAMAGE: 968 fbsrv_vp_imagemap_damage(dev, callid, &call); 969 break; 970 971 /* Sequence methods (viewport specific) */ 972 973 case FB_VP_SEQUENCE_START: 974 fbsrv_vp_sequence_start(dev, callid, &call); 975 break; 976 case FB_VP_SEQUENCE_STOP: 977 fbsrv_vp_sequence_stop(dev, callid, &call); 978 break; 979 980 default: 981 async_answer_0(callid, EINVAL); 982 } 983 } 984 } 985 986 int main(int argc, char *argv[]) 987 { 988 printf("%s: HelenOS framebuffer service\n", NAME); 989 990 /* Register server */ 991 int rc = loc_server_register(NAME, client_connection); 992 if (rc != EOK) { 993 printf("%s: Unable to register driver (%d)\n", NAME, rc); 994 return 1; 995 } 996 997 ega_init(); 998 kchar_init(); 999 kfb_init(); 1000 niagara_init(); 1001 ski_init(); 1002 1003 printf("%s: Accepting connections\n", NAME); 1004 task_retval(0); 1005 async_manager(); 1006 1007 /* Never reached */ 1008 return 0; 1009 } -
uspace/srv/hid/fb/fb.h
r867e2555 r925a21e 1 1 /* 2 * Copyright (c) 20 06 Ondrej Palkovsky2 * Copyright (c) 2011 Martin Decky 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup fb30 * @ingroup fbs31 * @{32 */33 /** @file34 */35 36 29 #ifndef FB_FB_H_ 37 30 #define FB_FB_H_ 38 31 39 #include <stdint.h> 32 #include <sys/types.h> 33 #include <bool.h> 34 #include <loc.h> 35 #include <io/console.h> 36 #include <io/style.h> 37 #include <io/color.h> 38 #include <fb.h> 39 #include <screenbuffer.h> 40 #include <imgmap.h> 40 41 41 typedef void (* putpixel_cb_t)(void *, unsigned int, unsigned int, uint32_t); 42 struct fbdev; 43 struct fbvp; 42 44 43 extern int fb_init(void); 45 typedef struct { 46 int (* yield)(struct fbdev *dev); 47 int (* claim)(struct fbdev *dev); 48 void (* pointer_update)(struct fbdev *dev, sysarg_t x, sysarg_t y, 49 bool visible); 50 51 int (* get_resolution)(struct fbdev *dev, sysarg_t *width, 52 sysarg_t *height); 53 void (* font_metrics)(struct fbdev *dev, sysarg_t width, 54 sysarg_t height, sysarg_t *cols, sysarg_t *rows); 55 56 int (* vp_create)(struct fbdev *dev, struct fbvp *vp); 57 void (* vp_destroy)(struct fbdev *dev, struct fbvp *vp); 58 59 void (* vp_clear)(struct fbdev *dev, struct fbvp *vp); 60 console_caps_t (* vp_get_caps)(struct fbdev *dev, struct fbvp *vp); 61 62 void (* vp_cursor_update)(struct fbdev *dev, struct fbvp *vp, 63 sysarg_t prev_col, sysarg_t prev_row, sysarg_t col, sysarg_t row, 64 bool visible); 65 void (* vp_cursor_flash)(struct fbdev *dev, struct fbvp *vp, 66 sysarg_t col, sysarg_t row); 67 68 void (* vp_char_update)(struct fbdev *dev, struct fbvp *vp, sysarg_t col, 69 sysarg_t row); 70 71 void (* vp_imgmap_damage)(struct fbdev *dev, struct fbvp *vp, 72 imgmap_t *imgmap, sysarg_t col, sysarg_t row, sysarg_t cols, 73 sysarg_t rows); 74 } fbdev_ops_t; 75 76 typedef struct fbdev { 77 link_t link; 78 79 atomic_t refcnt; 80 bool claimed; 81 82 sysarg_t index; 83 service_id_t dsid; 84 struct fbvp *active_vp; 85 86 list_t vps; 87 list_t frontbufs; 88 list_t imagemaps; 89 list_t sequences; 90 91 fbdev_ops_t ops; 92 void *data; 93 } fbdev_t; 94 95 typedef struct fbvp { 96 link_t link; 97 98 sysarg_t x; 99 sysarg_t y; 100 101 sysarg_t width; 102 sysarg_t height; 103 104 sysarg_t cols; 105 sysarg_t rows; 106 107 char_attrs_t attrs; 108 list_t sequences; 109 110 screenbuffer_t *backbuf; 111 sysarg_t top_row; 112 113 bool cursor_active; 114 bool cursor_flash; 115 116 void *data; 117 } fbvp_t; 118 119 typedef struct { 120 link_t link; 121 122 size_t size; 123 unsigned int flags; 124 void *data; 125 } frontbuf_t; 126 127 typedef struct { 128 link_t link; 129 link_t seq_link; 130 131 size_t size; 132 unsigned int flags; 133 void *data; 134 } imagemap_t; 135 136 typedef struct { 137 link_t link; 138 139 list_t imagemaps; 140 size_t count; 141 } sequence_t; 142 143 typedef struct { 144 link_t link; 145 146 sequence_t *seq; 147 size_t current; 148 } sequence_vp_t; 149 150 extern fbdev_t *fbdev_register(fbdev_ops_t *, void *); 44 151 45 152 #endif 46 47 /** @}48 */ -
uspace/srv/hid/fb/gfx/font-8x16.c
r867e2555 r925a21e 43 43 * glyph in the font or returns an index to the question 44 44 * mark glyph if no specific glyph exists. 45 * 45 46 */ 46 47 uint16_t fb_font_glyph(const wchar_t ch) -
uspace/srv/hid/fb/gfx/font-8x16.h
r867e2555 r925a21e 36 36 #define FONT_8X16_H_ 37 37 38 #include <sys/types.h> 39 38 40 #define FONT_GLYPHS 2899 39 41 #define FONT_WIDTH 8 40 42 #define FONT_SCANLINES 16 41 43 42 #include <sys/types.h> 43 44 extern uint16_t fb_font_glyph(const wchar_t ch); 44 extern uint16_t fb_font_glyph(const wchar_t); 45 45 extern uint8_t fb_font[FONT_GLYPHS][FONT_SCANLINES]; 46 46 -
uspace/srv/hid/fb/port/ega.h
r867e2555 r925a21e 27 27 */ 28 28 29 /** @addtogroup egafb30 * @brief HelenOS EGA framebuffer.31 * @ingroup fbs32 * @{33 */34 29 /** @file 35 30 */ 36 31 37 #ifndef FB_ EGA_H_38 #define FB_ EGA_H_32 #ifndef FB_PORT_EGA_H_ 33 #define FB_PORT_EGA_H_ 39 34 40 35 extern int ega_init(void); -
uspace/srv/hid/fb/port/kchar.c
r867e2555 r925a21e 28 28 */ 29 29 30 /** @defgroup msimfb MSIM text console31 * @brief HelenOS MSIM text console.32 * @ingroup fbs33 * @{34 */35 30 /** @file 36 31 */ 37 32 38 #include < async.h>39 #include < libc.h>33 #include <sys/types.h> 34 #include <errno.h> 40 35 #include <sysinfo.h> 36 #include <ddi.h> 41 37 #include <as.h> 42 #include <ddi.h> 43 #include <errno.h> 38 #include <align.h> 39 #include "../ctl/serial.h" 40 #include "kchar.h" 44 41 45 #include "serial_console.h" 46 #include "msim.h" 42 typedef struct { 43 uint8_t *addr; 44 } kchar_t; 47 45 48 #define WIDTH 80 49 #define HEIGHT 24 46 static kchar_t kchar; 50 47 51 static char *virt_addr; 52 53 static void msim_putc(const char c) 48 static void kchar_putchar(wchar_t ch) 54 49 { 55 *virt_addr = c; 50 if ((ch >= 0) && (ch < 128)) 51 *kchar.addr = ch; 52 else 53 *kchar.addr = '?'; 56 54 } 57 55 58 int msim_init(void)56 static void kchar_control_puts(const char *str) 59 57 { 60 sysarg_t phys_addr; 61 if (sysinfo_get_value("fb.address.physical", &phys_addr) != EOK) 62 return -1; 58 while (*str) 59 *kchar.addr = *(str++); 60 } 61 62 int kchar_init(void) 63 { 64 sysarg_t present; 65 int rc = sysinfo_get_value("fb", &present); 66 if (rc != EOK) 67 present = false; 63 68 64 virt_addr = (char *) as_get_mappable_page(1); 69 if (!present) 70 return ENOENT; 65 71 66 if (physmem_map((void *) phys_addr, virt_addr, 1, 67 AS_AREA_READ | AS_AREA_WRITE) != 0) 68 return -1; 72 sysarg_t kind; 73 rc = sysinfo_get_value("fb.kind", &kind); 74 if (rc != EOK) 75 kind = (sysarg_t) -1; 69 76 70 serial_console_init(msim_putc, WIDTH, HEIGHT); 77 if (kind != 3) 78 return EINVAL; 71 79 72 async_set_client_connection(serial_client_connection); 73 return 0; 80 sysarg_t paddr; 81 rc = sysinfo_get_value("fb.address.physical", &paddr); 82 if (rc != EOK) 83 return rc; 84 85 kchar.addr = as_get_mappable_page(1); 86 if (kchar.addr == NULL) 87 return ENOMEM; 88 89 rc = physmem_map((void *) paddr, kchar.addr, 90 ALIGN_UP(1, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE); 91 if (rc != EOK) 92 return rc; 93 94 return serial_init(kchar_putchar, kchar_control_puts); 74 95 } 75 96 -
uspace/srv/hid/fb/port/kchar.h
r867e2555 r925a21e 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2008 Martin Decky 3 4 * All rights reserved. 4 5 * … … 27 28 */ 28 29 29 #ifndef FB_MAIN_H_ 30 #define FB_MAIN_H_ 30 /** @file 31 */ 31 32 32 extern void receive_comm_area(ipc_callid_t, ipc_call_t *, void **); 33 #ifndef FB_PORT_KCHAR_H_ 34 #define FB_PORT_KCHAR_H_ 35 36 extern int kchar_init(void); 33 37 34 38 #endif 39 40 /** @} 41 */ -
uspace/srv/hid/fb/port/niagara.c
r867e2555 r925a21e 29 29 */ 30 30 31 /** @defgroup niagarafb32 * @brief userland driver of the Niagara console output33 * @{34 */35 31 /** @file 36 32 */ 37 33 38 #include <async.h> 34 #include <sys/types.h> 35 #include <errno.h> 39 36 #include <sysinfo.h> 37 #include <ddi.h> 40 38 #include <as.h> 41 #include <errno.h> 42 #include <stdio.h> 43 #include <ddi.h> 44 45 #include "serial_console.h" 39 #include <align.h> 40 #include "../ctl/serial.h" 46 41 #include "niagara.h" 47 42 48 #define WIDTH 80 49 #define HEIGHT 24 43 #define OUTPUT_FIFO_SIZE ((PAGE_SIZE) - 2 * sizeof(uint64_t)) 50 44 51 /**52 * Virtual address mapped to the buffer shared with the kernel counterpart.53 */54 static uintptr_t output_buffer_addr;55 56 /*57 * Kernel counterpart of the driver reads characters to be printed from here.58 * Keep in sync with the definition from59 * kernel/arch/sparc64/src/drivers/niagara.c.60 */61 #define OUTPUT_BUFFER_SIZE ((PAGE_SIZE) - 2 * 8)62 45 typedef volatile struct { 63 46 uint64_t read_ptr; 64 47 uint64_t write_ptr; 65 char data[OUTPUT_BUFFER_SIZE]; 66 } 67 __attribute__ ((packed)) 68 __attribute__ ((aligned(PAGE_SIZE))) 69 *output_buffer_t; 48 char data[OUTPUT_FIFO_SIZE]; 49 } __attribute__((packed)) output_fifo_t; 70 50 71 output_buffer_t output_buffer; 51 typedef struct { 52 output_fifo_t *fifo; 53 } niagara_t; 72 54 73 /** 74 * Pushes the character to the Niagara serial. 75 * @param c character to be pushed 76 */ 77 static void niagara_putc(char c) 55 static niagara_t niagara; 56 57 static void niagara_putc(const char c) 78 58 { 79 while ( output_buffer->write_ptr ==80 (output_buffer->read_ptr + OUTPUT_BUFFER_SIZE - 1)81 % OUTPUT_BUFFER_SIZE)82 ;83 output_buffer->data[output_buffer->write_ptr] = (uint64_t)c;84 output_buffer->write_ptr =85 ((output_buffer->write_ptr) + 1) % OUTPUT_BUFFER_SIZE;59 while (niagara.fifo->write_ptr == 60 (niagara.fifo->read_ptr + OUTPUT_FIFO_SIZE - 1) 61 % OUTPUT_FIFO_SIZE); 62 63 niagara.fifo->data[niagara.fifo->write_ptr] = c; 64 niagara.fifo->write_ptr = 65 ((niagara.fifo->write_ptr) + 1) % OUTPUT_FIFO_SIZE; 86 66 } 87 67 88 /** 89 * Initializes the Niagara serial driver. 90 */ 68 static void niagara_putchar(wchar_t ch) 69 { 70 if ((ch >= 0) && (ch < 128)) 71 niagara_putc(ch); 72 else 73 niagara_putc('?'); 74 } 75 76 static void niagara_control_puts(const char *str) 77 { 78 while (*str) 79 niagara_putc(*(str++)); 80 } 81 91 82 int niagara_init(void) 92 83 { 84 sysarg_t present; 85 int rc = sysinfo_get_value("fb", &present); 86 if (rc != EOK) 87 present = false; 88 89 if (!present) 90 return ENOENT; 91 92 sysarg_t kind; 93 rc = sysinfo_get_value("fb.kind", &kind); 94 if (rc != EOK) 95 kind = (sysarg_t) -1; 96 97 if (kind != 5) 98 return EINVAL; 99 93 100 sysarg_t paddr; 94 if (sysinfo_get_value("niagara.outbuf.address", &paddr) != EOK) 95 return -1; 101 rc = sysinfo_get_value("niagara.outbuf.address", &paddr); 102 if (rc != EOK) 103 return rc; 96 104 97 output_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE); 98 int result = physmem_map((void *) paddr, 99 (void *) output_buffer_addr, 1, 105 niagara.fifo = 106 (output_fifo_t *) as_get_mappable_page(sizeof(output_fifo_t)); 107 if (niagara.fifo == NULL) 108 return ENOMEM; 109 110 rc = physmem_map((void *) paddr, (void *) niagara.fifo, 1, 100 111 AS_AREA_READ | AS_AREA_WRITE); 101 102 if (result != 0) { 103 printf("Niagara: uspace driver couldn't map physical memory: %d\n", 104 result); 105 } 106 107 output_buffer = (output_buffer_t) output_buffer_addr; 108 109 serial_console_init(niagara_putc, WIDTH, HEIGHT); 110 async_set_client_connection(serial_client_connection); 111 return 0; 112 if (rc != EOK) 113 return rc; 114 115 return serial_init(niagara_putchar, niagara_control_puts); 112 116 } 113 117 114 /** 115 * @} 118 /** @} 116 119 */ 117 -
uspace/srv/hid/fb/port/niagara.h
r867e2555 r925a21e 27 27 */ 28 28 29 /** @defgroup niagarafb30 * @brief userland driver of the Niagara console output31 * @{32 */33 34 29 /** @file 35 30 */ 36 31 37 #ifndef FB_ NIAGARA_H_38 #define FB_ NIAGARA_H_32 #ifndef FB_PORT_NIAGARA_H_ 33 #define FB_PORT_NIAGARA_H_ 39 34 40 int niagara_init(void);35 extern int niagara_init(void); 41 36 42 37 #endif 43 38 44 /** 39 /** 45 40 * @} 46 41 */ -
uspace/srv/hid/fb/port/ski.c
r867e2555 r925a21e 1 1 /* 2 * Copyright (c) 200 5 Jakub Jermar3 * Copyright (c) 2008 Jiri Svoboda2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2008 Martin Decky 4 4 * All rights reserved. 5 5 * … … 28 28 */ 29 29 30 /** @defgroup msimfb MSIM text console31 * @brief HelenOS MSIM text console.32 * @ingroup fbs33 * @{34 */35 30 /** @file 36 31 */ 37 32 38 #include < async.h>39 #include < libc.h>33 #include <sys/types.h> 34 #include <errno.h> 40 35 #include <sysinfo.h> 41 #include <as.h> 42 #include <ddi.h> 43 44 #include "serial_console.h" 36 #include "../ctl/serial.h" 45 37 #include "ski.h" 46 38 47 # define SKI_PUTCHAR 3139 #ifdef UARCH_ia64 48 40 49 #define WIDTH 80 50 #define HEIGHT 24 41 #define SKI_PUTCHAR 31 51 42 52 43 /** Display character on ski debug console … … 55 46 * display character on debug console. 56 47 * 57 * @param ch Character to be printed. 48 * @param c Character to be printed. 49 * 58 50 */ 59 static void ski_putc(const char c h)51 static void ski_putc(const char c) 60 52 { 61 53 asm volatile ( 62 54 "mov r15 = %0\n" 63 "mov r32 = %1\n" /* r32 is in0 */64 "break 0x80000\n" /* modifies r8 */55 "mov r32 = %1\n" /* r32 is in0 */ 56 "break 0x80000\n" /* modifies r8 */ 65 57 : 66 : "i" (SKI_PUTCHAR), "r" (c h)58 : "i" (SKI_PUTCHAR), "r" (c) 67 59 : "r15", "in0", "r8" 68 60 ); 69 61 70 if (c h== '\n')62 if (c == '\n') 71 63 ski_putc('\r'); 64 } 65 66 static void ski_putchar(wchar_t ch) 67 { 68 if ((ch >= 0) && (ch < 128)) 69 ski_putc(ch); 70 else 71 ski_putc('?'); 72 } 73 74 static void ski_control_puts(const char *str) 75 { 76 while (*str) 77 ski_putc(*(str++)); 72 78 } 73 79 74 80 int ski_init(void) 75 81 { 76 serial_console_init(ski_putc, WIDTH, HEIGHT); 82 sysarg_t present; 83 int rc = sysinfo_get_value("fb", &present); 84 if (rc != EOK) 85 present = false; 77 86 78 async_set_client_connection(serial_client_connection); 79 return 0; 87 if (!present) 88 return ENOENT; 89 90 sysarg_t kind; 91 rc = sysinfo_get_value("fb.kind", &kind); 92 if (rc != EOK) 93 kind = (sysarg_t) -1; 94 95 if (kind != 6) 96 return EINVAL; 97 98 return serial_init(ski_putchar, ski_control_puts); 80 99 } 81 100 82 /** 83 * @} 101 #else /* UARCH_ia64 */ 102 103 int ski_init(void) 104 { 105 return ENOENT; 106 } 107 108 #endif 109 110 /** @} 84 111 */ -
uspace/srv/hid/fb/port/ski.h
r867e2555 r925a21e 27 27 */ 28 28 29 /** @addtogroup skifb30 * @brief HelenOS ski text console.31 * @ingroup fbs32 * @{33 */34 29 /** @file 35 30 */ 36 31 37 #ifndef FB_ SKI_H_38 #define FB_ SKI_H_32 #ifndef FB_PORT_SKI_H_ 33 #define FB_PORT_SKI_H_ 39 34 40 35 extern int ski_init(void); … … 44 39 /** @} 45 40 */ 46 -
uspace/srv/hid/input/ctl/kbdev.c
r867e2555 r925a21e 48 48 #include <kbd_ctl.h> 49 49 #include <kbd_port.h> 50 #include <loc.h> 50 51 #include <stdlib.h> 51 52 #include <vfs/vfs_sess.h> 52 53 #include <sys/typefmt.h> 53 54 54 55 static int kbdev_ctl_init(kbd_dev_t *); … … 70 71 /** Session with kbdev device */ 71 72 async_sess_t *sess; 72 73 /** File descriptor of open kbdev device */74 int fd;75 73 } kbdev_t; 76 74 … … 84 82 85 83 kbdev->kbd_dev = kdev; 86 kbdev->fd = -1;87 84 88 85 return kbdev; … … 93 90 if (kbdev->sess != NULL) 94 91 async_hangup(kbdev->sess); 95 if (kbdev->fd >= 0)96 close(kbdev->fd);97 92 free(kbdev); 98 93 } … … 100 95 static int kbdev_ctl_init(kbd_dev_t *kdev) 101 96 { 102 const char *pathname;103 97 async_sess_t *sess; 104 98 async_exch_t *exch; 105 99 kbdev_t *kbdev; 106 int fd;107 100 int rc; 108 101 109 pathname = kdev->dev_path; 110 111 fd = open(pathname, O_RDWR); 112 if (fd < 0) { 113 return -1; 114 } 115 116 sess = fd_session(EXCHANGE_SERIALIZE, fd); 102 sess = loc_service_connect(EXCHANGE_SERIALIZE, kdev->svc_id, 0); 117 103 if (sess == NULL) { 118 printf("%s: Failed starting session with '%s '\n", NAME, pathname);119 close(fd);104 printf("%s: Failed starting session with '%s.'\n", NAME, 105 kdev->svc_name); 120 106 return -1; 121 107 } … … 124 110 if (kbdev == NULL) { 125 111 printf("%s: Failed allocating device structure for '%s'.\n", 126 NAME, pathname);112 NAME, kdev->svc_name); 127 113 return -1; 128 114 } 129 115 130 kbdev->fd = fd;131 116 kbdev->sess = sess; 132 117 133 118 exch = async_exchange_begin(sess); 134 119 if (exch == NULL) { 135 printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname); 120 printf("%s: Failed starting exchange with '%s'.\n", NAME, 121 kdev->svc_name); 136 122 kbdev_destroy(kbdev); 137 123 return -1; … … 141 127 if (rc != EOK) { 142 128 printf("%s: Failed creating callback connection from '%s'.\n", 143 NAME, pathname);129 NAME, kdev->svc_name); 144 130 async_exchange_end(exch); 145 131 kbdev_destroy(kbdev); -
uspace/srv/hid/input/generic/input.c
r867e2555 r925a21e 38 38 39 39 #include <adt/list.h> 40 #include <bool.h> 40 41 #include <ipc/services.h> 41 42 #include <ipc/input.h> … … 46 47 #include <stdio.h> 47 48 #include <ns.h> 48 #include <ns_obsolete.h>49 49 #include <async.h> 50 #include <async_obsolete.h>51 50 #include <errno.h> 52 51 #include <adt/fifo.h> 53 52 #include <io/console.h> 54 53 #include <io/keycode.h> 55 #include < devmap.h>54 #include <loc.h> 56 55 #include <input.h> 57 56 #include <kbd.h> … … 62 61 #include <mouse.h> 63 62 64 // FIXME: remove this header65 #include <kernel/ipc/ipc_methods.h>66 67 /* In microseconds */68 #define DISCOVERY_POLL_INTERVAL (10 * 1000 * 1000)69 70 63 #define NUM_LAYOUTS 3 71 64 … … 79 72 static void kbd_devs_reclaim(void); 80 73 81 int client_phone = -1;74 async_sess_t *client_sess = NULL; 82 75 83 76 /** List of keyboard devices */ … … 88 81 89 82 bool irc_service = false; 90 int irc_phone = -1;83 async_sess_t *irc_sess = NULL; 91 84 92 85 void kbd_push_data(kbd_dev_t *kdev, sysarg_t data) … … 172 165 173 166 ev.c = layout_parse_ev(kdev->active_layout, &ev); 174 async_obsolete_msg_4(client_phone, INPUT_EVENT_KEY, ev.type, ev.key, 175 ev.mods, ev.c); 167 168 async_exch_t *exch = async_exchange_begin(client_sess); 169 async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c); 170 async_exchange_end(exch); 176 171 } 177 172 … … 179 174 void mouse_push_event_move(mouse_dev_t *mdev, int dx, int dy) 180 175 { 181 async_obsolete_msg_2(client_phone, INPUT_EVENT_MOVE, dx, dy); 176 async_exch_t *exch = async_exchange_begin(client_sess); 177 async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy); 178 async_exchange_end(exch); 182 179 } 183 180 … … 185 182 void mouse_push_event_button(mouse_dev_t *mdev, int bnum, int press) 186 183 { 187 async_obsolete_msg_2(client_phone, INPUT_EVENT_BUTTON, bnum, press); 184 async_exch_t *exch = async_exchange_begin(client_sess); 185 async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press); 186 async_exchange_end(exch); 188 187 } 189 188 190 189 static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 191 190 { 192 ipc_callid_t callid;193 ipc_call_t call;194 int retval;195 196 191 async_answer_0(iid, EOK); 197 192 198 193 while (true) { 199 callid = async_get_call(&call); 194 ipc_call_t call; 195 ipc_callid_t callid = async_get_call(&call); 200 196 201 197 if (!IPC_GET_IMETHOD(call)) { 202 if (client_ phone != -1) {203 async_ obsolete_hangup(client_phone);204 client_ phone = -1;198 if (client_sess != NULL) { 199 async_hangup(client_sess); 200 client_sess = NULL; 205 201 } 206 202 … … 209 205 } 210 206 211 switch (IPC_GET_IMETHOD(call)) { 212 case IPC_M_CONNECT_TO_ME: 213 if (client_phone != -1) { 214 retval = ELIMIT; 207 async_sess_t *sess = 208 async_callback_receive_start(EXCHANGE_SERIALIZE, &call); 209 if (sess != NULL) { 210 if (client_sess == NULL) { 211 client_sess = sess; 212 async_answer_0(callid, EOK); 213 } else 214 async_answer_0(callid, ELIMIT); 215 } else { 216 switch (IPC_GET_IMETHOD(call)) { 217 case INPUT_YIELD: 218 kbd_devs_yield(); 219 async_answer_0(callid, EOK); 215 220 break; 221 case INPUT_RECLAIM: 222 kbd_devs_reclaim(); 223 async_answer_0(callid, EOK); 224 break; 225 default: 226 async_answer_0(callid, EINVAL); 216 227 } 217 client_phone = IPC_GET_ARG5(call);218 retval = 0;219 break;220 case INPUT_YIELD:221 kbd_devs_yield();222 retval = 0;223 break;224 case INPUT_RECLAIM:225 kbd_devs_reclaim();226 retval = 0;227 break;228 default:229 retval = EINVAL;230 228 } 231 232 async_answer_0(callid, retval);233 229 } 234 230 } … … 275 271 kdev->port_ops = port; 276 272 kdev->ctl_ops = ctl; 277 kdev-> dev_path = NULL;273 kdev->svc_id = 0; 278 274 279 275 /* Initialize port driver. */ … … 303 299 mdev->port_ops = port; 304 300 mdev->proto_ops = proto; 305 mdev-> dev_path = NULL;301 mdev->svc_id = 0; 306 302 307 303 /* Initialize port driver. */ … … 324 320 /** Add new kbdev device. 325 321 * 326 * @param dev_path Filesystem path to the device (/dev/class/...)322 * @param service_id Service ID of the keyboard device 327 323 * 328 324 */ 329 static int kbd_add_kbdev( const char *dev_path)325 static int kbd_add_kbdev(service_id_t service_id, kbd_dev_t **kdevp) 330 326 { 331 327 kbd_dev_t *kdev = kbd_dev_new(); … … 333 329 return -1; 334 330 335 kdev-> dev_path = dev_path;331 kdev->svc_id = service_id; 336 332 kdev->port_ops = NULL; 337 333 kdev->ctl_ops = &kbdev_ctl; 338 334 335 int rc = loc_service_get_name(service_id, &kdev->svc_name); 336 if (rc != EOK) { 337 kdev->svc_name = NULL; 338 goto fail; 339 } 340 339 341 /* Initialize controller driver. */ 340 342 if ((*kdev->ctl_ops->init)(kdev) != 0) { … … 343 345 344 346 list_append(&kdev->kbd_devs, &kbd_devs); 347 *kdevp = kdev; 345 348 return EOK; 346 349 347 350 fail: 351 if (kdev->svc_name != NULL) 352 free(kdev->svc_name); 348 353 free(kdev); 349 354 return -1; … … 352 357 /** Add new mousedev device. 353 358 * 354 * @param dev_path Filesystem path to the device (/dev/class/...)359 * @param service_id Service ID of the mouse device 355 360 * 356 361 */ 357 static int mouse_add_mousedev( const char *dev_path)362 static int mouse_add_mousedev(service_id_t service_id, mouse_dev_t **mdevp) 358 363 { 359 364 mouse_dev_t *mdev = mouse_dev_new(); … … 361 366 return -1; 362 367 363 mdev-> dev_path = dev_path;368 mdev->svc_id = service_id; 364 369 mdev->port_ops = NULL; 365 370 mdev->proto_ops = &mousedev_proto; 366 371 372 int rc = loc_service_get_name(service_id, &mdev->svc_name); 373 if (rc != EOK) { 374 mdev->svc_name = NULL; 375 goto fail; 376 } 377 367 378 /* Initialize controller driver. */ 368 379 if ((*mdev->proto_ops->init)(mdev) != 0) { … … 371 382 372 383 list_append(&mdev->mouse_devs, &mouse_devs); 384 *mdevp = mdev; 373 385 return EOK; 374 386 … … 480 492 } 481 493 482 /** Periodically check for new input devices. 483 * 484 * Looks under /dev/class/keyboard and /dev/class/mouse. 485 * 486 * @param arg Ignored 487 * 488 */ 489 static int dev_discovery_fibril(void *arg) 490 { 491 char *dev_path; 492 size_t kbd_id = 1; 493 size_t mouse_id = 1; 494 static int dev_check_new_kbdevs(void) 495 { 496 category_id_t keyboard_cat; 497 service_id_t *svcs; 498 size_t count, i; 499 bool already_known; 494 500 int rc; 495 501 496 while (true) { 497 async_usleep(DISCOVERY_POLL_INTERVAL); 498 499 /* 500 * Check for new keyboard device 501 */ 502 rc = asprintf(&dev_path, "/dev/class/keyboard\\%zu", kbd_id); 503 if (rc < 0) 504 continue; 505 506 if (kbd_add_kbdev(dev_path) == EOK) { 507 printf("%s: Connected keyboard device '%s'\n", 508 NAME, dev_path); 509 510 /* XXX Handle device removal */ 511 ++kbd_id; 502 rc = loc_category_get_id("keyboard", &keyboard_cat, IPC_FLAG_BLOCKING); 503 if (rc != EOK) { 504 printf("%s: Failed resolving category 'keyboard'.\n", NAME); 505 return ENOENT; 506 } 507 508 /* 509 * Check for new keyboard devices 510 */ 511 rc = loc_category_get_svcs(keyboard_cat, &svcs, &count); 512 if (rc != EOK) { 513 printf("%s: Failed getting list of keyboard devices.\n", 514 NAME); 515 return EIO; 516 } 517 518 for (i = 0; i < count; i++) { 519 already_known = false; 520 521 /* Determine whether we already know this device. */ 522 list_foreach(kbd_devs, kdev_link) { 523 kbd_dev_t *kdev = list_get_instance(kdev_link, 524 kbd_dev_t, kbd_devs); 525 if (kdev->svc_id == svcs[i]) { 526 already_known = true; 527 break; 528 } 512 529 } 513 530 514 free(dev_path); 515 516 /* 517 * Check for new mouse device 518 */ 519 rc = asprintf(&dev_path, "/dev/class/mouse\\%zu", mouse_id); 520 if (rc < 0) 521 continue; 522 523 if (mouse_add_mousedev(dev_path) == EOK) { 524 printf("%s: Connected mouse device '%s'\n", 525 NAME, dev_path); 526 527 /* XXX Handle device removal */ 528 ++mouse_id; 531 if (!already_known) { 532 kbd_dev_t *kdev; 533 if (kbd_add_kbdev(svcs[i], &kdev) == EOK) { 534 printf("%s: Connected keyboard device '%s'\n", 535 NAME, kdev->svc_name); 536 } 529 537 } 530 531 free(dev_path); 532 } 538 } 539 540 free(svcs); 541 542 /* XXX Handle device removal */ 533 543 534 544 return EOK; 535 545 } 536 546 537 /** Start a fibril for discovering new devices. */ 538 static void input_start_dev_discovery(void) 539 { 540 fid_t fid = fibril_create(dev_discovery_fibril, NULL); 541 if (!fid) { 542 printf("%s: Failed to create device discovery fibril.\n", 547 static int dev_check_new_mousedevs(void) 548 { 549 category_id_t mouse_cat; 550 service_id_t *svcs; 551 size_t count, i; 552 bool already_known; 553 int rc; 554 555 rc = loc_category_get_id("mouse", &mouse_cat, IPC_FLAG_BLOCKING); 556 if (rc != EOK) { 557 printf("%s: Failed resolving category 'mouse'.\n", NAME); 558 return ENOENT; 559 } 560 561 /* 562 * Check for new mouse devices 563 */ 564 rc = loc_category_get_svcs(mouse_cat, &svcs, &count); 565 if (rc != EOK) { 566 printf("%s: Failed getting list of mouse devices.\n", 543 567 NAME); 544 return; 545 } 546 547 fibril_add_ready(fid); 568 return EIO; 569 } 570 571 for (i = 0; i < count; i++) { 572 already_known = false; 573 574 /* Determine whether we already know this device. */ 575 list_foreach(mouse_devs, mdev_link) { 576 mouse_dev_t *mdev = list_get_instance(mdev_link, 577 mouse_dev_t, mouse_devs); 578 if (mdev->svc_id == svcs[i]) { 579 already_known = true; 580 break; 581 } 582 } 583 584 if (!already_known) { 585 mouse_dev_t *mdev; 586 if (mouse_add_mousedev(svcs[i], &mdev) == EOK) { 587 printf("%s: Connected mouse device '%s'\n", 588 NAME, mdev->svc_name); 589 } 590 } 591 } 592 593 free(svcs); 594 595 /* XXX Handle device removal */ 596 597 return EOK; 598 } 599 600 static int dev_check_new(void) 601 { 602 int rc; 603 604 rc = dev_check_new_kbdevs(); 605 if (rc != EOK) 606 return rc; 607 608 rc = dev_check_new_mousedevs(); 609 if (rc != EOK) 610 return rc; 611 612 return EOK; 613 } 614 615 static void cat_change_cb(void) 616 { 617 dev_check_new(); 618 } 619 620 /** Start listening for new devices. */ 621 static int input_start_dev_discovery(void) 622 { 623 int rc; 624 625 rc = loc_register_cat_change_cb(cat_change_cb); 626 if (rc != EOK) { 627 printf("%s: Failed registering callback for device discovery. " 628 "(%d)\n", NAME, rc); 629 return rc; 630 } 631 632 return dev_check_new(); 548 633 } 549 634 … … 561 646 562 647 if (irc_service) { 563 while (irc_phone < 0) 564 irc_phone = service_obsolete_connect_blocking(SERVICE_IRC, 0, 0); 648 while (irc_sess == NULL) 649 irc_sess = service_connect_blocking(EXCHANGE_SERIALIZE, 650 SERVICE_IRC, 0, 0); 565 651 } 566 652 … … 572 658 573 659 /* Register driver */ 574 int rc = devmap_driver_register(NAME, client_connection);660 int rc = loc_server_register(NAME, client_connection); 575 661 if (rc < 0) { 576 printf("%s: Unable to register driver (%d)\n", NAME, rc);662 printf("%s: Unable to register server (%d)\n", NAME, rc); 577 663 return -1; 578 664 } 579 665 580 char kbd[ DEVMAP_NAME_MAXLEN + 1];581 snprintf(kbd, DEVMAP_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME);582 583 devmap_handle_t devmap_handle;584 if ( devmap_device_register(kbd, &devmap_handle) != EOK) {585 printf("%s: Unable to register device %s\n", NAME, kbd);666 char kbd[LOC_NAME_MAXLEN + 1]; 667 snprintf(kbd, LOC_NAME_MAXLEN, "%s/%s", NAMESPACE, NAME); 668 669 service_id_t service_id; 670 if (loc_service_register(kbd, &service_id) != EOK) { 671 printf("%s: Unable to register service %s\n", NAME, kbd); 586 672 return -1; 587 673 } -
uspace/srv/hid/input/include/input.h
r867e2555 r925a21e 40 40 41 41 #include <bool.h> 42 #include <async.h> 42 43 43 44 #define NAME "input" … … 45 46 46 47 extern bool irc_service; 47 extern int irc_phone;48 extern async_sess_t *irc_sess; 48 49 49 50 #endif -
uspace/srv/hid/input/include/kbd.h
r867e2555 r925a21e 40 40 41 41 #include <adt/list.h> 42 #include <ipc/loc.h> 42 43 43 44 struct kbd_port_ops; … … 49 50 link_t kbd_devs; 50 51 51 /** Path to the device (only for kbdev devices) */ 52 const char *dev_path; 52 /** Service ID (only for kbdev devices) */ 53 service_id_t svc_id; 54 55 /** Device service name (only for kbdev devices) */ 56 char *svc_name; 53 57 54 58 /** Port ops */ -
uspace/srv/hid/input/include/mouse.h
r867e2555 r925a21e 39 39 40 40 #include <adt/list.h> 41 #include <ipc/loc.h> 41 42 42 43 struct mouse_port_ops; … … 47 48 link_t mouse_devs; 48 49 49 /** Path to the device (only for mouseev devices) */ 50 const char *dev_path; 50 /** Service ID (only for mousedev devices) */ 51 service_id_t svc_id; 52 53 /** Device service name (only for mousedev devices) */ 54 char *svc_name; 51 55 52 56 /** Port ops */ -
uspace/srv/hid/input/port/adb.c
r867e2555 r925a21e 43 43 #include <fcntl.h> 44 44 #include <errno.h> 45 #include < devmap.h>45 #include <loc.h> 46 46 47 47 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg); … … 66 66 { 67 67 const char *dev = "adb/kbd"; 68 devmap_handle_t handle;68 service_id_t service_id; 69 69 async_exch_t *exch; 70 70 int rc; … … 72 72 kbd_dev = kdev; 73 73 74 rc = devmap_device_get_handle(dev, &handle, 0);74 rc = loc_service_get_id(dev, &service_id, 0); 75 75 if (rc != EOK) 76 76 return rc; 77 77 78 dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);78 dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0); 79 79 if (dev_sess == NULL) { 80 80 printf("%s: Failed to connect to device\n", NAME); -
uspace/srv/hid/input/port/adb_mouse.c
r867e2555 r925a21e 41 41 #include <mouse.h> 42 42 #include <errno.h> 43 #include <devmap.h> 43 #include <loc.h> 44 #include <stdio.h> 44 45 45 46 static mouse_dev_t *mouse_dev; … … 78 79 mouse_dev = mdev; 79 80 80 devmap_handle_t handle;81 int rc = devmap_device_get_handle(dev, &handle, 0);81 service_id_t service_id; 82 int rc = loc_service_get_id(dev, &service_id, 0); 82 83 if (rc != EOK) 83 84 return rc; 84 85 85 dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle, 0);86 dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0); 86 87 if (dev_sess == NULL) { 87 88 printf("%s: Failed to connect to device\n", NAME); -
uspace/srv/hid/input/port/chardev.c
r867e2555 r925a21e 40 40 #include <kbd_port.h> 41 41 #include <kbd.h> 42 #include < devmap.h>42 #include <loc.h> 43 43 #include <errno.h> 44 44 #include <stdio.h> … … 71 71 static int chardev_port_init(kbd_dev_t *kdev) 72 72 { 73 devmap_handle_t handle;73 service_id_t service_id; 74 74 async_exch_t *exch; 75 75 unsigned int i; … … 79 79 80 80 for (i = 0; i < num_devs; i++) { 81 rc = devmap_device_get_handle(in_devs[i], &handle, 0);81 rc = loc_service_get_id(in_devs[i], &service_id, 0); 82 82 if (rc == EOK) 83 83 break; … … 89 89 } 90 90 91 dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,91 dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 92 92 IPC_FLAG_BLOCKING); 93 93 if (dev_sess == NULL) { -
uspace/srv/hid/input/port/chardev_mouse.c
r867e2555 r925a21e 39 39 #include <async.h> 40 40 #include <errno.h> 41 #include < devmap.h>41 #include <loc.h> 42 42 #include <input.h> 43 43 #include <mouse_port.h> … … 82 82 static int chardev_port_init(mouse_dev_t *mdev) 83 83 { 84 devmap_handle_t handle;84 service_id_t service_id; 85 85 unsigned int i; 86 86 int rc; … … 89 89 90 90 for (i = 0; i < num_devs; i++) { 91 rc = devmap_device_get_handle(in_devs[i], &handle, 0);91 rc = loc_service_get_id(in_devs[i], &service_id, 0); 92 92 if (rc == EOK) 93 93 break; … … 99 99 } 100 100 101 dev_sess = devmap_device_connect(EXCHANGE_ATOMIC, handle,101 dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 102 102 IPC_FLAG_BLOCKING); 103 103 if (dev_sess == NULL) { -
uspace/srv/hid/input/port/ns16550.c
r867e2555 r925a21e 38 38 #include <ipc/irc.h> 39 39 #include <async.h> 40 #include <async_obsolete.h>41 40 #include <sysinfo.h> 42 41 #include <input.h> … … 158 157 kbd_push_data(kbd_dev, IPC_GET_ARG2(*call)); 159 158 160 if (irc_service) 161 async_obsolete_msg_1(irc_phone, IRC_CLEAR_INTERRUPT, 162 IPC_GET_IMETHOD(*call)); 159 if (irc_service) { 160 async_exch_t *exch = async_exchange_begin(irc_sess); 161 async_msg_1(exch, IRC_CLEAR_INTERRUPT, IPC_GET_IMETHOD(*call)); 162 async_exchange_end(exch); 163 } 163 164 } 164 165 -
uspace/srv/hid/input/proto/mousedev.c
r867e2555 r925a21e 44 44 #include <ipc/mouseev.h> 45 45 #include <input.h> 46 #include <loc.h> 46 47 #include <mouse.h> 47 48 #include <mouse_port.h> 48 49 #include <mouse_proto.h> 50 #include <sys/typefmt.h> 49 51 50 52 /** Mousedev softstate */ … … 55 57 /** Session to mouse device */ 56 58 async_sess_t *sess; 57 58 /** File descriptor of open mousedev device */59 int fd;60 59 } mousedev_t; 61 60 … … 67 66 68 67 mousedev->mouse_dev = mdev; 69 mousedev->fd = -1;70 68 71 69 return mousedev; … … 76 74 if (mousedev->sess != NULL) 77 75 async_hangup(mousedev->sess); 78 79 if (mousedev->fd >= 0)80 close(mousedev->fd);81 76 82 77 free(mousedev); … … 122 117 static int mousedev_proto_init(mouse_dev_t *mdev) 123 118 { 124 const char *pathname = mdev->dev_path; 125 126 int fd = open(pathname, O_RDWR); 127 if (fd < 0) 128 return -1; 129 130 async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd); 119 async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, 120 mdev->svc_id, 0); 131 121 if (sess == NULL) { 132 printf("%s: Failed starting session with '%s'\n", NAME, pathname);133 close(fd);122 printf("%s: Failed starting session with '%s'\n", NAME, 123 mdev->svc_name); 134 124 return -1; 135 125 } … … 138 128 if (mousedev == NULL) { 139 129 printf("%s: Failed allocating device structure for '%s'.\n", 140 NAME, pathname);130 NAME, mdev->svc_name); 141 131 return -1; 142 132 } 143 133 144 mousedev->fd = fd;145 134 mousedev->sess = sess; 146 135 147 136 async_exch_t *exch = async_exchange_begin(sess); 148 137 if (exch == NULL) { 149 printf("%s: Failed starting exchange with '%s'.\n", NAME, pathname); 138 printf("%s: Failed starting exchange with '%s'.\n", NAME, 139 mdev->svc_name); 150 140 mousedev_destroy(mousedev); 151 141 return -1; … … 157 147 if (rc != EOK) { 158 148 printf("%s: Failed creating callback connection from '%s'.\n", 159 NAME, pathname);149 NAME, mdev->svc_name); 160 150 mousedev_destroy(mousedev); 161 151 return -1; -
uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.c
r867e2555 r925a21e 39 39 #include <ddi.h> 40 40 #include <libarch/ddi.h> 41 #include < devmap.h>41 #include <loc.h> 42 42 #include <io/console.h> 43 43 #include <vfs/vfs.h> 44 44 #include <ipc/mouseev.h> 45 45 #include <async.h> 46 #include <async_obsolete.h>47 46 #include <unistd.h> 48 47 #include <stdio.h> … … 53 52 #include "s3c24xx_ts.h" 54 53 55 // FIXME: remove this header 56 #include <kernel/ipc/ipc_methods.h> 57 58 #define NAME "s3c24ser" 59 #define NAMESPACE "hid" 54 #define NAME "s3c24ser" 55 #define NAMESPACE "hid" 60 56 61 57 static irq_cmd_t ts_irq_cmds[] = { … … 90 86 printf(NAME ": S3C24xx touchscreen driver\n"); 91 87 92 rc = devmap_driver_register(NAME, s3c24xx_ts_connection);88 rc = loc_server_register(NAME, s3c24xx_ts_connection); 93 89 if (rc < 0) { 94 90 printf(NAME ": Unable to register driver.\n"); … … 103 99 return -1; 104 100 105 rc = devmap_device_register(NAMESPACE "/mouse", &ts->devmap_handle);101 rc = loc_service_register(NAMESPACE "/mouse", &ts->service_id); 106 102 if (rc != EOK) { 107 103 printf(NAME ": Unable to register device %s.\n", … … 134 130 135 131 ts->io = vaddr; 136 ts->client_ phone = -1;132 ts->client_sess = NULL; 137 133 ts->state = ts_wait_pendown; 138 134 ts->last_x = 0; … … 284 280 button = 1; 285 281 press = 0; 286 async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press); 282 283 async_exch_t *exch = async_exchange_begin(ts->client_sess); 284 async_msg_2(exch, MOUSEEV_BUTTON_EVENT, button, press); 285 async_exchange_end(exch); 287 286 288 287 s3c24xx_ts_wait_for_int_mode(ts, updn_down); … … 325 324 326 325 /* Send notifications to client. */ 327 async_obsolete_msg_2(ts->client_phone, MOUSEEV_MOVE_EVENT, dx, dy); 328 async_obsolete_msg_2(ts->client_phone, MOUSEEV_BUTTON_EVENT, button, press); 326 async_exch_t *exch = async_exchange_begin(ts->client_sess); 327 async_msg_2(exch, MOUSEEV_MOVE_EVENT, dx, dy); 328 async_msg_2(exch, MOUSEEV_BUTTON_EVENT, button, press); 329 async_exchange_end(exch); 329 330 330 331 ts->last_x = x_pos; … … 377 378 void *arg) 378 379 { 379 ipc_callid_t callid;380 ipc_call_t call;381 int retval;382 383 380 async_answer_0(iid, EOK); 384 385 while (1) { 386 callid = async_get_call(&call); 381 382 while (true) { 383 ipc_call_t call; 384 ipc_callid_t callid = async_get_call(&call); 387 385 388 386 if (!IPC_GET_IMETHOD(call)) { 389 if (ts->client_ phone != -1) {390 async_ obsolete_hangup(ts->client_phone);391 ts->client_ phone = -1;387 if (ts->client_sess != NULL) { 388 async_hangup(ts->client_sess); 389 ts->client_sess = NULL; 392 390 } 393 391 394 392 async_answer_0(callid, EOK); 395 393 return; 396 394 } 397 395 398 switch (IPC_GET_IMETHOD(call)) { 399 case IPC_M_CONNECT_TO_ME: 400 if (ts->client_phone != -1) { 401 retval = ELIMIT; 402 break; 403 } 404 ts->client_phone = IPC_GET_ARG5(call); 405 retval = 0; 406 break; 407 default: 408 retval = EINVAL; 409 } 410 async_answer_0(callid, retval); 396 async_sess_t *sess = 397 async_callback_receive_start(EXCHANGE_SERIALIZE, &call); 398 if (sess != NULL) { 399 if (ts->client_sess == NULL) { 400 ts->client_sess = sess; 401 async_answer_0(callid, EOK); 402 } else 403 async_answer_0(callid, ELIMIT); 404 } else 405 async_answer_0(callid, EINVAL); 411 406 } 412 407 } -
uspace/srv/hid/s3c24xx_ts/s3c24xx_ts.h
r867e2555 r925a21e 39 39 40 40 #include <sys/types.h> 41 #include <async.h> 41 42 42 43 /** S3C24xx ADC and touch-screen I/O */ … … 121 122 s3c24xx_adc_io_t *io; 122 123 123 /** Callback phoneto the client */124 int client_phone;124 /** Callback session to the client */ 125 async_sess_t *client_sess; 125 126 126 /** Device handle*/127 devmap_handle_t devmap_handle;127 /** Service ID */ 128 service_id_t service_id; 128 129 129 130 /** Device/driver state */
Note:
See TracChangeset
for help on using the changeset viewer.
