wanpipe/api/tdm_api/aft_tdm_voice_api_zap.c

511 lines
10 KiB
C

/*****************************************************************************
* aft_api.c AFT T1/E1: HDLC API Sample Code
*
* Author(s): Nenad Corbic <ncorbic@sangoma.com>
*
* 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.
* ============================================================================
*/
#if 0
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if_wanpipe.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <signal.h>
#endif
#define WAN_IFNAME_SZ 100
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include "lib_api.h"
#define DAHDI_ISSUES 1
#include "zapcompat_user.h"
#define MAX_TX_DATA 15000 /* Size of tx data */
#define MAX_FRAMES 5000 /* Number of frames to transmit */
#define MAX_RX_DATA 15000
#define BLOCK_SIZE 160
unsigned short Rx_lgth;
unsigned char Rx_data[MAX_RX_DATA];
unsigned char Tx_data[MAX_TX_DATA ];
ZT_PARAMS tp;
/* Prototypes */
int MakeConnection(int);
void handle_span_chan( void);
void sig_end(int sigid);
int dev_fd;
FILE *tx_fd=NULL,*rx_fd=NULL;
int zap_ec_ctrl(int sock, int tap)
{
struct dahdi_echocanparams ecp = { .tap_length = tap };
int res;
res=ioctl(sock, DAHDI_ECHOCANCEL_PARAMS, &ecp);
if (res) {
fprintf(stderr, "Failed to configure ec tap=%i: %s\n", tap, strerror(errno));
}
return res;
}
/***************************************************
* 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
*
* ------------------------------------------
* | sizeof(wp_api_hdr_t) 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[sizeof(wp_api_hdr_t)];
* }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[sizeof(wp_api_hdr_t)];
* }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 print_packet(unsigned char *buf, int len)
{
int x;
printf("{ | ");
for (x=0;x<len;x++){
if (x && x%24 == 0){
printf("\n ");
}
if (x && x%8 == 0)
printf(" | ");
printf("%02x ",buf[x]);
}
printf("}\n");
}
void handle_span_chan(void)
{
unsigned int Rx_count,Tx_count,Tx_length;
fd_set ready,fd_write,oob;
int err,i;
#if 0
int rlen;
int stream_sync=0;
#endif
Rx_count = 0;
Tx_count = 0;
Tx_length = tx_size;
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 );
/* Cast the Tx data packet with the tx element
* structure. We must insert a sizeof(wp_api_hdr_t) byte
* driver header, which driver will remove
* before passing packet out the physical port */
/* Create a Tx packet based on user info, or
* by deafult incrementing number starting from 0 */
for (i=0;i<Tx_length;i++){
if (tx_data == -1){
Tx_data[i] = (unsigned char)i;
}else{
#if 0
Tx_data[i] = (unsigned char)tx_data+(i%4);
#else
Tx_data[i] = (unsigned char)tx_data;
#endif
}
}
/* Main Rx Tx OOB routine */
for(;;) {
/* Initialize all select() descriptors */
FD_ZERO(&ready);
FD_ZERO(&fd_write);
FD_ZERO(&oob);
FD_SET(dev_fd,&oob);
FD_SET(dev_fd,&ready);
if (write_enable){
FD_SET(dev_fd,&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, &fd_write, &oob, NULL)){
fflush(stdout);
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 sizeof(wp_api_hdr_t) byte header
* attached by the driver.
*
* 3. Check error_flag:
* CRC,Abort..etc
*/
memset(Rx_data, 0, sizeof(Rx_data));
err = read(dev_fd, Rx_data, sizeof(Rx_data));
if (!read_enable){
goto bitstrm_skip_read;
}
/* err indicates bytes received */
if(err <= 0) {
printf("\nError receiving data\n");
break;
}
/* 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){
printf("Received %i Length = %i\n",
Rx_count,Rx_lgth);
printf("Data: ");
print_packet(Rx_data,Rx_lgth);
}else{
//putchar('R');
}
if (rx_cnt > 0 && Rx_count >= rx_cnt){
break;
}
bitstrm_skip_read:
;
}
if (FD_ISSET(dev_fd,&fd_write)){
err = write(dev_fd,Tx_data,Tx_length);
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;
}
}
}
}
if (tx_fd){
fclose(tx_fd);
}
if (rx_fd){
fclose(rx_fd);
}
close (dev_fd);
}
int rbs_event (int fd, unsigned char rbs_bits)
{
printf("%d: GOT RBS EVENT: RBS BITS=0x%X\n",
fd,rbs_bits);
return 0;
}
int MakeConnection(int chan)
{
int i;
int sock;
ZT_BUFFERINFO bi;
char chan_name[100];
#ifdef DAHDI_ISSUES
sprintf(chan_name,"/dev/dahdi/%d",chan);
#else
sprintf(chan_name,"/dev/zap/%d",chan);
#endif
printf("Opening chan %i %s\n",chan,chan_name);
#ifdef DAHDI_ISSUES
sock = open("/dev/dahdi/channel", O_RDWR | O_NONBLOCK, 0600);
#else
sock = open("/dev/zap/channel", O_RDWR | O_NONBLOCK, 0600);
#endif
if( sock < 0 ) {
perror("Open Span Chan: ");
return -1 ;
}
if (ioctl(sock, ZT_SPECIFY, &chan)) {
perror("Open Span Chan: ");
close(sock);
sock=-1;
return -1;
}
if (tp.sigtype != ZT_SIG_HARDHDLC) {
if (ioctl(sock, ZT_SET_BLOCKSIZE, &tx_size)) {
fprintf(stderr, "Unable to set block size to %d: %s\n", tx_size, strerror(errno));
return -1;
}
}
if (ioctl(sock, ZT_GET_PARAMS, &tp)) {
fprintf(stderr, "Unable to get channel parameters\n");
return -1;
}
if (tp.sigtype == ZT_SIG_HARDHDLC) {
printf("HARDWARE HDLC %s\n",chan_name);
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
bi.numbufs = 32;
bi.bufsize = 1024;
if (ioctl(sock, ZT_SET_BUFINFO, &bi)) {
fprintf(stderr, "Unable to set appropriate buffering on channel %s\n", chan_name);
return -1;
}
}
ioctl(sock, ZT_GETEVENT);
i = ZT_FLUSH_ALL;
if (ioctl(sock,ZT_FLUSH,&i) == -1){
perror("tor_flush");
return -1;
}
#if 0
if (tp.sigtype != ZT_SIG_HARDHDLC) {
printf("Setting AUDIO MODE\n");
if (ioctl(sock, DAHDI_AUDIOMODE, &i)) {
printf("Error Failed to set Auido mode %s\n\n",chan_name);
return -1;
}
zap_ec_ctrl(sock,0);
if (zap_ec_ctrl(sock,32) != 0) {
return -1;
}
printf("dev=%s ec enabled\n\n",chan_name);
}
#endif
printf("Socket bound to dev=%s\n\n",chan_name);
return sock;
}
/***************************************************************
* 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;
int span,chan;
proceed=init_args(argc,argv);
if (proceed != 1){
usage(argv[0]);
return -1;
}
if (tx_size < 160) {
tx_size = 160;
}
signal(SIGINT,&sig_end);
dev_fd =-1;
span=atoi(card_name);
chan=atoi(if_name);
chan=(span-1)*31+chan;
dev_fd = MakeConnection(chan);
if( dev_fd < 0){
printf("Failed to open span chan\n");
exit (1);
}
printf("HANDLING SPAN %i CHAN %i FD=%i\n",
atoi(card_name),atoi(if_name),dev_fd);
handle_span_chan();
zap_ec_ctrl(dev_fd,0);
close(dev_fd);
return 0;
return 0;
};
void sig_end(int sigid)
{
printf("Got Signal %i\n",sigid);
if (tx_fd){
fclose(tx_fd);
}
if (rx_fd){
fclose(rx_fd);
}
if (dev_fd){
close (dev_fd);
}
exit(1);
}