~ubuntu-branches/ubuntu/quantal/zaptel/quantal

« back to all changes in this revision

Viewing changes to kernel/xpp/card_fxs.c

  • Committer: Bazaar Package Importer
  • Author(s): Tzafrir Cohen
  • Date: 2008-08-28 22:58:23 UTC
  • mfrom: (11.1.11 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080828225823-r8bdunirm8hmc76m
Tags: 1:1.4.11~dfsg-2
* Patch xpp_fxs_power: Fixed an issue with hook detection of the Astribank
  FXS module.
* Don't fail init.d script if fxotune fails. This may happen if running it
  when Asterisk is already running.
* Bump standards version to 3.8.0.0 .
* Ignore false lintian warning ("m-a a-i" has "a a").
* Patch xpp_fxo_cid_always: do always pass PCM if that's what the user
  asked.
* Patch vzaphfc_proc_root_dir: fix vzaphfc on 2.6.26.
* Patch wcte12xp_flags: Proper time for irq save flags.
* Patch headers_2627: Fix location of semaphore.h for 2.6.27 .
* Patch xpp_fxs_dtmf_leak: Don't play DTMFs to the wrong channel.
* Patch wctdm_fix_alarm: Fix sending channel alarms.
* Patch device_class_2626: Fix building 2.6.26 (Closes: #493397).
* Using dh_lintian for lintian overrides, hence requiring debhelper 6.0.7.
* Lintian: we know we have direct changes. Too bad we're half-upstream :-(
* Fix doc-base section names. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Written by Oron Peled <oron@actcom.co.il>
 
3
 * Copyright (C) 2004-2006, Xorcom
 
4
 *
 
5
 * All rights reserved.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
 *
 
21
 */
 
22
 
 
23
#include <linux/init.h>
 
24
#include <linux/module.h>
 
25
#include <linux/fs.h>
 
26
#include <linux/delay.h>
 
27
#include "xpd.h"
 
28
#include "xproto.h"
 
29
#include "xpp_zap.h"
 
30
#include "card_fxo.h"
 
31
#include "zap_debug.h"
 
32
#include "xbus-core.h"
 
33
 
 
34
static const char rcsid[] = "$Id: card_fxs.c 4266 2008-05-13 21:08:09Z tzafrir $";
 
35
 
 
36
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");   /* must be before zap_debug.h */
 
37
static DEF_PARM_BOOL(reversepolarity, 0, 0644, "Reverse Line Polarity");
 
38
static DEF_PARM_BOOL(vmwineon, 0, 0644, "Indicate voicemail to a neon lamp");
 
39
static DEF_PARM_BOOL(dtmf_detection, 1, 0644, "Do DTMF detection in hardware");
 
40
#ifdef  POLL_DIGITAL_INPUTS
 
41
static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs");
 
42
#endif
 
43
 
 
44
#ifdef  ZT_VMWI
 
45
static DEF_PARM_BOOL(vmwi_ioctl, 0, 0644, "Asterisk support VMWI notification via ioctl");
 
46
#else
 
47
#define vmwi_ioctl      0       /* not supported */
 
48
#endif
 
49
 
 
50
/* Signaling is opposite (fxo signalling for fxs card) */
 
51
#if 1
 
52
#define FXS_DEFAULT_SIGCAP      (ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS)
 
53
#else
 
54
#define FXS_DEFAULT_SIGCAP      (ZT_SIG_SF | ZT_SIG_EM)
 
55
#endif
 
56
 
 
57
#define LINES_DIGI_OUT  2
 
58
#define LINES_DIGI_INP  4
 
59
 
 
60
enum fxs_leds {
 
61
        LED_GREEN,
 
62
        LED_RED,
 
63
        OUTPUT_RELAY,
 
64
};
 
65
 
 
66
#define NUM_LEDS        2
 
67
 
 
68
/* Shortcuts */
 
69
#define SLIC_WRITE      1
 
70
#define SLIC_READ       0
 
71
#define SLIC_DIRECT_REQUEST(xbus,xpd,port,writing,reg,dL)       \
 
72
        xpp_register_request((xbus), (xpd), (port), (writing), (reg), 0, 0, (dL), 0, 0, 0)
 
73
#define SLIC_INDIRECT_REQUEST(xbus,xpd,port,writing,reg,dL,dH)  \
 
74
        xpp_register_request((xbus), (xpd), (port), (writing), 0x1E, 1, (reg), (dL), 1, (dH), 0)
 
75
 
 
76
#define VALID_PORT(port)        (((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST)
 
77
 
 
78
#define REG_DIGITAL_IOCTRL      0x06    /* LED and RELAY control */
 
79
 
 
80
/* Values of SLIC linefeed control register (0x40) */
 
81
enum fxs_state {
 
82
        FXS_LINE_OPEN           = 0x00, /* Open */
 
83
        FXS_LINE_ACTIVE         = 0x01, /* Forward active */
 
84
        FXS_LINE_OHTRANS        = 0x02, /* Forward on-hook transmission */
 
85
        FXS_LINE_TIPOPEN        = 0x03, /* TIP open */
 
86
        FXS_LINE_RING           = 0x04, /* Ringing */
 
87
        FXS_LINE_REV_ACTIVE     = 0x05, /* Reverse active */
 
88
        FXS_LINE_REV_OHTRANS    = 0x06, /* Reverse on-hook transmission */
 
89
        FXS_LINE_RING_OPEN      = 0x07  /* RING open */
 
90
};
 
91
 
 
92
#define FXS_LINE_POL_ACTIVE     ((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE)
 
93
#define FXS_LINE_POL_OHTRANS    ((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS)
 
94
 
 
95
/*
 
96
 * DTMF detection
 
97
 */
 
98
#define REG_DTMF_DECODE         0x18    /* 24 - DTMF Decode Status */
 
99
#define REG_BATTERY             0x42    /* 66 - Battery Feed Control */
 
100
#define REG_BATTERY_BATSL       BIT(1)  /* Battery Feed Select */
 
101
 
 
102
#define REG_LOOPCLOSURE         0x44    /* 68 -  Loop Closure/Ring Trip Detect Status */
 
103
#define REG_LOOPCLOSURE_LCR     BIT(0)  /* Loop Closure Detect Indicator. */
 
104
 
 
105
/*---------------- FXS Protocol Commands ----------------------------------*/
 
106
 
 
107
static /* 0x0F */ DECLARE_CMD(FXS, XPD_STATE, bool on);
 
108
 
 
109
static bool fxs_packet_is_valid(xpacket_t *pack);
 
110
static void fxs_packet_dump(const char *msg, xpacket_t *pack);
 
111
static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
 
112
#ifdef  WITH_METERING
 
113
static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
 
114
#endif
 
115
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
 
116
 
 
117
#define PROC_REGISTER_FNAME     "slics"
 
118
#define PROC_FXS_INFO_FNAME     "fxs_info"
 
119
#ifdef  WITH_METERING
 
120
#define PROC_METERING_FNAME     "metering_gen"
 
121
#endif
 
122
 
 
123
struct FXS_priv_data {
 
124
#ifdef  WITH_METERING
 
125
        struct proc_dir_entry   *meteringfile;
 
126
#endif
 
127
        struct proc_dir_entry   *fxs_info;
 
128
        xpp_line_t              ledstate[NUM_LEDS];     /* 0 - OFF, 1 - ON */
 
129
        xpp_line_t              ledcontrol[NUM_LEDS];   /* 0 - OFF, 1 - ON */
 
130
        xpp_line_t              search_fsk_pattern;
 
131
        xpp_line_t              found_fsk_pattern;
 
132
        xpp_line_t              update_offhook_state;
 
133
        xpp_line_t              want_dtmf_events;       /* what zaptel want */
 
134
        xpp_line_t              want_dtmf_mute;         /* what zaptel want */
 
135
        int                     led_counter[NUM_LEDS][CHANNELS_PERXPD];
 
136
        int                     ohttimer[CHANNELS_PERXPD];
 
137
#define OHT_TIMER               6000    /* How long after RING to retain OHT */
 
138
        enum fxs_state          idletxhookstate[CHANNELS_PERXPD];       /* IDLE changing hook state */
 
139
        enum fxs_state          lasttxhook[CHANNELS_PERXPD];
 
140
};
 
141
 
 
142
/*
 
143
 * LED counter values:
 
144
 *      n>1     : BLINK every n'th tick
 
145
 */
 
146
#define LED_COUNTER(priv,pos,color)     ((priv)->led_counter[color][pos])
 
147
#define IS_BLINKING(priv,pos,color)     (LED_COUNTER(priv,pos,color) > 0)
 
148
#define MARK_BLINK(priv,pos,color,t)    ((priv)->led_counter[color][pos] = (t))
 
149
#define MARK_OFF(priv,pos,color)        do { BIT_CLR((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0)
 
150
#define MARK_ON(priv,pos,color)         do { BIT_SET((priv)->ledcontrol[color],(pos)); MARK_BLINK((priv),(pos),(color),0); } while(0)
 
151
 
 
152
#define LED_BLINK_RING                  (1000/8)        /* in ticks */
 
153
 
 
154
/*---------------- FXS: Static functions ----------------------------------*/
 
155
static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, enum fxs_state value)
 
156
{
 
157
        struct FXS_priv_data    *priv;
 
158
 
 
159
        priv = xpd->priv;
 
160
        LINE_DBG(SIGNAL, xpd, chan, "value=0x%02X\n", value);
 
161
        priv->lasttxhook[chan] = value;
 
162
        return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
 
163
}
 
164
 
 
165
static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
 
166
{
 
167
        int             value = (on) ? REG_BATTERY_BATSL : 0x00;
 
168
 
 
169
        BUG_ON(!xbus);
 
170
        BUG_ON(!xpd);
 
171
        LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
 
172
        return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_BATTERY, value);
 
173
}
 
