📄 btmodem.c
字号:
/* Affix - Bluetooth Protocol Stack for Linux Copyright (C) 2001 Nokia Corporation Authors: Christian Plog <plog@informatik.uni-bonn.de> emulation part: Imre Deak <imre.deak@nokia.com> Dmitry Kasatkin <dmitry.kasatkin@nokia.com> 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* $Id: btmodem.c,v 1.4 2003/03/14 10:47:40 kds Exp $ Modem multiplexer/emulator Fixes: Dmitry Kasatkin :*/ #include <syslog.h>#include <sys/types.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#include <errno.h>#include <time.h>#include <string.h>#include <ctype.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <affix/btcore.h>/* The size of the read buffer: */#define BUFFER_SIZE 1024/* Global variables, are used in subroutines: */char *mddev; /* name of the serial device for the modem*/char *bty; /* name of the serial device emulation on the bluetoothconnection */char *mdbuf; /* buffer for data read from the modem but not yet delivered to the bluetooth device */char *btbuf; /* buffer for data read from the bluetooth device but not yet delivered to the modem */int btfd; /* the file handle of the bluetooth serial device */int mdfd; /* the file handle of the serial device for the modem */int verbose; /* does the user want comments? */int logging; /* does the user want logs? */char *logfile; /* the name of the logfile */FILE *logfp; /* file handle for the logfile */char *logtext; /* used for construction of the strings to log */int silent; /* whether to be silent on stdout or not */long btrxcount; /* bytes received over bluetooth */long bttxcount; /* bytes send over bluetooth */long mdrxcount; /* bytes received over the modem line */long mdtxcount; /* bytes send over the modem line */int crtscts; /* use RTS/CTS instead of XON/XOFF */int val;#define TIMEOUT 30000 // reads from device, one character at a time with a fixed timeoutint read_line_nonblk(int fd, char *buf, int max_size){ int i; fd_set fset_rd; struct timeval tv; int res; if (max_size < 1) return -1; for (i = 0; i < max_size - 1; i++) { FD_ZERO(&fset_rd); FD_SET(fd, &fset_rd); tv.tv_sec = 0; tv.tv_usec = TIMEOUT * 1000; if (select(fd + 1, &fset_rd, NULL, NULL, &tv) <= 0) return i; if ((res = read(fd, &buf[i], 1)) <= 0) return -1; buf[i + 1] = '\0'; if (buf[i] == '\n' || buf[i] == '\r') return i + 1; } return -1;}void nsleep(int sec, int nsec){ struct timespec req; req.tv_sec = sec; req.tv_nsec = nsec; /* 1msec */ nanosleep(&req, NULL);}int write_to_modem(int fd, char *buf, int size){ int i; for (i = 0; i < size; i++) { if (write(fd, buf++, 1) != 1) return -1; nsleep(0, 500000); } return 0;}#define CARRIER_STR "\r\nCARRIER\r\n"#define CONNECT_STR "\r\nCONNECT 9600\r\n"#define OK_STR "\r\nOK\r\n"int emulate(void){ static char buf[512]; struct termios term; openlog(NULL/*"btmodem"*/, 0, LOG_USER); if (tcgetattr(1, &term) != 0) { syslog(LOG_ERR, "tcgetattr failed.\n"); goto failed; } cfmakeraw(&term); term.c_cflag |= CRTSCTS; if (tcsetattr(1, TCSANOW, &term) != 0) { syslog(LOG_ERR, "tcsetattr failed.\n"); goto failed; } for (;;) { int i; int res = read_line_nonblk(0, buf, sizeof(buf)); if (res <= 0) { syslog(LOG_ERR, "input failed.\n"); goto failed; } syslog(LOG_DEBUG, "Got %s\n", buf); for (i = 0; i < (int)strlen(buf); i++) buf[i] = toupper(buf[i]); if (strncmp(buf, "AT", 2) == 0) { if (strncmp(buf, "ATD", 3) == 0 || strstr(buf, "DT") || strstr(buf, "DP")) { nsleep(1, 0); syslog(LOG_DEBUG, "Send %s %s", CARRIER_STR, CONNECT_STR); if (write_to_modem(1, CARRIER_STR, sizeof(CARRIER_STR) - 1) != 0 || write_to_modem(1, CONNECT_STR, sizeof(CONNECT_STR) - 1) != 0) { syslog(LOG_ERR, "write to modem failed.\n"); goto failed; }#if 0 syslog(LOG_DEBUG, "Set CD\n"); val = TIOCM_CD; if (ioctl(1, TIOCMBIS, &val) != 0) { syslog(LOG_ERR, "failed to set CD. errno=%d\n", errno); goto failed; }#endif break; } else { syslog(LOG_DEBUG, "Send OK\\r"); if (write_to_modem(1, OK_STR, sizeof(OK_STR) - 1) != 0) { syslog(LOG_ERR, "write to modem failed.\n"); goto failed; } } } else if (strncmp(buf, "CLIENT", 6) == 0) { syslog(LOG_DEBUG, "Send CLIENTSERVER\n"); write(1, "CLIENTSERVER", 12); break; } else { syslog(LOG_DEBUG, "Send ERROR\n"); write(1, "\r\nERROR\r\n", 9); } } closelog(); return 0;failed: closelog(); return -1;}/* Writes the string to the log facilities - always expects complete lines! */void logit(char *logtext){ if (silent != 1) { printf(logtext); printf("\n"); fflush(stdout); } if (logging) { fprintf(logfp, "btmodem [%d]: ", getpid()); fprintf(logfp, logtext); fprintf(logfp, "\n"); fflush(logfp); }}/* Frees all used ressources: */void free_ressources(void){ if (verbose) logit("Freeing buffer for modem data"); if (mdbuf) free(mdbuf); if (verbose) logit("Freeing buffer for bluetooth data"); if (btbuf) free(btbuf); if (verbose) logit("Closeing modem device"); if (mdfd) close(mdfd); if (verbose) logit("Closing bluetooth serial device"); if (btfd) close(btfd); if (verbose) logit("Freeing buffer for devicename of modem"); if (mddev) free(mddev); if (verbose) logit("Freeing buffer for devicename of bluetooth serial device"); if (bty) free(bty); if (verbose) logit("Freeing buffer for name of log file"); if (logfile) free(logfile); if (logtext) free(logtext); if (verbose) logit("Closing log file"); if (logfp) fclose(logfp); fflush(stdout);}/* Handles breaks: */void handle_interruption(int sig){ if (sig == 2) printf("\nInterrupted\n"); else printf("\nAborted!\n"); fflush(stdout); free_ressources(); exit(0);}/* Shows all the parameters: */void usage(void){ printf("Syntax: btmodem [-e] [-b bluetooth] [-h] [-l [logfile]] [-m modem] [-q] [-v [-v]] [-x [count]]\n"); printf(" -e Modem emulation (use stdin/stdout). -m is not used\n"); printf(" -b client The device name of the client serial connection,\n"); printf(" usually over a bluetooth connection.\n"); printf(" Default: /dev/bty0\n"); printf(" -h Use hardware flow control (RTS/CTS) instead of the\n"); printf(" default XON/XOFF\n"); printf(" -l [logfile] Log in a file. The default name for the logfile is\n"); printf(" /var/log/btmodem\n"); printf(" -m modem The device name of the serial port on which the modem\n"); printf(" is connected. The defualt is: /dev/ttyS0\n"); printf(" -q Quiet mode - do not show any messages on stdout.\n"); printf(" This has no influence on the information written in\n"); printf(" the logfile\n"); printf(" -v Verbose mode: Show a lot of information as output on\n"); printf(" stdout and in the logfile if logging is activated\n"); printf(" REMARK: usually only important status messages are\n"); printf(" shown.\n"); printf(" WARNING: if both -q and -v are set, -q takes\n"); printf(" precedence!\n"); printf(" -v -v Higher verbosity: Show Even more information,\n"); printf(" including all data transmitted in verbatim form\n"); printf(" -x [count] Show the data as hexdump (always, regardless of\n"); printf(" verbosity. If the quiet mode is set, don't show the\n"); printf(" hexdump on the screen). The hexdump is written to the\n"); printf(" logfile. If -v -v and -x is set, the data will be\n"); printf(" shown twice, once verbatim and once as hexdump. count\n"); printf(" is the number of bytes shown in each line.\n"); printf(" Default: 16\n");}/* Setup for the serial ports: */void modem_setup(int desc){ struct termios settings; int result; result = tcgetattr(desc, &settings); if (result < 0) { perror ("error in tcgetattr"); return; } cfmakeraw(&settings); if (result < 0) { perror ("error in cfmakeraw"); return; } settings.c_cflag &= ~(PARENB | CSIZE | CSTOPB); settings.c_cflag |= (CS8); if (crtscts) { settings.c_cflag |= (CRTSCTS); settings.c_iflag &= ~(IXON | IXOFF); logit("Using hardware flow control"); } else { settings.c_cflag &= ~(CRTSCTS); settings.c_iflag |= (IXON | IXOFF); logit("Using software flow control"); } settings.c_lflag &= ~(ECHO | ICANON); cfsetspeed(&settings, B115200); result = tcsetattr (desc, TCSANOW, &settings); if (result < 0) { perror ("error in tcgetattr"); return; }}/* Makes an hexdump out of buffer and prints it with loggit *//* each line will contain linewidth bytes with two signs each */void print_hexdump(unsigned char *buffer, int bufsize, int linewidth, int modemin){ char *helpbuffer; int i, pos; if (!linewidth) return; helpbuffer = (char *)malloc(linewidth * 3 + 1); memset(helpbuffer, 0, linewidth * 3 + 1); pos = 0; if (modemin) helpbuffer[0] = '>'; else helpbuffer[0] = '<'; for (i = 0; i < bufsize; i++) { pos++; snprintf(helpbuffer + strlen(helpbuffer), linewidth * 3 + 1 - strlen(helpbuffer), "%.2X ", buffer[i]); /* If line is long enough, then print the line and start a new one: */ if (pos == linewidth) { pos = 0; logit(helpbuffer); memset(helpbuffer, 0, linewidth * 3 + 1); if (modemin) helpbuffer[0] = '>'; else helpbuffer[0] = '<'; } } /* If at least one sign is in the buffer, then print it: */ if (pos > 0) logit(helpbuffer); free(helpbuffer);}int main(int argc, char **argv){ int param; /* Command line option to parse */ int endprog; /* whether to abort the main loop */ int mddata; /* count of bytes read and buffered from the modem */ int btdata; /* count of bytes read and buffered from the bluetooth device */ int mdrxsize; /* count of bytes now read from the modem */ int btrxsize; /* count of bytes now read from the bluetooth device */ int mdtxsize; /* count of bytes writen to the modem */ int bttxsize; /* count of bytes writen to the bluetooth device */ int mdsig; /* the new signal stats on the modem lines */ int oldmdsig; /* the old signal stats on the modem lines */ int btsig; /* the new signal stats on the bluetooth lines */ int oldbtsig; /* the old signal stats on the bluetooth lines */ int setmdsig; /* which signals to set on the modem lines */ int setbtsig; /* which signals to set on the bluetooth lines */ int unsetmdsig; /* which signals to unset on the modem lines */ int unsetbtsig; /* which signals to unset on the bluetooth lines */ int maxhandle; /* the maximum file handle (neccessary for select) */ int hexdumplinewidth; /* number of chars in each line of an hexdump */ fd_set readfds; fd_set writefds; struct timeval tv; int emu = 0; openlog(NULL/*argv[0]*/, 0, LOG_DAEMON); BTINFO("%s %s started.", argv[0], affix_version);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -