jolly has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/libosmo-abis/+/41140?usp=email )


Change subject: Add CAS channel support
......................................................................

Add CAS channel support

CAS is currently supported by e1d driver only.

Change-Id: I81cc89e01bb4207dc899ab28f24a131f24b61c9c
---
M include/osmocom/abis/e1_input.h
M src/e1_input.c
M src/input/dahdi.c
M src/input/e1d.c
M src/input/misdn.c
5 files changed, 154 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/40/41140/1

diff --git a/include/osmocom/abis/e1_input.h b/include/osmocom/abis/e1_input.h
index 66985ea..ccf6926 100644
--- a/include/osmocom/abis/e1_input.h
+++ b/include/osmocom/abis/e1_input.h
@@ -77,6 +77,7 @@
        E1INP_TS_TYPE_RAW,
        E1INP_TS_TYPE_HDLC,
        E1INP_TS_TYPE_I460,
+       E1INP_TS_TYPE_CAS,
 };
 const char *e1inp_tstype_name(enum e1inp_ts_type tp);
 extern const struct value_string e1inp_ts_type_names[];
@@ -120,6 +121,12 @@
                        struct llist_head tx_queue;
                } hdlc;
                struct {
+                       /* call-back for every received frame */
+                       void (*recv_cb)(struct e1inp_ts *ts, struct msgb *msg);
+                       /* pending to-be-transmitted msgb */
+                       struct msgb *tx_msg;
+               } cas;
+               struct {
                        struct osmo_i460_timeslot i460_ts;
                } i460;
        };
@@ -335,6 +342,11 @@
                         void (*hdlc_recv_cb)(struct e1inp_ts *ts,
                                              struct msgb *msg));

+/* configure and initialize one timeslot dedicated to CAS frames */
+int e1inp_ts_config_cas(struct e1inp_ts *ts, struct e1inp_line *line,
+                       void (*cas_recv_cb)(struct e1inp_ts *ts,
+                                           struct msgb *msg));
+
 /* configure and initialize one timeslot dedicated to nothing */
 int e1inp_ts_config_none(struct e1inp_ts *ts, struct e1inp_line *line);

@@ -410,5 +422,6 @@

 int e1inp_ts_send_raw(struct e1inp_ts *ts, struct msgb *msg);
 int e1inp_ts_send_hdlc(struct e1inp_ts *ts, struct msgb *msg);
+int e1inp_ts_send_cas(struct e1inp_ts *ts, struct msgb *msg);

 #endif /* _E1_INPUT_H */
diff --git a/src/e1_input.c b/src/e1_input.c
index 066a572..656d657 100644
--- a/src/e1_input.c
+++ b/src/e1_input.c
@@ -283,6 +283,7 @@
        { E1INP_TS_TYPE_RAW,    "RAW" },
        { E1INP_TS_TYPE_HDLC,   "HDLC" },
        { E1INP_TS_TYPE_I460,   "I460" },
+       { E1INP_TS_TYPE_CAS,    "CAS" },
        { 0, NULL }
 };

@@ -361,6 +362,23 @@
        return 0;
 }

+int e1inp_ts_send_cas(struct e1inp_ts *ts, struct msgb *msg)
+{
+       struct e1inp_driver *driver;
+
+       OSMO_ASSERT(ts->type == E1INP_TS_TYPE_CAS);
+
+       /* notify the driver we have something to write */
+       driver = ts->line->driver;
+       driver->want_write(ts);
+
+       /* update CAS message */
+       msgb_free(ts->cas.tx_msg);
+       ts->cas.tx_msg = msg;
+
+       return 0;
+}
+
 /* Depending on its typ a timeslot may hold resources which must be cleaned up
  * or reset before the type of the timeslot type may be changed. */
 static int cleanup_e1inp_ts(struct e1inp_ts *e1i_ts)
@@ -390,6 +408,10 @@
        case E1INP_TS_TYPE_HDLC:
                msgb_queue_free(&e1i_ts->hdlc.tx_queue);
                return 0;
+       case E1INP_TS_TYPE_CAS:
+               msgb_free(e1i_ts->cas.tx_msg);
+               e1i_ts->cas.tx_msg = NULL;
+               return 0;
        case E1INP_TS_TYPE_I460:
                /* The caller is responsible for removing all I.460 subchannels
                 * first. */
@@ -504,6 +526,23 @@
        return 0;
 }