174
 
 
175
/*
 
176
 * LED and RELAY control is done via SLIC register 0x06:
 
177
 *         7     6     5     4     3     2     1     0
 
178
 *      +-----+-----+-----+-----+-----+-----+-----+-----+
 
179
 *      | M2  | M1  | M3  | C2  | O1  | O3  | C1  | C3  |
 
180
 *      +-----+-----+-----+-----+-----+-----+-----+-----+
 
181
 *
 
182
 *      Cn      - Control bit (control one digital line)
 
183
 *      On      - Output bit (program a digital line for output)
 
184
 *      Mn      - Mask bit (only the matching output control bit is affected)
 
185
 *
 
186
 *      C3      - OUTPUT RELAY (0 - OFF, 1 - ON)
 
187
 *      C1      - GREEN LED (0 - OFF, 1 - ON)
 
188
 *      O3      - Output RELAY (this line is output)
 
189
 *      O1      - Output GREEN (this line is output)
 
190
 *      C2      - RED LED (0 - OFF, 1 - ON)
 
191
 *      M3      - Mask RELAY. (1 - C3 effect the OUTPUT RELAY)
 
192
 *      M2      - Mask RED. (1 - C2 effect the RED LED)
 
193
 *      M1      - Mask GREEN. (1 - C1 effect the GREEN LED)
 
194
 *
 
195
 *      The OUTPUT RELAY (actually a relay out) is connected to line 0 and 4 only.
 
196
 */
 
197
 
 
198
//                                                      GREEN   RED     OUTPUT RELAY
 
199
static const int        led_register_mask[] = {         BIT(7), BIT(6), BIT(5) };
 
200
static const int        led_register_vals[] = {         BIT(4), BIT(1), BIT(0) };
 
201
 
 
202
/*
 
203
 * pos can be:
 
204
 *      - A line number
 
205
 *      - ALL_LINES. This is not valid anymore since 8-Jan-2007.
 
206
 */
 
207
static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on)
 
208
{
 
209
        int                     ret = 0;
 
210
        struct FXS_priv_data    *priv;
 
211
        int                     value;
 
212
        xbus_t                  *xbus;
 
213
 
 
214
        BUG_ON(!xpd);
 
215
        BUG_ON(chan == ALL_LINES);
 
216
        xbus = xpd->xbus;
 
217
        priv = xpd->priv;
 
218
        which = which % NUM_LEDS;
 
219
        if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan))
 
220
                goto out;
 
221
        if(chan == PORT_BROADCAST) {
 
222
                priv->ledstate[which] = (on) ? ~0 : 0;
 
223
        } else {
 
224
                if(on) {
 
225
                        BIT_SET(priv->ledstate[which], chan);
 
226
                } else {
 
227
                        BIT_CLR(priv->ledstate[which], chan);
 
228
                }
 
229
        }
 
230
        LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off");
 
231
        value = BIT(2) | BIT(3);
 
232
        value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
 
233
        if(on)
 
234
                value |= led_register_vals[which];
 
235
        ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE,
 
236
                        REG_DIGITAL_IOCTRL, value);
 
237
out:
 
238
        return ret;
 
239
}
 
240
 
 
241
static void handle_fxs_leds(xpd_t *xpd)
 
242
{
 
243
        int                     i;
 
244
        const enum fxs_leds     colors[] = { LED_GREEN, LED_RED };
 
245
        enum fxs_leds           color;
 
246
        unsigned int            timer_count;
 
247
        struct FXS_priv_data    *priv;
 
248
 
 
249
        BUG_ON(!xpd);
 
250
        priv = xpd->priv;
 
251
        timer_count = xpd->timer_count;
 
252
        for(color = 0; color < ARRAY_SIZE(colors); color++) {
 
253
                for_each_line(xpd, i) {
 
254
                        if(IS_SET(xpd->digital_outputs | xpd->digital_inputs, i))
 
255
                                continue;
 
256
                        if((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) {         // Blinking
 
257
                                int     mod_value = LED_COUNTER(priv, i, color);
 
258
 
 
259
                                if(!mod_value)
 
260
                                        mod_value = DEFAULT_LED_PERIOD;         /* safety value */
 
261
                                // led state is toggled
 
262
                                if((timer_count % mod_value) == 0) {
 
263
                                        LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF");
 
264
                                        if(!IS_SET(priv->ledstate[color], i)) {
 
265
                                                do_led(xpd, i, color, 1);
 
266
                                        } else {
 
267
                                                do_led(xpd, i, color, 0);
 
268
                                        }
 
269
                                }
 
270
                        } else if(IS_SET(priv->ledcontrol[color] & ~priv->ledstate[color], i)) {
 
271
                                                do_led(xpd, i, color, 1);
 
272
                        } else if(IS_SET(~priv->ledcontrol[color] & priv->ledstate[color], i)) {
 
273
                                                do_led(xpd, i, color, 0);
 
274
                        }
 
275
 
 
276
                }
 
277
        }
 
278
}
 
279
 
 
280
static void restore_leds(xpd_t *xpd)
 
281
{
 
282
        struct FXS_priv_data    *priv;
 
283
        int                     i;
 
284
 
 
285
        priv = xpd->priv;
 
286
        for_each_line(xpd, i) {
 
287
                if(IS_SET(xpd->offhook, i))
 
288
                        MARK_ON(priv, i, LED_GREEN);
 
289
                else
 
290
                        MARK_OFF(priv, i, LED_GREEN);
 
291
        }
 
292
}
 
293
 
 
294
#ifdef  WITH_METERING
 
295
static int metering_gen(xpd_t *xpd, lineno_t chan, bool on)
 
296
{
 
297
        byte    value = (on) ? 0x94 : 0x00;
 
298
 
 
299
        LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n", (on)?"ON":"OFF");
 
300
        return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23, value);
 
301
}
 
302
#endif
 
303
 
 
304
/*---------------- FXS: Methods -------------------------------------------*/
 
305
 
 
306
static void fxs_proc_remove(xbus_t *xbus, xpd_t *xpd)
 
307
{
 
308
        struct FXS_priv_data    *priv;
 
309
 
 
310
        BUG_ON(!xpd);
 
311
        priv = xpd->priv;
 
312
#ifdef  CONFIG_PROC_FS
 
313
#ifdef  WITH_METERING
 
314
        if(priv->meteringfile) {
 
315
                XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n");
 
316
                priv->meteringfile->data = NULL;
 
317
                remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
 
318
                priv->meteringfile = NULL;
 
319
        }
 
320
#endif
 
321
        if(priv->fxs_info) {
 
322
                XPD_DBG(PROC, xpd, "Removing xpd FXS_INFO file\n");
 
323
                remove_proc_entry(PROC_FXS_INFO_FNAME, xpd->proc_xpd_dir);
 
324
                priv->fxs_info = NULL;
 
325
        }
 
326
#endif
 
327
}
 
328
 
 
329
static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
 
330
{
 
331
        struct FXS_priv_data    *priv;
 
332
 
 
333
        BUG_ON(!xpd);
 
334
        priv = xpd->priv;
 
335
 
 
336
#ifdef  CONFIG_PROC_FS
 
337
        XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n");
 
338
        priv->fxs_info = create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxs_info_read, xpd);
 
339
        if(!priv->fxs_info) {
 
340
                XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXS_INFO_FNAME);
 
341
                goto err;
 
342
        }
 
343
        priv->fxs_info->owner = THIS_MODULE;
 
344
#ifdef  WITH_METERING
 
345
        XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
 
346
        priv->meteringfile = create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir);
 
