Merge pull request #115 from mx3L/topic_ehttpstream_headers
[openblackhole/openblackhole-enigma2.git] / lib / gdi / lcd.cpp
1 #include <lib/gdi/lcd.h>
2
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <sys/ioctl.h>
6
7 #include <lib/gdi/esize.h>
8 #include <lib/base/init.h>
9 #include <lib/base/init_num.h>
10 #ifdef HAVE_TEXTLCD
11         #include <lib/base/estring.h>
12 #endif
13 #include <lib/gdi/glcddc.h>
14
15 eLCD *eLCD::instance;
16
17 eLCD::eLCD()
18 {
19         lcdfd = -1;
20         locked = 0;
21         instance = this;
22 }
23
24 eLCD *eLCD::getInstance()
25 {
26         return instance;
27 }
28
29 void eLCD::setSize(int xres, int yres, int bpp)
30 {
31         res = eSize(xres, yres);
32         _buffer = new unsigned char[xres * yres * bpp/8];
33         memset(_buffer, 0, res.height() * res.width() * bpp / 8);
34         _stride = res.width() * bpp / 8;
35         eDebug("[eLCD] (%dx%dx%d) buffer %p %d bytes, stride %d", xres, yres, bpp, _buffer, xres * yres * bpp / 8, _stride);
36 }
37
38 eLCD::~eLCD()
39 {
40         if (_buffer)
41                 delete [] _buffer;
42 }
43
44 int eLCD::lock()
45 {
46         if (locked)
47                 return -1;
48
49         locked = 1;
50         return lcdfd;
51 }
52
53 void eLCD::unlock()
54 {
55         locked = 0;
56 }
57
58 #ifdef HAVE_TEXTLCD
59 void eLCD::renderText(ePoint start, const char *text)
60 {
61         if (lcdfd >= 0 && start.y() < 5)
62         {
63                 std::string message = text;
64                 message = replace_all(message, "\n", " ");
65                 ::write(lcdfd, message.c_str(), message.size());
66         }
67 }
68 #endif
69
70 eDBoxLCD::eDBoxLCD()
71 {
72         int xres = 132, yres = 64, bpp = 8;
73         flipped = false;
74         inverted = 0;
75         lcd_type = 0;
76 #ifndef NO_LCD
77         lcdfd = open("/dev/dbox/oled0", O_RDWR);
78         if (lcdfd < 0)
79         {
80                 if (!access("/proc/stb/lcd/oled_brightness", W_OK) ||
81                     !access("/proc/stb/fp/oled_brightness", W_OK) )
82                         lcd_type = 2;
83                 lcdfd = open("/dev/dbox/lcd0", O_RDWR);
84         }
85         else
86                 lcd_type = 1;
87
88         if (lcdfd < 0)
89                 eDebug("[eDboxLCD] No oled0 or lcd0 device found!");
90         else
91         {
92
93 #ifndef LCD_IOCTL_ASC_MODE
94 #define LCDSET                  0x1000
95 #define LCD_IOCTL_ASC_MODE      (21|LCDSET)
96 #define LCD_MODE_ASC            0
97 #define LCD_MODE_BIN            1
98 #endif
99
100                 int i = LCD_MODE_BIN;
101                 ioctl(lcdfd, LCD_IOCTL_ASC_MODE, &i);
102                 FILE *f = fopen("/proc/stb/lcd/xres", "r");
103                 if (f)
104                 {
105                         int tmp;
106                         if (fscanf(f, "%x", &tmp) == 1)
107                                 xres = tmp;
108                         fclose(f);
109                         f = fopen("/proc/stb/lcd/yres", "r");
110                         if (f)
111                         {
112                                 if (fscanf(f, "%x", &tmp) == 1)
113                                         yres = tmp;
114                                 fclose(f);
115                                 f = fopen("/proc/stb/lcd/bpp", "r");
116                                 if (f)
117                                 {
118                                         if (fscanf(f, "%x", &tmp) == 1)
119                                                 bpp = tmp;
120                                         fclose(f);
121                                 }
122                         }
123                         lcd_type = 3;
124                 }
125                 eDebug("[eDboxLCD] xres=%d, yres=%d, bpp=%d lcd_type=%d", xres, yres, bpp, lcd_type);
126
127                 instance = this;
128                 setSize(xres, yres, bpp);
129         }
130 #endif
131 }
132
133 void eDBoxLCD::setInverted(unsigned char inv)
134 {
135         inverted = inv;
136         update();
137 }
138
139 void eDBoxLCD::setFlipped(bool onoff)
140 {
141         flipped = onoff;
142         update();
143 }
144
145 int eDBoxLCD::setLCDContrast(int contrast)
146 {
147 #ifndef NO_LCD
148         if (lcdfd < 0)
149                 return(0);
150
151 #ifndef LCD_IOCTL_SRV
152 #define LCDSET                  0x1000
153 #define LCD_IOCTL_SRV                   (10|LCDSET)
154 #endif
155         eDebug("[eDboxLCD] setLCDContrast %d", contrast);
156
157         int fp;
158         if((fp = open("/dev/dbox/fp0", O_RDWR)) < 0)
159         {
160                 eDebug("[eDboxLCD] can't open /dev/dbox/fp0: %m");
161                 return(-1);
162         }
163
164         if(ioctl(lcdfd, LCD_IOCTL_SRV, &contrast) < 0)
165                 eDebug("[eDboxLCD] can't set lcd contrast: %m");
166         close(fp);
167 #endif
168         return(0);
169 }
170
171 int eDBoxLCD::setLCDBrightness(int brightness)
172 {
173 #ifndef NO_LCD
174         if (lcdfd < 0)
175                 return(0);
176
177         eDebug("[eDboxLCD] setLCDBrightness %d", brightness);
178         FILE *f = fopen("/proc/stb/lcd/oled_brightness", "w");
179         if (!f)
180                 f = fopen("/proc/stb/fp/oled_brightness", "w");
181         if (f)
182         {
183                 if (fprintf(f, "%d", brightness) == 0)
184                         eDebug("[eDboxLCD] write /proc/stb/lcd|fp/oled_brightness failed: %m");
185                 fclose(f);
186         }
187         else
188         {
189                 int fp;
190                 if ((fp = open("/dev/dbox/fp0", O_RDWR)) < 0)
191                 {
192                         eDebug("[eDboxLCD] can't open /dev/dbox/fp0: %m");
193                         return(-1);
194                 }
195 #ifndef FP_IOCTL_LCD_DIMM
196 #define FP_IOCTL_LCD_DIMM       3
197 #endif
198                 if (ioctl(fp, FP_IOCTL_LCD_DIMM, &brightness) < 0)
199                         eDebug("[eDboxLCD] can't set lcd brightness: %m");
200                 close(fp);
201         }
202 #endif
203         return(0);
204 }
205
206 eDBoxLCD::~eDBoxLCD()
207 {
208         if (lcdfd >= 0)
209         {
210                 close(lcdfd);
211                 lcdfd = -1;
212         }
213 }
214
215 void eDBoxLCD::update()
216 {
217 #ifndef HAVE_TEXTLCD
218         if (lcdfd < 0)
219                 return;
220
221         if (lcd_type == 0 || lcd_type == 2)
222         {
223                 unsigned char raw[132 * 8];
224                 int x, y, yy;
225                 for (y = 0; y < 8; y++)
226                 {
227                         for (x = 0; x < 132; x++)
228                         {
229                                 int pix = 0;
230                                 for (yy = 0; yy < 8; yy++)
231                                         pix |= (_buffer[(y * 8 + yy) * 132 + x] >= 108) << yy;
232                                 if (flipped)
233                                 {
234                                         /* 8 pixels per byte, swap bits */
235 #define BIT_SWAP(a) (( ((a << 7)&0x80) + ((a << 5)&0x40) + ((a << 3)&0x20) + ((a << 1)&0x10) + ((a >> 1)&0x08) + ((a >> 3)&0x04) + ((a >> 5)&0x02) + ((a >> 7)&0x01) )&0xff)
236                                         raw[(7 - y) * 132 + (131 - x)] = BIT_SWAP(pix ^ inverted);
237                                 }
238                                 else
239                                         raw[y * 132 + x] = pix ^ inverted;
240                         }
241                 }
242                 write(lcdfd, raw, 132 * 8);
243         }
244         else if (lcd_type == 3)
245         {
246                 /* for now, only support flipping / inverting for 8bpp displays */
247                 if ((flipped || inverted) && _stride == res.width())
248                 {
249                         unsigned int height = res.height();
250                         unsigned int width = res.width();
251                         unsigned char raw[_stride * height];
252                         for (unsigned int y = 0; y < height; y++)
253                         {
254                                 for (unsigned int x = 0; x < width; x++)
255                                 {
256                                         if (flipped)
257                                                 /* 8bpp, no bit swapping */
258                                                 raw[(height - 1 - y) * width + (width - 1 - x)] = _buffer[y * width + x] ^ inverted;
259                                         else
260                                                 raw[y * width + x] = _buffer[y * width + x] ^ inverted;
261                                 }
262                         }
263                         write(lcdfd, raw, _stride * height);
264                 }
265                 else
266                         write(lcdfd, _buffer, _stride * res.height());
267         }
268         else /* lcd_type == 1 */
269         {
270                 unsigned char raw[64 * 64];
271                 int x, y;
272                 memset(raw, 0, 64 * 64);
273                 for (y = 0; y < 64; y++)
274                 {
275                         int pix = 0;
276                         for (x = 0; x < 128 / 2; x++)
277                         {
278                                 pix = (_buffer[y * 132 + x * 2 + 2] & 0xF0) | (_buffer[y * 132 + x * 2 + 1 + 2] >> 4);
279                                 if (inverted)
280                                         pix = 0xFF - pix;
281                                 if (flipped)
282                                 {
283                                         /* device seems to be 4bpp, swap nibbles */
284                                         unsigned char byte;
285                                         byte = (pix >> 4) & 0x0f;
286                                         byte |= (pix << 4) & 0xf0;
287                                         raw[(63 - y) * 64 + (63 - x)] = byte;
288                                 }
289                                 else
290                                         raw[y * 64 + x] = pix;
291                         }
292                 }
293                 write(lcdfd, raw, 64 * 64);
294         }
295 #endif
296 }