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 

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