347
        if(!priv->meteringfile) {
 
348
                XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME);
 
349
                goto err;
 
350
        }
 
351
        priv->meteringfile->owner = THIS_MODULE;
 
352
        priv->meteringfile->write_proc = proc_xpd_metering_write;
 
353
        priv->meteringfile->read_proc = NULL;
 
354
        priv->meteringfile->data = xpd;
 
355
#endif
 
356
#endif
 
357
        return 0;
 
358
err:
 
359
        return -EINVAL;
 
360
}
 
361
 
 
362
static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table, byte subtype, int subunits, bool to_phone)
 
363
{
 
364
        xpd_t                   *xpd = NULL;
 
365
        int                     channels;
 
366
        int                     regular_channels;
 
367
        struct FXS_priv_data    *priv;
 
368
        int                     i;
 
369
 
 
370
        if(!to_phone) {
 
371
                XBUS_NOTICE(xbus,
 
372
                        "XPD=%d%d: try to instanciate FXS with reverse direction\n",
 
373
                        unit, subunit);
 
374
                return NULL;
 
375
        }
 
376
        if(subtype == 2)
 
377
                regular_channels = min(6, CHANNELS_PERXPD);
 
378
        else
 
379
                regular_channels = min(8, CHANNELS_PERXPD);
 
380
        channels = regular_channels;
 
381
        if(unit == 0)
 
382
                channels += 6;  /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
 
383
        xpd = xpd_alloc(sizeof(struct FXS_priv_data), proto_table, channels);
 
384
        if(!xpd)
 
385
                return NULL;
 
386
        if(unit == 0) {
 
387
                XBUS_DBG(GENERAL, xbus, "First XPD detected. Initialize digital outputs/inputs\n");
 
388
                xpd->digital_outputs = BITMASK(LINES_DIGI_OUT) << regular_channels;
 
389
                xpd->digital_inputs = BITMASK(LINES_DIGI_INP) << (regular_channels + LINES_DIGI_OUT);
 
390
        }
 
391
        xpd->direction = TO_PHONE;
 
392
        xpd->type_name = "FXS";
 
393
        if(xpd_common_init(xbus, xpd, unit, subunit, subtype, subunits) < 0)
 
394
                goto err;
 
395
        if(fxs_proc_create(xbus, xpd) < 0)
 
396
                goto err;
 
397
        priv = xpd->priv;
 
398
        for_each_line(xpd, i) {
 
399
                priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
 
400
        }
 
401
        return xpd;
 
402
err:
 
403
        xpd_free(xpd);
 
404
        return NULL;
 
405
}
 
406
 
 
407
static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
 
408
{
 
409
        struct FXS_priv_data    *priv;
 
410
        int                     ret = 0;
 
411
        int                     i;
 
412
 
 
413
        BUG_ON(!xpd);
 
414
        priv = xpd->priv;
 
415
        /*
 
416
         * Setup ring timers
 
417
         */
 
418
        /* Software controled ringing (for CID) */
 
419
        ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE, 0x22, 0x00);   /* Ringing Oscilator Control */
 
420
        if(ret < 0)
 
421
                goto err;
 
422
        for_each_line(xpd, i) {
 
423
                linefeed_control(xbus, xpd, i, FXS_LINE_POL_ACTIVE);
 
424
        }
 
425
        XPD_DBG(GENERAL, xpd, "done\n");
 
426
        for_each_line(xpd, i) {
 
427
                do_led(xpd, i, LED_GREEN, 0);
 
428
                do_led(xpd, i, LED_RED, 0);
 
429
        }
 
430
        for_each_line(xpd, i) {
 
431
                do_led(xpd, i, LED_GREEN, 1);
 
432
                msleep(50);
 
433
        }
 
434
        for_each_line(xpd, i) {
 
435
                do_led(xpd, i, LED_GREEN, 0);
 
436
                msleep(50);
 
437
        }
 
438
        restore_leds(xpd);
 
439
        pcm_recompute(xpd, 0);
 
440
        /*
 
441
         * We should query our offhook state long enough time after we
 
442
         * set the linefeed_control()
 
443
         * So we do this after the LEDs
 
444
         */
 
445
        for_each_line(xpd, i) {
 
446
                if(IS_SET(xpd->digital_outputs | xpd->digital_inputs, i))
 
447
                        continue;
 
448
                SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_LOOPCLOSURE, 0);
 
449
        }
 
450
        return 0;
 
451
err:
 
452
        fxs_proc_remove(xbus, xpd);
 
453
        XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret);
 
454
        return ret;
 
455
}
 
456
 
 
457
static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd)
 
458
{
 
459
        struct FXS_priv_data    *priv;
 
460
 
 
461
        BUG_ON(!xpd);
 
462
        priv = xpd->priv;
 
463
        XPD_DBG(GENERAL, xpd, "\n");
 
464
        fxs_proc_remove(xbus, xpd);
 
465
        return 0;
 
466
}
 
467
 
 
468
static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on)
 
469
{
 
470
        xbus_t                  *xbus;
 
471
        struct FXS_priv_data    *priv;
 
472
        int                     i;
 
473
 
 
474
        BUG_ON(!xpd);
 
475
        xbus = xpd->xbus;
 
476
        BUG_ON(!xbus);
 
477
        priv = xpd->priv;
 
478
        BUG_ON(!priv);
 
479
        XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off");
 
480
#ifdef ZT_SPANSTAT_V2 
 
481
        xpd->span.spantype = "FXS";
 
482
#endif 
 
483
        for_each_line(xpd, i) {
 
484
                struct zt_chan  *cur_chan = &xpd->chans[i];
 
485
 
 
486
                XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i);
 
487
                if(IS_SET(xpd->digital_outputs, i)) {
 
488
                        snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%02d/%1d%1d/%d",
 
489
                                xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
 
490
                } else if(IS_SET(xpd->digital_inputs, i)) {
 
491
                        snprintf(cur_chan->name, MAX_CHANNAME, "XPP_IN/%02d/%1d%1d/%d",
 
492
                                xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
 
493
                } else {
 
494
                        snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%02d/%1d%1d/%d",
 
495
                                xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
 
496
                }
 
497
                cur_chan->chanpos = i + 1;
 
498
                cur_chan->pvt = xpd;
 
499
                cur_chan->sigcap = FXS_DEFAULT_SIGCAP;
 
500
        }
 
501
        for_each_line(xpd, i) {
 
502
                MARK_ON(priv, i, LED_GREEN);
 
503
                msleep(4);
 
504
                MARK_ON(priv, i, LED_RED);
 
505
        }
 
506
        return 0;
 
507
}
 
508
 
 
509
static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on)
 
510
{
 
511
        xbus_t                  *xbus;
 
512
        struct FXS_priv_data    *priv;
 
513
        int                     i;
 
514
 
 
515
        BUG_ON(!xpd);
 
516
        xbus = xpd->xbus;
 
517
        BUG_ON(!xbus);
 
518
        priv = xpd->priv;
 
519
        BUG_ON(!priv);
 
520
        XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off");
 
521
        for_each_line(xpd, i) {
 
522
                MARK_OFF(priv, i, LED_GREEN);
 
523
                msleep(2);
 
524
                MARK_OFF(priv, i, LED_RED);
 
525
                msleep(2);
 
526
        }
 
527
        restore_leds(xpd);
 
528
        return 0;
 
529
}
 
530
 
 
531
/*
 
532
 * Called with XPD spinlocked
 
533
 */
 
534
static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
 
535
{
 
536
        LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE");
 
537
        if(muteit)
 
538
                BIT_SET(xpd->mute_dtmf, pos);
 
539
        else
 
540
                BIT_CLR(xpd->mute_dtmf, pos);
 
541
}
 
542
 
 
543
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, int on)
 
544
{
 
545
        int     ret = 0;
 
546
        BUG_ON(!xbus);
 
547
        BUG_ON(!xpd);
 
548
 
 
549
        LINE_DBG(SIGNAL, xpd, pos, "%s%s\n", (on)?"ON":"OFF", (vmwineon)?"":" (Ignored)");
 
550
        if (!vmwineon)
 
551
                return 0;
 
552
        if (on) {
 
553
                /* A write to register 0x40 will now turn on/off the VM led */
 
554
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03);
 
555
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B);
 
556
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00);
 
557
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19);
 
558
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
 
559
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0);
 
560
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01);
 
561
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0);
 
562
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05);
 
563
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x46);
 
564
        } else {
 
565
                /* A write to register 0x40 will now turn on/off the ringer */
 
566
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00);
 
567
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x60, 0x01);
 
568
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xF0, 0x7E);
 
569
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x00);
 
570
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
 
571
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
 
572
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
 
573
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
 
574
                ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
 
575
                ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x36);
 
