~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to drv_LW_ABP.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:28:49 UTC
  • mfrom: (0.1.1 upstream)
  • Revision ID: siretart@tauware.de-20110427172849-mj5cj5a0igpcc9fn
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: drv_LW_ABP.c 1071 2009-11-22 05:27:53Z michael $
 
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_LW_ABP.c $
 
3
 *
 
4
 * driver for Logic Way GmbH ABP08 (serial) and ABP09 (USB) appliance control panels
 
5
 * http://www.logicway.de/pages/mde-hardware.shtml#ABP.AMC
 
6
 *
 
7
 * Copyright (C) 2009 Arndt Kritzner <kritzner@logicway.de>
 
8
 * Copyright (C) 2005 Michael Reinelt <michael@reinelt.co.at>
 
9
 * Copyright (C) 2005, 2006, 2007, 2009 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 
10
 *
 
11
 * This file is part of LCD4Linux.
 
12
 *
 
13
 * LCD4Linux is free software; you can redistribute it and/or modify
 
14
 * it under the terms of the GNU General Public License as published by
 
15
 * the Free Software Foundation; either version 2, or (at your option)
 
16
 * any later version.
 
17
 *
 
18
 * LCD4Linux is distributed in the hope that it will be useful,
 
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 * GNU General Public License for more details.
 
22
 *
 
23
 * You should have received a copy of the GNU General Public License
 
24
 * along with this program; if not, write to the Free Software
 
25
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
26
 *
 
27
 */
 
28
 
 
29
/* 
 
30
 *
 
31
 * exported fuctions:
 
32
 *
 
33
 * struct DRIVER drv_LW_ABP
 
34
 *
 
35
 */
 
36
 
 
37
#include "config.h"
 
38
 
 
39
#include <stdlib.h>
 
40
#include <stdio.h>
 
41
#include <unistd.h>
 
42
#include <string.h>
 
43
#include <sys/types.h>
 
44
#include <sys/stat.h>
 
45
#include <time.h>
 
46
#include <errno.h>
 
47
 
 
48
#include "debug.h"
 
49
#include "cfg.h"
 
50
#include "qprintf.h"
 
51
#include "udelay.h"
 
52
#include "timer.h"
 
53
#include "plugin.h"
 
54
#include "widget.h"
 
55
#include "widget_text.h"
 
56
#include "widget_bar.h"
 
57
#include "widget_keypad.h"
 
58
#include "drv.h"
 
59
 
 
60
/* text mode display? */
 
61
#include "drv_generic_text.h"
 
62
#include "drv_generic_keypad.h"
 
63
 
 
64
/* serial port? */
 
65
#include "drv_generic_serial.h"
 
66
 
 
67
/* i2c bus? */
 
68
#ifdef WITH_I2C
 
69
#include "drv_generic_i2c.h"
 
70
#endif
 
71
 
 
72
#define KEY_UP 4
 
73
#define KEY_DOWN 3
 
74
#define KEY_LEFT 2
 
75
#define KEY_RIGHT 1
 
76
 
 
77
static char Name[] = "LW_ABP";
 
78
static char logicway[] = "www.logicway.de";
 
79
 
 
80
/* ring buffer for bytes received from the display */
 
81
static unsigned char RingBuffer[256];
 
82
static unsigned int RingRPos = 0;
 
83
static unsigned int RingWPos = 0;
 
84
 
 
85
static int button = -1;
 
86
static char *colors[] =
 
87
    { "r 0", "r 1", "g 0", "g 1", "b 0", "b 1", "c 0", "c 1", "m 0", "m 1", "y 0", "y 1", "w 0", "w 1", NULL };
 
88
 
 
89
#define TIMESYNC_FIRST  600
 
90
#define TIMESYNC_INTERVAL 24*3600
 
91
static time_t next_timesync;
 
92
 
 
93
static char *switchcontact = NULL;
 
94
static int statresult = 0;
 
