1/** 2 * \file 3 * \brief Framebuffer glue 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18#include <barrelfish/barrelfish.h> 19#include <if/fb_defs.h> 20#include <if/keyboard_defs.h> 21#include <barrelfish/nameservice_client.h> 22#include <vfs/vfs.h> 23#include <vfs/vfs_path.h> 24 25#include "slideshow.h" 26 27static struct fb_binding *fb_client; 28static struct keyboard_binding *kb_client; 29 30static char *vidmem; /// Pointer to video memory 31 32// original video mode 33static uint16_t origmode; 34static bool origlinear; 35static char fontbackup[65536]; 36 37void wait_for_vsync(void) 38{ 39 errval_t err = fb_client->rpc_tx_vtbl.vsync(fb_client); 40 assert(err_is_ok(err)); 41} 42 43void quit(void) 44{ 45 errval_t err, ret; 46 47 // Restore font backup 48 memcpy(vidmem, fontbackup, 65536); 49 50 err = fb_client->rpc_tx_vtbl.set_vesamode(fb_client, origmode, origlinear, 51 true, &ret); 52 assert(err_is_ok(err)); 53 assert(err_is_ok(ret)); 54 exit(0); 55} 56 57static struct keyboard_rx_vtbl keyboard_rx_vtbl = { 58 .key_event = keyboard_key_event, 59}; 60 61static void keyboard_connected_callback(void *st, errval_t err, 62 struct keyboard_binding *cl) 63{ 64 assert(err_is_ok(err)); 65 cl->rx_vtbl = keyboard_rx_vtbl; 66 kb_client = cl; 67} 68 69static void fb_connected_callback(void *st, errval_t err, struct fb_binding *b) 70{ 71 assert(err_is_ok(err)); 72 73 fb_client = b; 74 fb_rpc_client_init(fb_client); 75} 76 77static void start_keyboard_client(void) 78{ 79 iref_t iref; 80 errval_t err; 81 82 err = nameservice_blocking_lookup("keyboard", &iref); 83 if (err_is_fail(err)) { 84 fprintf(stderr, "slideshow: could not connect to the keyboard driver.\n"); 85 abort(); 86 } 87 assert(iref != 0); 88 89 err = keyboard_bind(iref, keyboard_connected_callback, NULL, 90 get_default_waitset(), IDC_BIND_FLAGS_DEFAULT); 91 assert(err_is_ok(err)); 92} 93 94static int fb_client_connect(void) 95{ 96 iref_t iref; 97 errval_t err; 98 99 err = nameservice_blocking_lookup("framebuffer", &iref); 100 if (err_is_fail(err)) { 101 DEBUG_ERR(err, "could not lookup IREF for framebuffer driver"); 102 abort(); 103 } 104 105 err = fb_bind(iref, fb_connected_callback, NULL, get_default_waitset(), 106 IDC_BIND_FLAG_RPC_CAP_TRANSFER); 107 if (err_is_fail(err)) { 108 DEBUG_ERR(err, "could not connect to framebuffer driver"); 109 abort(); 110 } 111 112 return 0; 113} 114 115static int keyboard_client_connect(void) 116{ 117 start_keyboard_client(); 118 while (kb_client == NULL) { 119 messages_wait_and_handle_next(); 120 } 121 return 0; 122} 123 124static int cmpstringp(const void *p1, const void *p2) 125{ 126 return strcmp(*(char * const *)p1, *(char * const *)p2); 127} 128 129static void load_slides(const char *indir) 130{ 131 errval_t err; 132 133 // Make dir relative to '/' 134 char *dir = vfs_path_mkabsolute("/", indir); 135 assert(dir != NULL); 136 137 vfs_handle_t dh; 138 err = vfs_opendir(dir, &dh); 139 if (err_is_fail(err)) { 140 USER_PANIC_ERR(err, "error opening directory\n"); 141 } 142 143 char *paths[MAX_SLIDES] = { NULL }; 144 for(;;) { 145 struct vfs_fileinfo info; 146 char *name; 147 148 err = vfs_dir_read_next(dh, &name, &info); 149 if (err_is_fail(err)) { 150 if (err_no(err) == FS_ERR_INDEX_BOUNDS) { 151 break; 152 } else { 153 USER_PANIC_ERR(err, "error reading directory\n"); 154 } 155 } 156 157 if (info.type == VFS_DIRECTORY) { 158 printf("Skipped %s", name); 159 free(name); 160 continue; 161 } 162 163 paths[nslides] = vfs_path_mkabsolute(dir, name); 164 assert(paths[nslides] != NULL); 165 free(name); 166 167 if (++nslides == MAX_SLIDES) { 168 printf("slideshow: reached MAX_SLIDES (%d)\n", MAX_SLIDES); 169 break; 170 } 171 } 172 173 // Sort filenames 174 qsort(paths, nslides, sizeof(char *), cmpstringp); 175 176 for(int i = 0; i < nslides; i++) { 177 printf("Opening %s\n", paths[i]); 178 179 vfs_handle_t fh; 180 err = vfs_open(paths[i], &fh); 181 if (err_is_fail(err)) { 182 USER_PANIC_ERR(err, "failed to open '%s'\n", paths[i]); 183 } 184 185 struct vfs_fileinfo info; 186 err = vfs_stat(fh, &info); 187 if (err_is_fail(err)) { 188 USER_PANIC_ERR(err, "failed to stat '%s'\n", paths[i]); 189 } 190 191 void *buf = malloc(info.size); 192 assert(buf != NULL); 193 194 size_t len; 195 err = vfs_read(fh, buf, info.size, &len); 196 if (err_is_fail(err)) { 197 USER_PANIC_ERR(err, "vfs_read '%s' failed\n", paths[i]); 198 } else if (len != info.size) { 199 USER_PANIC("short read %lu != %lu\n", len, info.size); 200 } 201 202 vfs_close(fh); 203 free(paths[i]); 204 205 slide[i] = buf; 206 slide_length[i] = info.size; 207 } 208 209 vfs_closedir(dh); 210 free(dir); 211} 212 213int main(int argc, char *argv[]) 214{ 215 int xres, yres, bpp; 216 errval_t err, ret; 217 218 // Parse commandline 219 if(argc < 5) { 220 fprintf(stderr, "Usage: %s <xres> <yres> <bpp> <slides path>\n", 221 argv[0]); 222 return EXIT_FAILURE; 223 } 224 225 xres = atoi(argv[1]); 226 yres = atoi(argv[2]); 227 bpp = atoi(argv[3]); 228 229 vfs_init(); 230 231 // Connect to framebuffer driver 232 fb_client_connect(); 233 234 // Connect to keyboard driver 235 keyboard_client_connect(); 236 237 // Load the slides off multiboot 238 load_slides(argv[4]); 239 240 // Get current video mode 241 err = fb_client->rpc_tx_vtbl.get_vesamode(fb_client, &origmode, &origlinear, &ret); 242 assert(err_is_ok(err)); 243 assert(err_is_ok(ret)); 244 245 // Set videomode 246 err = fb_client->rpc_tx_vtbl.set_videomode(fb_client, xres, yres, bpp, &ret); 247 assert(err_is_ok(err)); 248 assert(err_is_ok(ret)); 249 250 // Get and map framebuffer 251 struct capref fbcap; 252 uint32_t fboffset; 253 err = fb_client->rpc_tx_vtbl.get_framebuffer(fb_client, &ret, &fbcap, &fboffset); 254 assert(err_is_ok(err)); 255 assert(err_is_ok(ret)); 256 257 struct frame_identity fbid = { .base = 0, .bytes = 0 }; 258 err = invoke_frame_identify(fbcap, &fbid); 259 assert(err_is_ok(err)); 260 err = vspace_map_one_frame((void**)&vidmem, fbid.bytes, fbcap, 261 NULL, NULL); 262 assert(err_is_ok(err)); 263 264 vidmem += fboffset; 265 266 // Save textmode bit of framebuffer and hopefully capture the font 267 memcpy(fontbackup, vidmem, 65536); 268 269 // Start the show 270 slideshow(vidmem, xres, yres, bpp); 271 messages_handler_loop(); 272} 273