~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to drv_LCDLinux.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:24:15 UTC
  • mto: This revision was merged to the branch mainline in revision 750.
  • Revision ID: siretart@tauware.de-20110427172415-6n4aptmvmz0eztvm
Tags: upstream-0.11.0~svn1143
ImportĀ upstreamĀ versionĀ 0.11.0~svn1143

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: drv_LCDLinux.c 975 2009-01-18 11:16:20Z michael $
 
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_LCDLinux.c $
 
3
 *
 
4
 * driver for the LCD-Linux HD44780 kernel driver
 
5
 * http://lcd-linux.sourceforge.net
 
6
 *
 
7
 * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
 
8
 * Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 
9
 *
 
10
 * This file is part of LCD4Linux.
 
11
 *
 
12
 * LCD4Linux is free software; you can redistribute it and/or modify
 
13
 * it under the terms of the GNU General Public License as published by
 
14
 * the Free Software Foundation; either version 2, or (at your option)
 
15
 * any later version.
 
16
 *
 
17
 * LCD4Linux is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; if not, write to the Free Software
 
24
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
25
 *
 
26
 */
 
27
 
 
28
/* 
 
29
 *
 
30
 * exported fuctions:
 
31
 *
 
32
 * struct DRIVER drv_LCDLinux
 
33
 *
 
34
 */
 
35
 
 
36
#include "config.h"
 
37
 
 
38
#include <stdlib.h>
 
39
#include <stdio.h>
 
40
#include <string.h>
 
41
#include <errno.h>
 
42
#include <unistd.h>
 
43
#include <fcntl.h>
 
44
#include <sys/types.h>
 
45
#include <sys/stat.h>
 
46
#include <sys/ioctl.h>
 
47
 
 
48
#include "debug.h"
 
49
#include "cfg.h"
 
50
#include "qprintf.h"
 
51
#include "plugin.h"
 
52
#include "widget.h"
 
53
#include "widget_text.h"
 
54
#include "widget_icon.h"
 
55
#include "widget_bar.h"
 
56
#include "drv.h"
 
57
#include "drv_generic_text.h"
 
58
 
 
59
#define LCD_LINUX_MAIN
 
60
#include <linux/lcd-linux.h>
 
61
#include <linux/hd44780.h>
 
62
 
 
63
static char Name[] = "LCD-Linux";
 
64
static char Device[] = "/dev/lcd";
 
65
static int lcdlinux_fd = -1;
 
66
 
 
67
 
 
68
/****************************************/
 
69
/***  hardware dependant functions    ***/
 
70
/****************************************/
 
71
 
 
72
static void drv_LL_send(const char *string, const int len)
 
73
{
 
74
    int run, ret;
 
75
 
 
76
    for (run = 0; run < 10; run++) {
 
77
        ret = write(lcdlinux_fd, string, len);
 
78
        if (ret >= 0 || errno != EAGAIN)
 
79
            break;
 
80
        if (run > 0)
 
81
            info("%s: write(%s): EAGAIN #%d", Name, Device, run);
 
82
        usleep(1000);
 
83
    }
 
84
 
 
85
    if (ret < 0) {
 
86
        error("%s: write(%s) failed: %s", Name, Device, strerror(errno));
 
87
    } else if (ret != len) {
 
88
        error("%s: partial write(%s): len=%d ret=%d", Name, Device, len, ret);
 
89
    }
 
90
 
 
91
    return;
 
92
}
 
93
 
 
94
 
 
95
static void drv_LL_clear(void)
 
96
{
 
97
    /* No return value check since this ioctl cannot fail */
 
98
    ioctl(lcdlinux_fd, LCDL_CLEAR_DISP);
 
99
}
 
100
 
 
101
 
 
102
static void drv_LL_write(const int row, const int col, const char *data, int len)
 
103
{
 
104
    int pos = row * DCOLS + col;
 
105
 
 
106
    if (lseek(lcdlinux_fd, pos, SEEK_SET) == (off_t) - 1) {
 
107
        error("%s: lseek(%s) failed: %s", Name, Device, strerror(errno));
 
108
    }
 
109
    drv_LL_send(data, len);
 
110
}
 
111
 
 
112
 
 
113
static void drv_LL_defchar(const int ascii, const unsigned char *matrix)
 
114
{
 
115
    char buf[9];
 
116
    int i;
 
117
 
 
118
    buf[0] = ascii;
 
119
    for (i = 1; i < 9; i++) {
 
120
        buf[i] = *matrix++ & 0x1f;
 
121
    }
 
122
 
 
123
    if (ioctl(lcdlinux_fd, LCDL_SET_CGRAM_CHAR, &buf) != 0) {
 
124
        error("%s: ioctl(LCDL_SET_CGRAM_CHAR) failed: %s", Name, strerror(errno));
 
125
    }
 
126
}
 
127
 
 
128
 
 
129
static int drv_LL_start(const char *section, const int quiet)
 