95
static time_t switchcontact_lastchange = 0;
 
96
static time_t switchcontact_time = 0;
 
97
#define SWITCH_ACTION_DURATION 1000
 
98
 
 
99
/****************************************/
 
100
/***  hardware dependant functions    ***/
 
101
/****************************************/
 
102
 
 
103
static int drv_LW_ABP_open(const char *section)
 
104
{
 
105
    /* open serial port */
 
106
    /* don't mind about device, speed and stuff, this function will take care of */
 
107
 
 
108
    if (drv_generic_serial_open(section, Name, 0) < 0)
 
109
        return -1;
 
110
 
 
111
    return 0;
 
112
}
 
113
 
 
114
 
 
115
static int drv_LW_ABP_close(void)
 
116
{
 
117
    drv_generic_serial_close();
 
118
 
 
119
    return 0;
 
120
}
 
121
 
 
122
 
 
123
/* dummy function that sends something to the display */
 
124
static void drv_LW_ABP_send(const char *data, const unsigned int len)
 
125
{
 
126
    /* send data to the serial port is easy... */
 
127
    drv_generic_serial_write(data, len);
 
128
}
 
129
 
 
130
 
 
131
/* text mode displays only */
 
132
static void drv_LW_ABP_reset(void)
 
133
{
 
134
    char cmd[] = "lcd init\r\n";
 
135
 
 
136
    /* do whatever is necessary to initialize the display */
 
137
    drv_LW_ABP_send(cmd, strlen(cmd));
 
138
}
 
139
 
 
140
static void drv_LW_ABP_clear(void)
 
141
{
 
142
    char cmd[] = "lcd clear\r\n";
 
143
 
 
144
    /* do whatever is necessary to clear the display */
 
145
    drv_LW_ABP_send(cmd, strlen(cmd));
 
146
}
 
147
 
 
148
static int drv_LW_ABP_time(unsigned char force)
 
149
{
 
150
    char cmd[] = "date set ";
 
151
    char command[50];
 
152
    time_t t = time(NULL);
 
153
 
 
154
    if (force || (t > next_timesync)) {
 
155
        /* do whatever is necessary to set clock on the display */
 
156
        sprintf(command, "%s%lu\r\n", cmd, (unsigned long) t);
 
157
        drv_LW_ABP_send(command, strlen(command));
 
158
        next_timesync = t + TIMESYNC_INTERVAL;
 
159
        info("%s: synced time to %lu, next is %lu\n", Name, (unsigned long) t, (unsigned long) next_timesync);
 
160
        return 1;
 
161
    }
 
162
 
 
163
    return 0;
 
164
}
 
165
 
 
166
static int drv_LW_ABP_switchcontact(void)
 
