diff options
| author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2013-03-01 17:08:40 +0100 | 
|---|---|---|
| committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2013-03-01 17:08:40 +0100 | 
| commit | c8998259fd683e7cc7c6dee88067baa9af477a03 (patch) | |
| tree | 2dd7840302b795bebaee4852ba92e064d6ecb855 /system/core | |
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'system/core')
| -rw-r--r-- | system/core/0001-init-Add-support-for-DRM-KMS-devices.patch | 30 | ||||
| -rw-r--r-- | system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch | 756 | 
2 files changed, 786 insertions, 0 deletions
diff --git a/system/core/0001-init-Add-support-for-DRM-KMS-devices.patch b/system/core/0001-init-Add-support-for-DRM-KMS-devices.patch new file mode 100644 index 0000000..89520bb --- /dev/null +++ b/system/core/0001-init-Add-support-for-DRM-KMS-devices.patch @@ -0,0 +1,30 @@ +From fbc8ecd836449f9734f6088a86b247d302d67929 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Sat, 15 Sep 2012 03:54:06 +0200 +Subject: [PATCH 1/2] init: Add support for DRM/KMS devices + +Create the associated devices nodes in /dev/dri/. + +Change-Id: Ib53681bb2219dc0c349837ecc9797677d30f801e +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +--- + init/devices.c |    3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/init/devices.c b/init/devices.c +index 3b4d369..970a2c2 100644 +--- a/init/devices.c ++++ b/init/devices.c +@@ -595,6 +595,9 @@ static void handle_generic_device_event(struct uevent *uevent) +              /* ignore other USB events */ +              return; +          } ++     } else if (!strncmp(uevent->subsystem, "drm", 3)) { ++         base = "/dev/dri/"; ++         make_dir(base, 0755); +      } else if (!strncmp(uevent->subsystem, "graphics", 8)) { +          base = "/dev/graphics/"; +          make_dir(base, 0755); +--  +1.7.8.6 + diff --git a/system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch b/system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch new file mode 100644 index 0000000..db7110f --- /dev/null +++ b/system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch @@ -0,0 +1,756 @@ +From a99e4e5fea639e2d163071011c2b866dde1e848b Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Sat, 15 Sep 2012 03:53:03 +0200 +Subject: [PATCH] init: Support DRM/KMS to display the boot logo + +Change-Id: Ia42ef34a65f8aeebeedb947b2d7067154720f5d2 +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +--- + init/Android.mk |    2 +- + init/logo-drm.c |  379 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + init/logo-fb.c  |  163 ++++++++++++++++++++++++ + init/logo.c     |  163 ------------------------ + 4 files changed, 543 insertions(+), 164 deletions(-) + create mode 100644 init/logo-drm.c + create mode 100644 init/logo-fb.c + delete mode 100644 init/logo.c + +diff --git a/init/Android.mk b/init/Android.mk +index f3287a8..485fc7f 100644 +--- a/init/Android.mk ++++ b/init/Android.mk +@@ -10,7 +10,7 @@ LOCAL_SRC_FILES:= \ + 	property_service.c \ + 	util.c \ + 	parser.c \ +-	logo.c \ ++	logo-drm.c \ + 	keychords.c \ + 	signal_handler.c \ + 	init_parser.c \ +diff --git a/init/logo-drm.c b/init/logo-drm.c +new file mode 100644 +index 0000000..22ecf08 +--- /dev/null ++++ b/init/logo-drm.c +@@ -0,0 +1,379 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ *      http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include <stdbool.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <fcntl.h> ++#include <sys/mman.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++ ++#include <linux/kd.h> ++ ++#include <drm/drm.h> ++#include <drm/drm_mode.h> ++#include <drm/drm_fourcc.h> ++ ++#include "log.h" ++ ++#ifdef ANDROID ++#include <cutils/memory.h> ++#else ++void android_memset16(void *_ptr, unsigned short val, unsigned count) ++{ ++	unsigned short *ptr = _ptr; ++	count >>= 1; ++	while(count--) ++		*ptr++ = val; ++} ++#endif ++ ++struct drm { ++	int fd; ++	struct { ++		uint32_t crtc; ++		uint32_t connector; ++		struct drm_mode_modeinfo mode; ++	} kms; ++	struct { ++		unsigned int handle; ++		void *map; ++		size_t size; ++		size_t pitch; ++	} bo; ++	struct { ++		unsigned int id; ++	} fb; ++}; ++ ++#define U642VOID(x)	((void *)(unsigned long)(x)) ++#define VOID2U64(x)	((uint64_t)(unsigned long)(x)) ++ ++static void drm_close(struct drm *drm, bool destroy) ++{ ++	struct drm_mode_destroy_dumb dumb; ++	uint32_t id; ++ ++	if (drm->bo.map) ++		munmap(drm->bo.map, drm->bo.size); ++ ++	if (destroy) { ++		if (drm->fb.id) { ++			id = drm->fb.id; ++			ioctl(drm->fd, DRM_IOCTL_MODE_RMFB, &id); ++		} ++ ++		if (drm->bo.handle) { ++			memset(&dumb, 0, sizeof dumb); ++			dumb.handle = drm->bo.handle; ++			ioctl(drm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, dumb); ++		} ++	} ++ ++	close(drm->fd); ++} ++ ++static int drm_get_resources(struct drm *drm) ++{ ++	struct drm_mode_card_res counts; ++	struct drm_mode_card_res res; ++	int ret; ++ ++retry: ++	memset(&res, 0, sizeof res); ++	ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETRESOURCES, &res); ++	if (ret < 0) ++		return -1; ++ ++	counts = res; ++	memset(&res, 0, sizeof res); ++ ++	if (counts.count_crtcs) { ++		res.count_crtcs = counts.count_crtcs; ++		res.crtc_id_ptr = VOID2U64(malloc(res.count_crtcs * ++						  sizeof(uint32_t))); ++		if (!res.crtc_id_ptr) { ++			ret = -1; ++			goto done; ++		} ++	} ++ ++	if (counts.count_connectors) { ++		res.count_connectors = counts.count_connectors; ++		res.connector_id_ptr = VOID2U64(malloc(res.count_connectors * ++						       sizeof(uint32_t))); ++		if (!res.connector_id_ptr) { ++			ret = -1; ++			goto done; ++		} ++	} ++ ++	ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETRESOURCES, &res); ++	if (ret < 0) ++		goto done; ++ ++	/* The number of available connectors and etc may have changed with a ++	 * hotplug event in between the ioctls, in which case the field is ++	 * silently ignored by the kernel. ++	 */ ++	if (counts.count_crtcs < res.count_crtcs || ++	    counts.count_connectors < res.count_connectors) { ++		free(U642VOID(res.crtc_id_ptr)); ++		free(U642VOID(res.connector_id_ptr)); ++		goto retry; ++	} ++ ++	/* We need at least one CRTC and one connector. */ ++	if (res.count_crtcs == 0 || res.count_connectors == 0) { ++		ret = -1; ++		goto done; ++	} ++ ++	drm->kms.crtc = *(uint32_t *)U642VOID(res.crtc_id_ptr); ++	drm->kms.connector = *(uint32_t *)U642VOID(res.connector_id_ptr); ++ ++	ret = 0; ++ ++done: ++	free(U642VOID(res.crtc_id_ptr)); ++	free(U642VOID(res.connector_id_ptr)); ++ ++	return ret; ++} ++ ++static int drm_get_modes(struct drm *drm) ++{ ++	struct drm_mode_get_connector counts; ++	struct drm_mode_get_connector conn; ++	int ret; ++ ++retry: ++	memset(&conn, 0, sizeof conn); ++	conn.connector_id = drm->kms.connector; ++ ++	ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn); ++	if (ret < 0) ++		return -1; ++ ++	counts = conn; ++	memset(&conn, 0, sizeof conn); ++	conn.connector_id = drm->kms.connector; ++ ++	if (counts.count_modes) { ++		conn.count_modes = counts.count_modes; ++		conn.modes_ptr = VOID2U64(malloc(conn.count_modes * ++						 sizeof(struct drm_mode_modeinfo))); ++		if (!conn.modes_ptr) { ++			ret = -1; ++			goto done; ++		} ++	} ++ ++	ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn); ++	if (ret < 0) ++		goto done; ++ ++	/* The number of available connectors and etc may have changed with a ++	 * hotplug event in between the ioctls, in which case the field is ++	 * silently ignored by the kernel. ++	 */ ++	if (counts.count_modes < conn.count_modes) { ++		free(U642VOID(conn.modes_ptr)); ++		goto retry; ++	} ++ ++	/* We need at least one mode. */ ++	if (conn.count_modes == 0) { ++		ret = -1; ++		goto done; ++	} ++ ++	drm->kms.mode = *(struct drm_mode_modeinfo *)U642VOID(conn.modes_ptr); ++ ++	ret = 0; ++ ++done: ++	free(U642VOID(conn.modes_ptr)); ++ ++	return ret; ++} ++ ++static int drm_open(struct drm *drm) ++{ ++	struct drm_get_cap cap = { DRM_CAP_DUMB_BUFFER, 0 }; ++	struct drm_mode_create_dumb dumb; ++	struct drm_mode_map_dumb map; ++	struct drm_mode_fb_cmd2 fb; ++	void *mem; ++	int ret; ++ ++	drm->fd = open("/dev/dri/card0", O_RDWR); ++	if (drm->fd < 0) ++		return -1; ++ ++	/* Verify that the driver supports dumb buffers. */ ++	ret = ioctl(drm->fd, DRM_IOCTL_GET_CAP, &cap); ++	if (ret < 0) ++		goto error; ++	if (!cap.value) ++		goto error; ++ ++	ret = drm_get_resources(drm); ++	if (ret < 0) ++		goto error; ++ ++	ret = drm_get_modes(drm); ++	if (ret < 0) ++		goto error; ++ ++	/* Create a buffer and map it. */ ++	memset(&dumb, 0, sizeof dumb); ++	dumb.bpp = 16; ++	dumb.width = drm->kms.mode.hdisplay; ++	dumb.height = drm->kms.mode.vdisplay; ++ ++	ret = ioctl(drm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb); ++	if (ret < 0) ++		goto error; ++ ++	drm->bo.handle = dumb.handle; ++	drm->bo.size = dumb.size; ++	drm->bo.pitch = dumb.pitch; ++ ++	memset(&map, 0, sizeof map); ++	map.handle = drm->bo.handle; ++ ++	ret = ioctl(drm->fd, DRM_IOCTL_MODE_MAP_DUMB, &map); ++	if (ret < 0) ++		goto error; ++ ++	mem = mmap(0, drm->bo.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm->fd, ++		   map.offset); ++	if (mem == MAP_FAILED) ++		goto error; ++ ++	drm->bo.map = mem; ++ ++	/* Create a frame buffer. */ ++	memset(&fb, 0, sizeof fb); ++	fb.width = drm->kms.mode.hdisplay; ++	fb.height = drm->kms.mode.vdisplay; ++	fb.pixel_format = DRM_FORMAT_RGB565; ++	fb.handles[0] = drm->bo.handle; ++	fb.pitches[0] = drm->bo.pitch; ++ ++	ret = ioctl (drm->fd, DRM_IOCTL_MODE_ADDFB2, &fb); ++	if (ret < 0) ++		goto error; ++ ++	drm->fb.id = fb.fb_id; ++ ++	return 0; ++ ++error: ++	drm_close(drm, true); ++	return -1; ++} ++ ++static void drm_update(struct drm *drm) ++{ ++	struct drm_mode_crtc crtc; ++	uint32_t connector = drm->kms.connector; ++	int ret; ++ ++	memset(&crtc, 0, sizeof crtc); ++	crtc.crtc_id = drm->kms.crtc; ++	crtc.fb_id = drm->fb.id; ++	crtc.set_connectors_ptr = VOID2U64(&connector); ++	crtc.count_connectors = 1; ++	crtc.mode = drm->kms.mode; ++	crtc.mode_valid = 1; ++ ++	ioctl(drm->fd, DRM_IOCTL_MODE_SETCRTC, &crtc); ++} ++ ++static int vt_set_mode(int graphics) ++{ ++	int fd, r; ++	fd = open("/dev/tty0", O_RDWR | O_SYNC); ++	if (fd < 0) ++		return -1; ++	r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT)); ++	close(fd); ++	return r; ++} ++ ++/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ ++ ++int load_565rle_image(char *fn) ++{ ++	struct drm drm; ++	struct stat s; ++	unsigned short *data, *bits, *ptr; ++	unsigned count, max; ++	int fd; ++ ++	if (vt_set_mode(1)) ++		return -1; ++ ++	fd = open(fn, O_RDONLY); ++	if (fd < 0) { ++		ERROR("cannot open '%s'\n", fn); ++		goto fail_restore_text; ++	} ++ ++	if (fstat(fd, &s) < 0) ++		goto fail_close_file; ++ ++	data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); ++	if (data == MAP_FAILED) ++		goto fail_close_file; ++ ++	if (drm_open(&drm)) ++		goto fail_unmap_data; ++ ++	max = drm.bo.size; ++	ptr = data; ++	count = s.st_size; ++	bits = drm.bo.map; ++	while (count > 3) { ++		unsigned n = ptr[0]; ++		if (n > max) ++			break; ++		android_memset16(bits, ptr[1], n << 1); ++		bits += n; ++		max -= n; ++		ptr += 2; ++		count -= 4; ++	} ++ ++	munmap(data, s.st_size); ++	drm_update(&drm); ++	drm_close(&drm, false); ++	close(fd); ++	unlink(fn); ++	return 0; ++ ++fail_unmap_data: ++	munmap(data, s.st_size); ++fail_close_file: ++	close(fd); ++fail_restore_text: ++	vt_set_mode(0); ++	return -1; ++} +diff --git a/init/logo-fb.c b/init/logo-fb.c +new file mode 100644 +index 0000000..614224c +--- /dev/null ++++ b/init/logo-fb.c +@@ -0,0 +1,163 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ *      http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <fcntl.h> ++#include <sys/mman.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++ ++#include <linux/fb.h> ++#include <linux/kd.h> ++ ++#include "log.h" ++ ++#ifdef ANDROID ++#include <cutils/memory.h> ++#else ++void android_memset16(void *_ptr, unsigned short val, unsigned count) ++{ ++    unsigned short *ptr = _ptr; ++    count >>= 1; ++    while(count--) ++        *ptr++ = val; ++} ++#endif ++ ++struct FB { ++    unsigned short *bits; ++    unsigned size; ++    int fd; ++    struct fb_fix_screeninfo fi; ++    struct fb_var_screeninfo vi; ++}; ++ ++#define fb_width(fb) ((fb)->vi.xres) ++#define fb_height(fb) ((fb)->vi.yres) ++#define fb_size(fb) ((fb)->vi.xres * (fb)->vi.yres * 2) ++ ++static int fb_open(struct FB *fb) ++{ ++    fb->fd = open("/dev/graphics/fb0", O_RDWR); ++    if (fb->fd < 0) ++        return -1; ++ ++    if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) ++        goto fail; ++    if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) ++        goto fail; ++ ++    fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE,  ++                    MAP_SHARED, fb->fd, 0); ++    if (fb->bits == MAP_FAILED) ++        goto fail; ++ ++    return 0; ++ ++fail: ++    close(fb->fd); ++    return -1; ++} ++ ++static void fb_close(struct FB *fb) ++{ ++    munmap(fb->bits, fb_size(fb)); ++    close(fb->fd); ++} ++ ++/* there's got to be a more portable way to do this ... */ ++static void fb_update(struct FB *fb) ++{ ++    fb->vi.yoffset = 1; ++    ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); ++    fb->vi.yoffset = 0; ++    ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); ++} ++ ++static int vt_set_mode(int graphics) ++{ ++    int fd, r; ++    fd = open("/dev/tty0", O_RDWR | O_SYNC); ++    if (fd < 0) ++        return -1; ++    r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT)); ++    close(fd); ++    return r; ++} ++ ++/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ ++ ++int load_565rle_image(char *fn) ++{ ++    struct FB fb; ++    struct stat s; ++    unsigned short *data, *bits, *ptr; ++    unsigned count, max; ++    int fd; ++ ++    if (vt_set_mode(1))  ++        return -1; ++ ++    fd = open(fn, O_RDONLY); ++    if (fd < 0) { ++        ERROR("cannot open '%s'\n", fn); ++        goto fail_restore_text; ++    } ++ ++    if (fstat(fd, &s) < 0) { ++        goto fail_close_file; ++    } ++ ++    data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); ++    if (data == MAP_FAILED) ++        goto fail_close_file; ++ ++    if (fb_open(&fb)) ++        goto fail_unmap_data; ++ ++    max = fb_width(&fb) * fb_height(&fb); ++    ptr = data; ++    count = s.st_size; ++    bits = fb.bits; ++    while (count > 3) { ++        unsigned n = ptr[0]; ++        if (n > max) ++            break; ++        android_memset16(bits, ptr[1], n << 1); ++        bits += n; ++        max -= n; ++        ptr += 2; ++        count -= 4; ++    } ++ ++    munmap(data, s.st_size); ++    fb_update(&fb); ++    fb_close(&fb); ++    close(fd); ++    unlink(fn); ++    return 0; ++ ++fail_unmap_data: ++    munmap(data, s.st_size);     ++fail_close_file: ++    close(fd); ++fail_restore_text: ++    vt_set_mode(0); ++    return -1; ++} ++ +diff --git a/init/logo.c b/init/logo.c +deleted file mode 100644 +index 614224c..0000000 +--- a/init/logo.c ++++ /dev/null +@@ -1,163 +0,0 @@ +-/* +- * Copyright (C) 2008 The Android Open Source Project +- * +- * Licensed under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. +- * You may obtain a copy of the License at +- * +- *      http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software +- * distributed under the License is distributed on an "AS IS" BASIS, +- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- * See the License for the specific language governing permissions and +- * limitations under the License. +- */ +- +-#include <stdio.h> +-#include <stdlib.h> +-#include <unistd.h> +-#include <fcntl.h> +-#include <sys/mman.h> +-#include <sys/stat.h> +-#include <sys/types.h> +- +-#include <linux/fb.h> +-#include <linux/kd.h> +- +-#include "log.h" +- +-#ifdef ANDROID +-#include <cutils/memory.h> +-#else +-void android_memset16(void *_ptr, unsigned short val, unsigned count) +-{ +-    unsigned short *ptr = _ptr; +-    count >>= 1; +-    while(count--) +-        *ptr++ = val; +-} +-#endif +- +-struct FB { +-    unsigned short *bits; +-    unsigned size; +-    int fd; +-    struct fb_fix_screeninfo fi; +-    struct fb_var_screeninfo vi; +-}; +- +-#define fb_width(fb) ((fb)->vi.xres) +-#define fb_height(fb) ((fb)->vi.yres) +-#define fb_size(fb) ((fb)->vi.xres * (fb)->vi.yres * 2) +- +-static int fb_open(struct FB *fb) +-{ +-    fb->fd = open("/dev/graphics/fb0", O_RDWR); +-    if (fb->fd < 0) +-        return -1; +- +-    if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) +-        goto fail; +-    if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) +-        goto fail; +- +-    fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE,  +-                    MAP_SHARED, fb->fd, 0); +-    if (fb->bits == MAP_FAILED) +-        goto fail; +- +-    return 0; +- +-fail: +-    close(fb->fd); +-    return -1; +-} +- +-static void fb_close(struct FB *fb) +-{ +-    munmap(fb->bits, fb_size(fb)); +-    close(fb->fd); +-} +- +-/* there's got to be a more portable way to do this ... */ +-static void fb_update(struct FB *fb) +-{ +-    fb->vi.yoffset = 1; +-    ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); +-    fb->vi.yoffset = 0; +-    ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); +-} +- +-static int vt_set_mode(int graphics) +-{ +-    int fd, r; +-    fd = open("/dev/tty0", O_RDWR | O_SYNC); +-    if (fd < 0) +-        return -1; +-    r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT)); +-    close(fd); +-    return r; +-} +- +-/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ +- +-int load_565rle_image(char *fn) +-{ +-    struct FB fb; +-    struct stat s; +-    unsigned short *data, *bits, *ptr; +-    unsigned count, max; +-    int fd; +- +-    if (vt_set_mode(1))  +-        return -1; +- +-    fd = open(fn, O_RDONLY); +-    if (fd < 0) { +-        ERROR("cannot open '%s'\n", fn); +-        goto fail_restore_text; +-    } +- +-    if (fstat(fd, &s) < 0) { +-        goto fail_close_file; +-    } +- +-    data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); +-    if (data == MAP_FAILED) +-        goto fail_close_file; +- +-    if (fb_open(&fb)) +-        goto fail_unmap_data; +- +-    max = fb_width(&fb) * fb_height(&fb); +-    ptr = data; +-    count = s.st_size; +-    bits = fb.bits; +-    while (count > 3) { +-        unsigned n = ptr[0]; +-        if (n > max) +-            break; +-        android_memset16(bits, ptr[1], n << 1); +-        bits += n; +-        max -= n; +-        ptr += 2; +-        count -= 4; +-    } +- +-    munmap(data, s.st_size); +-    fb_update(&fb); +-    fb_close(&fb); +-    close(fd); +-    unlink(fn); +-    return 0; +- +-fail_unmap_data: +-    munmap(data, s.st_size);     +-fail_close_file: +-    close(fd); +-fail_restore_text: +-    vt_set_mode(0); +-    return -1; +-} +- +--  +1.7.8.6 +  | 