130
{
 
131
    char *s;
 
132
    int rows = -1, cols = -1;
 
133
    int use_busy = 0, bus4bits = 0, commit = 0;
 
134
    struct lcd_parameters buf;
 
135
 
 
136
    /* emit version information */
 
137
    info("%s: Version %s", Name, LCD_LINUX_VERSION);
 
138
 
 
139
    /* get size from config file */
 
140
    s = cfg_get(section, "Size", NULL);
 
141
    if (s != NULL || *s != '\0') {
 
142
        if (sscanf(s, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) {
 
143
            error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source());
 
144
            free(s);
 
145
            return -1;
 
146
        }
 
147
    }
 
148
    free(s);
 
149
 
 
150
    /* open device */
 
151
    lcdlinux_fd = open(Device, O_WRONLY);
 
152
    if (lcdlinux_fd == -1) {
 
153
        error("%s: open(%s) failed: %s", Name, Device, strerror(errno));
 
154
        return -1;
 
155
    }
 
156
 
 
157
    /* get display size */
 
158
    memset(&buf, 0, sizeof(buf));
 
159
    if (ioctl(lcdlinux_fd, LCDL_GET_PARAM, &buf) != 0) {
 
160
        error("%s: ioctl(LCDL_GET_PARAM) failed: %s", Name, strerror(errno));
 
161
        error("%s: Could not query display information!", Name);
 
162
        return -1;
 
163
    }
 
164
    info("%s: %dx%d display with %d controllers, flags=0x%02lx:",
 
165
         Name, buf.cntr_cols, buf.cntr_rows * buf.num_cntr, buf.num_cntr, buf.flags);
 
166
    info("%s:   busy-flag checking %sabled", Name, (buf.flags & HD44780_CHECK_BF) ? "en" : "dis");
 
167
    info("%s:   bus width %d bits", Name, (buf.flags & HD44780_4BITS_BUS) ? 4 : 8);
 
168
    info("%s:   font size %s", Name, (buf.flags & HD44780_5X10_FONT) ? "5x10" : "5x8");
 
169
 
 
170
    /* overwrite width size from lcd4linux.conf */
 
171
    if (buf.vs_rows || buf.vs_cols) {
 
172
        info("%s: disabling virtual screen", Name);
 
173
        buf.vs_rows = 0;
 
174
        buf.vs_cols = 0;
 
175
        commit = 1;
 
176
    }
 
177
 
 
178
    if ((rows > 0 && rows != buf.cntr_rows * buf.num_cntr) || (cols > 0 && cols != buf.cntr_cols)) {
 
179
        info("%s: changing size to %dx%d", Name, cols, rows);
 
180
        buf.cntr_rows = rows / buf.num_cntr;
 
181
        buf.cntr_cols = cols;
 
182
        commit = 1;
 
183
    }
 
184
 
 
185
    DROWS = buf.cntr_rows * buf.num_cntr;
 
186
    DCOLS = buf.cntr_cols;
 
187
 
 
188
    /* overwrite busy-flag checking from lcd4linux.conf */
 
189
    cfg_number(section, "UseBusy", 0, 0, 1, &use_busy);
 
190
    if (use_busy && !(buf.flags & HD44780_CHECK_BF)) {
 
191
        info("%s: activating busy-flag checking", Name);
 
192
        buf.flags |= HD44780_CHECK_BF;
 
193
        commit = 1;
 
194
    } else if (!use_busy && (buf.flags & HD44780_CHECK_BF)) {
 
195
        info("%s: deactivating busy-flag checking", Name);
 
196
        buf.flags &= ~HD44780_CHECK_BF;
 
197
        commit = 1;
 
198
    }
 
199
 
 
200
    /* overwrite bus length from lcd4linux.conf */
 
201
    cfg_number(section, "Bus4Bit", 0, 0, 1, &bus4bits);
 
202
    if (bus4bits && !(buf.flags & HD44780_4BITS_BUS)) {
 
203
        info("%s: setting bus length to 4 bits", Name);
 
204
        buf.flags |= HD44780_4BITS_BUS;
 
205
        commit = 1;
 
206
    } else if (!bus4bits && (buf.flags & HD44780_4BITS_BUS)) {
 
207
        info("%s: setting bus length to 8 bits", Name);
 
208
        buf.flags &= ~HD44780_4BITS_BUS;
 
209
        commit = 1;
 
210
    }
 
211
 
 
212
    if (commit && ioctl(lcdlinux_fd, LCDL_SET_PARAM, &buf) != 0) {
 
213
        error("%s: ioctl(LCDL_SET_PARAM) failed: %s", Name, strerror(errno));
 
214
        return -1;
 
215
    }
 
216
 
 
217
    /* initialize display */
 
218
    drv_LL_clear();             /* clear display */
 
219
 
 
220
    /* Disable control characters interpretation. */
 
221
    /* No return value check since this ioctl cannot fail */
 
222
    ioctl(lcdlinux_fd, LCDL_RAW_MODE, 1);
 
223
 
 
224
    if (!quiet) {
 
225
        char buffer[40];
 
226
        qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
 
227
        if (drv_generic_text_greet(buffer, "lcd-linux.sf.net")) {
 
228
            sleep(3);
 
229
            drv_LL_clear();
 
230
        }
 
231
    }
 
232
 
 
233
    return 0;
 
234
}
 