167
{
 
168
    char cmd[] = "switch time ";
 
169
    char command[50];
 
170
    struct stat statinfo;
 
171
    FILE *configfile;
 
172
    int scanresult;
 
173
    int config_entries;
 
174
    char inputline[101];
 
175
    if ((switchcontact != NULL) && (*switchcontact != '\0')) {
 
176
        if (stat(switchcontact, &statinfo) == -1) {
 
177
            if (statresult != -1) {
 
178
                error("%s: specified switch contact control file %s not found", Name, switchcontact);
 
179
                switchcontact_time = 0;
 
180
                sprintf(command, "%s%lu %u\r\n", cmd, (unsigned long) switchcontact_time, SWITCH_ACTION_DURATION);
 
181
                drv_LW_ABP_send(command, strlen(command));
 
182
                info("%s: switchtime deactivated", Name);
 
183
                statresult = -1;
 
184
            }
 
185
        } else {
 
186
            if (statresult == -1) {
 
187
                info("%s: specified switch contact control file %s appeared", Name, switchcontact);
 
188
                statresult = 0;
 
189
            }
 
190
            if ((switchcontact_lastchange == 0) || (switchcontact_lastchange < statinfo.st_mtime)) {
 
191
                info("%s: specified switch contact control file %s has changed (%lu < %lu)", Name, switchcontact,
 
192
                     (unsigned long) switchcontact_lastchange, (unsigned long) statinfo.st_mtime);
 
193
                switchcontact_lastchange = statinfo.st_mtime;
 
194
                configfile = fopen(switchcontact, "r");
 
195
                if (configfile == NULL) {
 
196
                    error("%s: could not open specified switch contact control file %s", Name, switchcontact);
 
197
                } else {
 
198
                    config_entries = 0;
 
199
                    while (!feof(configfile)) {
 
200
                        if (fgets(inputline, 100, configfile) != NULL) {
 
201
                            if ((scanresult = sscanf(inputline, "switchtime=%lu", &switchcontact_time)) == 1) {
 
202
                                info("%s: switchtime read %lu (file %s)", Name, (unsigned long) switchcontact_time,
 
203
                                     switchcontact);
 
204
                                config_entries++;
 
205
                            }
 
206
                        }
 
207
                    }
 
208
                    fclose(configfile);
 
209
                    if (config_entries > 0) {
 
210
                        if (switchcontact_time < time(NULL)) {
 
211
                            switchcontact_time = 0;
 
212
                            info("%s: switchtime is in past %lu (now %lu), so deactivated", Name,
 
213
                                 (unsigned long) switchcontact_time, time(NULL));
 
214
                        }
 
215
                    } else {
 
216
                        switchcontact_time = 0;
 
217
                    }
 
218
                    if (switchcontact_time != 0) {
 
219
                        sprintf(command, "%s%lu %u\r\n", cmd, (unsigned long) switchcontact_time,
 
220
                                SWITCH_ACTION_DURATION);
 
221
                        drv_LW_ABP_send(command, strlen(command));
 
222
                        info("%s: switchtime set to %lu", Name, (unsigned long) switchcontact_time);
 
223
                    } else {
 
224
                        sprintf(command, "%s%lu %u\r\n", cmd, (unsigned long) switchcontact_time,
 
225
                                SWITCH_ACTION_DURATION);
 
226
                        drv_LW_ABP_send(command, strlen(command));
 
227
                        info("%s: switchtime deactivated", Name);
 
228
                    }
 
229
                }
 
230
            }
 
231
        }
 
232
    }
 
233
 
 
234
    return 0;
 
235
}
 
236
 
 
237
/* text mode displays only */
 
238
static void drv_LW_ABP_write(const int row, const int col, const char *data, int len)
 
239
{
 
240
    char cmd[] = "lcd set line ";
 
241
    char row_[5];
 
242
    char col_[5];
 
243
 
 
244
    /* do the cursor positioning here */
 
245
    drv_LW_ABP_send(cmd, strlen(cmd));
 
246
    sprintf(row_, "%d", row + 1);
 
247
    drv_LW_ABP_send(row_, strlen(row_));
 
248
    if (col > 0) {
 
249
        drv_LW_ABP_send(",", 1);
 
250
        sprintf(col_, "%d", col + 1);
 
251
        drv_LW_ABP_send(col_, strlen(col_));
 
252
    }
 
253
    drv_LW_ABP_send(" ", 1);
 
254
 
 
255
    /* send string to the display */
 
256
    drv_LW_ABP_send(data, len);
 
257
    drv_LW_ABP_send("\r\n", 2);
 
258
 
 
259
}
 
260
 
 
261
static unsigned char byte(int pos)
 
262
{
 
263
    if (pos >= 0) {
 
264
        pos += RingRPos;
 
265
        if ((unsigned) pos >= sizeof(RingBuffer))
 
266
            pos -= sizeof(RingBuffer);
 
267
    } else {
 
268
        pos += RingWPos;
 
269
        if (pos < 0)
 
270
            pos += sizeof(RingBuffer);
 
271
    }
 
272
    return RingBuffer[pos];
 
273
}
 
