📄 btd.c
字号:
/* * btd.c -- Control application for AXIS Open BT stack * * o Responsible for control of physical transport layer (UART), * o Initializing/shutdown of stack incl SDP server database * o Handles multipoint ppp connections * o Handles HW upgrade * * Copyright (C) 2000, 2001 Axis Communications AB * * Author: Mattias Agren <mattias.agren@axis.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. * * Exceptionally, Axis Communications AB grants discretionary and * conditional permissions for additional use of the text contained * in the company's release of the AXIS OpenBT Stack under the * provisions set forth hereunder. * * Provided that, if you use the AXIS OpenBT Stack with other files, * that do not implement functionality as specified in the Bluetooth * System specification, to produce an executable, this does not by * itself cause the resulting executable to be covered by the GNU * General Public License. Your use of that executable is in no way * restricted on account of using the AXIS OpenBT Stack code with it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the provisions of the GNU * General Public License. * * $Id: btd.c,v 1.32 2001/10/16 15:02:20 pkj Exp $ * *//* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Syntax: ./btdm [options]options: -u, --physdev <uart device> Sets which uart device that will be used by the stack default: ttyS0 -m, --modem-emul <1/0> Use modem emulation (used when emulate modem in windows dialup. Can also be done from command line mode. default: on -n, --local-name <prefix> prefix used for the local bluetooth device name default: nothing -R, --reset reset bluetooth hardware before use default: no reset -i, --initial-speed <speed | baudbase/divisor> sets initial uart speed default: 115200 baud -s, --speed <speed | baudbase/divisor> sets uart speed 9600, 19200, 38400, 57600, 115200, 230400, 460800 default: 115200 baud -f, --noflow force uart communication to not use CTS and RTS default: flow control activated if defined hardware support it e.g ./btdm --reset --speed 460800 --physdev /dev/ttyS0 --local-name OpenBT ./btdm --reset --speed 1000000/1 --physdev /dev/ttyS0 --local-name OpenBT- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <signal.h>#include <syslog.h>#include <getopt.h>#include <setjmp.h>#include <termios.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/wait.h>#include <arpa/inet.h>#include "btd.h"#include "bt_conf.h"#include "bt_vendor.h"#include "bt_misc.h"#include "bt_if.h"#include "bt_ipa.h"#define D(x) //x/* ========================================================== *//* PPPD stuff */#define NOCONNECTION 0#define CONNECTED 1#define WAITING_PPPCONF 2 #define PPPCONF_DONE 3#define MODEM_STARTED 4#define PPPD_STARTED 5#define WAITING_RETURN_PPPCONF 6typedef struct peer_struct{ int state; int pppd_pid; int do_modememul; unsigned char remote_bd[6]; struct ip_set *ipset;} peer_struct;struct peer_struct peerlist[BT_NBR_DATAPORTS];struct ip_set ipsetlist[BT_NBR_DATAPORTS];static unsigned char dev[20];static unsigned char ip_addresses[35];static unsigned char ms_dns1[35];static unsigned char ms_dns2[35];static unsigned char ms_wins1[35];static unsigned char ms_wins2[35];static unsigned char netmask[35];static char remote_bd_str[18];static char local_bd_str[18];static fd_set rfd;static struct timeval tv;#define PEER(line) (peerlist[line])#define IPSET(line) (ipsetlist[line])#define STATE(line) (peerlist[line].state)static unsigned char *pppd_options[32];/* ========================================================== *//* IPA stuff */static int ipa_fd = -1;static struct ipa_msg *msg;static unsigned char ipa_buf[256];static int parse_ipa_response(struct ipa_msg *msg);static int ipa_sendrequest(int line, unsigned char *bd, unsigned short type);/* ========================================================== *//* General BTD stuff */#define PID_FILE "/var/run/btd.pid"#define MODEMEMULCMD "memul" /* change name !*/#define PPPDCMD "pppd"static int do_hwinit = 1; /* do vendor specific initialization */static int do_reset = 0; /* reset hw using I/O pins */static int modem_emul = 1; /* default modem emulation is enabled */static char *init_hw_speedstr = NULL; /* not set */static int flow_control = USE_FLOW_CTRL;static char *physdev = DEFAULT_PHYS_DEV;static char *speedstr = DEFAULT_SPEED;static char local_name[LOCAL_NAME_LENGTH+1]; /* 'friendly' name in HW module */static int btd_pid = -1;static int sdpsrv_pid = 0;static int bt_cfd = -1; /* control tty for bt stack */static int phys_fd = -1; /* physical device e.g ttyS0 */static sigjmp_buf jmpbuffer; /* used to jump back in program after doing reset *//* long option list */static struct option long_options[] ={ { "noflow", 1, NULL, 'f' }, /* do not use flow control */ { "initial-speed", 1, NULL, 'i' }, /* initial uart speed */ { "physdev", 1, NULL, 'u' }, /* phys device used from stack */ { "modem-emul", 1, NULL, 'm' }, { "local-name", 1, NULL, 'n' }, /* set local bluetooth name */ { "reset", 0, NULL, 'R' }, /* reset BT HW */ { "speed", 1, NULL, 's' }, /* uart speed towards hw */ { 0, 0, 0, 0 }};static int option_index = 0;static void init();static void init_sighandler(void);static void btd_cleanup(void);static void btd_killchilds(void);static void sighandler(int sig);static void discover_connections(int bt_cfd);static void build_pppdopts(int line, char **opts);static int start_pppd(int line, char *speedstr, char **opts);/* ========================================================== */intmain(int argc, char **argv){ int result, opt; int bt_disc = N_BT; syslog(LOG_INFO, "Bluetooth daemon starting"); if (atexit(btd_cleanup) < 0) { printf("btd failed to register cleanup function.\n"); exit(1); } /* now parse options */ while ((opt = getopt_long(argc, argv, "fi:m:nRs:u:", long_options, &option_index)) != -1) { switch(opt) { case 'f': /* do not use flow control */ flow_control = USE_NO_FLOW; D(syslog(LOG_INFO, "no flow control")); break; case 'i': /* uart device */ init_hw_speedstr = optarg; D(syslog(LOG_INFO, "init_hw_speed %s baud", init_hw_speedstr)); break; case 'm': /* uart device */ modem_emul = atoi(optarg); break; case 'n': D(syslog(LOG_INFO, "setting local name to %s", optarg)); strncpy(local_name, optarg, LOCAL_NAME_LENGTH); local_name[LOCAL_NAME_LENGTH] = '\0'; break; case 'R': /* try to reset the hardware */ D(syslog(LOG_INFO, "reset HW")); do_reset = 1; break; case 's': /* speed */ D(syslog(LOG_INFO, "phys dev running at %s", optarg)); speedstr = optarg; break; case 'u': /* uart device */ D(syslog(LOG_INFO, "phys dev: %s", optarg)); physdev = optarg; break; default: break; } } /* Set restart point */ if (sigsetjmp(jmpbuffer, 1) != 0) { syslog(LOG_INFO, "Restart..."); sleep(1); } init(); if ((phys_fd = open(physdev, O_RDWR | O_NOCTTY)) < 0) { perror("Could not open phys dev"); exit(1); } /* Sets initial HW baudrate */ if (init_hw_speedstr != NULL) fd_setup(phys_fd, init_hw_speedstr, flow_control); else init_phys(phys_fd, flow_control); /* Set the current tty to the bluetooth discpline */ set_bt_line_disc(phys_fd, bt_disc, physdev); bt_cfd = bt_openctrl(); tcflush(phys_fd, TCIOFLUSH); /* Hardreset of BT hardware */ if (do_reset) reset_hw(); if (init_stack(bt_cfd) < 0) { /* For some reason, the stack sometimes fails to initialize the first time. So let us try an extra time, just to be sure... */ if (init_stack(bt_cfd) < 0) { init_failed(bt_cfd, phys_fd, init_hw_speedstr, flow_control); } } if (do_hwinit) init_hw(bt_cfd, phys_fd, speedstr); /* All initialized and ready to accept connections */ while (1) { tv.tv_sec = 0; tv.tv_usec = 500000; FD_ZERO(&rfd); if (ipa_fd >= 0) FD_SET(ipa_fd, &rfd); result = select(FD_SETSIZE, &rfd, NULL, NULL, &tv); switch (result) { case 0: {#ifdef USE_IPASSIGN /* Check for outstanding IPA requests */ int i = 0, waiting_iparsp = 0; while (i < BT_NBR_DATAPORTS) { if ((STATE(i) == WAITING_PPPCONF) || (STATE(i) == WAITING_RETURN_PPPCONF)) { D(syslog(LOG_INFO, "Waiting for IPA response")); waiting_iparsp = 1; } i++; } if (waiting_iparsp) break;#endif /* Timeout, check for new rfcomm cons */ discover_connections(bt_cfd); } break; case -1: if (errno != EINTR) { /* Error */ perror("select"); /* FIXME -- e.g if ipa server restarts !!! */ } break; default: {#ifdef USE_IPASSIGN /* Got data on some fd */ int retval; /* IPA response */ if (ipa_fd >= 0 && FD_ISSET(ipa_fd, &rfd)) { msg = (struct ipa_msg*) ipa_buf; /* Got response from IPA, if ok then start pppd or modem emul */ ipa_read(ipa_fd, msg); if ((retval = parse_ipa_response(msg)) < 0) { unsigned int con_id; int line = ((struct ipa_status*)(msg->msg))->id; syslog(LOG_INFO, "Got IPA error %d, disconnecting line %d", retval, line); con_id = CREATE_RFCOMM_ID(line, 0); if (bt_disconnect(bt_cfd, con_id) < 0) { /* FIXME: What to do if disconnection fails */ syslog(LOG_INFO, "Disconnection failed"); } else { STATE(line) = NOCONNECTION; } } } #endif } break; } } /* while */} /* main */ /* Checks for new connections and starts pppd/modememulator */static void discover_connections(int bt_cfd){ int line; D(syslog(LOG_INFO, __FUNCTION__)); for (line = 0; line < BT_NBR_DATAPORTS; line++) { if ((STATE(line) == NOCONNECTION) && bt_isconnected(bt_cfd, line)) { syslog(LOG_INFO, "Found connection on line: %d", line); STATE(line) = CONNECTED; read_remote_bd(bt_cfd, line, PEER(line).remote_bd); printf("Remote bd: %s\n", bd2str(PEER(line).remote_bd)); if (ipa_fd >= 0) { D(syslog(LOG_INFO, "Sending IPA request")); PEER(line).ipset = &IPSET(line); STATE(line) = WAITING_PPPCONF; if (ipa_sendrequest(line, PEER(line).remote_bd, IPAREQ_GETIPSET) < 0) { syslog(LOG_INFO, "IPA request failed or no IPA server"); /* Build without IPA anyway */ STATE(line) = PPPCONF_DONE; build_pppdopts(line, (char**)pppd_options); start_pppd(line, speedstr, (char**)pppd_options); } else D(syslog(LOG_INFO, "IPA request sent")); } else /* No IPA server available */ { STATE(line) = PPPCONF_DONE; build_pppdopts(line, (char**)pppd_options); start_pppd(line, speedstr, (char**)pppd_options); } } }}/* only server */void build_pppdopts(int line, char **opts){ int i = 0; struct ip_set *ipset = PEER(line).ipset; char local_ip[20]; if (ipa_fd >= 0) show_ipset(ipset, line); D(syslog(LOG_INFO, __FUNCTION__)); sprintf(dev, "/dev/ttyBT%d",line); /* general options */ opts[i++] = (char*)PPPDCMD; opts[i++] = dev; opts[i++] = speedstr; /* move these to options file ? */ opts[i++] = "crtscts"; opts[i++] = "nopersist"; opts[i++] = "silent"; opts[i++] = "passive"; /* check if we have used IPA */ if (ipset) { /* FIXME -- maybe parhand can modify ppp options file directly */ /* Use radius ? */ if (ipset->useradius) { unsigned char local_bd[6]; opts[i++] = "useradius"; opts[i++] = "auth"; opts[i++] = "login"; opts[i++] = "localbdaddr"; read_local_bd(bt_cfd, local_bd); sprintf(local_bd_str, "%02x:%02x:%02x:%02x:%02x:%02x", local_bd[0],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -