root/tags/0.10.0/drv_LCDLinux.c

Revision 547, 9.8 kB (checked in by reinelt, 4 years ago)

[lcd4linux @ 2005-05-08 04:32:43 by reinelt]
CodingStyle? added and applied

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