274
 
 
275
static void drv_LW_ABP_process_button(void)
 
276
{
 
277
    /* Key Activity */
 
278
    debug("%s: Key Activity: %d", Name, button);
 
279
    drv_generic_keypad_press(button);
 
280
}
 
281
 
 
282
static int drv_LW_ABP_poll(void)
 
283
{
 
284
    char received[100];
 
285
 
 
286
    /* read into RingBuffer */
 
287
    while (1) {
 
288
        char buffer[32];
 
289
        int num, n;
 
290
        num = drv_generic_serial_poll(buffer, sizeof(buffer));
 
291
        if (num <= 0)
 
292
            break;
 
293
        /* put result into RingBuffer */
 
294
        for (n = 0; n < num; n++) {
 
295
            RingBuffer[RingWPos++] = (unsigned char) buffer[n];
 
296
            if (RingWPos >= sizeof(RingBuffer))
 
297
                RingWPos = 0;
 
298
        }
 
299
    }
 
300
 
 
301
    received[0] = '\0';
 
302
 
 
303
    /* process RingBuffer */
 
304
    while (1) {
 
305
        char command[32];
 
306
        int n, num;
 
307
        /* packet size */
 
308
        num = RingWPos - RingRPos;
 
309
        if (num < 0)
 
310
            num += sizeof(RingBuffer);
 
311
        /* minimum packet size=3 */
 
312
        if (num < 1) {
 
313
            if (strlen(received) > 0) {
 
314
                debug("%s: received: %s", Name, received);
 
315
            }
 
316
            return 0;
 
317
        }
 
318
        if (byte(0) != '[') {
 
319
            goto GARBAGE;
 
320
        }
 
321
        for (n = 0; (n < num) && ((unsigned) n < (sizeof(command) - 1)); n++) {
 
322
            command[n] = byte(n);
 
323
            if (command[n] == ']') {
 
324
                n++;
 
325
                break;
 
326
            }
 
327
        }
 
328
        command[n] = '\0';
 
329
        if (command[n - 1] != ']') {
 
330
            if (strlen(command) < 4) {
 
331
                if (strlen(received) > 0) {
 
332
                    debug("%s: received: %s", Name, received);
 
333
                }
 
334
                return 0;
 
335
            }
 
336
            goto GARBAGE;
 
337
        }
 
338
        info("%s: command read from keypad: %s\n", Name, command);
 
339
        if (sscanf(command, "[T%d]", &button) == 1) {
 
340
            info("%s: button %d pressed\n", Name, button);
 
341
        } else {
 
342
            goto GARBAGE;
 
343
        }
 
344
        /* increment read pointer */
 
345
        RingRPos += strlen(command);
 
346
        if (RingRPos >= sizeof(RingBuffer))
 
347
            RingRPos -= sizeof(RingBuffer);
 
348
        /* a packet arrived */
 
349
        if (strlen(received) > 0) {
 
350
            debug("%s: received: %s", Name, received);
 
351
        }
 
352
        return 1;
 
353
      GARBAGE:
 
354
        switch (byte(0)) {
 
355
        case '\n':
 
356
        case '\r':
 
357
        case '>':
 
358
            if (strlen(received) > 0) {
 
359
                debug("%s: received: %s", Name, received);
 
360
                received[0] = '\0';
 
361
            }
 
362
            break;
 
363
        default:
 
364
            if (byte(0) < ' ')
 
365
                debug("%s: dropping garbage byte %02x", Name, byte(0));
 
366
            else if ((strlen(received) + 2) > sizeof(received)) {
 
367
                debug("%s: received: %s", Name, received);
 
368
                received[0] = '\0';
 
369
            }
 
370
            sprintf(received, "%s%c", received, byte(0));
 
371
            break;
 
372
        }
 
373
        RingRPos++;
 
374
        if (RingRPos >= sizeof(RingBuffer))
 
375
            RingRPos = 0;
 
376
        continue;
 
377
    }
 
378
 
 
379
    /* not reached */
 
380
    return 0;
 
381
}
 
