/*
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 timeout
int 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);
if (argc == 1) {
usage();
return 0;
}
/* Initialize all variables: */
mddev = NULL;
bty = NULL;
mdfd = 0;
btfd = 0;
endprog = 0;
mdbuf = NULL;
btbuf = NULL;
verbose = 0;
oldmdsig = 0;
oldbtsig = 0;
logging = 0;
logfile = NULL;
logfp = 0;
logtext = 0;
silent = 0;
crtscts = 0;
hexdumplinewidth = 0;
mdtxcount = mdrxcount = btrxcount = bttxcount = 0;
/* Read the command line parameters: */
while ((param = getopt(argc, argv, "eb:hl::m:qvx::?")) != -1) {
switch (param) {
case 'e':
emu = 1;
break;
case 'b': /* Get the string with the bluetooth bty: */
bty = (char *)malloc(strlen(optarg)+1);
memset(bty, 0, strlen(optarg)+1);
memcpy(bty, optarg, strlen(optarg));
break;
case 'h':
crtscts = 1;
break;
case 'l':
logging = 1;
if (optarg != 0) {
logfile = (char *)malloc(strlen(optarg)+1);
memset(logfile, 0, strlen(optarg)+1);
memcpy(logfile, optarg, strlen(optarg));
} else {
logfile = (char *)malloc(19);
memset(logfile, 0, 19);
memcpy(logfile, "/var/log/btmodem", 18);
}
break;
case 'm': /* Get the string with the modem tty: */
mddev = (char *)malloc(strlen(optarg)+1);
memset(mddev, 0, strlen(optarg)+1);
memcpy(mddev, optarg, strlen(optarg));
break;
case 'q':
silent = 1;
break;
case 'v':
verbose++;
break;
case 'x':
hexdumplinewidth = 16;
if (optarg != 0) {
hexdumplinewidth = atoi(optarg);
}
break;
case '?':
default:
free_ressources();
usage();
exit(1);
}
}
if (emu)
return emulate();
logtext = (char *)malloc(BUFFER_SIZE);
memset(logtext, 0, BUFFER_SIZE);
/* Open the logfile: */
if (logging) {
logfp = fopen(logfile, "a");
if (logfp == NULL) {
perror("Unable to open logfile");
handle_interruption(0);
}
}
/* Set the devicenames to default values, if not yet initialized: */
if (bty == NULL) {
bty = (char *)malloc(10);
memset(bty, 0, 10);
memcpy(bty, "/sdcard/blue/", 9);
}
if (mddev == NULL) {
mddev = (char *)malloc(11);
memset(mddev, 0, 11);
memcpy(mddev, "/sdcard/blue/", 10);
}
snprintf(logtext, BUFFER_SIZE, "Connecting bluetooth serial connection on device %s with modem on device %s",
bty, mddev);
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
if (verbose)
logit("Installing signal handler for interruption");
signal(SIGINT, &handle_interruption);
fflush(stdout);
/* Open the devices */
btfd = open(bty, O_RDWR);
mdfd = open(mddev, O_RDWR);
if (btfd == -1) {
perror("Unable to open bluetooth serial device");
handle_interruption(0);
}
if (mdfd == -1) {
perror("Unable to open modem device");
handle_interruption(0);
}
/* Initialize the serial connection to the modem: */
modem_setup(mdfd);
modem_setup(btfd);
snprintf(logtext, BUFFER_SIZE, "Opened devices %s and %s successfully", bty, mddev);
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
/* Make them nonblocking */
val = fcntl(mdfd, F_GETFL, 0);
fcntl(mdfd, F_SETFL, val | O_NONBLOCK);
val = fcntl(btfd, F_GETFL, 0);
fcntl(btfd, F_SETFL, val | O_NONBLOCK);
/* Get the maximal file descriptor for select: */
if (mdfd > btfd)
maxhandle = mdfd;
else
maxhandle = btfd;
/* Initialize the buffers: */
mdbuf = (char *)malloc(BUFFER_SIZE);
btbuf = (char *)malloc(BUFFER_SIZE);
memset(mdbuf, 0, BUFFER_SIZE);
memset(btbuf, 0, BUFFER_SIZE);
btdata = 0;
mddata = 0;
mdrxsize = 0;
btrxsize = 0;
if (verbose > 1)
logit("Buffers for data created and initialized");
/* Initialize the bluetooth connection with the modem stat */
ioctl(mdfd, TIOCMGET, &oldmdsig);
/* Check DSR stat: */
snprintf(logtext, BUFFER_SIZE, "Initializing lines on bluetooth connection: DSR: ");
if ((oldmdsig & TIOCM_DSR) == TIOCM_DSR) {
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "1, ");
setbtsig |= TIOCM_DTR;
} else {
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "0, ");
unsetbtsig |= TIOCM_DTR;
}
/* Check RI stat: */
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "RI: ");
if ((oldmdsig & TIOCM_RI) == TIOCM_RI) {
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "1, ");
setbtsig |= TIOCM_RI;
} else {
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "0, ");
unsetbtsig |= TIOCM_RI;
}
/* Check CAR stat: */
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "CAR: ");
if ((oldmdsig & TIOCM_CAR) == TIOCM_CAR) {
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "1");
setbtsig |= TIOCM_CAR;
} else {
snprintf(logtext+strlen(logtext), BUFFER_SIZE - strlen(logtext), "0");
unsetbtsig |= TIOCM_CAR;
}
if (verbose)
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
ioctl(btfd, TIOCMBIS, &setbtsig);
ioctl(btfd, TIOCMBIC, &unsetbtsig);
ioctl(btfd, TIOCMGET, &oldbtsig);
/*
* The main loop of the program.
* Runs until interupted
*/
while (endprog == 0) {
/* Read the signals on the devices: */
ioctl(mdfd, TIOCMGET, &mdsig);
ioctl(btfd, TIOCMGET, &btsig);
/* If the signals differ from the old ones,
check if some signals must be set on the other side: */
if (btsig != oldbtsig) {
snprintf(logtext, BUFFER_SIZE, "Line change on bluetooth side: ");
setmdsig = 0;
unsetmdsig = 0;
/* Check if stat of DSR has changed: */
if ((btsig & TIOCM_DSR) != (oldbtsig & TIOCM_DSR)) {
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "DTR -> ");
if ((btsig & TIOCM_DSR) == TIOCM_DSR) {
setmdsig |= TIOCM_DTR;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "1 ");
} else {
unsetmdsig |= TIOCM_DTR;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "0 ");
}
}
if (verbose)
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
ioctl(mdfd, TIOCMBIS, &setmdsig);
ioctl(mdfd, TIOCMBIC, &unsetmdsig);
oldbtsig = btsig;
}
if (mdsig != oldmdsig) {
snprintf(logtext, BUFFER_SIZE, "Line change on modemside: ");
setbtsig = 0;
unsetbtsig = 0;
/* Check if DSR has changed: */
if ((mdsig & TIOCM_DSR) != (oldmdsig & TIOCM_DSR)) {
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "DSR -> ");
if ((mdsig & TIOCM_DSR) == TIOCM_DSR) {
setbtsig |= TIOCM_DTR;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "1 ");
} else {
unsetbtsig |= TIOCM_DTR;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "0 ");
}
}
/* Check if RI has changed: */
if ((mdsig & TIOCM_RI) != (oldmdsig & TIOCM_RI)) {
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "RI -> ");
if ((mdsig & TIOCM_RI) == TIOCM_RI) {
setbtsig |= TIOCM_RI;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "1 ");
} else {
unsetbtsig |= TIOCM_RI;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "0 ");
}
}
/* Check if CAR has changed: */
if ((mdsig & TIOCM_CAR) != (oldmdsig & TIOCM_CAR)) {
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "CAR -> ");
if ((mdsig & TIOCM_CAR) == TIOCM_CAR) {
setbtsig |= TIOCM_CAR;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "1 ");
} else {
unsetbtsig |= TIOCM_CAR;
snprintf(logtext + strlen(logtext), BUFFER_SIZE - strlen(logtext), "0 ");
}
}
if (verbose)
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
ioctl(btfd, TIOCMBIS, &setbtsig);
ioctl(btfd, TIOCMBIC, &unsetbtsig);
oldmdsig = mdsig;
}
/* Handle the data on the serial devices: */
FD_ZERO(&readfds);
FD_ZERO(&writefds);
/* Check only for data if we can read something: */
if (btdata < BUFFER_SIZE)
FD_SET(btfd, &readfds);
if (mddata < BUFFER_SIZE)
FD_SET(mdfd, &readfds);
/* Check if we can write data - as long as we have some: */
if (mddata > 0)
FD_SET(btfd, &writefds);
if (btdata > 0)
FD_SET(mdfd, &writefds);
/* Now check the file handles: */
tv.tv_sec = 0;
tv.tv_usec = 10000;
select(maxhandle+1, &readfds, &writefds, NULL, &tv);
/* First write data, if possible: */
/* to the modem: */
if (FD_ISSET(mdfd, &writefds)) {
/* Try to write, ignore error: */
if ((mdtxsize = write(mdfd, btbuf, btdata)) == -1) {
/* NO ERRORHANDLING! */
} else {
/* If verbosity is high enough, show the data: */
if (verbose > 1) {
snprintf(logtext, BUFFER_SIZE, "Data written to modem");
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
memcpy(logtext, btbuf, btdata);
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
}
/* If asked for, print an hexdump of the data: */
// print_hexdump(btbuf, btdata, hexdumplinewidth, 1);
/* If only partial written, copy the rest to the beginning: */
if (mdtxsize != btdata) {
memmove(btbuf, btbuf + mdtxsize, btdata - mdtxsize);
}
/* Decrease the byte count for the buffer: */
btdata -= mdtxsize;
mdtxcount += mdtxsize;
}
}
/* to the bluetooth device: */
if (FD_ISSET(btfd, &writefds)) {
/* Try to write, ignore error: */
if ((bttxsize = write(btfd, mdbuf, mddata)) == -1) {
/* NO ERRORHANDLING! */
} else {
/* If verbosity is high enough, show the data: */
if (verbose > 1) {
snprintf(logtext, BUFFER_SIZE, "Data written to bluetooth");
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
memcpy(logtext, mdbuf, mddata);
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
}
/* If asked for, print an hexdump of the data: */
// print_hexdump(mdbuf, mddata, hexdumplinewidth, 0);
/* If only partial written, copy the rest to the beginning: */
if (bttxsize != mddata) {
memmove(mdbuf, mdbuf + bttxsize, mddata - bttxsize);
}
/* Decrease the byte count for the buffer: */
mddata -= bttxsize;
bttxcount += bttxsize;
}
}
/* Now read the data - if there is data and there is space in the buffers: */
/* from the modem: */
if (FD_ISSET(mdfd, &readfds)) {
/* Try to read the data, ignore error: */
if ((mdrxsize = read(mdfd, mdbuf + mddata, BUFFER_SIZE - mddata)) == -1) {
/* NO ERRORHANDLING! */
} else {
if (verbose > 1) {
snprintf(logtext, BUFFER_SIZE, "Data read from modem");
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
}
mddata += mdrxsize;
mdrxcount += mdrxsize;
}
}
/* from the bluetooth device: */
if (FD_ISSET(btfd, &readfds)) {
/* Try to read the data, ignore error: */
if ((btrxsize = read(btfd, btbuf + btdata, BUFFER_SIZE - btdata)) == -1) {
/* NO ERRORHANDLING! */
} else {
if (verbose > 1) {
snprintf(logtext, BUFFER_SIZE, "Data read from bluetooth");
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
} else if (btrxsize == 0) {
/* Check for null packets to close the socket: */
endprog = 1;
}
btdata += btrxsize;
btrxcount += btrxsize;
}
}
}
logit("Connection closed");
snprintf(logtext, BUFFER_SIZE, "Modem stats: %ld bytes received, %ld bytes sent",
mdrxcount, mdtxcount);
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
snprintf(logtext, BUFFER_SIZE, "Bluetooth stats: %ld bytes received, %ld bytes sent",
btrxcount, bttxcount);
logit(logtext);
memset(logtext, 0, BUFFER_SIZE);
free_ressources();
return 0;
}
No comments:
Post a Comment