576
        }
 
577
 
 
578
        return (ret ? -EPROTO : 0);
 
579
}
 
580
 
 
581
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
 
582
{
 
583
        struct FXS_priv_data    *priv;
 
584
        bool            on;
 
585
 
 
586
        BUG_ON(!xpd);
 
587
        if (!vmwineon || IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
 
588
                return;
 
589
        priv = xpd->priv;
 
590
        on = IS_SET(xpd->msg_waiting, pos);
 
591
        LINE_DBG(SIGNAL, xpd, pos, "%s\n", (on)?"ON":"OFF");
 
592
        set_vm_led_mode(xbus, xpd, pos, on);
 
593
        do_chan_power(xbus, xpd, pos, on);
 
594
        linefeed_control(xbus, xpd, pos, (on) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
 
595
}
 
596
 
 
597
static int relay_out(xpd_t *xpd, int pos, bool on)
 
598
{
 
599
        int             value;
 
600
        int             which = pos;
 
601
        int             relay_channels[] = { 0, 4 };
 
602
 
 
603
        BUG_ON(!xpd);
 
604
        /* map logical position to output port number (0/1) */
 
605
        which -= (xpd->subtype == 2) ? 6 : 8;
 
606
        LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which, (on) ? "on" : "off");
 
607
        which = which % ARRAY_SIZE(relay_channels);
 
608
        value = BIT(2) | BIT(3);
 
609
        value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
 
610
        if(on)
 
611
                value |= led_register_vals[OUTPUT_RELAY];
 
612
        return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels[which],
 
613
                        SLIC_WRITE, REG_DIGITAL_IOCTRL, value);
 
614
}
 
615
 
 
616
static int send_ring(xpd_t *xpd, lineno_t chan, bool on)
 
617
{
 
618
        int                     ret = 0;
 
619
        xbus_t                  *xbus;
 
620
        struct FXS_priv_data    *priv;
 
621
        enum fxs_state          value = (on) ? FXS_LINE_RING : FXS_LINE_POL_ACTIVE;
 
622
 
 
623
        BUG_ON(!xpd);
 
624
        xbus = xpd->xbus;
 
625
        BUG_ON(!xbus);
 
626
        LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on)?"on":"off");
 
627
        priv = xpd->priv;
 
628
        set_vm_led_mode(xbus, xpd, chan, 0);
 
629
        do_chan_power(xbus, xpd, chan, on);             // Power up (for ring)
 
630
        ret = linefeed_control(xbus, xpd, chan, value);
 
631
        if(on) {
 
632
                MARK_BLINK(priv, chan, LED_GREEN, LED_BLINK_RING);
 
633
        } else {
 
634
                if(IS_BLINKING(priv, chan, LED_GREEN))
 
635
                        MARK_BLINK(priv, chan, LED_GREEN, 0);
 
636
        }
 
637
        return ret;
 
638
}
 
639
 
 
640
static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
 
641
{
 
642
        struct FXS_priv_data    *priv;
 
643
        int                     ret = 0;
 
644
        struct zt_chan          *chan = NULL;
 
645
        enum fxs_state          txhook;
 
646
        unsigned long           flags;
 
647
 
 
648
        LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
 
649
        priv = xpd->priv;
 
650
        BUG_ON(xpd->direction != TO_PHONE);
 
651
        if (IS_SET(xpd->digital_inputs, pos)) {
 
652
                LINE_DBG(SIGNAL, xpd, pos, "Ignoring signal sent to digital input line\n");
 
653
                return 0;
 
654
        }
 
655
        if(SPAN_REGISTERED(xpd))
 
656
                chan = &xpd->span.chans[pos];
 
657
        switch(txsig) {
 
658
                case ZT_TXSIG_ONHOOK:
 
659
                        spin_lock_irqsave(&xpd->lock, flags);
 
660
                        xpd->ringing[pos] = 0;
 
661
                        BIT_CLR(xpd->cid_on, pos);
 
662
                        BIT_CLR(priv->search_fsk_pattern, pos);
 
663
                        BIT_CLR(priv->want_dtmf_events, pos);
 
664
                        BIT_CLR(priv->want_dtmf_mute, pos);
 
665
                        __do_mute_dtmf(xpd, pos, 0);
 
666
                        __pcm_recompute(xpd, 0);        /* already spinlocked */
 
667
                        spin_unlock_irqrestore(&xpd->lock, flags);
 
668
                        if(IS_SET(xpd->digital_outputs, pos)) {
 
669
                                LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output OFF\n", txsig2str(txsig));
 
670
                                ret = relay_out(xpd, pos, 0);
 
671
                                return ret;
 
672
                        }
 
673
                        if (priv->lasttxhook[pos] == FXS_LINE_OPEN) {
 
674
                                /*
 
675
                                 * Restore state after KEWL hangup.
 
676
                                 */
 
677
                                LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n");
 
678
                                linefeed_control(xbus, xpd, pos, FXS_LINE_POL_ACTIVE);
 
679
                                if(IS_SET(xpd->offhook, pos))
 
680
                                        MARK_ON(priv, pos, LED_GREEN);
 
681
                        }
 
682
                        ret = send_ring(xpd, pos, 0);                   // RING off
 
683
                        if (!IS_SET(xpd->offhook, pos))
 
684
                                start_stop_vm_led(xbus, xpd, pos);
 
685
                        txhook = priv->lasttxhook[pos];
 
686
                        if(chan) {
 
687
                                switch(chan->sig) {
 
688
                                        case ZT_SIG_EM:
 
689
                                        case ZT_SIG_FXOKS:
 
690
                                        case ZT_SIG_FXOLS:
 
691
                                                txhook = priv->idletxhookstate[pos];
 
692
                                                break;
 
693
                                        case ZT_SIG_FXOGS:
 
694
                                                txhook = FXS_LINE_TIPOPEN;
 
695
                                                break;
 
696
                                }
 
697
                        }
 
698
                        ret = linefeed_control(xbus, xpd, pos, txhook);
 
699
                        break;
 
700
                case ZT_TXSIG_OFFHOOK:
 
701
                        if(IS_SET(xpd->digital_outputs, pos)) {
 
702
                                LINE_NOTICE(xpd, pos, "%s -> Is digital output. Ignored\n", txsig2str(txsig));
 
703
                                return -EINVAL;
 
704
                        }
 
705
                        txhook = priv->lasttxhook[pos];
 
706
                        if(xpd->ringing[pos]) {
 
707
                                BIT_SET(xpd->cid_on, pos);
 
708
                                pcm_recompute(xpd, 0);
 
709
                                txhook = FXS_LINE_OHTRANS;
 
710
                        }
 
711
                        xpd->ringing[pos] = 0;
 
712
                        if(chan) {
 
713
                                switch(chan->sig) {
 
714
                                        case ZT_SIG_EM:
 
715
                                                txhook = FXS_LINE_POL_ACTIVE;
 
716
                                                break;
 
717
                                        default:
 
718
                                                txhook = priv->idletxhookstate[pos];
 
719
                                                break;
 
720
                                }
 
721
                        }
 
722
                        ret = linefeed_control(xbus, xpd, pos, txhook);
 
723
                        break;
 
724
                case ZT_TXSIG_START:
 
725
                        xpd->ringing[pos] = 1;
 
726
                        BIT_CLR(xpd->cid_on, pos);
 
727
                        BIT_CLR(priv->search_fsk_pattern, pos);
 
728
                        pcm_recompute(xpd, 0);
 
729
                        if(IS_SET(xpd->digital_outputs, pos)) {
 
730
                                LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output ON\n", txsig2str(txsig));
 
731
                                ret = relay_out(xpd, pos, 1);
 
732
                                return ret;
 
733
                        }
 
734
                        ret = send_ring(xpd, pos, 1);                   // RING on
 
735
                        break;
 
736
                case ZT_TXSIG_KEWL:
 
737
                        if(IS_SET(xpd->digital_outputs, pos)) {
 
738
                                LINE_DBG(SIGNAL, xpd, pos, "%s -> Is digital output. Ignored\n", txsig2str(txsig));
 
739
                                return -EINVAL;
 
740
                        }
 
741
                        linefeed_control(xbus, xpd, pos, FXS_LINE_OPEN);
 
742
                        MARK_OFF(priv, pos, LED_GREEN);
 
743
                        break;
 
744
                default:
 
745
                        XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n",
 
746
                                __FUNCTION__, txsig2str(txsig), txsig);
 
747
                        ret = -EINVAL;
 
748
        }
 
749
        return ret;
 
750
}
 
751
 
 
752
/*
 
753
 * Private ioctl()
 
754
 * We don't need it now, since we detect vmwi via FSK patterns
 
755
 */
 
756
static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
 