382
 
 
383
static void drv_LW_ABP_timer(void __attribute__ ((unused)) * notused)
 
384
{
 
385
    while (drv_LW_ABP_poll()) {
 
386
        drv_LW_ABP_process_button();
 
387
    }
 
388
 
 
389
    drv_LW_ABP_time(0);
 
390
    drv_LW_ABP_switchcontact();
 
391
}
 
392
 
 
393
static int drv_LW_ABP_keypad(const int num)
 
394
{
 
395
    int val = 0;
 
396
 
 
397
    switch (num) {
 
398
    case KEY_UP:
 
399
        debug("%s: Key Up", Name);
 
400
        val += WIDGET_KEY_PRESSED;
 
401
        val += WIDGET_KEY_UP;
 
402
        break;
 
403
    case KEY_DOWN:
 
404
        debug("%s: Key Down", Name);
 
405
        val += WIDGET_KEY_PRESSED;
 
406
        val += WIDGET_KEY_DOWN;
 
407
        break;
 
408
    case KEY_LEFT:
 
409
        debug("%s: Key Left / Cancel", Name);
 
410
        val += WIDGET_KEY_PRESSED;
 
411
        val += WIDGET_KEY_LEFT;
 
412
//      val += WIDGET_KEY_CANCEL;
 
413
        break;
 
414
    case KEY_RIGHT:
 
415
        debug("%s: Key Right / Confirm", Name);
 
416
        val += WIDGET_KEY_PRESSED;
 
417
        val += WIDGET_KEY_RIGHT;
 
418
//      val += WIDGET_KEY_CONFIRM;
 
419
        break;
 
420
    default:
 
421
        debug("%s: Unbound Key '%d'", Name, num);
 
422
        break;
 
423
    }
 
424
 
 
425
    return val;
 
426
}
 
427
 
 
428
static char *drv_LW_ABP_background(char *color)
 
429
{
 
430
    static char *Background = NULL;
 
431
    char cmd[] = "lcd set color ";
 
432
    int idx;
 
433
    if (color != NULL) {
 
434
        for (idx = 0; colors[idx] != NULL; idx++) {
 
435
            if (strcmp(color, colors[idx]) == 0)
 
436
                break;
 
437
        }
 
438
        if (colors[idx] != NULL) {
 
439
            Background = colors[idx];
 
440
            debug("%s: set background color %s", Name, Background);
 
441
            drv_LW_ABP_send(cmd, strlen(cmd));
 
442
            drv_LW_ABP_send(color, strlen(color));
 
443
            drv_LW_ABP_send("\r\n", 2);
 
444
        }
 
445
    }
 
446
    return Background;
 
447
}
 
448
 
 
449
static int drv_LW_ABP_contrast(int contrast)
 
450
{
 
451
    return contrast;
 
452
}
 
453
 
 
454
 
 
455
/* start text mode display */
 
456
static int drv_LW_ABP_start(const char *section)
 
