~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to plugin_isdn.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: plugin_isdn.c 840 2007-09-09 12:17:42Z michael $
 
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_isdn.c $
 
3
 *
 
4
 * plugin for ISDN subsystem
 
5
 *
 
6
 * Copyright (C) 2003 Michael Reinelt <michael@reinelt.co.at>
 
7
 * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 
8
 *
 
9
 * Based on the old isdn client (isdn.c) which is
 
10
 * Copyright (C) 1999, 2000 Michael Reinelt <michael@reinelt.co.at>
 
11
 *
 
12
 * This file is part of LCD4Linux.
 
13
 *
 
14
 * LCD4Linux is free software; you can redistribute it and/or modify
 
15
 * it under the terms of the GNU General Public License as published by
 
16
 * the Free Software Foundation; either version 2, or (at your option)
 
17
 * any later version.
 
18
 *
 
19
 * LCD4Linux is distributed in the hope that it will be useful,
 
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 * GNU General Public License for more details.
 
23
 *
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with this program; if not, write to the Free Software
 
26
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
27
 *
 
28
 */
 
29
 
 
30
/* 
 
31
 * exported functions:
 
32
 *
 
33
 * int plugin_init_isdn (void)
 
34
 *  adds functions to access ISDN information
 
35
 *
 
36
 */
 
37
 
 
38
 
 
39
#include "config.h"
 
40
 
 
41
#include <stdlib.h>
 
42
#include <stdio.h>
 
43
#include <string.h>
 
44
#include <unistd.h>
 
45
#include <errno.h>
 
46
#include <fcntl.h>
 
47
#include <sys/ioctl.h>
 
48
#include <sys/types.h>
 
49
 
 
50
#ifdef HAVE_LINUX_ISDN_H
 
51
#include <linux/isdn.h>
 
52
#else
 
53
#warning isdn.h not found. CPS support deactivated.
 
54
#endif
 
55
 
 
56
#include "debug.h"
 
57
#include "plugin.h"
 
58
#include "qprintf.h"
 
59
#include "hash.h"
 
60
 
 
61
 
 
62
typedef struct {
 
63
    unsigned long in;
 
64
    unsigned long out;
 
65
} CPS;
 
66
 
 
67
 
 
68
static HASH ISDN_INFO;
 
69
static HASH ISDN_CPS;
 
70
 
 
71
 
 
72
static void hash_put_info(const char *name, const int channel, const char *val)
 
73
{
 
74
    char key[16];
 
75
 
 
76
    qprintf(key, sizeof(key), "%s[%d]", name, channel);
 
77
    hash_put(&ISDN_INFO, key, val);
 
78
}
 
79
 
 
80
static int parse_isdninfo(void)
 
81
{
 
82
    int age;
 
83
    FILE *stream;
 
84
    long flags;
 
85
 
 
86
    /* reread every 10 msec only */
 
87
    age = hash_age(&ISDN_INFO, NULL);
 
88
    if (age > 0 && age <= 10)
 
89
        return 0;
 
90
 
 
91
    /* open file */
 
92
    stream = fopen("/dev/isdninfo", "r");
 
93
    if (stream == NULL) {
 
94
        error("open(/dev/isdninfo) failed: %s", strerror(errno));
 
95
        return -1;
 
96
    }
 
97
 
 
98
    /* get flags */
 
99
    flags = fcntl(fileno(stream), F_GETFL);
 
100
    if (flags < 0) {
 
101
        error("fcntl(/dev/isdninfo, F_GETFL) failed: %s", strerror(errno));
 
102
        return -1;
 
103
    }
 
104
 
 
105
    /* set O_NONBLOCK */
 
106
    if (fcntl(fileno(stream), F_SETFL, flags | O_NONBLOCK) < 0) {
 
107
        error("fcntl(/dev/isdninfo, F_SETFL, O_NONBLOCK) failed: %s", strerror(errno));
 
108
        return -1;
 
109
    }
 
110
 
 
111
    while (!feof(stream)) {
 
112
        char buffer[4096];
 
113
        char *beg, *end;
 
114
        if (fgets(buffer, sizeof(buffer), stream) == NULL)
 
115
            break;
 
116
        beg = strchr(buffer, ':');
 
117
        if (beg != NULL) {
 
118
            char delim[] = " \t\n";
 
119
            int i = 0;
 
120
            *beg++ = '\0';
 
121
            while (*beg && strchr(delim, *beg))
 
122
                beg++;
 
123
            while (beg && *beg) {
 
124
                if ((end = strpbrk(beg, delim)))
 
125
                    *end = '\0';
 
126
                hash_put_info(buffer, i, beg);
 
127
                beg = end ? end + 1 : NULL;
 
128
                while (*beg && strchr(delim, *beg))
 
129
                    beg++;
 
130
                i++;
 
131
            }
 
132
        } else {
 
133
            error("Huh? no colon found in <%s>", buffer);
 
134
        }
 
135
    }
 
136
 
 
137
    fclose(stream);
 
138
 
 
139
    return 0;
 
140
}
 
