Newer
Older
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2006, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
* \file
* \brief Bluetooth Mobile Device channel driver
*
* \author Dave Bowerman <david.bowerman@gmail.com>
*
* \ingroup channel_drivers
*/
/*! \li \ref chan_mobile.c uses the configuration file \ref chan_mobile.conf
* \addtogroup configuration_file Configuration Files
*/
/*!
* \page chan_mobile.conf chan_mobile.conf
* \verbinclude chan_mobile.conf.sample
*/
/*** MODULEINFO
<depend>bluetooth</depend>
<defaultenabled>no</defaultenabled>
<support_level>extended</support_level>
***/
#include "asterisk.h"
#include <pthread.h>
#include <signal.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sco.h>
#include <bluetooth/l2cap.h>
#include "asterisk/compat.h"
#include "asterisk/lock.h"
#include "asterisk/callerid.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/cli.h"
#include "asterisk/devicestate.h"
#include "asterisk/causes.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/io.h"
#include "asterisk/smoother.h"
#include "asterisk/format_cache.h"
#define MBL_CONFIG "chan_mobile.conf"
#define MBL_CONFIG_OLD "mobile.conf"
#define DEVICE_FRAME_SIZE 48
#define DEVICE_FRAME_FORMAT ast_format_slin
#define CHANNEL_FRAME_SIZE 320
static int discovery_interval = 60; /* The device discovery interval, default 60 seconds. */
static pthread_t discovery_thread = AST_PTHREADT_NULL; /* The discovery thread */
static sdp_session_t *sdp_session;
AST_MUTEX_DEFINE_STATIC(unload_mutex);
static int unloading_flag = 0;
static inline int check_unloading(void);
static inline void set_unloading(void);
enum mbl_type {
MBL_TYPE_PHONE,
MBL_TYPE_HEADSET
};
struct adapter_pvt {
int dev_id; /* device id */
int hci_socket; /* device descriptor */
char id[31]; /* the 'name' from mobile.conf */
bdaddr_t addr; /* adddress of adapter */
unsigned int inuse:1; /* are we in use ? */
unsigned int alignment_detection:1; /* do alignment detection on this adapter? */
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
struct io_context *io; /*!< io context for audio connections */
struct io_context *accept_io; /*!< io context for sco listener */
int *sco_id; /*!< the io context id of the sco listener socket */
int sco_socket; /*!< sco listener socket */
pthread_t sco_listener_thread; /*!< sco listener thread */
AST_LIST_ENTRY(adapter_pvt) entry;
};
static AST_RWLIST_HEAD_STATIC(adapters, adapter_pvt);
struct msg_queue_entry;
struct hfp_pvt;
struct mbl_pvt {
struct ast_channel *owner; /* Channel we belong to, possibly NULL */
struct ast_frame fr; /* "null" frame */
ast_mutex_t lock; /*!< pvt lock */
/*! queue for messages we are expecting */
AST_LIST_HEAD_NOLOCK(msg_queue, msg_queue_entry) msg_queue;
enum mbl_type type; /* Phone or Headset */
char id[31]; /* The id from mobile.conf */
int group; /* group number for group dialling */
bdaddr_t addr; /* address of device */
struct adapter_pvt *adapter; /* the adapter we use */
char context[AST_MAX_CONTEXT]; /* the context for incoming calls */
struct hfp_pvt *hfp; /*!< hfp pvt */
int rfcomm_port; /* rfcomm port number */
int rfcomm_socket; /* rfcomm socket descriptor */
char rfcomm_buf[256];
char io_buf[CHANNEL_FRAME_SIZE + AST_FRIENDLY_OFFSET];
struct ast_smoother *bt_out_smoother; /* our bt_out_smoother, for making 48 byte frames */
struct ast_smoother *bt_in_smoother; /* our smoother, for making "normal" CHANNEL_FRAME_SIZEed byte frames */
int sco_socket; /* sco socket descriptor */
pthread_t monitor_thread; /* monitor thread handle */
int timeout; /*!< used to set the timeout for rfcomm data (may be used in the future) */
unsigned int no_callsetup:1;
unsigned int has_sms:1;
unsigned int do_alignment_detection:1;
unsigned int alignment_detection_triggered:1;
unsigned int blackberry:1;
short alignment_samples[4];
int alignment_count;
int ring_sched_id;
struct ast_dsp *dsp;
struct ast_sched_context *sched;
/* flags */
unsigned int outgoing:1; /*!< outgoing call */
unsigned int incoming:1; /*!< incoming call */
unsigned int outgoing_sms:1; /*!< outgoing sms */
unsigned int incoming_sms:1; /*!< outgoing sms */
unsigned int needcallerid:1; /*!< we need callerid */
unsigned int needchup:1; /*!< we need to send a chup */
unsigned int needring:1; /*!< we need to send a RING */
David Brooks
committed
unsigned int answered:1; /*!< we sent/received an answer */
unsigned int connected:1; /*!< do we have an rfcomm connection to a device */
AST_LIST_ENTRY(mbl_pvt) entry;
};
/*! Structure used by hfp_parse_clip to return two items */
struct cidinfo {
char *cnum;
char *cnam;
};
static AST_RWLIST_HEAD_STATIC(devices, mbl_pvt);
static int handle_response_ok(struct mbl_pvt *pvt, char *buf);
static int handle_response_error(struct mbl_pvt *pvt, char *buf);
static int handle_response_ciev(struct mbl_pvt *pvt, char *buf);
static int handle_response_clip(struct mbl_pvt *pvt, char *buf);
static int handle_response_ring(struct mbl_pvt *pvt, char *buf);
static int handle_response_cmti(struct mbl_pvt *pvt, char *buf);
static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf);
Matthew Nicholson
committed
static int handle_response_cusd(struct mbl_pvt *pvt, char *buf);
static int handle_response_busy(struct mbl_pvt *pvt);
static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf);
static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf);
static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf);
/* CLI stuff */
static char *handle_cli_mobile_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static char *handle_cli_mobile_search(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static char *handle_cli_mobile_rfcomm(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
Matthew Nicholson
committed
static char *handle_cli_mobile_cusd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static struct ast_cli_entry mbl_cli[] = {
AST_CLI_DEFINE(handle_cli_mobile_show_devices, "Show Bluetooth Cell / Mobile devices"),
AST_CLI_DEFINE(handle_cli_mobile_search, "Search for Bluetooth Cell / Mobile devices"),
AST_CLI_DEFINE(handle_cli_mobile_rfcomm, "Send commands to the rfcomm port for debugging"),
Matthew Nicholson
committed
AST_CLI_DEFINE(handle_cli_mobile_cusd, "Send CUSD commands to the mobile"),
};
/* App stuff */
Loading
Loading full blame...