457
{
 
458
    int contrast;
 
459
    int rows = -1, cols = -1;
 
460
    char *s;
 
461
    char *background;
 
462
 
 
463
    s = cfg_get(section, "Size", NULL);
 
464
    if (s == NULL || *s == '\0') {
 
465
        error("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
 
466
        return -1;
 
467
    }
 
468
    if (sscanf(s, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) {
 
469
        error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source());
 
470
        free(s);
 
471
        return -1;
 
472
    }
 
473
 
 
474
    DROWS = rows;
 
475
    DCOLS = cols;
 
476
 
 
477
    next_timesync = time(NULL) + TIMESYNC_FIRST;
 
478
 
 
479
    /* open communication with the display */
 
480
    if (drv_LW_ABP_open(section) < 0) {
 
481
        return -1;
 
482
    }
 
483
 
 
484
    drv_LW_ABP_reset();         /* initialize display */
 
485
 
 
486
    background = cfg_get(section, "Background", NULL);
 
487
    if ((background != NULL) && (*background != '\0')) {
 
488
        if (drv_LW_ABP_background(background) == NULL) {
 
489
            debug("%s: wrong background color specified: %s", Name, background);
 
490
        }
 
491
    }
 
492
 
 
493
    switchcontact = cfg_get(section, "Switchcontact", NULL);
 
494
 
 
495
    if (cfg_number(section, "Contrast", 0, 0, 255, &contrast) > 0) {
 
496
        drv_LW_ABP_contrast(contrast);
 
497
    }
 
498
 
 
499
    drv_LW_ABP_clear();         /* clear display */
 
500
 
 
501
    return 0;
 
502
}
 
503
 
 
504
/****************************************/
 
505
/***            plugins               ***/
 
506
/****************************************/
 
507
 
 
508
static void plugin_contrast(RESULT * result, RESULT * arg1)
 
509
{
 
510
    double contrast;
 
511
 
 
512
    contrast = drv_LW_ABP_contrast(R2N(arg1));
 
513
    SetResult(&result, R_NUMBER, &contrast);
 
514
}
 
515
 
 
516
static void plugin_background(RESULT * result, const int argc, RESULT * argv[])
 
517
{
 
518
    char *color;
 
519
 
 
520
    switch (argc) {
 
521
    case 0:
 
522
        color = drv_LW_ABP_background(NULL);
 
523
        SetResult(&result, R_STRING, &color);
 
524
        break;
 
525
    case 1:
 
526
        color = drv_LW_ABP_background(R2S(argv[0]));
 
527
        SetResult(&result, R_STRING, &color);
 
528
        break;
 
529
    default:
 
530
        error("%s.backlight(): wrong number of parameters (%d)", Name, argc);
 
531
        SetResult(&result, R_STRING, "");
 
532
    }
 
533
}
 
534
 
 
535
 
 
536
/****************************************/
 
537
/***        widget callbacks          ***/
 
538
/****************************************/
 
539
 
 
540
 
 
541
/* using drv_generic_text_draw(W) */
 
542
/* using drv_generic_text_icon_draw(W) */
 
543
/* using drv_generic_text_bar_draw(W) */
 
544
/* using drv_generic_gpio_draw(W) */
 
545
 
 
546
 
 
547
/****************************************/
 
548
/***        exported functions        ***/
 
549
/****************************************/
 
550
 
 
551
 
 
552
/* list models */
 
553
int drv_LW_ABP_list(void)
 
554
{
 
555
    printf("Logic Way ABP driver");
 
556
    return 0;
 
557
}
 
558
 
 
559
 
 
560
/* initialize driver & display */
 
561
/* use this function for a text display */
 
562
int drv_LW_ABP_init(const char *section, const int quiet)
 
563
{
 
564
    WIDGET_CLASS wc;
 
565
    int ret;
 
566
 
 
567
    info("%s: %s", Name, "$Rev: 1071 $");
 
568
 
 
569
    /* display preferences */
 
570
    XRES = 5;                   /* pixel width of one char  */
 
571
    YRES = 8;                   /* pixel height of one char  */
 
572
    CHARS = 0;                  /* number of user-defineable characters */
 
573
    CHAR0 = 0;                  /* ASCII of first user-defineable char */
 
574
    GOTO_COST = 10;             /* number of bytes a goto command requires */
 
575
 
 
576
    /* real worker functions */
 
577
    drv_generic_text_real_write = drv_LW_ABP_write;
 
578
    drv_generic_keypad_real_press = drv_LW_ABP_keypad;
 
579
 
 
580
    /* regularly process display answers */
 
581
    timer_add(drv_LW_ABP_timer, NULL, 100, 0);
 
582
 
 
583
    /* start display */
 
584
    if ((ret = drv_LW_ABP_start(section)) != 0)
 
585
        return ret;
 
586
 
 
587
    if (!quiet) {
 
588
        char buffer[40];
 
589
        qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
 
590
        if (drv_generic_text_greet(buffer, logicway)) {
 
591
            sleep(3);
 
592
            drv_LW_ABP_clear();
 
593
        }
 
594
    }
 
595
 
 
596
    /* initialize generic text driver */
 
597
    if ((ret = drv_generic_text_init(section, Name)) != 0)
 
598
        return ret;
 
599
 
 
600
    /* initialize generic icon driver */
 
601
    if ((ret = drv_generic_text_icon_init()) != 0)
 
602
        return ret;
 
603
 
 
604
    /* initialize generic bar driver */
 
605
    if ((ret = drv_generic_text_bar_init(0)) != 0)
 
606
        return ret;
 
607
 
 
608
    /* initialize generic key pad driver */
 
609
    if ((ret = drv_generic_keypad_init(section, Name)) != 0)
 
610
        return ret;
 
611
 
 
612
    /* add fixed chars to the bar driver */
 
613
    drv_generic_text_bar_add_segment(0, 0, 255, 32);    /* ASCII  32 = blank */
 
614
 
 
615
    /* register text widget */
 
616
    wc = Widget_Text;
 
617
    wc.draw = drv_generic_text_draw;
 
618
    widget_register(&wc);
 
619
 
 
620
    /* register bar widget */
 
621
    wc = Widget_Bar;
 
622
    wc.draw = drv_generic_text_bar_draw;
 
623
    widget_register(&wc);
 
624
 
 
625
    /* register plugins */
 
626
    AddFunction("LCD::contrast", 1, plugin_contrast);
 
627
    AddFunction("LCD::background", -1, plugin_background);
 
628
 
 
629
    return 0;
 
630
}
 
631
 
 
632
 
 
633
 
 
634
/* close driver & display */
 
635
/* use this function for a text display */
 
636
int drv_LW_ABP_quit(const int quiet)
 
637
{
 
638
    char switchactive[] = "switch scheduled";
 
639
    char timeinfo[17];
 
640
    struct tm switchtime_info;
 
641
 
 
642
    info("%s: shutting down.", Name);
 
643
 
 
644
    drv_generic_text_quit();
 
645
    drv_generic_keypad_quit();
 
646
 
 
647
    /* clear display */
 
648
    drv_LW_ABP_clear();
 
649
 
 
650
    /* say goodbye... */
 
651
    if (switchcontact_time < time(NULL)) {
 
652
        switchcontact_time = 0;
 
653
        info("%s: switchtime is in past %lu (now %lu), so deactivated", Name, (unsigned long) switchcontact_time,
 
654
             time(NULL));
 
655
    }
 
656
    if (switchcontact_time == 0) {
 
657
        if (!quiet) {
 
658
            drv_generic_text_greet("goodbye!", NULL);
 
659
        }
 
660
    } else {
 
661
        drv_LW_ABP_write(0, 0, logicway, strlen(logicway));
 
662
        drv_LW_ABP_write(1, 0, switchactive, strlen(switchactive));
 
663
        localtime_r(&switchcontact_time, &switchtime_info);
 
664
        if (strftime(timeinfo, sizeof(timeinfo), "for %a %X", &switchtime_info) > 0) {
 
665
            drv_LW_ABP_write(2, 0, timeinfo, strlen(timeinfo));
 
666
        }
 
667
    }
 
668
 
 
669
    debug("closing connection");
 
670
    drv_LW_ABP_close();
 
671
 
 
672
    return (0);
 
673
}
 
674
 
 
675
 
 
676
/* use this one for a text display */
 
677
DRIVER drv_LW_ABP = {
 
678
    .name = Name,
 
679
    .list = drv_LW_ABP_list,
 
680
    .init = drv_LW_ABP_init,
 
681
    .quit = drv_LW_ABP_quit,
 
682
};