/* * Asterisk -- A telephony toolkit for Linux. * * Serial RS232 CDR records. * * Copyright (C) 1999, Mark Spencer * * Brian K. West * * This program is free software, distributed under the terms of * the GNU General Public License. * */ #include #include #include #include #include #include #include #include #include #define DATE_FORMAT "%Y-%m-%d %T" /* Define RS232 */ #define BAUDRATE B9600 #define DEFAULT_PORT "/dev/tty2" /* #define RS232_LOGUNIQUEID 1 */ /* #define RS232_LOGUSERFIELD 1 */ #include #include #include #include #include #include #include #include #include #include AST_MUTEX_DEFINE_STATIC(rs232_lock); static char *desc = "Serial RS232 CDR Backend"; static char *name = "serial"; static FILE *mf = NULL; static int rs232_fd; int rs232_send_input(int fd, char *string); int rs232_send_char(int fd, int c); int rs232_open_port(char *device); int rs232_init_port(int fd); int rs232_open_port(char *device) { int fd; fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) ast_verbose( VERBOSE_PREFIX_4 "Unable to open port %s\n", device); else fcntl(fd, F_SETFL, 0); return (fd); } int rs232_init_port(int fd) { int arg = TIOCM_DTR; struct termios tio; tcgetattr(fd, &tio); cfsetispeed(&tio, BAUDRATE); cfsetospeed(&tio, BAUDRATE); tio.c_cflag |= CS8; tio.c_cflag &= ~PARENB; tio.c_cflag &= ~CSTOPB; tio.c_cflag &= ~CSIZE; tio.c_cflag &= ~CRTSCTS; tio.c_cflag &= ~(ICANON | ECHO | ECHOE | ISIG); tio.c_cflag &= ~(IGNPAR | IXON | IXOFF | IXANY | IGNBRK); tio.c_cc[VMIN] = 0; tio.c_cc[VTIME] = 0; tio.c_cflag &= ~OPOST; tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &tio); ioctl(fd, TIOCMBIS, &arg); return(0); } int rs232_send_input(int fd, char *string) { int n = 0; int cnt = strlen(string); for(n = 0;n= bufsize - 4) return -1; buf[pos++] = '\"'; error = -1; while(pos < bufsize - 3) { if (!s[spos]) { error = 0; break; } if (s[spos] == '\"') buf[pos++] = '\"'; buf[pos++] = s[spos]; spos++; } buf[pos++] = '\"'; buf[pos++] = ','; buf[pos++] = '\0'; return error; } static int append_int(char *buf, int s, size_t bufsize) { char tmp[32]; int pos = strlen(buf); snprintf(tmp, sizeof(tmp), "%d", s); if (pos + strlen(tmp) > bufsize - 3) return -1; strncat(buf, tmp, bufsize - strlen(buf) - 1); pos = strlen(buf); buf[pos++] = ','; buf[pos++] = '\0'; return 0; } static int append_date(char *buf, struct timeval tv, size_t bufsize) { char tmp[80] = ""; struct tm tm; time_t t; t = tv.tv_sec; if (strlen(buf) > bufsize - 3) return -1; if (!tv.tv_sec && !tv.tv_usec) { strncat(buf, ",", bufsize - strlen(buf) - 1); return 0; } localtime_r(&t,&tm); strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm); return append_string(buf, tmp, bufsize); } static int build_rs232_record(char *buf, size_t bufsize, struct ast_cdr *cdr) { buf[0] = '\0'; append_string(buf, cdr->accountcode, bufsize); append_string(buf, cdr->src, bufsize); append_string(buf, cdr->dst, bufsize); append_string(buf, cdr->dcontext, bufsize); append_string(buf, cdr->clid, bufsize); append_string(buf, cdr->channel, bufsize); append_string(buf, cdr->dstchannel, bufsize); append_string(buf, cdr->lastapp, bufsize); append_string(buf, cdr->lastdata, bufsize); append_date(buf, cdr->start, bufsize); append_date(buf, cdr->answer, bufsize); append_date(buf, cdr->end, bufsize); append_int(buf, cdr->duration, bufsize); append_int(buf, cdr->billsec, bufsize); append_string(buf, ast_cdr_disp2str(cdr->disposition), bufsize); append_string(buf, ast_cdr_flags2str(cdr->amaflags), bufsize); #ifdef RS232_LOGUNIQUEID append_string(buf, cdr->uniqueid, bufsize); #endif #ifdef RS232_LOGUSERFIELD append_string(buf, cdr->userfield,bufsize); #endif if (strlen(buf) < bufsize - 5) { buf[strlen(buf) - 1] = '\0'; strncat(buf, "\n", bufsize - strlen(buf) - 1); return 0; } return -1; } static int rs232_log(struct ast_cdr *cdr) { char buf[1024]; ast_mutex_lock(&rs232_lock); if (build_rs232_record(buf, sizeof(buf), cdr)) { ast_log(LOG_WARNING, "Unable to create RS232 record in %d bytes. CDR not recorded!\n", (int)sizeof(buf)); } else { rs232_send_input(rs232_fd, buf); } ast_mutex_unlock(&rs232_lock); return 0; } char *description(void) { return desc; } int unload_module(void) { if (mf) fclose(mf); if (rs232_fd) close(rs232_fd); ast_cdr_unregister(name); return 0; } int load_module(void) { int res; rs232_fd = rs232_open_port(DEFAULT_PORT); rs232_init_port(rs232_fd); res = ast_cdr_register(name, desc, rs232_log); if (res) { ast_log(LOG_ERROR, "Unable to register RS232 CDR handling\n"); if (mf) fclose(mf); } return res; } int reload(void) { return 0; } int usecount(void) { return 0; } char *key() { return ASTERISK_GPL_KEY; }