757
{
 
758
        struct FXS_priv_data    *priv;
 
759
        xbus_t                  *xbus;
 
760
        int                     val;
 
761
        unsigned long           flags;
 
762
 
 
763
        BUG_ON(!xpd);
 
764
        priv = xpd->priv;
 
765
        BUG_ON(!priv);
 
766
        xbus = xpd->xbus;
 
767
        BUG_ON(!xbus);
 
768
        if(!TRANSPORT_RUNNING(xbus))
 
769
                return -ENODEV;
 
770
        if (pos < 0 || pos >= xpd->channels) {
 
771
                XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n",
 
772
                        pos, __FUNCTION__, cmd);
 
773
                return -EINVAL;
 
774
        }
 
775
        
 
776
        switch (cmd) {
 
777
                case ZT_ONHOOKTRANSFER:
 
778
                        if (get_user(val, (int __user *)arg))
 
779
                                return -EFAULT;
 
780
                        LINE_DBG(SIGNAL, xpd, pos, "ZT_ONHOOKTRANSFER (%d millis)\n", val);
 
781
                        if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
 
782
                                return 0;       /* Nothing to do */
 
783
                        BIT_CLR(xpd->cid_on, pos);
 
784
                        if(priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE) {
 
785
                                priv->ohttimer[pos] = OHT_TIMER;
 
786
                                priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS;
 
787
                                BIT_SET(priv->search_fsk_pattern, pos);
 
788
                                pcm_recompute(xpd, priv->search_fsk_pattern);
 
789
                        }
 
790
                        if(!IS_SET(xpd->offhook, pos))
 
791
                                start_stop_vm_led(xbus, xpd, pos);
 
792
                        return 0;
 
793
                case ZT_TONEDETECT:
 
794
                        if (get_user(val, (int __user *)arg))
 
795
                                return -EFAULT;
 
796
                        LINE_DBG(SIGNAL, xpd, pos, "ZT_TONEDETECT: %s %s (dtmf_detection=%s)\n",
 
797
                                        (val & ZT_TONEDETECT_ON) ? "ON" : "OFF",
 
798
                                        (val & ZT_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE",
 
799
                                        (dtmf_detection ? "YES" : "NO"));
 
800
                        if(!dtmf_detection) {
 
801
                                spin_lock_irqsave(&xpd->lock, flags);
 
802
                                if(IS_SET(priv->want_dtmf_events, pos)) {
 
803
                                        /* Detection mode changed: Disable DTMF interrupts */
 
804
                                        SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0);
 
805
                                }
 
806
                                BIT_CLR(priv->want_dtmf_events, pos);
 
807
                                BIT_CLR(priv->want_dtmf_mute, pos);
 
808
                                __do_mute_dtmf(xpd, pos, 0);
 
809
                                __pcm_recompute(xpd, 0);        /* already spinlocked */
 
810
                                spin_unlock_irqrestore(&xpd->lock, flags);
 
811
                                return -ENOTTY;
 
812
                        }
 
813
                        /*
 
814
                         * During natively bridged calls, Asterisk
 
815
                         * will request one of the sides to stop sending
 
816
                         * dtmf events. Check the requested state.
 
817
                         */
 
818
                        spin_lock_irqsave(&xpd->lock, flags);
 
819
                        if(val & ZT_TONEDETECT_ON) {
 
820
                                if(!IS_SET(priv->want_dtmf_events, pos)) {
 
821
                                        /* Detection mode changed: Enable DTMF interrupts */
 
822
                                        LINE_DBG(SIGNAL, xpd, pos,
 
823
                                                "ZT_TONEDETECT: Enable Hardware DTMF\n");
 
824
                                        SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 1);
 
825
                                }
 
826
                                BIT_SET(priv->want_dtmf_events, pos);
 
827
                        } else {
 
828
                                if(IS_SET(priv->want_dtmf_events, pos)) {
 
829
                                        /* Detection mode changed: Disable DTMF interrupts */
 
830
                                        LINE_DBG(SIGNAL, xpd, pos,
 
831
                                                "ZT_TONEDETECT: Disable Hardware DTMF\n");
 
832
                                        SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0);
 
833
                                }
 
834
                                BIT_CLR(priv->want_dtmf_events, pos);
 
835
                        }
 
836
                        if(val & ZT_TONEDETECT_MUTE) {
 
837
                                BIT_SET(priv->want_dtmf_mute, pos);
 
838
                        } else {
 
839
                                BIT_CLR(priv->want_dtmf_mute, pos);
 
840
                                __do_mute_dtmf(xpd, pos, 0);
 
841
                                __pcm_recompute(xpd, 0);
 
842
                        }
 
843
                        spin_unlock_irqrestore(&xpd->lock, flags);
 
844
                        return 0;
 
845
                case ZT_SETPOLARITY:
 
846
                        if (get_user(val, (int __user *)arg))
 
847
                                return -EFAULT;
 
848
                        /* Can't change polarity while ringing or when open */
 
849
                        if (priv->lasttxhook[pos] == FXS_LINE_RING || priv->lasttxhook[pos] == FXS_LINE_OPEN) {
 
850
                                LINE_ERR(xpd, pos, "ZT_SETPOLARITY: %s Cannot change when lasttxhook=0x%X\n",
 
851
                                                (val)?"ON":"OFF", priv->lasttxhook[pos]);
 
852
                                return -EINVAL;
 
853
                        }
 
854
                        LINE_DBG(SIGNAL, xpd, pos, "ZT_SETPOLARITY: %s\n", (val)?"ON":"OFF");
 
855
                        if ((val && !reversepolarity) || (!val && reversepolarity))
 
856
                                priv->lasttxhook[pos] |= FXS_LINE_RING;
 
857
                        else
 
858
                                priv->lasttxhook[pos] &= ~FXS_LINE_RING;
 
859
                        linefeed_control(xbus, xpd, pos, priv->lasttxhook[pos]);
 
860
                        return 0;
 
861
#ifdef  ZT_VMWI
 
862
                case ZT_VMWI:           /* message-waiting led control */
 
863
                        if (get_user(val, (int __user *)arg))
 
864
                                return -EFAULT;
 
865
                        if(!vmwi_ioctl) {
 
866
                                LINE_NOTICE(xpd, pos, "Got ZT_VMWI notification but vmwi_ioctl parameter is off. Ignoring.\n");
 
867
                                return 0;
 
868
                        }
 
869
                        /* Digital inputs/outputs don't have VM leds */
 
870
                        if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
 
871
                                return 0;
 
872
                        if (val)
 
873
                                BIT_SET(xpd->msg_waiting, pos);
 
874
                        else
 
875
                                BIT_CLR(xpd->msg_waiting, pos);
 
876
                        return 0;
 
877
#endif
 
878
                default:
 
879
                        report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
 
880
        }
 
881
        return -ENOTTY;
 
882
}
 
883
 
 
884
static int FXS_card_open(xpd_t *xpd, lineno_t chan)
 
885
{
 
886
        struct FXS_priv_data    *priv;
 
887
        bool                    is_offhook;
 
888
 
 
889
        BUG_ON(!xpd);
 
890
        priv = xpd->priv;
 
891
        is_offhook = IS_SET(xpd->offhook, chan);
 
892
        if(is_offhook)
 
893
                LINE_NOTICE(xpd, chan, "Already offhook during open. OK.\n");
 
894
        else
 
895
                LINE_DBG(SIGNAL, xpd, chan, "is onhook\n");
 
896
        /*
 
897
         * Delegate updating zaptel to FXS_card_tick():
 
898
         *   The problem is that zt_hooksig() is spinlocking the channel and
 
899
         *   we are called by zaptel with the spinlock already held on the
 
900
         *   same channel.
 
901
         */
 
902
        BIT_SET(priv->update_offhook_state, chan);
 
903
        return 0;
 
904
}
 
905
 
 
906
static int FXS_card_close(xpd_t *xpd, lineno_t chan)
 
907
{
 
908
        struct FXS_priv_data    *priv;
 
909
 
 
910
        BUG_ON(!xpd);
 
911
        LINE_DBG(GENERAL, xpd, chan, "\n");
 
912
        priv = xpd->priv;
 
913
        priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE;
 
914
        return 0;
 
915
}
 
916
 
 
917
#ifdef  POLL_DIGITAL_INPUTS
 
918
/*
 
919
 * INPUT polling is done via SLIC register 0x06 (same as LEDS):
 
920
 *         7     6     5     4     3     2     1     0
 
921
 *      +-----+-----+-----+-----+-----+-----+-----+-----+
 
922
 *      | I1  | I3  |     |     | I2  | I4  |     |     |
 
923
 *      +-----+-----+-----+-----+-----+-----+-----+-----+
 
924
 *
 
925
 */
 