235
 
 
236
 
 
237
/****************************************/
 
238
/***            plugins               ***/
 
239
/****************************************/
 
240
 
 
241
/* none */
 
242
 
 
243
 
 
244
/****************************************/
 
245
/***        widget callbacks          ***/
 
246
/****************************************/
 
247
 
 
248
 
 
249
/* using drv_generic_text_draw(W) */
 
250
/* using drv_generic_text_icon_draw(W) */
 
251
/* using drv_generic_text_bar_draw(W) */
 
252
 
 
253
 
 
254
/****************************************/
 
255
/***        exported functions        ***/
 
256
/****************************************/
 
257
 
 
258
 
 
259
/* list models */
 
260
int drv_LL_list(void)
 
261
{
 
262
    printf("LCD-Linux HD44780 kernel driver");
 
263
    return 0;
 
264
}
 
265
 
 
266
 
 
267
/* initialize driver & display */
 
268
int drv_LL_init(const char *section, const int quiet)
 
269
{
 
270
    WIDGET_CLASS wc;
 
271
    int asc255bug;
 
272
    int ret;
 
273
 
 
274
    info("%s: %s", Name, "$Rev: 975 $");
 
275
 
 
276
    /* display preferences */
 
277
    XRES = 5;                   /* pixel width of one char  */
 
278
    YRES = 8;                   /* pixel height of one char  */
 
279
    CHARS = 8;                  /* number of user-defineable characters */
 
280
    CHAR0 = 0;                  /* ASCII of first user-defineable char */
 
281
    GOTO_COST = -1;             /* number of bytes a goto command requires */
 
282
 
 
283
    /* real worker functions */
 
284
    drv_generic_text_real_write = drv_LL_write;
 
285
    drv_generic_text_real_defchar = drv_LL_defchar;
 
286
 
 
287
 
 
288
    /* start display */
 
289
    if ((ret = drv_LL_start(section, quiet)) != 0)
 
290
        return ret;
 
291
 
 
292
    /* initialize generic text driver */
 
293
    if ((ret = drv_generic_text_init(section, Name)) != 0)
 
294
        return ret;
 
295
 
 
296
    /* initialize generic icon driver */
 
297
    if ((ret = drv_generic_text_icon_init()) != 0)
 
298
        return ret;
 
299
 
 
300
    /* initialize generic bar driver */
 
301
    if ((ret = drv_generic_text_bar_init(0)) != 0)
 
302
        return ret;
 
303
 
 
304
    /* add fixed chars to the bar driver */
 
305
    /* most displays have a full block on ascii 255, but some have kind of  */
 
306
    /* an 'inverted P'. If you specify 'asc255bug 1 in the config, this */
 
307
    /* char will not be used, but rendered by the bar driver */
 
308
    cfg_number(section, "asc255bug", 0, 0, 1, &asc255bug);
 
309
    drv_generic_text_bar_add_segment(0, 0, 255, 32);    /* ASCII  32 = blank */
 
310
    if (!asc255bug)
 
311
        drv_generic_text_bar_add_segment(255, 255, 255, 255);   /* ASCII 255 = block */
 
312
 
 
313
    /* register text widget */
 
314
    wc = Widget_Text;
 
315
    wc.draw = drv_generic_text_draw;
 
316
    widget_register(&wc);
 
317
 
 
318
    /* register icon widget */
 
319
    wc = Widget_Icon;
 
320
    wc.draw = drv_generic_text_icon_draw;
 
321
    widget_register(&wc);
 
322
 
 
323
    /* register bar widget */
 
324
    wc = Widget_Bar;
 
325
    wc.draw = drv_generic_text_bar_draw;
 
326
    widget_register(&wc);
 
327
 
 
328
    /* register plugins */
 
329
    /* none */
 
330
 
 
331
    return 0;
 
332
}
 
333
 
 
334
 
 
335
/* close driver & display */
 
336
int drv_LL_quit(const int quiet)
 
337
{
 
338
 
 
339
    info("%s: shutting down.", Name);
 
340
 
 
341
    drv_generic_text_quit();
 
342
 
 
343
    /* clear display */
 
344
    drv_LL_clear();
 
345
 
 
346
    /* say goodbye... */
 
347
    if (!quiet) {
 
348
        drv_generic_text_greet("goodbye!", NULL);
 
349
    }
 
350
 
 
351
    /* Enable control characters interpretation. */
 
352
    /* No return value check since this ioctl cannot fail */
 
353
    ioctl(lcdlinux_fd, LCDL_RAW_MODE, 0);
 
354
 
 
355
    /* close device */
 
356
    close(lcdlinux_fd);
 
357
 
 
358
    return (0);
 
359
}
 
360
 
 
361
 
 
362
DRIVER drv_LCDLinux = {
 
363
    .name = Name,
 
364
    .list = drv_LL_list,
 
365
    .init = drv_LL_init,
 
366
    .quit = drv_LL_quit,
 
367
};