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 }

Generated on Sun Aug 17 23:56:55 2008 for libhpsangoma by  doxygen 1.4.7