926
static int      input_channels[] = { 6, 7, 2, 3 };      // Slic numbers of input relays
 
927
 
 
928
static void poll_inputs(xpd_t *xpd)
 
929
{
 
930
        int     i;
 
931
 
 
932
        BUG_ON(xpd->xbus_idx != 0);     // Only unit #0 has digital inputs
 
933
        for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
 
934
                byte    pos = input_channels[i];
 
935
 
 
936
                SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_READ, 0x06, 0);
 
937
        }
 
938
}
 
939
#endif
 
940
 
 
941
static void handle_linefeed(xpd_t *xpd)
 
942
{
 
943
        struct FXS_priv_data    *priv;
 
944
        int                     i;
 
945
 
 
946
        BUG_ON(!xpd);
 
947
        priv = xpd->priv;
 
948
        BUG_ON(!priv);
 
949
        for_each_line(xpd, i) {
 
950
                if (priv->lasttxhook[i] == FXS_LINE_RING) {
 
951
                        /* RINGing, prepare for OHT */
 
952
                        priv->ohttimer[i] = OHT_TIMER;
 
953
                        priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS;
 
954
                } else {
 
955
                        if (priv->ohttimer[i]) {
 
956
                                priv->ohttimer[i]--;
 
957
                                if (!priv->ohttimer[i]) {
 
958
                                        priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
 
959
                                        BIT_CLR(xpd->cid_on, i);
 
960
                                        BIT_CLR(priv->search_fsk_pattern, i);
 
961
                                        pcm_recompute(xpd, 0);
 
962
                                        if (priv->lasttxhook[i] == FXS_LINE_POL_OHTRANS) {
 
963
                                                /* Apply the change if appropriate */
 
964
                                                linefeed_control(xpd->xbus, xpd, i, FXS_LINE_POL_ACTIVE);
 
965
                                        }
 
966
                                }
 
967
                        }
 
968
                }
 
969
        }
 
970
}
 
971
 
 
972
/*
 
973
 * Optimized memcmp() like function. Only test for equality (true/false).
 
974
 * This optimization reduced the detect_vmwi() runtime by a factor of 3.
 
975
 */
 
976
static inline bool mem_equal(const char a[], const char b[], size_t len)
 
977
{
 
978
        int     i;
 
979
 
 
980
        for(i = 0; i < len; i++)
 
981
                if(a[i] != b[i])
 
982
                        return 0;
 
983
        return 1;
 
984
}
 
985
 
 
986
/*
 
987
 * Detect Voice Mail Waiting Indication
 
988
 */
 
989
static void detect_vmwi(xpd_t *xpd)
 
990
{
 
991
        struct FXS_priv_data    *priv;
 
992
        xbus_t                  *xbus;
 
993
        static const byte       FSK_COMMON_PATTERN[] = { 0xA8, 0x49, 0x22, 0x3B, 0x9F, 0xFF, 0x1F, 0xBB };
 
994
        static const byte       FSK_ON_PATTERN[] = { 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF };
 
995
        static const byte       FSK_OFF_PATTERN[] = { 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F };
 
996
        int                     i;
 
997
 
 
998
        BUG_ON(!xpd);
 
999
        xbus = xpd->xbus;
 
1000
        priv = xpd->priv;
 
1001
        BUG_ON(!priv);
 
1002
        for_each_line(xpd, i) {
 
1003
                struct zt_chan  *chan = &xpd->span.chans[i];
 
1004
                byte            *writechunk = chan->writechunk;
 
1005
 
 
1006
                if(IS_SET(xpd->offhook | xpd->cid_on | xpd->digital_inputs | xpd->digital_outputs, i))
 
1007
                        continue;
 
1008
#if 0
 
1009
                if(writechunk[0] != 0x7F && writechunk[0] != 0) {
 
1010
                        int     j;
 
1011
 
 
1012
                        LINE_DBG(GENERAL, xpd, pos, "MSG:");
 
1013
                        for(j = 0; j < ZT_CHUNKSIZE; j++) {
 
1014
                                if(debug)
 
1015
                                        printk(" %02X", writechunk[j]);
 
1016
                        }
 
1017
                        if(debug)
 
1018
                                printk("\n");
 
1019
                }
 
1020
#endif
 
1021
                if(unlikely(mem_equal(writechunk, FSK_COMMON_PATTERN, ZT_CHUNKSIZE)))
 
1022
                        BIT_SET(priv->found_fsk_pattern, i);
 
1023
                else if(unlikely(IS_SET(priv->found_fsk_pattern, i))) {
 
1024
                        BIT_CLR(priv->found_fsk_pattern, i);
 
1025
                        if(unlikely(mem_equal(writechunk, FSK_ON_PATTERN, ZT_CHUNKSIZE))) {
 
1026
                                LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n");
 
1027
                                BIT_SET(xpd->msg_waiting, i);
 
1028
                                start_stop_vm_led(xbus, xpd, i);
 
1029
                        } else if(unlikely(mem_equal(writechunk, FSK_OFF_PATTERN, ZT_CHUNKSIZE))) {
 
1030
                                LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n");
 
1031
                                BIT_CLR(xpd->msg_waiting, i);
 
1032
                                start_stop_vm_led(xbus, xpd, i);
 
1033
                        } else {
 
1034
                                int     j;
 
1035
 
 
1036
                                LINE_NOTICE(xpd, i, "MSG WAITING Unexpected:");
 
1037
                                for(j = 0; j < ZT_CHUNKSIZE; j++) {
 
1038
                                        printk(" %02X", writechunk[j]);
 
1039
                                }
 
1040
                                printk("\n");
 
1041
                        }
 
1042
                }
 
1043
        }
 
1044
}
 
1045
 
 
1046
static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
 
1047
{
 
1048
        struct FXS_priv_data    *priv;
 
1049
 
 
1050
        BUG_ON(!xpd);
 
1051
        priv = xpd->priv;
 
1052
        BUG_ON(!priv);
 
1053
#ifdef  POLL_DIGITAL_INPUTS
 
1054
        if(poll_digital_inputs && xpd->xbus_idx == 0) {
 
1055
                if((xpd->timer_count % poll_digital_inputs) == 0)
 
1056
                        poll_inputs(xpd);
 
1057
        }
 
1058
#endif
 
1059
        handle_fxs_leds(xpd);
 
1060
        handle_linefeed(xpd);
 
1061
        if(priv->update_offhook_state) {        /* set in FXS_card_open() */
 
1062
                int     i;
 
1063
 
 
1064
                for_each_line(xpd, i) {
 
1065
                        if(!IS_SET(priv->update_offhook_state, i))
 
1066
                                continue;
 
1067
                        /*
 
1068
                         * Update zaptel with current state of line.
 
1069
                         */
 
1070
                        if(IS_SET(xpd->offhook, i)) {
 
1071
                                update_line_status(xpd, i, 1);
 
1072
                        } else {
 
1073
                                update_line_status(xpd, i, 0);
 
1074
                        }
 
1075
                        BIT_CLR(priv->update_offhook_state, i);
 
1076
                }
 
1077
        }
 
1078
        if(SPAN_REGISTERED(xpd)) {
 
1079
                if(vmwineon && !vmwi_ioctl)
 
1080
                        detect_vmwi(xpd);       /* Detect via FSK modulation */
 
1081
        }
 
1082
        return 0;
 
1083
}
 
1084
 
 
1085
/*---------------- FXS: HOST COMMANDS -------------------------------------*/
 
1086
 
 
1087
static /* 0x0F */ HOSTCMD(FXS, XPD_STATE, bool on)
 
1088
{
 
1089
        BUG_ON(!xbus);
 
1090
        BUG_ON(!xpd);
 
1091
        XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off");
 
1092
        return 0;
 
1093
}
 
1094
 
 
1095
/*---------------- FXS: Astribank Reply Handlers --------------------------*/
 
1096
 
 
1097
/*
 
1098
 * Should be called with spinlocked XPD
 
1099
 */
 
1100
static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, xpp_line_t change_mask)
 
