1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License. 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License. 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/mman.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/fb.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/kd.h> 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 28ed8a7d84428ec945c48b6b53dc5a3a18fabaf683Colin Cross#include "log.h" 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef ANDROID 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/memory.h> 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid android_memset16(void *_ptr, unsigned short val, unsigned count) 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short *ptr = _ptr; 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count >>= 1; 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(count--) 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ptr++ = val; 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct FB { 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short *bits; 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned size; 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct fb_fix_screeninfo fi; 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct fb_var_screeninfo vi; 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define fb_width(fb) ((fb)->vi.xres) 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define fb_height(fb) ((fb)->vi.yres) 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define fb_size(fb) ((fb)->vi.xres * (fb)->vi.yres * 2) 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int fb_open(struct FB *fb) 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fb->fd = open("/dev/graphics/fb0", O_RDWR); 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fb->fd < 0) 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto fail; 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto fail; 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project MAP_SHARED, fb->fd, 0); 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fb->bits == MAP_FAILED) 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto fail; 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail: 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fb->fd); 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fb_close(struct FB *fb) 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project munmap(fb->bits, fb_size(fb)); 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fb->fd); 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* there's got to be a more portable way to do this ... */ 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void fb_update(struct FB *fb) 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fb->vi.yoffset = 1; 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fb->vi.yoffset = 0; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int vt_set_mode(int graphics) 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd, r; 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = open("/dev/tty0", O_RDWR | O_SYNC); 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT)); 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return r; 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint load_565rle_image(char *fn) 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct FB fb; 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned short *data, *bits, *ptr; 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned count, max; 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (vt_set_mode(1)) 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = open(fn, O_RDONLY); 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) { 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ERROR("cannot open '%s'\n", fn); 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto fail_restore_text; 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fstat(fd, &s) < 0) { 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto fail_close_file; 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (data == MAP_FAILED) 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto fail_close_file; 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fb_open(&fb)) 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto fail_unmap_data; 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project max = fb_width(&fb) * fb_height(&fb); 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr = data; 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count = s.st_size; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bits = fb.bits; 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while (count > 3) { 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned n = ptr[0]; 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (n > max) 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project android_memset16(bits, ptr[1], n << 1); 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bits += n; 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project max -= n; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += 2; 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count -= 4; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project munmap(data, s.st_size); 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fb_update(&fb); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fb_close(&fb); 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unlink(fn); 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail_unmap_data: 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project munmap(data, s.st_size); 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail_close_file: 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail_restore_text: 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project vt_set_mode(0); 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 164