+int e1inp_ts_config_cas(struct e1inp_ts *ts, struct e1inp_line *line,
+                       void (*cas_recv_cb)(struct e1inp_ts *ts,
+                                           struct msgb *msg))
+{
+       if (ts->type == E1INP_TS_TYPE_CAS && ts->line && line)
+               return 0;
+
+       cleanup_e1inp_ts(ts);
+
+       ts->type = E1INP_TS_TYPE_CAS;
+       ts->line = line;
+       ts->cas.recv_cb = cas_recv_cb;
+       ts->cas.tx_msg = NULL;
+
+       return 0;
+}
+
 int e1inp_ts_config_none(struct e1inp_ts *ts, struct e1inp_line *line)
 {
        if (ts->type == E1INP_TS_TYPE_NONE && ts->line && line)
@@ -879,6 +918,9 @@
        case E1INP_TS_TYPE_HDLC:
                ts->hdlc.recv_cb(ts, msg);
                break;
+       case E1INP_TS_TYPE_CAS:
+               ts->cas.recv_cb(ts, msg);
+               break;
        case E1INP_TS_TYPE_I460:
                osmo_i460_demux_in(&ts->i460.i460_ts, msg->l2h, 
msgb_l2len(msg));
                msgb_free(msg);
@@ -1013,6 +1055,10 @@
                /* Get msgb from tx_queue */
                msg = msgb_dequeue(&e1i_ts->hdlc.tx_queue);
                break;
+       case E1INP_TS_TYPE_CAS:
+               /* Get msgb from tx_msg, but don't remove it. */
+               msg = e1i_ts->cas.tx_msg;
+               break;
        case E1INP_TS_TYPE_I460:
                msg = msgb_alloc(TSX_ALLOC_SIZE, "I460_TX");
                if (!msg)
diff --git a/src/input/dahdi.c b/src/input/dahdi.c
index b9a3fcf..1e6df31 100644
--- a/src/input/dahdi.c
+++ b/src/input/dahdi.c
@@ -718,6 +718,9 @@
                         * write flow control */
                        bfd->when = OSMO_FD_READ | OSMO_FD_EXCEPT;// | 
OSMO_FD_WRITE;
                        break;
+               case E1INP_TS_TYPE_CAS:
+                       LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "CAS not supported by 
dahdi driver.\n");
+                       return -ENOTSUP;
                }

                if (bfd->fd < 0)
diff --git a/src/input/e1d.c b/src/input/e1d.c
index dd4e9fe..9d48bbb 100644
--- a/src/input/e1d.c
+++ b/src/input/e1d.c
@@ -542,6 +542,35 @@
        return ret;
 }

+/* write to a CAS channel TS */
+static int handle_ts_cas_write(struct osmo_fd *bfd)
+{
+       struct e1inp_line *line = bfd->data;
+       unsigned int ts_nr = bfd->priv_nr;
+       struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+       struct msgb *msg;
+       int ret;
+
+       /* Disable write, as there can be only one CAS message. */
+       osmo_fd_write_disable(bfd);
+
+       /* Get the msg, but don't free it. When the application is restarted,
+        * it will be sent again, so the application gets the latest CAS 
message. */
+       msg = e1inp_tx_ts(e1i_ts, NULL);
+       if (!msg)
+               return 0;
+
+       LOGPITS(e1i_ts, DLMIB, LOGL_DEBUG, "CAS CHAN TX: %s\n", 
osmo_hexdump(msg->data, msg->len));
+
+       ret = write(bfd->fd, msg->data, msg->len);
+       if (ret < msg->len) {
+               LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "write returns %d instead 
of %d\n", ret, msg->len);
+               osmo_fsm_inst_dispatch(g_e1d_fsm_inst, EV_CONN_LOST, line);
+       }
+
+       return ret;
+}
+
 #define TSX_ALLOC_SIZE 4096

 /* read from a hdlc channel TS */
@@ -573,6 +602,35 @@
        return ret;
 }

