2
* Written by Oron Peled <oron@actcom.co.il>
3
* Copyright (C) 2004-2006, Xorcom
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.
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.
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.
23
#include <linux/init.h>
24
#include <linux/module.h>
26
#include <linux/delay.h>
31
#include "zap_debug.h"
32
#include "xbus-core.h"
34
static const char rcsid[] = "$Id: card_fxs.c 4266 2008-05-13 21:08:09Z tzafrir $";
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");
45
static DEF_PARM_BOOL(vmwi_ioctl, 0, 0644, "Asterisk support VMWI notification via ioctl");
47
#define vmwi_ioctl 0 /* not supported */
50
/* Signaling is opposite (fxo signalling for fxs card) */
52
#define FXS_DEFAULT_SIGCAP (ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS)
54
#define FXS_DEFAULT_SIGCAP (ZT_SIG_SF | ZT_SIG_EM)
57
#define LINES_DIGI_OUT 2
58
#define LINES_DIGI_INP 4
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)
76
#define VALID_PORT(port) (((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST)
78
#define REG_DIGITAL_IOCTRL 0x06 /* LED and RELAY control */
80
/* Values of SLIC linefeed control register (0x40) */
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 */
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)
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 */
102
#define REG_LOOPCLOSURE 0x44 /* 68 - Loop Closure/Ring Trip Detect Status */
103
#define REG_LOOPCLOSURE_LCR BIT(0) /* Loop Closure Detect Indicator. */
105
/*---------------- FXS Protocol Commands ----------------------------------*/
107
static /* 0x0F */ DECLARE_CMD(FXS, XPD_STATE, bool on);
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);
113
static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
115
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
117
#define PROC_REGISTER_FNAME "slics"
118
#define PROC_FXS_INFO_FNAME "fxs_info"
120
#define PROC_METERING_FNAME "metering_gen"
123
struct FXS_priv_data {
125
struct proc_dir_entry *meteringfile;
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];
143
* LED counter values:
144
* n>1 : BLINK every n'th tick
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)
152
#define LED_BLINK_RING (1000/8) /* in ticks */
154
/*---------------- FXS: Static functions ----------------------------------*/
155
static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, enum fxs_state value)
157
struct FXS_priv_data *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);
165
static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
167
int value = (on) ? REG_BATTERY_BATSL : 0x00;
171
LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
172
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_BATTERY, value);
176
* LED and RELAY control is done via SLIC register 0x06:
178
* +-----+-----+-----+-----+-----+-----+-----+-----+
179
* | M2 | M1 | M3 | C2 | O1 | O3 | C1 | C3 |
180
* +-----+-----+-----+-----+-----+-----+-----+-----+
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)
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)
195
* The OUTPUT RELAY (actually a relay out) is connected to line 0 and 4 only.
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) };
205
* - ALL_LINES. This is not valid anymore since 8-Jan-2007.
207
static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on)
210
struct FXS_priv_data *priv;
215
BUG_ON(chan == ALL_LINES);
218
which = which % NUM_LEDS;
219
if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan))
221
if(chan == PORT_BROADCAST) {
222
priv->ledstate[which] = (on) ? ~0 : 0;
225
BIT_SET(priv->ledstate[which], chan);
227
BIT_CLR(priv->ledstate[which], chan);
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]);
234
value |= led_register_vals[which];
235
ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE,
236
REG_DIGITAL_IOCTRL, value);
241
static void handle_fxs_leds(xpd_t *xpd)
244
const enum fxs_leds colors[] = { LED_GREEN, LED_RED };
246
unsigned int timer_count;
247
struct FXS_priv_data *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))
256
if((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { // Blinking
257
int mod_value = LED_COUNTER(priv, i, color);
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);
267
do_led(xpd, i, color, 0);
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);
280
static void restore_leds(xpd_t *xpd)
282
struct FXS_priv_data *priv;
286
for_each_line(xpd, i) {
287
if(IS_SET(xpd->offhook, i))
288
MARK_ON(priv, i, LED_GREEN);
290
MARK_OFF(priv, i, LED_GREEN);
295
static int metering_gen(xpd_t *xpd, lineno_t chan, bool on)
297
byte value = (on) ? 0x94 : 0x00;
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);
304
/*---------------- FXS: Methods -------------------------------------------*/
306
static void fxs_proc_remove(xbus_t *xbus, xpd_t *xpd)
308
struct FXS_priv_data *priv;
312
#ifdef CONFIG_PROC_FS
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;
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;
329
static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
331
struct FXS_priv_data *priv;
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);
343
priv->fxs_info->owner = THIS_MODULE;
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);
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;
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)
366
int regular_channels;
367
struct FXS_priv_data *priv;
372
"XPD=%d%d: try to instanciate FXS with reverse direction\n",
377
regular_channels = min(6, CHANNELS_PERXPD);
379
regular_channels = min(8, CHANNELS_PERXPD);
380
channels = regular_channels;
382
channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
383
xpd = xpd_alloc(sizeof(struct FXS_priv_data), proto_table, channels);
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);
391
xpd->direction = TO_PHONE;
392
xpd->type_name = "FXS";
393
if(xpd_common_init(xbus, xpd, unit, subunit, subtype, subunits) < 0)
395
if(fxs_proc_create(xbus, xpd) < 0)
398
for_each_line(xpd, i) {
399
priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
407
static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
409
struct FXS_priv_data *priv;
418
/* Software controled ringing (for CID) */
419
ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE, 0x22, 0x00); /* Ringing Oscilator Control */
422
for_each_line(xpd, i) {
423
linefeed_control(xbus, xpd, i, FXS_LINE_POL_ACTIVE);
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);
430
for_each_line(xpd, i) {
431
do_led(xpd, i, LED_GREEN, 1);
434
for_each_line(xpd, i) {
435
do_led(xpd, i, LED_GREEN, 0);
439
pcm_recompute(xpd, 0);
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
445
for_each_line(xpd, i) {
446
if(IS_SET(xpd->digital_outputs | xpd->digital_inputs, i))
448
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_LOOPCLOSURE, 0);
452
fxs_proc_remove(xbus, xpd);
453
XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret);
457
static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd)
459
struct FXS_priv_data *priv;
463
XPD_DBG(GENERAL, xpd, "\n");
464
fxs_proc_remove(xbus, xpd);
468
static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on)
471
struct FXS_priv_data *priv;
479
XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off");
480
#ifdef ZT_SPANSTAT_V2
481
xpd->span.spantype = "FXS";
483
for_each_line(xpd, i) {
484
struct zt_chan *cur_chan = &xpd->chans[i];
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);
494
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%02d/%1d%1d/%d",
495
xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
497
cur_chan->chanpos = i + 1;
499
cur_chan->sigcap = FXS_DEFAULT_SIGCAP;
501
for_each_line(xpd, i) {
502
MARK_ON(priv, i, LED_GREEN);
504
MARK_ON(priv, i, LED_RED);
509
static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on)
512
struct FXS_priv_data *priv;
520
XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off");
521
for_each_line(xpd, i) {
522
MARK_OFF(priv, i, LED_GREEN);
524
MARK_OFF(priv, i, LED_RED);
532
* Called with XPD spinlocked
534
static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
536
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE");
538
BIT_SET(xpd->mute_dtmf, pos);
540
BIT_CLR(xpd->mute_dtmf, pos);
543
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, int on)
549
LINE_DBG(SIGNAL, xpd, pos, "%s%s\n", (on)?"ON":"OFF", (vmwineon)?"":" (Ignored)");
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);
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);
578
return (ret ? -EPROTO : 0);
581
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
583
struct FXS_priv_data *priv;
587
if (!vmwineon || IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
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]);
597
static int relay_out(xpd_t *xpd, int pos, bool on)
601
int relay_channels[] = { 0, 4 };
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]);
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);
616
static int send_ring(xpd_t *xpd, lineno_t chan, bool on)
620
struct FXS_priv_data *priv;
621
enum fxs_state value = (on) ? FXS_LINE_RING : FXS_LINE_POL_ACTIVE;
626
LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on)?"on":"off");
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);
632
MARK_BLINK(priv, chan, LED_GREEN, LED_BLINK_RING);
634
if(IS_BLINKING(priv, chan, LED_GREEN))
635
MARK_BLINK(priv, chan, LED_GREEN, 0);
640
static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
642
struct FXS_priv_data *priv;
644
struct zt_chan *chan = NULL;
645
enum fxs_state txhook;
648
LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
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");
655
if(SPAN_REGISTERED(xpd))
656
chan = &xpd->span.chans[pos];
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);
673
if (priv->lasttxhook[pos] == FXS_LINE_OPEN) {
675
* Restore state after KEWL hangup.
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);
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];
691
txhook = priv->idletxhookstate[pos];
694
txhook = FXS_LINE_TIPOPEN;
698
ret = linefeed_control(xbus, xpd, pos, txhook);
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));
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;
711
xpd->ringing[pos] = 0;
715
txhook = FXS_LINE_POL_ACTIVE;
718
txhook = priv->idletxhookstate[pos];
722
ret = linefeed_control(xbus, xpd, pos, txhook);
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);
734
ret = send_ring(xpd, pos, 1); // RING on
737
if(IS_SET(xpd->digital_outputs, pos)) {
738
LINE_DBG(SIGNAL, xpd, pos, "%s -> Is digital output. Ignored\n", txsig2str(txsig));
741
linefeed_control(xbus, xpd, pos, FXS_LINE_OPEN);
742
MARK_OFF(priv, pos, LED_GREEN);
745
XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n",
746
__FUNCTION__, txsig2str(txsig), txsig);
754
* We don't need it now, since we detect vmwi via FSK patterns
756
static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
758
struct FXS_priv_data *priv;
768
if(!TRANSPORT_RUNNING(xbus))
770
if (pos < 0 || pos >= xpd->channels) {
771
XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n",
772
pos, __FUNCTION__, cmd);
777
case ZT_ONHOOKTRANSFER:
778
if (get_user(val, (int __user *)arg))
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);
790
if(!IS_SET(xpd->offhook, pos))
791
start_stop_vm_led(xbus, xpd, pos);
794
if (get_user(val, (int __user *)arg))
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);
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);
814
* During natively bridged calls, Asterisk
815
* will request one of the sides to stop sending
816
* dtmf events. Check the requested state.
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);
826
BIT_SET(priv->want_dtmf_events, pos);
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);
834
BIT_CLR(priv->want_dtmf_events, pos);
836
if(val & ZT_TONEDETECT_MUTE) {
837
BIT_SET(priv->want_dtmf_mute, pos);
839
BIT_CLR(priv->want_dtmf_mute, pos);
840
__do_mute_dtmf(xpd, pos, 0);
841
__pcm_recompute(xpd, 0);
843
spin_unlock_irqrestore(&xpd->lock, flags);
846
if (get_user(val, (int __user *)arg))
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]);
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;
858
priv->lasttxhook[pos] &= ~FXS_LINE_RING;
859
linefeed_control(xbus, xpd, pos, priv->lasttxhook[pos]);
862
case ZT_VMWI: /* message-waiting led control */
863
if (get_user(val, (int __user *)arg))
866
LINE_NOTICE(xpd, pos, "Got ZT_VMWI notification but vmwi_ioctl parameter is off. Ignoring.\n");
869
/* Digital inputs/outputs don't have VM leds */
870
if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
873
BIT_SET(xpd->msg_waiting, pos);
875
BIT_CLR(xpd->msg_waiting, pos);
879
report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
884
static int FXS_card_open(xpd_t *xpd, lineno_t chan)
886
struct FXS_priv_data *priv;
891
is_offhook = IS_SET(xpd->offhook, chan);
893
LINE_NOTICE(xpd, chan, "Already offhook during open. OK.\n");
895
LINE_DBG(SIGNAL, xpd, chan, "is onhook\n");
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
902
BIT_SET(priv->update_offhook_state, chan);
906
static int FXS_card_close(xpd_t *xpd, lineno_t chan)
908
struct FXS_priv_data *priv;
911
LINE_DBG(GENERAL, xpd, chan, "\n");
913
priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE;
917
#ifdef POLL_DIGITAL_INPUTS
919
* INPUT polling is done via SLIC register 0x06 (same as LEDS):
921
* +-----+-----+-----+-----+-----+-----+-----+-----+
922
* | I1 | I3 | | | I2 | I4 | | |
923
* +-----+-----+-----+-----+-----+-----+-----+-----+
926
static int input_channels[] = { 6, 7, 2, 3 }; // Slic numbers of input relays
928
static void poll_inputs(xpd_t *xpd)
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];
936
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_READ, 0x06, 0);
941
static void handle_linefeed(xpd_t *xpd)
943
struct FXS_priv_data *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;
955
if (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);
973
* Optimized memcmp() like function. Only test for equality (true/false).
974
* This optimization reduced the detect_vmwi() runtime by a factor of 3.
976
static inline bool mem_equal(const char a[], const char b[], size_t len)
980
for(i = 0; i < len; i++)
987
* Detect Voice Mail Waiting Indication
989
static void detect_vmwi(xpd_t *xpd)
991
struct FXS_priv_data *priv;
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 };
1002
for_each_line(xpd, i) {
1003
struct zt_chan *chan = &xpd->span.chans[i];
1004
byte *writechunk = chan->writechunk;
1006
if(IS_SET(xpd->offhook | xpd->cid_on | xpd->digital_inputs | xpd->digital_outputs, i))
1009
if(writechunk[0] != 0x7F && writechunk[0] != 0) {
1012
LINE_DBG(GENERAL, xpd, pos, "MSG:");
1013
for(j = 0; j < ZT_CHUNKSIZE; j++) {
1015
printk(" %02X", writechunk[j]);
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);
1036
LINE_NOTICE(xpd, i, "MSG WAITING Unexpected:");
1037
for(j = 0; j < ZT_CHUNKSIZE; j++) {
1038
printk(" %02X", writechunk[j]);
1046
static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
1048
struct FXS_priv_data *priv;
1053
#ifdef POLL_DIGITAL_INPUTS
1054
if(poll_digital_inputs && xpd->xbus_idx == 0) {
1055
if((xpd->timer_count % poll_digital_inputs) == 0)
1059
handle_fxs_leds(xpd);
1060
handle_linefeed(xpd);
1061
if(priv->update_offhook_state) { /* set in FXS_card_open() */
1064
for_each_line(xpd, i) {
1065
if(!IS_SET(priv->update_offhook_state, i))
1068
* Update zaptel with current state of line.
1070
if(IS_SET(xpd->offhook, i)) {
1071
update_line_status(xpd, i, 1);
1073
update_line_status(xpd, i, 0);
1075
BIT_CLR(priv->update_offhook_state, i);
1078
if(SPAN_REGISTERED(xpd)) {
1079
if(vmwineon && !vmwi_ioctl)
1080
detect_vmwi(xpd); /* Detect via FSK modulation */
1085
/*---------------- FXS: HOST COMMANDS -------------------------------------*/
1087
static /* 0x0F */ HOSTCMD(FXS, XPD_STATE, bool on)
1091
XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off");
1095
/*---------------- FXS: Astribank Reply Handlers --------------------------*/
1098
* Should be called with spinlocked XPD
1100
static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, xpp_line_t change_mask)
1103
struct FXS_priv_data *priv;
1107
BUG_ON(xpd->direction != TO_PHONE);
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))
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... */
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);
1125
LINE_DBG(SIGNAL, xpd, i, "ONHOOK\n");
1126
MARK_OFF(priv, i, LED_GREEN);
1127
update_line_status(xpd, i, 0);
1131
__pcm_recompute(xpd, 0); /* in a spinlock */
1134
HANDLER_DEF(FXS, SIG_CHANGED)
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;
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);
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!!!)
1150
spin_lock_irqsave(&xpd->lock, flags);
1151
process_hookstate(xpd, sig_status, sig_toggles);
1152
spin_unlock_irqrestore(&xpd->lock, flags);
1156
#ifdef POLL_DIGITAL_INPUTS
1157
static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
1160
bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
1161
xpp_line_t lines = BIT(info->portnum);
1163
/* Map SLIC number into line number */
1164
for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
1165
int channo = input_channels[i];
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);
1185
static const char dtmf_digits[] = {
1186
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#', 'A', 'B', 'C', 'D'
1190
* This function is called with spinlocked XPD
1192
static void process_dtmf(xpd_t *xpd, xpp_line_t lines, byte val)
1196
bool is_down = val & 0x10;
1197
struct FXS_priv_data *priv;
1201
if(!SPAN_REGISTERED(xpd))
1207
XPD_NOTICE(xpd, "Bad DTMF value %d. Ignored\n", 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);
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");
1224
LINE_DBG(SIGNAL, xpd, i,
1225
"Ignored DTMF digit %s '%c'\n",
1226
(is_down)?"DOWN":"UP", digit);
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.
1233
if(is_down && want_mute)
1234
__do_mute_dtmf(xpd, i, 1);
1236
__do_mute_dtmf(xpd, i, 0);
1237
__pcm_recompute(xpd, 0); /* XPD is locked */
1239
zt_qevent_lock(&xpd->chans[i], event | digit);
1245
static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
1247
unsigned long flags;
1248
struct FXS_priv_data *priv;
1252
spin_lock_irqsave(&xpd->lock, flags);
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",
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);
1264
process_dtmf(xpd, lines, val);
1266
#ifdef POLL_DIGITAL_INPUTS
1268
* Process digital inputs polling results
1270
else if(xpd->xbus_idx == 0 && !indirect && regnum == REG_DIGITAL_IOCTRL) {
1271
process_digital_inputs(xpd, info);
1274
else if(!indirect && regnum == REG_LOOPCLOSURE) { /* OFFHOOK ? */
1275
byte val = REG_FIELD(info, data_low);
1276
xpp_line_t mask = BIT(info->portnum);
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);
1286
XPD_NOTICE(xpd, "Spurious register reply(ignored): %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
1288
regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high));
1291
/* Update /proc info only if reply relate to the last slic read request */
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;
1298
spin_unlock_irqrestore(&xpd->lock, flags);
1302
static xproto_table_t PROTO_TABLE(FXS) = {
1303
.owner = THIS_MODULE,
1305
/* Prototable Card Opcode */
1306
XENTRY( FXS, FXS, SIG_CHANGED ),
1308
.name = "FXS", /* protocol name */
1309
.ports_per_subunit = 8,
1310
.type = XPD_TYPE_FXS,
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,
1326
.XPD_STATE = XPROTO_CALLER(FXS, XPD_STATE),
1328
.packet_is_valid = fxs_packet_is_valid,
1329
.packet_dump = fxs_packet_dump,
1332
static bool fxs_packet_is_valid(xpacket_t *pack)
1334
const xproto_entry_t *xe;
1336
// DBG(GENERAL, "\n");
1337
xe = xproto_card_entry(&PROTO_TABLE(FXS), XPACKET_OP(pack));
1341
static void fxs_packet_dump(const char *msg, xpacket_t *pack)
1343
DBG(GENERAL, "%s\n", msg);
1346
/*------------------------- SLIC Handling --------------------------*/
1348
static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
1351
unsigned long flags;
1353
struct FXS_priv_data *priv;
1359
spin_lock_irqsave(&xpd->lock, flags);
1362
len += sprintf(page + len, "%-8s %-10s %-10s %-10s\n",
1368
for_each_line(xpd, i) {
1371
if(IS_SET(xpd->digital_outputs, i))
1373
else if(IS_SET(xpd->digital_inputs, i))
1377
len += sprintf(page + len, "%c%7d %10d %10d %10d\n",
1380
priv->idletxhookstate[i],
1381
priv->lasttxhook[i],
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));
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));
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));
1403
len += sprintf(page + len, "\n");
1405
spin_unlock_irqrestore(&xpd->lock, flags);
1406
if (len <= off+count)
1408
*start = page + off;
1417
#ifdef WITH_METERING
1418
static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
1421
char buf[MAX_PROC_WRITE];
1428
if(count >= MAX_PROC_WRITE - 1) {
1429
XPD_ERR(xpd, "Metering string too long (%lu)\n", count);
1432
if(copy_from_user(&buf, buffer, count))
1435
ret = sscanf(buf, "%d", &num);
1437
XPD_ERR(xpd, "Metering value should be number. Got '%s'\n", buf);
1441
if(chan != PORT_BROADCAST && chan > xpd->channels) {
1442
XPD_ERR(xpd, "Metering tone: bad channel number %d\n", chan);
1445
if((ret = metering_gen(xpd, chan, 1)) < 0) {
1446
XPD_ERR(xpd, "Failed sending metering tone\n");
1453
static int __init card_fxs_startup(void)
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);
1460
INFO("FEATURE: without DIGITAL INPUTS support\n");
1463
INFO("FEATURE: ZT_VMWI\n");
1465
INFO("FEATURE: NO ZT_VMWI\n");
1467
#ifdef WITH_METERING
1468
INFO("FEATURE: WITH METERING Generation\n");
1470
INFO("FEATURE: NO METERING Generation\n");
1472
xproto_register(&PROTO_TABLE(FXS));
1476
static void __exit card_fxs_cleanup(void)
1478
xproto_unregister(&PROTO_TABLE(FXS));
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);
1487
module_init(card_fxs_startup);
1488
module_exit(card_fxs_cleanup);