1101
{
 
1102
        xbus_t                  *xbus;
 
1103
        struct FXS_priv_data    *priv;
 
1104
        int                     i;
 
1105
 
 
1106
        BUG_ON(!xpd);
 
1107
        BUG_ON(xpd->direction != TO_PHONE);
 
1108
        xbus = xpd->xbus;
 
1109
        priv = xpd->priv;
 
1110
        XPD_DBG(SIGNAL, xpd, "offhook=0x%X change_mask=0x%X\n", offhook, change_mask);
 
1111
        for_each_line(xpd, i) {
 
1112
                if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
 
1113
                        continue;
 
1114
                if(IS_SET(change_mask, i)) {
 
1115
                        xpd->ringing[i] = 0;            /* No more ringing... */
 
1116
#ifdef  WITH_METERING
 
1117
                        metering_gen(xpd, i, 0);        /* Stop metering... */
 
1118
#endif
 
1119
                        MARK_BLINK(priv, i, LED_GREEN, 0);
 
1120
                        if(IS_SET(offhook, i)) {
 
1121
                                LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n");
 
1122
                                MARK_ON(priv, i, LED_GREEN);
 
1123
                                update_line_status(xpd, i, 1);
 
1124
                        } else {
 
1125
                                LINE_DBG(SIGNAL, xpd, i, "ONHOOK\n");
 
1126
                                MARK_OFF(priv, i, LED_GREEN);
 
1127
                                update_line_status(xpd, i, 0);
 
1128
                        }
 
1129
                }
 
1130
        }
 
1131
        __pcm_recompute(xpd, 0);        /* in a spinlock */
 
1132
}
 
1133
 
 
1134
HANDLER_DEF(FXS, SIG_CHANGED)
 
1135
{
 
1136
        xpp_line_t              sig_status = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_status);
 
1137
        xpp_line_t              sig_toggles = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_toggles);
 
1138
        unsigned long           flags;
 
1139
 
 
1140
        BUG_ON(!xpd);
 
1141
        BUG_ON(xpd->direction != TO_PHONE);
 
1142
        XPD_DBG(SIGNAL, xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status);
 
1143
#if 0
 
1144
        Is this needed?
 
1145
        for_each_line(xpd, i) {
 
1146
                if(IS_SET(sig_toggles, i))
 
1147
                        do_chan_power(xpd->xbus, xpd, BIT(i), 0);               // Power down (prevent overheating!!!)
 
1148
        }
 
1149
#endif
 
1150
        spin_lock_irqsave(&xpd->lock, flags);
 
1151
        process_hookstate(xpd, sig_status, sig_toggles);
 
1152
        spin_unlock_irqrestore(&xpd->lock, flags);
 
1153
        return 0;
 
1154
}
 
1155
 
 
1156
#ifdef  POLL_DIGITAL_INPUTS
 
1157
static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
 
1158
{
 
1159
        int             i;
 
1160
        bool            offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
 
1161
        xpp_line_t      lines = BIT(info->portnum);
 
1162
 
 
1163
        /* Map SLIC number into line number */
 
1164
        for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
 
1165
                int             channo = input_channels[i];
 
1166
                int             newchanno;
 
1167
 
 
1168
                if(IS_SET(lines, channo)) {
 
1169
                        newchanno = xpd->channels - LINES_DIGI_INP + i;
 
1170
                        BIT_CLR(lines, channo);
 
1171
                        BIT_SET(lines, newchanno);
 
1172
                        xpd->ringing[newchanno] = 0;                    // Stop ringing. No leds for digital inputs.
 
1173
                        if(offhook && !IS_SET(xpd->offhook, newchanno)) {               // OFFHOOK
 
1174
                                LINE_DBG(SIGNAL, xpd, newchanno, "OFFHOOK\n");
 
1175
                                update_line_status(xpd, newchanno, 1);
 
1176
                        } else if(!offhook && IS_SET(xpd->offhook, newchanno)) {        // ONHOOK
 
1177
                                LINE_DBG(SIGNAL, xpd, newchanno, "ONHOOK\n");
 
1178
                                update_line_status(xpd, newchanno, 0);
 
1179
                        }
 
1180
                }
 
1181
        }
 
1182
}
 
1183
#endif
 
1184
 
 
1185
static const char dtmf_digits[] = {
 
1186
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#', 'A', 'B', 'C', 'D'
 
1187
};
 
1188
 
 
1189
/*
 
1190
 * This function is called with spinlocked XPD
 
1191
 */
 
1192
static void process_dtmf(xpd_t *xpd, xpp_line_t lines, byte val)
 
1193
{
 
1194
        int                     i;
 
1195
        byte                    digit;
 
1196
        bool                    is_down = val & 0x10;
 
1197
        struct FXS_priv_data    *priv;
 
1198
 
 
1199
        if(!dtmf_detection)
 
1200
                return;
 
1201
        if(!SPAN_REGISTERED(xpd))
 
1202
                return;
 
1203
        priv = xpd->priv;
 
1204
        val &= 0xF;
 
1205
        if(val <= 0) {
 
1206
                if(is_down)
 
1207
                        XPD_NOTICE(xpd, "Bad DTMF value %d. Ignored\n", val);
 
1208
                return;
 
1209
        }
 
1210
        val--;
 
1211
        digit = dtmf_digits[val];
 
1212
        for_each_line(xpd, i) {
 
1213
                if(IS_SET(lines, i)) {
 
1214
                        int             event = (is_down) ? ZT_EVENT_DTMFDOWN : ZT_EVENT_DTMFUP;
 
1215
                        bool            want_mute = IS_SET(priv->want_dtmf_mute, i);
 
1216
                        bool            want_event = IS_SET(priv->want_dtmf_events, i);
 
1217
 
 
1218
                        if(want_event) {
 
1219
                                LINE_DBG(SIGNAL, xpd, i,
 
1220
                                        "DTMF digit %s (val=%d) '%c' (want_mute=%s)\n",
 
1221
                                        (is_down)?"DOWN":"UP", val, digit,
 
1222
                                        (want_mute) ? "yes" : "no");
 
1223
                        } else {
 
1224
                                LINE_DBG(SIGNAL, xpd, i,
 
1225
                                        "Ignored DTMF digit %s '%c'\n",
 
1226
                                        (is_down)?"DOWN":"UP", digit);
 
1227
                        }
 
1228
                        /*
 
1229
                         * FIXME: we currently don't use the want_dtmf_mute until
 
1230
                         * we are sure about the logic in Asterisk native bridging.
 
1231
                         * Meanwhile, simply mute it on button press.
 
1232
                         */
 
1233
                        if(is_down && want_mute)
 
1234
                                __do_mute_dtmf(xpd, i, 1);
 
1235
                        else
 
1236
                                __do_mute_dtmf(xpd, i, 0);
 
1237
                        __pcm_recompute(xpd, 0);        /* XPD is locked */
 
1238
                        if(want_event) 
 
1239
                                zt_qevent_lock(&xpd->chans[i], event | digit);
 
1240
                        break;
 
1241
                }
 
1242
        }
 
1243
}
 
1244
 
 
1245
static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
 
1246
{
 
1247
        unsigned long           flags;
 
1248
        struct FXS_priv_data    *priv;
 
1249
        byte                    regnum;
 
1250
        bool                    indirect;
 
1251
 
 
1252
        spin_lock_irqsave(&xpd->lock, flags);
 
1253
        priv = xpd->priv;
 
1254
        BUG_ON(!priv);
 
1255
        indirect = (REG_FIELD(info, regnum) == 0x1E);
 
1256
        regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
 
1257
        XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
 
1258
                        (indirect)?"I":"D",
 
1259
                        regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high));
 
1260
        if(!indirect && regnum == REG_DTMF_DECODE) {
 
1261
                byte            val = REG_FIELD(info, data_low);
 
1262
                xpp_line_t      lines = BIT(info->portnum);
 
1263
 
 
1264
                process_dtmf(xpd, lines, val);
 
1265
        }
 
1266
#ifdef  POLL_DIGITAL_INPUTS
 
1267
        /*
 
1268
         * Process digital inputs polling results
 
1269
         */
 
1270
        else if(xpd->xbus_idx == 0 && !indirect && regnum == REG_DIGITAL_IOCTRL) {
 
1271
                process_digital_inputs(xpd, info);
 
1272
        }
 
1273
#endif
 
1274
        else if(!indirect && regnum == REG_LOOPCLOSURE) {       /* OFFHOOK ? */
 
1275
                byte            val = REG_FIELD(info, data_low);
 
1276
                xpp_line_t      mask = BIT(info->portnum);
 
1277
                xpp_line_t      offhook;
 
1278
 
 
1279
                offhook = (val & REG_LOOPCLOSURE_LCR) ? mask : 0;
 
1280
                LINE_DBG(SIGNAL, xpd, info->portnum,
 
1281
                        "REG_LOOPCLOSURE: dataL=0x%X (offhook=0x%X mask=0x%X\n",
 
1282
                        val, offhook, mask);
 
1283
                process_hookstate(xpd, offhook, mask);
 
1284
        } else {
 
1285
#if 0
 
1286
                XPD_NOTICE(xpd, "Spurious register reply(ignored): %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
 
1287
                                (indirect)?"I":"D",
 
1288
                                regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high));
 
1289
#endif
 
1290
        }
 
1291
        /* Update /proc info only if reply relate to the last slic read request */
 
