diff options
Diffstat (limited to 'utils/nwztools/plattools')
-rw-r--r-- | utils/nwztools/plattools/test_fb.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/utils/nwztools/plattools/test_fb.c b/utils/nwztools/plattools/test_fb.c new file mode 100644 index 0000000000..77e8d4e497 --- /dev/null +++ b/utils/nwztools/plattools/test_fb.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Amaury Pouly | ||
11 | * | ||
12 | * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing | ||
13 | * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version 2 | ||
18 | * of the License, or (at your option) any later version. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | #include "nwz_lib.h" | ||
25 | #include "nwz_plattools.h" | ||
26 | #include <linux/fb.h> | ||
27 | #include <stdint.h> | ||
28 | #include <sys/mman.h> | ||
29 | |||
30 | static struct fb_fix_screeninfo finfo; | ||
31 | static struct fb_var_screeninfo vinfo; | ||
32 | static uint8_t *framebuffer; | ||
33 | |||
34 | static inline uint32_t read32(uint8_t *p) | ||
35 | { | ||
36 | return *p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24; | ||
37 | } | ||
38 | |||
39 | static inline void write32(uint8_t *p, uint32_t val) | ||
40 | { | ||
41 | *p++ = val & 0xff; val >>= 8; | ||
42 | *p++ = val & 0xff; val >>= 8; | ||
43 | *p++ = val & 0xff; val >>= 8; | ||
44 | *p++ = val; | ||
45 | } | ||
46 | |||
47 | /* assume lsb and little-endian */ | ||
48 | static inline void put_pix_mask(uint8_t *location, int offset, int len, uint8_t pix) | ||
49 | { | ||
50 | /* adjust pixel */ | ||
51 | pix >>= 8 - len; | ||
52 | uint32_t mask = ((1 << len) - 1) << offset; | ||
53 | uint32_t val = read32(location); | ||
54 | val = ((val) & ~mask) | pix << offset; | ||
55 | write32(location, val); | ||
56 | } | ||
57 | |||
58 | static inline void put_pix(int x, int y, uint8_t r, uint8_t g, uint8_t b) | ||
59 | { | ||
60 | x += vinfo.xoffset; | ||
61 | y += vinfo.yoffset; | ||
62 | uint8_t *location = framebuffer + x * (vinfo.bits_per_pixel / 8) + y * finfo.line_length; | ||
63 | put_pix_mask(location, vinfo.red.offset, vinfo.red.length, r); | ||
64 | put_pix_mask(location, vinfo.green.offset, vinfo.green.length, g); | ||
65 | put_pix_mask(location, vinfo.blue.offset, vinfo.blue.length, b); | ||
66 | } | ||
67 | |||
68 | static void dump_fb(FILE *out, const char *path) | ||
69 | { | ||
70 | fprintf(out, "%s:\n", path); | ||
71 | int fd = open(path, O_RDWR); | ||
72 | if(fd < 0) | ||
73 | { | ||
74 | fprintf(out, " cannot open"); | ||
75 | return; | ||
76 | } | ||
77 | /* get fixed info */ | ||
78 | if(ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) | ||
79 | { | ||
80 | fprintf(out, " ioctl failed (fix info)"); | ||
81 | close(fd); | ||
82 | return; | ||
83 | } | ||
84 | fprintf(out, " identification: %s\n", finfo.id); | ||
85 | fprintf(out, " type: %d\n", finfo.type); | ||
86 | fprintf(out, " visual: %d\n", finfo.visual); | ||
87 | fprintf(out, " accel: %d\n", finfo.accel); | ||
88 | fprintf(out, " line length: %d\n", finfo.line_length); | ||
89 | fprintf(out, " mem length: %d\n", finfo.smem_len); | ||
90 | /* get variable info */ | ||
91 | if(ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) | ||
92 | { | ||
93 | close(fd); | ||
94 | fprintf(out, " ioctl failed (var info)"); | ||
95 | return; | ||
96 | } | ||
97 | fprintf(out, " xres: %d\n", vinfo.xres); | ||
98 | fprintf(out, " yres: %d\n", vinfo.yres); | ||
99 | fprintf(out, " xoff: %d\n", vinfo.xoffset); | ||
100 | fprintf(out, " yoff: %d\n", vinfo.yoffset); | ||
101 | fprintf(out, " bbp: %d\n", vinfo.bits_per_pixel); | ||
102 | fprintf(out, " red: %d-%d\n", vinfo.red.offset + vinfo.red.length - 1, vinfo.red.offset); | ||
103 | fprintf(out, " green: %d-%d\n", vinfo.green.offset + vinfo.green.length - 1, vinfo.green.offset); | ||
104 | fprintf(out, " blue: %d-%d\n", vinfo.blue.offset + vinfo.blue.length - 1, vinfo.blue.offset); | ||
105 | /* get mode info */ | ||
106 | struct nwz_fb_image_info mode_info; | ||
107 | nwz_fb_set_standard_mode(fd); | ||
108 | if(ioctl(fd, NWZ_FB_GET_MODE, &mode_info) < 0) | ||
109 | { | ||
110 | close(fd); | ||
111 | fprintf(out, " ioctl failed (get mode)\n"); | ||
112 | return; | ||
113 | } | ||
114 | fprintf(out, " tc_enable: %d\n", mode_info.tc_enable); | ||
115 | fprintf(out, " t_color: %d\n", mode_info.t_color); | ||
116 | fprintf(out, " alpha: %d\n", mode_info.alpha); | ||
117 | fprintf(out, " rot: %d\n", mode_info.rot); | ||
118 | fprintf(out, " page: %d\n", mode_info.page); | ||
119 | fprintf(out, " update: %d\n", mode_info.update); | ||
120 | /* mmap device (but avoid TV) */ | ||
121 | if(vinfo.xres != 720) | ||
122 | { | ||
123 | long screensize = vinfo.yres_virtual * finfo.line_length; | ||
124 | framebuffer = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0); | ||
125 | if(framebuffer == 0) | ||
126 | { | ||
127 | close(fd); | ||
128 | fprintf(out, " mmap failed"); | ||
129 | return; | ||
130 | } | ||
131 | for(int y = 0; y < 10; y++) | ||
132 | for(int x = 0; x < 10; x++) | ||
133 | { | ||
134 | put_pix(x, y, 0xff, 0, 0); | ||
135 | put_pix(x + 10, y, 0, 0xff, 0); | ||
136 | put_pix(x + 20, y, 0, 0, 0xff); | ||
137 | } | ||
138 | } | ||
139 | sleep(3); | ||
140 | close(fd); | ||
141 | } | ||
142 | |||
143 | int NWZ_TOOL_MAIN(test_fb)(int argc, char **argv) | ||
144 | { | ||
145 | FILE *f = fopen("/contents/fb.txt", "w"); | ||
146 | if(!f) | ||
147 | f = stdout; | ||
148 | dump_fb(f, "/dev/fb/0"); | ||
149 | if(f) | ||
150 | fclose(f); | ||
151 | return 0; | ||
152 | } | ||