libhpsangoma: libhpsangoma_priv.c Source File

- Main Page
- Classes
- Files

# libhpsangoma_priv.c

    00001 /*****************************************************************************
    00002  * libhpsangoma_priv.c:  Sangoma High Performance TDM API - Span Based Library
    00003  *
    00004  * Author(s):   Nenad Corbic <ncorbic@sangoma.com>
    00005  *
    00006  * Copyright:   (c) 2008 Nenad Corbic <ncorbic@sangoma.com>
    00007  *
    00008  *              This program is free software; you can redistribute it and/or
    00009  *              modify it under the terms of the GNU General Public License
    00010  *              as published by the Free Software Foundation; either version
    00011  *              2 of the License, or (at your option) any later version.
    00012  * ============================================================================
    00013  *
    00014  */
    00015
    00016 #include "libhpsangoma.h"
    00017 #include "libhpsangoma_priv.h"
    00018 #define DFT_CARD "wanpipe1"
    00019
    00020
    00031 int sangoma_readmsg_hp_tdm(int fd, void *hdrbuf, int hdrlen, void *databuf, int datalen, int flag)
    00032 {
    00033         int rx_len=0;
    00034
    00035 #if defined(WIN32)
    00036
    00037 #error "WINDOWS HP TDMAPI NOT DEFINED"
    00038
    00039 #else
    00040         struct msghdr msg;
    00041         struct iovec iov[2];
    00042
    00043         memset(&msg,0,sizeof(struct msghdr));
    00044
    00045         iov[0].iov_len=hdrlen;
    00046         iov[0].iov_base=hdrbuf;
    00047
    00048         iov[1].iov_len=datalen;
    00049         iov[1].iov_base=databuf;
    00050
    00051         msg.msg_iovlen=2;
    00052         msg.msg_iov=iov;
    00053
    00054         rx_len = recvmsg(fd,&msg,0);
    00055
    00056         if (rx_len <= sizeof(api_rx_hdr_t)){
    00057                 return -EINVAL;
    00058         }
    00059
    00060         rx_len-=sizeof(api_rx_hdr_t);
    00061 #endif
    00062
    00063         return rx_len;
    00064 }
    00065
    00066
    00067
    00078 int sangoma_writemsg_hp_tdm(int fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen, int flag)
    00079 {
    00080         int bsent;
    00081
    00082 #if defined(WIN32)
    00083
    00084 #error "Windows TX not implemented"
    00085
    00086 #else
    00087         struct msghdr msg;
    00088         struct iovec iov[2];
    00089
    00090         memset(&msg,0,sizeof(struct msghdr));
    00091
    00092         iov[0].iov_len=hdrlen;
    00093         iov[0].iov_base=hdrbuf;
    00094
    00095         iov[1].iov_len=datalen;
    00096         iov[1].iov_base=databuf;
    00097
    00098         msg.msg_iovlen=2;
    00099         msg.msg_iov=iov;
    00100
    00101         bsent = sendmsg(fd,&msg,0);
    00102         if (bsent > 0){
    00103                 bsent-=sizeof(api_tx_hdr_t);
    00104         }
    00105 #endif
    00106         return bsent;
    00107 }
    00108
    00114 int do_wanpipemon_cmd(sangoma_hptdm_span_t *span)
    00115 {
    00116         struct ifreq ifr;
    00117         memset(&ifr,0,sizeof(ifr));
    00118         ifr.ifr_data = (void*)&span->wan_udp;
    00119         sprintf (ifr.ifr_name, "%s", span->if_name);
    00120         return ioctl(span->sock,SIOC_WANPIPE_PIPEMON,&ifr);
    00121 }
    00122
    00128 unsigned char sangoma_get_cfg(sangoma_hptdm_span_t *span)
    00129 {
    00130         span->wan_udp.wan_udphdr_command = READ_CONFIGURATION;
    00131         span->wan_udp.wan_udphdr_data_len = 0;
    00132         span->wan_udp.wan_udphdr_return_code = 0xaa;
    00133         do_wanpipemon_cmd(span);
    00134         if (span->wan_udp.wan_udphdr_return_code != 0){
    00135                 lib_printf(0,NULL,"Error: SPAN %i management command failed 0x02Xs (%s)",
    00136                         span->span_no+1, span->wan_udp.wan_udphdr_return_code,strerror(errno));
    00137                 return -1;
    00138         }
    00139
    00140         memcpy(&span->span_cfg,&span->wan_udp.wan_udphdr_data[0],sizeof(span->span_cfg));
    00141
    00142         return 0;
    00143 }
    00144
    00145
    00152 int sangoma_hptdm_span_open(sangoma_hptdm_span_t *span)
    00153 {
    00154         struct wan_sockaddr_ll  sa;
    00155         char if_name[100];
    00156         int sock=-1;
    00157         int err;
    00158
    00159         memset(&sa,0,sizeof(struct wan_sockaddr_ll));
    00160         sock = socket(AF_WANPIPE, SOCK_RAW, 0);
    00161         if( sock < 0 ) {
    00162                 perror("Socket");
    00163                 return -1;
    00164         } /* if */
    00165
    00166         sprintf(if_name, "w%ig1", span->span_no+1);
    00167
    00168         strcpy( (char*)sa.sll_device, if_name);
    00169         strcpy( (char*)sa.sll_card, DFT_CARD);
    00170         sa.sll_protocol = htons(PVC_PROT);
    00171         sa.sll_family=AF_WANPIPE;
    00172
    00173         if(bind(sock, (struct sockaddr *)&sa, sizeof(struct wan_sockaddr_ll)) < 0){
    00174         lib_printf(0,NULL,"bind failed on span span %i %s\n",
    00175                 span->span_no+1,strerror(errno));
    00176                         return -1;
    00177         }
    00178
    00179         span->sock=sock;
    00180
    00181         err= sangoma_get_cfg(span);
    00182         if (err) {
    00183                 goto sangoma_hptdm_span_open_error;
    00184         }
    00185
    00186         lib_printf(0,NULL,"libhp: span %i opened\n",
    00187                         span->span_no+1);
    00188
    00189         return 0;
    00190
    00191 sangoma_hptdm_span_open_error:
    00192
    00193         if (span->sock) {
    00194                 close(span->sock);
    00195                 span->sock=-1;
    00196         }
    00197
    00198         return err;
    00199 }
    00200
    00201
    00208 int sangoma_hp_tdm_handle_oob_event(sangoma_hptdm_span_t *span)
    00209 {
    00210         int err;
    00211         hp_tdmapi_rx_event_t *rx_event;
    00212
    00213         err = recv(span->sock, span->rx_data, sizeof(span->rx_data), MSG_OOB);
    00214         if (err > 0) {
    00215                 rx_event=(hp_tdmapi_rx_event_t*)&span->rx_data;
    00216                 if (span->span_reg.rx_event && span->span_reg.p) {
    00217                         span->span_reg.rx_event(span->span_reg.p, rx_event);
    00218                 }
    00219         }
    00220         /* For now treat all err as socket reload */
    00221         return 1;
    00222 }
    00223
    00230 int sangoma_hp_tdm_push_rx_data(sangoma_hptdm_span_t *span)
    00231 {
    00232         int i=0,x=0,err=0;
    00233         sangoma_hptdm_chan_t *chan=NULL;
    00234         hp_tmd_chunk_t *chunk=NULL;
    00235         int chan_no_hw;
    00236         char *rx_data = &span->rx_data[sizeof(api_rx_hdr_t)];
    00237
    00238
    00239         for (i=0;i<SMG_HP_TDM_MAX_CHANS;i++) {
    00240                 chan = &span->chan_idx[i].chan;
    00241                 if (!chan->init) {
    00242                         continue;
    00243                 }
    00244                 chan_no_hw = span->chan_idx[i].chan_no_hw;
    00245
    00246                 lib_printf(15,NULL, "SPAN %i Chan %i Chunk %i Channelizing\n",
    00247                                 span->span_no+1, chan->chan_no+1, span->chunk_sz);
    00248
    00249                 chunk = &chan->rx_chunk;
    00250
    00251                 for (x=0;x<span->chunk_sz;x++) {
    00252                         chunk->data[x] = rx_data[(span->max_chans*x)+chan_no_hw];
    00253                 }
    00254
    00255                 chunk->len = span->chunk_sz;
    00256                 if (chan->chan_reg.p && chan->chan_reg.rx_data) {
    00257                         err=chan->chan_reg.rx_data(chan->chan_reg.p,chunk->data,chunk->len);
    00258                 } else {
    00259                         err=1;
    00260                 }
    00261
    00262                 if (err) {
    00263                         chan->init=0;
    00264                         chan->chan_reg.p=NULL;
    00265                 }
    00266
    00267         }
    00268
    00269         return err;
    00270
    00271
    00272 }
    00273
    00280 int sangoma_hp_tdm_handle_read_event(sangoma_hptdm_span_t *span)
    00281 {
    00282         int err;
    00283         hp_tdmapi_rx_event_t *rx_event = (hp_tdmapi_rx_event_t*)&span->rx_data[0];
    00284
    00285         err = sangoma_readmsg_hp_tdm(span->sock,
    00286                                      &span->rx_data[0],sizeof(api_rx_hdr_t),
    00287                                      &span->rx_data[sizeof(api_rx_hdr_t)],
    00288                                      sizeof(span->rx_data) - sizeof(api_rx_hdr_t),
    00289                                      0);
    00290
    00291         if (err >  sizeof(api_rx_hdr_t)) {
    00292
    00293                 lib_printf(15,NULL, "SPAN %i Read Len = %i\n",span->span_no+1,err);
    00294
    00295                 if (rx_event->event_type) {
    00296
    00297                         if (span->span_reg.rx_event && span->span_reg.p) {
    00298                                 span->span_reg.rx_event(span->span_reg.p, rx_event);
    00299                         }
    00300
    00301                 } else {
    00302
    00303                         if (err % span->chunk_sz) {
    00304                                 lib_printf(0,NULL, "Error: SPAN %i Read Len = %i Block not chunk %i aligned! \n",span->span_no+1,err,span->chunk_sz);
    00305                                 /* Received chunk size is not aligned drop it for now */
    00306                                 return 0;
    00307                         }
    00308
    00309                         sangoma_hp_tdm_push_rx_data(span);
    00310                 }
    00311
    00312                 err=0;
    00313
    00314         } else {
    00315                 if (errno == EAGAIN) {
    00316                         err = 0;
    00317                 } else {
    00318                         err=-1;
    00319                 }
    00320         }
    00321
    00322         return err;
    00323 }
    00324
    00325
    00331 int sangoma_hp_tdm_handle_write_event(sangoma_hptdm_span_t *span)
    00332 {
    00333         int i=0,x=0,err=0;
    00334         sangoma_hptdm_chan_t *chan;
    00335         hp_tmd_chunk_t *chunk;
    00336         int chan_no_hw=0;
    00337         char *tx_data = &span->tx_data[sizeof(api_tx_hdr_t)];
    00338
    00339         memset(&span->tx_data,span->idle,sizeof(span->tx_data));
    00340
    00341
    00342         for (i=0;i<SMG_HP_TDM_MAX_CHANS;i++) {
    00343                 chan = &span->chan_idx[i].chan;
    00344                 if (!chan->init) {
    00345                         /* This channel is not open */
    00346                         continue;
    00347                 }
    00348                 chan_no_hw=span->chan_idx[i].chan_no_hw;
    00349
    00350                 chunk = &chan->tx_idx[chan->tx_idx_out];
    00351                 if (!chunk->init) {
    00352                         lib_printf(15,NULL,"span write s%ic%i tx chunk underrun out %i \n",
    00353                                         chan->span_no+1,chan->chan_no+1,chan->tx_idx_out);
    00354                         /* There is no tx data for this channel */
    00355                         continue;
    00356                 }
    00357
    00358                 for (x=0;x<span->chunk_sz;x++) {
    00359
    00360                         tx_data[(span->max_chans*x)+chan_no_hw] = chunk->data[chunk->offset];
    00361                         chunk->offset++;
    00362
    00363                         if (chunk->offset >= chunk->len) {
    00364                                 chunk->init=0;
    00365
    00366                                 lib_printf(15,NULL,"span write s%ic%i tx chunk out %i \n",
    00367                                         chan->span_no+1,chan->chan_no+1,chan->tx_idx_out);
    00368
    00369                                 chan->tx_idx_out++;
    00370                                 if (chan->tx_idx_out >= SMG_HP_TDM_CHUNK_IDX_SZ) {
    00371                                         chan->tx_idx_out=0;
    00372                                 }
    00373                                 chunk=&chan->tx_idx[chan->tx_idx_out];
    00374                                 if (!chunk->init) {
    00375                                         /* We are out of tx data on this channel */
    00376                                         break;
    00377                                 }
    00378                         }
    00379                 }
    00380         }
    00381
    00382
    00383         err = sangoma_writemsg_hp_tdm(span->sock,
    00384                                      span->tx_data,sizeof(api_tx_hdr_t),
    00385                                      tx_data, span->tx_size,
    00386                                      0);
    00387
    00388         lib_printf(15, NULL, "SPAN %i TX Len %i Expecting %i\n",
    00389                         span->span_no+1, err, span->tx_size+sizeof(api_tx_hdr_t));
    00390
    00391         if (err < span->tx_size) {
    00392                 if (errno == EAGAIN) {
    00393                         return 0;
    00394                 } else {
    00395                         return -1;
    00396                 }
    00397         } else {
    00398                 err=0;
    00399         }
    00400
    00401         return err;
    00402
    00403 }