/***************************************************************************** * aft_api.c AFT T1/E1: HDLC API Sample Code * * Author(s): Nenad Corbic * * Copyright: (c) 2003-2004 Sangoma Technologies Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * ============================================================================ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lib_api.h" #define MAX_TX_DATA 5000 /* Size of tx data */ #define MAX_FRAMES 5000 /* Number of frames to transmit */ #define MAX_RX_DATA 5000 unsigned short Rx_lgth; unsigned char Rx_data[MAX_RX_DATA]; unsigned char Tx_data[MAX_TX_DATA + sizeof(wp_tdm_api_rx_hdr_t)]; /* Prototypes */ int MakeConnection(void); void handle_span_chan( void); void sig_end(int sigid); int dev_fd; FILE *tx_fd=NULL,*rx_fd=NULL; wanpipe_tdm_api_t tdm_api; /*************************************************** * HANDLE SOCKET * * o Read a socket * o Cast data received to api_rx_element_t data type * o The received packet contains 16 bytes header * * ------------------------------------------ * | 16 bytes | X bytes ... * ------------------------------------------ * Header Data * * o Data structures: * ------------------ * typedef struct { * union { * struct { * unsigned char _event_type; * unsigned char _rbs_rx_bits; * unsigned int _time_stamp; * }wp_event; * struct { * unsigned char _rbs_rx_bits; * unsigned int _time_stamp; * }wp_rx; * unsigned char reserved[16]; * }wp_rx_hdr_u; * #define wp_api_event_type wp_rx_hdr_u.wp_event._event_type * #define wp_api_event_rbs_rx_bits wp_rx_hdr_u.wp_event._rbs_rx_bits * #define wp_api_event_time_stamp wp_rx_hdr_u.wp_event._time_stamp * } wp_tdm_api_rx_hdr_t; * * typedef struct { * wp_tdm_api_rx_hdr_t hdr; * unsigned char data[1]; * } wp_tdm_api_rx_element_t; * * typedef struct { * union { * struct { * unsigned char _rbs_rx_bits; * unsigned int _time_stamp; * }wp_tx; * unsigned char reserved[16]; * }wp_tx_hdr_u; * #define wp_api_time_stamp wp_tx_hdr_u.wp_tx._time_stamp * } wp_tdm_api_tx_hdr_t; * * typedef struct { * wp_tdm_api_tx_hdr_t hdr; * unsigned char data[1]; * } wp_tdm_api_tx_element_t; * * #define WPTDM_A_BIT 0x08 * #define WPTDM_B_BIT 0x04 * #define WPTDM_C_BIT 0x02 * #define WPTDM_D_BIT 0x01 * */ void handle_span_chan(void) { unsigned int Rx_count,Tx_count,Tx_length; wp_tdm_api_rx_element_t* api_rx_el; wp_tdm_api_tx_element_t * api_tx_el; fd_set ready,write,oob; int err,i; #if 0 int rlen; int stream_sync=0; #endif Rx_count = 0; Tx_count = 0; if (tdm_api.wp_tdm_cmd.hdlc) { Tx_length = tx_size; } else { Tx_length = tdm_api.wp_tdm_cmd.usr_mtu_mru; } printf("\n\nSocket Handler: Rx=%d Tx=%i TxCnt=%i TxLen=%i TxDelay=%i\n", read_enable,write_enable,tx_cnt,tx_size,tx_delay); /* Initialize the Tx Data buffer */ memset(&Tx_data[0],0,MAX_TX_DATA + sizeof(wp_tdm_api_rx_hdr_t)); /* Cast the Tx data packet with the tx element * structure. We must insert a 16 byte * driver header, which driver will remove * before passing packet out the physical port */ api_tx_el = (wp_tdm_api_tx_element_t*)&Tx_data[0]; /* Create a Tx packet based on user info, or * by deafult incrementing number starting from 0 */ for (i=0;idata[i] = (unsigned char)i; }else{ #if 0 api_tx_el->data[i] = (unsigned char)tx_data+(i%4); #else api_tx_el->data[i] = (unsigned char)tx_data; #endif } } sangoma_tdm_enable_rxhook_events(dev_fd, &tdm_api); /* Main Rx Tx OOB routine */ for(;;) { /* Initialize all select() descriptors */ FD_ZERO(&ready); FD_ZERO(&write); FD_ZERO(&oob); FD_SET(dev_fd,&oob); FD_SET(dev_fd,&ready); if (write_enable){ FD_SET(dev_fd,&write); } /* Select will block, until: * 1: OOB event, link level change * 2: Rx data available * 3: Interface able to Tx */ if(select(dev_fd + 1,&ready, &write, &oob, NULL)){ fflush(stdout); if (FD_ISSET(dev_fd,&oob)){ /* An OOB event is pending, usually indicating * a link level change */ err=sangoma_tdm_read_event(dev_fd,&tdm_api); if(err < 0 ) { printf("Failed to receive OOB %i , %i\n", Rx_count, err); err = ioctl(dev_fd,SIOC_WANPIPE_SOCK_STATE,0); printf("Sock state is %s\n", (err == 0) ? "CONNECTED" : (err == 1) ? "DISCONNECTED" : "CONNECTING"); break; } printf("GOT OOB EXCEPTION CMD Exiting\n"); } if (FD_ISSET(dev_fd,&ready)){ /* An Rx packet is pending * 1: Read the rx packet into the Rx_data * buffer. Confirm len > 0 * * 2: Cast Rx_data to the api_rx_element. * Thus, removing a 16 byte header * attached by the driver. * * 3. Check error_flag: * CRC,Abort..etc */ memset(Rx_data, 0, sizeof(Rx_data)); err = sangoma_readmsg_tdm(dev_fd, Rx_data, sizeof(wp_tdm_api_rx_hdr_t), &Rx_data[sizeof(wp_tdm_api_rx_hdr_t)], MAX_RX_DATA, 0); if (!read_enable){ goto bitstrm_skip_read; } /* err indicates bytes received */ if(err <= 0) { printf("\nError receiving data\n"); break; } api_rx_el = (wp_tdm_api_rx_element_t*)&Rx_data[0]; /* Check the packet length */ Rx_lgth = err; if(Rx_lgth<=0) { printf("\nShort frame received (%d)\n", Rx_lgth); return; } #if 0 if (api_rx_el->data[0] == tx_data && api_rx_el->data[1] == (tx_data+1)){ if (!stream_sync){ printf("GOT SYNC %x\n",api_rx_el->data[0]); } stream_sync=1; }else{ if (stream_sync){ printf("OUT OF SYNC: %x\n",api_rx_el->data[0]); } } #endif ++Rx_count; if (verbose){ #if 0 printf("Received %i Length = %i\n", Rx_count,Rx_lgth); printf("Data: "); for(i=0;idata[i]); } printf("\n"); #endif }else{ //putchar('R'); } #if 0 switch(api_rx_el->hdr.wp_api_event_type){ case WP_TDM_EVENT_DTMF: printf("DTMV Event: %c (%s:%s)!\n", api_rx_el->hdr.wp_api_event_dtmf_digit, (api_rx_el->hdr.wp_api_event_dtmf_type&WP_TDM_EVENT_DTMF_ROUT)?"ROUT":"SOUT", (api_rx_el->hdr.wp_api_event_dtmf_type&WP_TDM_EVENT_DTMF_PRESET)?"PRESET":"STOP"); break; case WP_TDM_EVENT_RXHOOK: printf("RXHOOK Event: %s!\n", (api_rx_el->hdr.wp_api_event_rxhook_state&WP_TDM_EVENT_RXHOOK_OFF)?"OFF-HOOK":"ON-HOOK"); break; case WP_TDM_EVENT_RING: printf("RING Event: %s!\n", (api_rx_el->hdr.wp_api_event_ring_state&WP_TDM_EVENT_RING_PRESENT)?"PRESENT":"STOP"); break; } #endif if (rx_cnt > 0 && Rx_count >= rx_cnt){ break; } bitstrm_skip_read: ; } if (FD_ISSET(dev_fd,&write)){ err = sangoma_writemsg_tdm(dev_fd, Tx_data,16, &Tx_data[16], Tx_length, 0); if (err <= 0){ if (errno == EBUSY){ if (verbose){ printf("Sock busy try again!\n"); } /* Socket busy try sending again !*/ }else{ printf("Faild to send %i \n",errno); perror("Send: "); break; } }else{ ++Tx_count; if (verbose){ //printf("Packet sent: Sent %i : %i\n", // err,Tx_count); }else{ //putchar('T'); } } } if (tx_delay){ usleep(tx_delay); } if (tx_cnt && tx_size && Tx_count >= tx_cnt && !(files_used & TX_FILE_USED)){ write_enable=0; if (rx_cnt > 0){ /* Dont break let rx finish */ }else{ break; } } } } sangoma_tdm_disable_rxhook_events(dev_fd, &tdm_api); if (tx_fd){ fclose(tx_fd); } if (rx_fd){ fclose(rx_fd); } close (dev_fd); return; } int rxhook_event (int fd, unsigned char state) { printf("%d: RXHOOK Event: %s!\n", fd, (state & WAN_EVENT_RXHOOK_OFF)?"OFF-HOOK":"ON-HOOK"); return 0; } /*************************************************************** * Main: * * o Make a socket connection to the driver. * o Call handle_span_chan() to read the socket * **************************************************************/ int main(int argc, char* argv[]) { int proceed; proceed=init_args(argc,argv); if (proceed != WAN_TRUE){ usage(argv[0]); return -1; } signal(SIGINT,&sig_end); memset(&tdm_api,0,sizeof(tdm_api)); tdm_api.wp_tdm_event.wp_rxhook_event = &rxhook_event; printf("TDM RXHOOK PTR = %p\n",tdm_api.wp_tdm_event.wp_rxhook_event); dev_fd =-1; dev_fd = sangoma_open_tdmapi_span_chan(atoi(card_name),atoi(if_name)); if( dev_fd < 0){ printf("Failed to open span chan (%s:%s:%d:%d)\n", card_name, if_name, atoi(card_name),atoi(if_name)); exit (1); } printf("HANDLING SPAN %i CHAN %i FD=%i\n", atoi(card_name),atoi(if_name),dev_fd); sangoma_tdm_set_codec(dev_fd,&tdm_api,WP_NONE); sangoma_get_full_cfg(dev_fd, &tdm_api); handle_span_chan(); close(dev_fd); return 0; return 0; }; void sig_end(int sigid) { printf("Got Signal %i\n",sigid); sangoma_tdm_disable_rxhook_events(dev_fd, &tdm_api); if (tx_fd){ fclose(tx_fd); } if (rx_fd){ fclose(rx_fd); } if (dev_fd){ close (dev_fd); } exit(1); }