libhpsangoma: libhpsangoma.c Source File

- Main Page
- Classes
- Files

# libhpsangoma.c

    00001 /*****************************************************************************
    00002  * libhpsangoma.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
    00019 /*---------------------------------------------------------
    00020   PRIVATE STRUCTURES
    00021  ----------------------------------------------------------*/
    00022
    00023 void (*lib_log)(int level, FILE *fp, char *file, const char *func, int line, char *fmt, ...)=NULL;
    00024
    00025
    00034 static int sangoma_hp_tdm_chan_push(struct sangoma_hptdm_chan *chan, char *data, int len)
    00035 {
    00036         hp_tmd_chunk_t *tx_chunk;
    00037         int free_slots;
    00038
    00039         if (!chan->init) {
    00040                 return -2;
    00041         }
    00042
    00043         if (len >= SMG_HP_MAX_CHAN_DATA) {
    00044                 /* Data Too Big */
    00045                 lib_printf(0,NULL,"chan_push c%i tx chunk len %i too big\n",
    00046                                 chan->span_no+1,chan->chan_no+1,chan->tx_idx_in,len);
    00047                 return -1;
    00048         }
    00049
    00050         /* Lock */
    00051         if (chan->tx_idx_in >= chan->tx_idx_out) {
    00052                 free_slots=SMG_HP_TDM_CHUNK_IDX_SZ-(chan->tx_idx_in-chan->tx_idx_out);
    00053         } else {
    00054                 free_slots=chan->tx_idx_out-chan->tx_idx_in;
    00055         }
    00056         /* Un Lock */
    00057
    00058         if (!free_slots) {
    00059                 /* We have just overruned the tx buffer */
    00060                 lib_printf(0,NULL,"chan_push c%i failed no free slots in %i out %i\n",
    00061                                 chan->span_no+1,chan->chan_no+1, chan->tx_idx_in,chan->tx_idx_out);
    00062                 return 1;
    00063         }
    00064
    00065         tx_chunk = &chan->tx_idx[chan->tx_idx_in];
    00066         if (tx_chunk->init) {
    00067                 /* This should NEVER happen the chunk should be free */
    00068                 lib_printf(15,NULL,"chan_push s%ic%i tx chunk overrun in %i \n",
    00069                                 chan->span_no+1,chan->chan_no+1,chan->tx_idx_in);
    00070                 return 1;
    00071         }
    00072
    00073         memset(tx_chunk,0,sizeof(hp_tmd_chunk_t));
    00074         memcpy(&tx_chunk->data,data,len);
    00075         tx_chunk->len=len;
    00076         tx_chunk->init=1;
    00077
    00078         lib_printf(15,NULL,"chan_push s%ic%i tx chunk in %i \n",
    00079                                 chan->span_no+1,chan->chan_no+1,chan->tx_idx_in);
    00080
    00081         chan->tx_idx_in++;
    00082         if (chan->tx_idx_in >= SMG_HP_TDM_CHUNK_IDX_SZ) {
    00083                 chan->tx_idx_in=0;
    00084         }
    00085
    00086         return 0;
    00087 }
    00088
    00089 /*-------------------------------------------------
    00090   Internal Span Methods
    00091  -------------------------------------------------*/
    00092
    00093
    00103 static int sangoma_hp_tdm_open_chan(sangoma_hptdm_span_t *span,
    00104                               sangoma_hptdm_chan_reg_t *cfg,
    00105                               unsigned int chan_no,
    00106                               sangoma_hptdm_chan_t **chan_ptr)
    00107 {
    00108         sangoma_hptdm_chan_t *chan;
    00109
    00110         if (!span->init) {
    00111                 return -1;
    00112         }
    00113
    00114         if (chan_no >= SMG_HP_TDM_MAX_CHANS) {
    00115                 lib_printf(0,NULL,"open_chan failed chan_no %i >= max chans %i\n",
    00116                                 chan_no, SMG_HP_TDM_MAX_CHANS);
    00117                 return -1;
    00118         }
    00119
    00120         if (!cfg->rx_data || !cfg->p) {
    00121                 return -1;
    00122         }
    00123
    00124         if (span->chan_idx[chan_no].chan_no_hw < 0) {
    00125                 lib_printf(0,NULL,"open_chan failed chan_no s%ic%i is not mapped to hardware\n",
    00126                                 span->span_no+1,chan_no+1);
    00127                 return -1;
    00128         }
    00129
    00130         chan = &span->chan_idx[chan_no].chan;
    00131         if (chan->init) {
    00132                 /* Chan Busy */
    00133                 lib_printf(0,NULL,"open_chan failed chan_no s%ic%i is busy\n",
    00134                                 span->span_no+1,chan_no+1);
    00135                 return 1;
    00136         }
    00137
    00138         memset(chan,0,sizeof(sangoma_hptdm_chan_t));
    00139
    00140         chan->chan_no = chan_no;
    00141         chan->span = span;
    00142         memcpy(&chan->chan_reg, cfg, sizeof(sangoma_hptdm_chan_reg_t));
    00143
    00144         chan->push = sangoma_hp_tdm_chan_push;
    00145
    00146         chan->init=1;
    00147         lib_printf(15,NULL,"open_chan chan_no s%ic%i ok\n",
    00148                                 span->span_no+1,chan_no+1);
    00149
    00150         *chan_ptr = chan;
    00151
    00152         return 0;
    00153
    00154 }
    00155
    00156
    00163 static int sangoma_hp_tdm_close_chan(sangoma_hptdm_chan_t *chan)
    00164 {
    00165         chan->init=0;
    00166         chan->chan_reg.p=NULL;
    00167         lib_printf(15,NULL,"close_chan chan_no s%ic%i ok\n",
    00168                                 chan->span_no+1,chan->chan_no+1);
    00169         return 0;
    00170 }
    00171
    00172
    00178 static int sangoma_hp_tdm_is_chan_closed (sangoma_hptdm_chan_t *chan)
    00179 {
    00180         return (chan->init == 0) ? 1:0;
    00181 }
    00182
    00188 static int sangoma_hp_tdm_close_span(sangoma_hptdm_span_t *span)
    00189 {
    00190         int i;
    00191         sangoma_hptdm_chan_t *chan=NULL;
    00192
    00193         for (i=0;i<SMG_HP_TDM_MAX_CHANS;i++) {
    00194                 chan = &span->chan_idx[i].chan;
    00195                 if (chan->init) {
    00196                         chan->init=0;
    00197                 }
    00198         }
    00199
    00200         close(span->sock);
    00201         span->sock=-1;
    00202
    00203         return 0;
    00204 }
    00205
    00211 static int sangoma_hp_tdm_event_ctrl_span(sangoma_hptdm_span_t *span, hp_tdmapi_tx_event_t *event)
    00212 {
    00213         int err;
    00214
    00215         if (!span->init || span->sock < 0) {
    00216                 return -1;
    00217         }
    00218
    00219         err = ioctl(span->sock,SIOC_WANPIPE_API,event);
    00220         if (err < 0){
    00221                 lib_printf(0,NULL,"Error: SPAN %i Failed to execute event!\n",
    00222                                 span->span_no+1);
    00223                 return -1;
    00224         }
    00225
    00226         return 0;
    00227 }
    00228
    00234 static int sangoma_hp_tdm_event_get_cfg(sangoma_hptdm_span_t *span, wan_if_cfg_t *if_cfg)
    00235 {
    00236         memcpy(if_cfg,&span->span_cfg,sizeof(if_cfg));
    00237         return 0;
    00238 }
    00239
    00245 static int sangoma_hp_tdm_run_span(sangoma_hptdm_span_t *span)
    00246 {
    00247         int err=0;
    00248         fd_set  sock_read,sock_write,sock_oob;
    00249
    00250         if (!span->init) {
    00251                 lib_printf(0, NULL, "Span %i not initialized %i\n",span->span_no+1);
    00252                 return -1;
    00253         }
    00254
    00255         lib_printf(15, NULL, "Starting RUN SPAN %i Sock=%i\n",span->span_no+1, span->sock);
    00256
    00257         if (span->sock < 0) {
    00258                 err=sangoma_hptdm_span_open(span);
    00259                 if (err) {
    00260                         usleep(500000);
    00261                         err=-2;
    00262                         goto sangoma_hp_tdm_run_span_exit;
    00263                 }
    00264         }
    00265
    00266         /* Initialize all select() descriptors */
    00267         FD_ZERO(&sock_read);
    00268         FD_ZERO(&sock_write);
    00269         FD_ZERO(&sock_oob);
    00270
    00271         FD_SET(span->sock,&sock_oob);
    00272         FD_SET(span->sock,&sock_read);
    00273         FD_SET(span->sock,&sock_write);
    00274
    00275         err=select(span->sock + 1,&sock_read, NULL, &sock_oob, NULL);
    00276
    00277         if (err > 0) {
    00278
    00279                 if (FD_ISSET(span->sock,&sock_oob)){
    00280                         err=sangoma_hp_tdm_handle_oob_event(span);
    00281                         if (err) {
    00282                                 lib_printf(0, NULL, "RUN SPAN: %i oob err %i\n",
    00283                                         span->span_no+1, err);
    00284                                 err=-3;
    00285                                 goto sangoma_hp_tdm_run_span_exit;
    00286                         }
    00287                 }
    00288                 if (FD_ISSET(span->sock,&sock_read)){
    00289                         err=sangoma_hp_tdm_handle_read_event(span);
    00290                         if (err) {
    00291                                 lib_printf(0, NULL, "RUN SPAN: %i read err %i\n",
    00292                                         span->span_no+1, err);
    00293                                 err=-4;
    00294                                 goto sangoma_hp_tdm_run_span_exit;
    00295                         }
    00296
    00297                         err=sangoma_hp_tdm_handle_write_event(span);
    00298                         if (err) {
    00299                                 lib_printf(0, NULL, "RUN SPAN: %i write err %i\n",
    00300                                         span->span_no+1, err);
    00301                                 err=-5;
    00302                                 goto sangoma_hp_tdm_run_span_exit;
    00303                         }
    00304                 }
    00305
    00306         } else if (err==0) {
    00307                 /* Timeout continue */
    00308                 return 0;
    00309
    00310         } else {
    00311                 /* Error */
    00312                 if (errno == EAGAIN) {
    00313                         goto sangoma_hp_tdm_run_span_exit;
    00314                 }
    00315
    00316                 err=-6;
    00317         }
    00318
    00319 sangoma_hp_tdm_run_span_exit:
    00320
    00321         if (err < 0) {
    00322                 if (span->sock) {
    00323                         close(span->sock);
    00324                         span->sock=-1;
    00325                 }
    00326         }
    00327
    00328         return err;
    00329 }
    00330
    00331
    00332
    00333 /*---------------------------------------------------------
    00334   PUBLIC STRUCTURES
    00335  ----------------------------------------------------------*/
    00336
    00337
    00338 /*
    00339   \brief Initialize and Configure Span - private functions not to be used directly!
    00340   \param span_no span number - integer
    00341   \param cfg span registration struct
    00342   \param version library version number added by the macro
    00343   \return NULL: fail,  Span Object: pass
    00344  *
    00345  * The __sangoma_hptdm_api_span_init() function must NOT be called directly!
    00346  *  One MUST use defined sangoma_hptdm_api_span_init() macro instead
    00347  */
    00348
    00349 sangoma_hptdm_span_t * __sangoma_hptdm_api_span_init(int span_no, sangoma_hptdm_span_reg_t *cfg, int version)
    00350 {
    00351         int err,i,ch=0;
    00352         sangoma_hptdm_span_t *span;
    00353
    00354         span = malloc(sizeof(sangoma_hptdm_span_t));
    00355         if (!span) {
    00356                 return NULL;
    00357         }
    00358
    00359         memset(span,0,sizeof(sangoma_hptdm_span_t));
    00360
    00361         span->span_no=span_no;
    00362         sprintf(span->if_name,"w%ig1",span_no+1);
    00363
    00364         if (cfg) {
    00365                 memcpy(&span->span_reg,cfg,sizeof(sangoma_hptdm_span_reg_t));
    00366                 if (!lib_log) {
    00367                         lib_log=cfg->log;
    00368                 }
    00369         }
    00370
    00371         err=sangoma_hptdm_span_open(span);
    00372         if (err) {
    00373                 free(span);
    00374                 return NULL;
    00375         }
    00376
    00377         if (span->span_cfg.media == WAN_MEDIA_E1) {
    00378                 span->span_cfg.active_ch = span->span_cfg.active_ch >> 1;
    00379         }
    00380
    00381         lib_printf(0,NULL,"Span %i Configuration\n",span->span_no+1);
    00382         lib_printf(0,NULL,"Used By\t:%i\n",span->span_cfg.usedby);
    00383         lib_printf(0,NULL,"Media\t:%i\n",span->span_cfg.media);
    00384         lib_printf(0,NULL,"Active Ch\t:0x%08X\n",span->span_cfg.active_ch);
    00385         lib_printf(0,NULL,"Chunk Sz\t:%i\n",span->span_cfg.chunk_sz);
    00386         lib_printf(0,NULL,"HW Coding\t:%i\n",span->span_cfg.hw_coding);
    00387         lib_printf(0,NULL,"If Number\t:%i\n",span->span_cfg.interface_number);
    00388
    00389
    00390         /* Map all channels to the actually configued on hardware */
    00391         for (i=0;i<SMG_HP_TDM_MAX_CHANS;i++) {
    00392                 span->chan_idx[i].chan_no_hw=-1;
    00393                 if (span->span_cfg.active_ch & (1<<i)) {
    00394                         span->chan_idx[i].chan_no_hw=ch;
    00395                         lib_printf(0,NULL,"Chan %i Mapped to %i",i,ch);
    00396                         ch++;
    00397                         span->max_chans++;
    00398                 } else {
    00399                         lib_printf(0,NULL,"Chan %i Not Mapped",i);
    00400                 }
    00401         }
    00402
    00403         lib_printf(0,NULL,"Total Chans\t:%i\n",span->max_chans);
    00404
    00405         /* Must be configurable */
    00406         span->chunk_sz=span->span_cfg.chunk_sz;
    00407         span->tx_size=span->max_chans*span->chunk_sz;
    00408
    00409         span->init=1;
    00410         span->idle=0xFF;
    00411
    00412         span->open_chan = sangoma_hp_tdm_open_chan;
    00413         span->close_chan = sangoma_hp_tdm_close_chan;
    00414         span->is_chan_closed = sangoma_hp_tdm_is_chan_closed;
    00415         span->run_span =sangoma_hp_tdm_run_span;
    00416         span->close_span = sangoma_hp_tdm_close_span;
    00417         span->event_ctrl = sangoma_hp_tdm_event_ctrl_span;
    00418         span->get_cfg = sangoma_hp_tdm_event_get_cfg;
    00419
    00420         lib_printf(5, NULL, "Span %i Initialized\n",span->span_no+1);
    00421
    00422         return span;
    00423 }
    00424
    00425 /*
    00426   \brief Free, Un-Initialize Span
    00427   \param span_no span object
    00428   \return 0 = pass, non zero fail
    00429  */
    00430
    00431 int sangoma_hptdm_api_span_free(sangoma_hptdm_span_t *span)
    00432 {
    00433         if (span->sock >= 0) {
    00434                 span->close_span(span);
    00435         }
    00436
    00437         free(span);
    00438         span=NULL;
    00439
    00440         return 0;
    00441 }
    00442