141
 
 
142
 
 
143
static void my_isdn_info(RESULT * result, RESULT * arg1, RESULT * arg2)
 
144
{
 
145
    char key[16], *val;
 
146
 
 
147
    if (parse_isdninfo() < 0) {
 
148
        SetResult(&result, R_STRING, "");
 
149
        return;
 
150
    }
 
151
 
 
152
    qprintf(key, sizeof(key), "%s[%d]", R2S(arg1), (int) R2N(arg2));
 
153
    val = hash_get(&ISDN_INFO, key, NULL);
 
154
    if (val == NULL)
 
155
        val = "";
 
156
    SetResult(&result, R_STRING, val);
 
157
}
 
158
 
 
159
 
 
160
#ifdef HAVE_LINUX_ISDN_H
 
161
 
 
162
static void hash_put_cps(const int channel, const CPS * cps)
 
163
{
 
164
    char key[16], val[16];
 
165
 
 
166
    qprintf(key, sizeof(key), channel < 0 ? "i" : "i%d", channel);
 
167
    qprintf(val, sizeof(val), "%u", cps->in);
 
168
    hash_put_delta(&ISDN_CPS, key, val);
 
169
 
 
170
    qprintf(key, sizeof(key), channel < 0 ? "o" : "o%d", channel);
 
171
    qprintf(val, sizeof(val), "%u", cps->out);
 
172
    hash_put_delta(&ISDN_CPS, key, val);
 
173
}
 
174
 
 
175
 
 
176
static int get_cps(void)
 
177
{
 
178
    int age, i;
 
179
    static int fd = -2;
 
180
    CPS cps[ISDN_MAX_CHANNELS];
 
181
    CPS sum;
 
182
 
 
183
    /* reread every 10 msec only */
 
184
    age = hash_age(&ISDN_CPS, NULL);
 
185
    if (age > 0 && age <= 10)
 
186
        return 0;
 
187
 
 
188
    if (fd == -1)
 
189
        return -1;
 
190
 
 
191
    if (fd == -2) {
 
192
        fd = open("/dev/isdninfo", O_RDONLY | O_NDELAY);
 
193
        if (fd == -1) {
 
194
            error("open(/dev/isdninfo) failed: %s", strerror(errno));
 
195
            return -1;
 
196
        }
 
197
    }
 
198
 
 
199
    if (ioctl(fd, IIOCGETCPS, &cps)) {
 
200
        error("ioctl(IIOCGETCPS) failed: %s", strerror(errno));
 
201
        fd = -1;
 
202
        return -1;
 
203
    }
 
204
 
 
205
    sum.in = 0;
 
206
    sum.out = 0;
 
207
    for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 
208
        sum.in += cps[i].in;
 
209
        sum.out += cps[i].out;
 
210
        hash_put_cps(i, &cps[i]);
 
211
    }
 
212
    hash_put_cps(-1, &sum);
 
213
 
 
214
    return 0;
 
215
}
 
216
 
 
217
 
 
218
static void my_isdn_cps(RESULT * result, RESULT * arg1, RESULT * arg2)
 
219
{
 
220
    double value;
 
221
 
 
222
    if (get_cps() < 0) {
 
223
        SetResult(&result, R_STRING, "");
 
224
        return;
 
225
    }
 
226
 
 
227
    value = hash_get_delta(&ISDN_CPS, R2S(arg1), NULL, R2N(arg2));
 
228
    SetResult(&result, R_NUMBER, &value);
 
229
 
 
230
}
 
231
 
 
232
#endif
 
233
 
 
234
 
 
235
int plugin_init_isdn(void)
 
236
{
 
237
    hash_create(&ISDN_INFO);
 
238
    hash_create(&ISDN_CPS);
 
239
 
 
240
    AddFunction("isdn::info", 2, my_isdn_info);
 
241
 
 
242
#ifdef HAVE_LINUX_ISDN_H
 
243
    AddFunction("isdn::cps", 2, my_isdn_cps);
 
244
#endif
 
245
 
 
246
    return 0;
 
247
}
 
248
 
 
249
 
 
250
void plugin_exit_isdn(void)
 
251
{
 
252
    hash_destroy(&ISDN_INFO);
 
253
    hash_destroy(&ISDN_CPS);
 
254
}