+/* read from a CAS channel TS */
+static int handle_ts_cas_read(struct osmo_fd *bfd)
+{
+       struct e1inp_line *line = bfd->data;
+       unsigned int ts_nr = bfd->priv_nr;
+       struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
+       struct msgb *msg = msgb_alloc(TSX_ALLOC_SIZE, "E1D CAS TS");
+       int ret;
+
+       if (!msg)
+               return -ENOMEM;
+
+       ret = read(bfd->fd, msg->data, TSX_ALLOC_SIZE);
+       if (ret <= 0) {
+               LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "%s read error: %d %s\n", 
__func__, ret, strerror(errno));
+               msgb_free(msg);
+               osmo_fsm_inst_dispatch(g_e1d_fsm_inst, EV_CONN_LOST, line);
+               return ret;
+       }
+
+       msgb_put(msg, ret);
+
+       msg->l2h = msg->data;
+       LOGPITS(e1i_ts, DLMIB, LOGL_DEBUG, "CAS CHAN RX: %s\n", 
msgb_hexdump_l2(msg));
+       ret = e1inp_rx_ts(e1i_ts, msg, 0, 0);
+
+       return ret;
+}
+
 static void e1d_write_msg(struct msgb *msg, void *cbdata)
 {
        struct osmo_fd *bfd = cbdata;
@@ -631,6 +689,12 @@
                if (what & OSMO_FD_WRITE)
                        ret = handle_ts_hdlc_write(bfd);
                break;
+       case E1INP_TS_TYPE_CAS:
+               if (what & OSMO_FD_READ)
+                       ret = handle_ts_cas_read(bfd);
+               if (what & OSMO_FD_WRITE)
+                       ret = handle_ts_cas_write(bfd);
+               break;
        default:
                LOGPITS(e1i_ts, DLINP, LOGL_NOTICE, "unknown/unsupported E1 TS 
type %u\n", e1i_ts->type);
                break;
@@ -777,6 +841,30 @@
                        }
                        bfd->when = OSMO_FD_READ;
                        break;
+               case E1INP_TS_TYPE_CAS:
+                       /* close/release LAPD instance, if any */
+                       if (e1i_ts->lapd) {
+                               lapd_instance_free(e1i_ts->lapd);
+                               e1i_ts->lapd = NULL;
+                       }
+                       /* close, if old timeslot mode doesn't match new config 
*/
+                       if (bfd->fd >= 0 && ts_info[ts].cfg.mode != 
E1DP_TSMODE_CAS) {
+                               close(bfd->fd);
+                               bfd->fd = -1;
+                       }
+                       if (bfd->fd < 0) {
+                               bfd->fd = osmo_e1dp_client_ts_open(g_e1d, 
e1d_intf, e1d_line, ts,
+                                                                  
E1DP_TSMODE_CAS, D_BCHAN_TX_GRAN);
+                       }
+                       if (bfd->fd < 0) {
+                               LOGPITS(e1i_ts, DLINP, LOGL_ERROR, "Could not 
open timeslot %d\n", ts);
+                               talloc_free(ts_info);
+                               osmo_fsm_inst_dispatch(g_e1d_fsm_inst, 
EV_CONN_LOST, NULL);
+                               return -EIO;
+                       }
+                       /* Also trigger one write, so latest CAS frame will be 
sent, if any. */
+                       bfd->when = OSMO_FD_READ | OSMO_FD_WRITE;
+                       break;
                case E1INP_TS_TYPE_TRAU:
                case E1INP_TS_TYPE_I460:
                case E1INP_TS_TYPE_RAW:
diff --git a/src/input/misdn.c b/src/input/misdn.c
index 8f04567..3172ee4 100644
--- a/src/input/misdn.c
+++ b/src/input/misdn.c
@@ -866,6 +866,9 @@
                        /* open raw socket */
                        bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
                        break;
+               case E1INP_TS_TYPE_CAS:
+                       LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "CAS not supported by 
mISDN\n");
+                       return -ENOTSUP;
                }

                /* failed to open? */
@@ -901,6 +904,7 @@
                        /* TS 16 is D-channel, so we use channel 0 */
                        addr.channel = (ts == 16) ? 0 : ts;
                        break;
+               case E1INP_TS_TYPE_CAS:
                default:
                        LOGPITS(e1i_ts, DLMI, LOGL_ERROR, "unsupported E1 TS 
type: %u\n", e1i_ts->type);
                        break;

--
To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41140?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: libosmo-abis
Gerrit-Branch: master
Gerrit-Change-Id: I81cc89e01bb4207dc899ab28f24a131f24b61c9c
Gerrit-Change-Number: 41140
Gerrit-PatchSet: 1
Gerrit-Owner: jolly <[email protected]>

Reply via email to