1292
        if(
 
1293
                        REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) &&
 
1294
                        REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) &&
 
1295
                        REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) {
 
1296
                xpd->last_reply = *info;
 
1297
        }
 
1298
        spin_unlock_irqrestore(&xpd->lock, flags);
 
1299
        return 0;
 
1300
}
 
1301
 
 
1302
static xproto_table_t PROTO_TABLE(FXS) = {
 
1303
        .owner = THIS_MODULE,
 
1304
        .entries = {
 
1305
                /*      Prototable      Card    Opcode          */
 
1306
                XENTRY( FXS,            FXS,    SIG_CHANGED     ),
 
1307
        },
 
1308
        .name = "FXS",  /* protocol name */
 
1309
        .ports_per_subunit = 8,
 
1310
        .type = XPD_TYPE_FXS,
 
1311
        .xops = {
 
1312
                .card_new       = FXS_card_new,
 
1313
                .card_init      = FXS_card_init,
 
1314
                .card_remove    = FXS_card_remove,
 
1315
                .card_zaptel_preregistration    = FXS_card_zaptel_preregistration,
 
1316
                .card_zaptel_postregistration   = FXS_card_zaptel_postregistration,
 
1317
                .card_hooksig   = FXS_card_hooksig,
 
1318
                .card_tick      = FXS_card_tick,
 
1319
                .card_pcm_fromspan      = generic_card_pcm_fromspan,
 
1320
                .card_pcm_tospan        = generic_card_pcm_tospan,
 
1321
                .card_open      = FXS_card_open,
 
1322
                .card_close     = FXS_card_close,
 
1323
                .card_ioctl     = FXS_card_ioctl,
 
1324
                .card_register_reply    = FXS_card_register_reply,
 
1325
 
 
1326
                .XPD_STATE      = XPROTO_CALLER(FXS, XPD_STATE),
 
1327
        },
 
1328
        .packet_is_valid = fxs_packet_is_valid,
 
1329
        .packet_dump = fxs_packet_dump,
 
1330
};
 
1331
 
 
1332
static bool fxs_packet_is_valid(xpacket_t *pack)
 
1333
{
 
1334
        const xproto_entry_t    *xe;
 
1335
 
 
1336
        // DBG(GENERAL, "\n");
 
1337
        xe = xproto_card_entry(&PROTO_TABLE(FXS), XPACKET_OP(pack));
 
1338
        return xe != NULL;
 
1339
}
 
1340
 
 
1341
static void fxs_packet_dump(const char *msg, xpacket_t *pack)
 
1342
{
 
1343
        DBG(GENERAL, "%s\n", msg);
 
1344
}
 
1345
 
 
1346
/*------------------------- SLIC Handling --------------------------*/
 
1347
 
 
1348
static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
 
1349
{
 
1350
        int                     len = 0;
 
1351
        unsigned long           flags;
 
1352
        xpd_t                   *xpd = data;
 
1353
        struct FXS_priv_data    *priv;
 
1354
        int                     i;
 
1355
        int                     led;
 
1356
 
 
1357
        if(!xpd)
 
1358
                return -ENODEV;
 
1359
        spin_lock_irqsave(&xpd->lock, flags);
 
1360
        priv = xpd->priv;
 
1361
        BUG_ON(!priv);
 
1362
        len += sprintf(page + len, "%-8s %-10s %-10s %-10s\n",
 
1363
                        "Channel",
 
1364
                        "idletxhookstate",
 
1365
                        "lasttxhook",
 
1366
                        "ohttimer"
 
1367
                        );
 
1368
        for_each_line(xpd, i) {
 
1369
                char    pref;
 
1370
 
 
1371
                if(IS_SET(xpd->digital_outputs, i))
 
1372
                        pref = 'O';
 
1373
                else if(IS_SET(xpd->digital_inputs, i))
 
1374
                        pref = 'I';
 
1375
                else
 
1376
                        pref = ' ';
 
1377
                len += sprintf(page + len, "%c%7d %10d %10d %10d\n",
 
1378
                                pref,
 
1379
                                i,
 
1380
                                priv->idletxhookstate[i],
 
1381
                                priv->lasttxhook[i],
 
1382
                                priv->ohttimer[i]
 
1383
                              );
 
1384
        }
 
1385
        len += sprintf(page + len, "\n");
 
1386
        for(led = 0; led < NUM_LEDS; led++) {
 
1387
                len += sprintf(page + len, "LED #%d", led);
 
1388
                len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
 
1389
                for_each_line(xpd, i) {
 
1390
                        if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
 
1391
                                len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[led], i));
 
1392
                }
 
1393
                len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol");
 
1394
                for_each_line(xpd, i) {
 
1395
                        if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
 
1396
                                len += sprintf(page + len, "%d ", IS_SET(priv->ledcontrol[led], i));
 
1397
                }
 
1398
                len += sprintf(page + len, "\n\t%-17s: ", "led_counter");
 
1399
                for_each_line(xpd, i) {
 
1400
                        if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
 
1401
                                len += sprintf(page + len, "%d ", LED_COUNTER(priv,i,led));
 
1402
                }
 
1403
                len += sprintf(page + len, "\n");
 
1404
        }
 
1405
        spin_unlock_irqrestore(&xpd->lock, flags);
 
1406
        if (len <= off+count)
 
1407
                *eof = 1;
 
1408
        *start = page + off;
 
1409
        len -= off;
 
1410
        if (len > count)
 
1411
                len = count;
 
1412
        if (len < 0)
 
1413
                len = 0;
 
1414
        return len;
 
1415
}
 
1416
 
 
1417
#ifdef  WITH_METERING
 
1418
static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
 
1419
{
 
1420
        xpd_t           *xpd = data;
 
1421
        char            buf[MAX_PROC_WRITE];
 
1422
        lineno_t        chan;
 
1423
        int             num;
 
1424
        int             ret;
 
1425
 
 
1426
        if(!xpd)
 
1427
                return -ENODEV;
 
1428
        if(count >= MAX_PROC_WRITE - 1) {
 
1429
                XPD_ERR(xpd, "Metering string too long (%lu)\n", count);
 
1430
                return -EINVAL;
 
1431
        }
 
1432
        if(copy_from_user(&buf, buffer, count))
 
1433
                return -EFAULT;
 
1434
        buf[count] = '\0';
 
1435
        ret = sscanf(buf, "%d", &num);
 
1436
        if(ret != 1) {
 
1437
                XPD_ERR(xpd, "Metering value should be number. Got '%s'\n", buf);
 
1438
                return -EINVAL;
 
1439
        }
 
1440
        chan = num;
 
1441
        if(chan != PORT_BROADCAST && chan > xpd->channels) {
 
1442
                XPD_ERR(xpd, "Metering tone: bad channel number %d\n", chan);
 
1443
                return -EINVAL;
 
1444
        }
 
1445
        if((ret = metering_gen(xpd, chan, 1)) < 0) {
 
1446
                XPD_ERR(xpd, "Failed sending metering tone\n");
 
1447
                return ret;
 
1448
        }
 
1449
        return count;
 
1450
}
 
1451
#endif
 
1452
 
 
1453
static int __init card_fxs_startup(void)
 
1454
{
 
1455
        INFO("revision %s\n", XPP_VERSION);
 
1456
#ifdef  POLL_DIGITAL_INPUTS
 
1457
        INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n",
 
1458
                        poll_digital_inputs);
 
1459
#else
 
1460
        INFO("FEATURE: without DIGITAL INPUTS support\n");
 
1461
#endif
 
1462
#ifdef  ZT_VMWI
 
1463
        INFO("FEATURE: ZT_VMWI\n");
 
1464
#else
 
1465
        INFO("FEATURE: NO ZT_VMWI\n");
 
1466
#endif
 
1467
#ifdef  WITH_METERING
 
1468
        INFO("FEATURE: WITH METERING Generation\n");
 
1469
#else
 
1470
        INFO("FEATURE: NO METERING Generation\n");
 
1471
#endif
 
1472
        xproto_register(&PROTO_TABLE(FXS));
 
1473
        return 0;
 
1474
}
 
1475
 
 
1476
static void __exit card_fxs_cleanup(void)
 
1477
{
 
1478
        xproto_unregister(&PROTO_TABLE(FXS));
 
1479
}
 
1480
 
 
1481
MODULE_DESCRIPTION("XPP FXS Card Driver");
 
1482
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
 
1483
MODULE_LICENSE("GPL");
 
1484
MODULE_VERSION(XPP_VERSION);
 
1485
MODULE_ALIAS_XPD(XPD_TYPE_FXS);
 
1486
 
 
1487
module_init(card_fxs_startup);
 
1488
module_exit(card_fxs_cleanup);