00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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 }
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
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
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
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
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
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 }