[asterisk-addons-commits] dcb: trunk r438 - /trunk/chan_mobile.c
SVN commits to the Asterisk addons project
asterisk-addons-commits at lists.digium.com
Thu Sep 6 05:41:21 CDT 2007
Author: dcb
Date: Thu Sep 6 05:41:21 2007
New Revision: 438
URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=438
Log:
code cleanup and formatting changes
Modified:
trunk/chan_mobile.c
Modified: trunk/chan_mobile.c
URL: http://svn.digium.com/view/asterisk-addons/trunk/chan_mobile.c?view=diff&rev=438&r1=437&r2=438
==============================================================================
--- trunk/chan_mobile.c (original)
+++ trunk/chan_mobile.c Thu Sep 6 05:41:21 2007
@@ -19,7 +19,7 @@
/*! \file
*
* \brief Bluetooth Mobile Device channel driver
- *
+ *
* \author Dave Bowerman <david.bowerman at gmail.com>
*
* \ingroup channel_drivers
@@ -74,7 +74,8 @@
static int prefformat = AST_FORMAT_SLINEAR;
-static int discovery_interval = 60; /* The device discovery interval, default 60 seconds. */
+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;
enum mbl_type {
@@ -107,11 +108,11 @@
};
struct adapter_pvt {
- int dev_id; /* device id */
+ int dev_id; /* device id */
int hci_socket; /* device descriptor */
char id[31]; /* the 'name' from mobile.conf */
bdaddr_t addr; /* adddress of adapter */
- char inuse; /* are we in use ? */
+ char inuse; /* are we in use ? */
int sco_socket;
AST_LIST_ENTRY(adapter_pvt) entry;
};
@@ -119,28 +120,28 @@
static AST_LIST_HEAD_STATIC(adapters, adapter_pvt);
struct mbl_pvt {
- struct ast_channel *owner; /* Channel we belong to, possibly NULL */
- struct ast_frame fr; /* "null" frame */
+ struct ast_channel *owner; /* Channel we belong to, possibly NULL */
+ struct ast_frame fr; /* "null" frame */
enum mbl_type type; /* Phone or Headset */
char id[31]; /* The id from mobile.conf */
- int group; /* group number for group dialling */
+ 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 adapter_pvt *adapter; /* the adapter we use */
+ char context[AST_MAX_CONTEXT]; /* the context for incoming calls */
char connected; /* is it connected? */
int rfcomm_port; /* rfcomm port number */
int rfcomm_socket; /* rfcomm socket descriptor */
char rfcomm_buf[256];
int sco_socket; /* sco socket descriptor */
- pthread_t sco_listener_thread; /* inbound sco listener for this device */
- enum mbl_state state; /* monitor thread current state */
- pthread_t monitor_thread; /* monitor thread handle */
+ pthread_t sco_listener_thread; /* inbound sco listener for this device */
+ enum mbl_state state; /* monitor thread current state */
+ pthread_t monitor_thread; /* monitor thread handle */
char sco_in_buf[48 + AST_FRIENDLY_OFFSET];
char sco_save_buf[48];
int sco_save_len;
- char dial_number[AST_MAX_EXTENSION]; /* number for the monitor thread to dial */
+ char dial_number[AST_MAX_EXTENSION]; /* number for the monitor thread to dial */
int dial_timeout;
- char ciev_call_0[4]; /* dynamically built reponse strings */
+ char ciev_call_0[4]; /* dynamically built reponse strings */
char ciev_call_1[4];
char ciev_callsetup_0[4];
char ciev_callsetup_1[4];
@@ -160,9 +161,6 @@
static AST_LIST_HEAD_STATIC(devices, mbl_pvt);
-/* The discovery thread */
-static pthread_t discovery_thread = AST_PTHREADT_NULL;
-
/* CLI stuff */
static const char show_usage[] =
"Usage: mobile show devices\n"
@@ -203,6 +201,7 @@
" Dest - destination\n"
" Message - text of the message\n";
+static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num);
static struct ast_channel *mbl_request(const char *type, int format, void *data, int *cause);
static int mbl_call(struct ast_channel *ast, char *dest, int timeout);
static int mbl_hangup(struct ast_channel *ast);
@@ -213,14 +212,16 @@
static int mbl_write(struct ast_channel *ast, struct ast_frame *frame);
static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int mbl_devicestate(void *data);
-static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num);
-
+
+static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel);
static int rfcomm_write(struct mbl_pvt *pvt, char *buf);
static int rfcomm_read(struct mbl_pvt *pvt, char *buf, char flush, int timeout);
+
static int sco_connect(bdaddr_t src, bdaddr_t dst);
static int sco_write(int s, char *buf, int len);
static int sco_read(int s, char *buf, int len);
static int sco_set_options(int s);
+
static void *do_sco_listen(void *data);
static int sdp_search(char *addr, int profile);
@@ -239,6 +240,12 @@
.fixup = mbl_fixup,
.devicestate = mbl_devicestate
};
+
+/*
+
+ CLI Commands implementation
+
+*/
static int do_show_devices(int fd, int argc, char **argv)
{
@@ -341,6 +348,12 @@
}
+/*
+
+ Dialplan applications implementation
+
+*/
+
static int mbl_status_exec(struct ast_channel *ast, void *data)
{
@@ -409,7 +422,6 @@
return -1;
}
-
AST_LIST_TRAVERSE(&devices, pvt, entry) {
if (!strcmp(pvt->id, device))
break;
@@ -444,346 +456,11 @@
}
-static struct ast_channel *mbl_request(const char *type, int format, void *data, int *cause)
-{
-
- struct ast_channel *chn = NULL;
- struct mbl_pvt *pvt;
- char *dest_dev = NULL;
- char *dest_num = NULL;
- int oldformat, group;
-
- if (!data) {
- ast_log(LOG_WARNING, "Channel requested with no data\n");
- *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
- return NULL;
- }
-
- oldformat = format;
- format &= (AST_FORMAT_SLINEAR);
- if (!format) {
- ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%d'\n", oldformat);
- *cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED;
- return NULL;
- }
-
- dest_dev = ast_strdupa((char *)data);
-
- dest_num = strchr(dest_dev, '/');
- if (dest_num)
- *dest_num++ = 0x00;
-
- /* Find requested device and make sure its connected. */
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
- if ((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) {
- group = atoi(dest_dev+1);
- if (pvt->group == group)
- break;
- } else if (!strcmp(pvt->id, dest_dev)) {
- break;
- }
- }
- if (!pvt || !pvt->connected || pvt->owner) {
- ast_log(LOG_WARNING, "Request to call on device %s which is not connected / already in use.\n", dest_dev);
- *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
- return NULL;
- }
-
- if ((pvt->type == MBL_TYPE_PHONE) && !dest_num) {
- ast_log(LOG_WARNING, "Cant determine destination number.\n");
- *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
- return NULL;
- }
-
- chn = mbl_new(AST_STATE_DOWN, pvt, NULL);
- if (!chn) {
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
- *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
- return NULL;
- }
-
- return chn;
-
-}
-
-static int mbl_call(struct ast_channel *ast, char *dest, int timeout)
-{
-
- struct mbl_pvt *pvt;
- char *dest_dev = NULL;
- char *dest_num = NULL;
-
- dest_dev = ast_strdupa((char *)dest);
-
- pvt = ast->tech_pvt;
- ast_mutex_lock(&pvt->owner->lock);
-
- if (pvt->type == MBL_TYPE_PHONE) {
- dest_num = strchr(dest_dev, '/');
- if (!dest_num) {
- ast_log(LOG_WARNING, "Cant determine destination number.\n");
- return -1;
- }
- *dest_num++ = 0x00;
- }
-
- if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
- ast_log(LOG_WARNING, "mbl_call called on %s, neither down nor reserved\n", ast->name);
- ast_mutex_unlock(&pvt->owner->lock);
- return -1;
- }
-
- ast_debug(1, "Calling %s on %s\n", dest, ast->name);
-
- if (pvt->type == MBL_TYPE_PHONE) {
- ast_copy_string(pvt->dial_number, dest_num, sizeof(pvt->dial_number));
- pvt->state = MBL_STATE_DIAL;
- pvt->dial_timeout = (timeout == 0) ? 30 : timeout;
- } else {
- pvt->state = MBL_STATE_RING;
- }
-
- ast_mutex_unlock(&pvt->owner->lock);
-
- return 0;
-
-}
-
-static int mbl_hangup(struct ast_channel *ast)
-{
-
- struct mbl_pvt *pvt;
-
- if (!ast->tech_pvt) {
- ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
- return 0;
- }
- pvt = ast->tech_pvt;
-
- ast_debug(1, "Hanging up device %s.\n", pvt->id);
-
- ast_channel_lock(ast);
- ast_channel_set_fd(ast, 0, -1);
- ast_channel_unlock(ast);
-
- if (pvt->type == MBL_TYPE_HEADSET && pvt->sco_socket != -1) {
- close(pvt->sco_socket);
- pvt->sco_socket = -1;
- }
-
- if ((pvt->state == MBL_STATE_INCOMING || pvt->state == MBL_STATE_OUTGOING || pvt->state == MBL_STATE_DIAL1 || pvt->state == MBL_STATE_RING3) && pvt->type == MBL_TYPE_PHONE) {
- rfcomm_write(pvt, "AT+CHUP\r");
- pvt->state = MBL_STATE_HANGUP;
- pvt->hangup_count = 0;
- } else
- pvt->state = MBL_STATE_IDLE;
-
- pvt->owner = NULL;
- ast->tech_pvt = NULL;
- ast_setstate(ast, AST_STATE_DOWN);
-
- return 0;
-
-}
-
-static int mbl_answer(struct ast_channel *ast)
-{
-
- struct mbl_pvt *pvt;
-
- pvt = ast->tech_pvt;
-
- rfcomm_write(pvt, "ATA\r");
-
- ast_setstate(ast, AST_STATE_UP);
-
- pvt->sent_answer = 1;
-
- return 0;
-
-}
-
-static int mbl_digit_begin(struct ast_channel *chan, char digit)
-{
-
- return 0;
-
-}
-
-static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
-{
-
- struct mbl_pvt *pvt;
- char buf[11];
-
- pvt = ast->tech_pvt;
-
- if (pvt->type == MBL_TYPE_HEADSET)
- return 0;
-
- ast_debug(1, "Dialed %c\n", digit);
-
- switch(digit) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '*':
- case '#':
- sprintf(buf, "AT+VTS=%c\r", digit);
- rfcomm_write(pvt, buf);
- break;
- default:
- ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
- return -1;
- }
-
- return 0;
-
-}
-
/*
- The SCO protocol basically delivers audio in 48 byte 'frames' in slin format.
- Here we just package these into an ast_frame and return them.
- The SCO connection from the device to Asterisk happens asynchronously, so it is feasible
- that Asterisk will call mbl_read() before the device has connected. In that case we just return
- a null frame.
+ Channel Driver callbacks
*/
-
-static struct ast_frame *mbl_read(struct ast_channel *ast)
-{
-
- struct mbl_pvt *pvt = ast->tech_pvt;
- struct ast_frame *f;
-
- if (!pvt->owner) {
- return &ast_null_frame;
- }
-
- if (pvt->state == MBL_STATE_HANGUP) {
- return &ast_null_frame;
- }
-
- if (pvt->sco_socket == -1) {
- return &ast_null_frame;
- }
-
- pvt->fr.frametype = AST_FRAME_VOICE;
- pvt->fr.subclass = AST_FORMAT_SLINEAR;
- pvt->fr.data = pvt->sco_in_buf + AST_FRIENDLY_OFFSET;
-
- if (sco_read(pvt->sco_socket, pvt->sco_in_buf + AST_FRIENDLY_OFFSET, 48)) {
- if ((pvt->type == MBL_TYPE_PHONE) && (pvt->skip_frames == 0)) {
- f = ast_dsp_process(0, pvt->dsp, &pvt->fr);
- if (f && (f->frametype == AST_FRAME_DTMF_END)) {
- pvt->fr.frametype = AST_FRAME_DTMF_END;
- pvt->fr.subclass = f->subclass;
- pvt->skip_frames = pvt->dtmf_skip;
- }
- } else {
- pvt->skip_frames--;
- }
- return &pvt->fr;
- }
-
- return &ast_null_frame;
-
-}
-
-/*
-
- We need to deliver 48 byte 'frames' of slin format audio to the device.
- mbl_write() handles this by buffering short frames until the next time we are called.
-
-*/
-
-static int mbl_write(struct ast_channel *ast, struct ast_frame *frame)
-{
-
- struct mbl_pvt *pvt = ast->tech_pvt;
- int num_frames, i, sco_need = 0;
- char *pfr;
-
- if (frame->frametype != AST_FRAME_VOICE) {
- return 0;
- }
- if (pvt->sco_socket == -1) {
- return 0;
- }
- if (ast->_state != AST_STATE_UP) {
- return 0;
- }
- if (pvt->state == MBL_STATE_HANGUP) {
- return 0;
- }
-
- if (pvt->sco_save_len > 0) {
- sco_need = 48 - pvt->sco_save_len;
- memcpy(pvt->sco_save_buf + pvt->sco_save_len, frame->data, sco_need);
- sco_write(pvt->sco_socket, pvt->sco_save_buf, 48);
- }
- num_frames = (frame->datalen - sco_need) / 48;
- pfr = frame->data + sco_need;
- for (i=0; i<num_frames; i++) {
- sco_write(pvt->sco_socket, pfr, 48);
- pfr += 48;
- }
- pvt->sco_save_len = (frame->datalen - sco_need) - (num_frames * 48);
- if (pvt->sco_save_len > 0) {
- memcpy(pvt->sco_save_buf, pfr, pvt->sco_save_len);
- }
- return 0;
-
-}
-
-static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
-{
-
- struct mbl_pvt *pvt = oldchan->tech_pvt;
-
- if (pvt && pvt->owner == oldchan)
- pvt->owner = newchan;
-
- return 0;
-
-}
-
-static int mbl_devicestate(void *data)
-{
-
- char *device;
- int res = AST_DEVICE_INVALID;
- struct mbl_pvt *pvt;
-
- device = ast_strdupa(S_OR(data, ""));
-
- ast_debug(1, "Checking device state for device %s\n", device);
-
- AST_LIST_TRAVERSE(&devices, pvt, entry) {
- if (!strcmp(pvt->id, device))
- break;
- }
-
- if (pvt) {
- if (pvt->connected) {
- if (pvt->owner)
- res = AST_DEVICE_INUSE;
- else
- res = AST_DEVICE_NOT_INUSE;
- }
- }
-
- return res;
-
-}
static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num)
{
@@ -818,13 +495,342 @@
chn->rings = 1;
ast_string_field_set(chn, language, "en");
pvt->owner = chn;
-
return chn;
}
return NULL;
}
+
+static struct ast_channel *mbl_request(const char *type, int format, void *data, int *cause)
+{
+
+ struct ast_channel *chn = NULL;
+ struct mbl_pvt *pvt;
+ char *dest_dev = NULL;
+ char *dest_num = NULL;
+ int oldformat, group;
+
+ if (!data) {
+ ast_log(LOG_WARNING, "Channel requested with no data\n");
+ *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
+ return NULL;
+ }
+
+ oldformat = format;
+ format &= (AST_FORMAT_SLINEAR);
+ if (!format) {
+ ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%d'\n", oldformat);
+ *cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED;
+ return NULL;
+ }
+
+ dest_dev = ast_strdupa((char *)data);
+
+ dest_num = strchr(dest_dev, '/');
+ if (dest_num)
+ *dest_num++ = 0x00;
+
+ /* Find requested device and make sure its connected. */
+ AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ if ((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) {
+ group = atoi(dest_dev+1);
+ if (pvt->group == group)
+ break;
+ } else if (!strcmp(pvt->id, dest_dev)) {
+ break;
+ }
+ }
+ if (!pvt || !pvt->connected || pvt->owner) {
+ ast_log(LOG_WARNING, "Request to call on device %s which is not connected / already in use.\n", dest_dev);
+ *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ return NULL;
+ }
+
+ if ((pvt->type == MBL_TYPE_PHONE) && !dest_num) {
+ ast_log(LOG_WARNING, "Cant determine destination number.\n");
+ *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
+ return NULL;
+ }
+
+ chn = mbl_new(AST_STATE_DOWN, pvt, NULL);
+ if (!chn) {
+ ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
+ *cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
+ return NULL;
+ }
+
+ return chn;
+
+}
+
+static int mbl_call(struct ast_channel *ast, char *dest, int timeout)
+{
+
+ struct mbl_pvt *pvt;
+ char *dest_dev = NULL;
+ char *dest_num = NULL;
+
+ dest_dev = ast_strdupa((char *)dest);
+
+ pvt = ast->tech_pvt;
+ ast_mutex_lock(&pvt->owner->lock);
+
+ if (pvt->type == MBL_TYPE_PHONE) {
+ dest_num = strchr(dest_dev, '/');
+ if (!dest_num) {
+ ast_log(LOG_WARNING, "Cant determine destination number.\n");
+ return -1;
+ }
+ *dest_num++ = 0x00;
+ }
+
+ if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
+ ast_log(LOG_WARNING, "mbl_call called on %s, neither down nor reserved\n", ast->name);
+ ast_mutex_unlock(&pvt->owner->lock);
+ return -1;
+ }
+
+ ast_debug(1, "Calling %s on %s\n", dest, ast->name);
+
+ if (pvt->type == MBL_TYPE_PHONE) {
+ ast_copy_string(pvt->dial_number, dest_num, sizeof(pvt->dial_number));
+ pvt->state = MBL_STATE_DIAL;
+ pvt->dial_timeout = (timeout == 0) ? 30 : timeout;
+ } else {
+ pvt->state = MBL_STATE_RING;
+ }
+
+ ast_mutex_unlock(&pvt->owner->lock);
+
+ return 0;
+
+}
+
+static int mbl_hangup(struct ast_channel *ast)
+{
+
+ struct mbl_pvt *pvt;
+
+ if (!ast->tech_pvt) {
+ ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
+ return 0;
+ }
+ pvt = ast->tech_pvt;
+
+ ast_debug(1, "Hanging up device %s.\n", pvt->id);
+
+ ast_channel_lock(ast);
+ ast_channel_set_fd(ast, 0, -1);
+ ast_channel_unlock(ast);
+
+ if (pvt->type == MBL_TYPE_HEADSET && pvt->sco_socket != -1) {
+ close(pvt->sco_socket);
+ pvt->sco_socket = -1;
+ }
+
+ if ((pvt->state == MBL_STATE_INCOMING || pvt->state == MBL_STATE_OUTGOING || pvt->state == MBL_STATE_DIAL1 || pvt->state == MBL_STATE_RING3) && pvt->type == MBL_TYPE_PHONE) {
+ rfcomm_write(pvt, "AT+CHUP\r");
+ pvt->state = MBL_STATE_HANGUP;
+ pvt->hangup_count = 0;
+ } else
+ pvt->state = MBL_STATE_IDLE;
+
+ pvt->owner = NULL;
+ ast->tech_pvt = NULL;
+ ast_setstate(ast, AST_STATE_DOWN);
+
+ return 0;
+
+}
+
+static int mbl_answer(struct ast_channel *ast)
+{
+
+ struct mbl_pvt *pvt;
+
+ pvt = ast->tech_pvt;
+
+ rfcomm_write(pvt, "ATA\r");
+
+ ast_setstate(ast, AST_STATE_UP);
+
+ pvt->sent_answer = 1;
+
+ return 0;
+
+}
+
+static int mbl_digit_begin(struct ast_channel *chan, char digit)
+{
+
+ return 0;
+
+}
+
+static int mbl_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
+{
+
+ struct mbl_pvt *pvt;
+ char buf[11];
+
+ pvt = ast->tech_pvt;
+
+ if (pvt->type == MBL_TYPE_HEADSET)
+ return 0;
+
+ ast_debug(1, "Dialed %c\n", digit);
+
+ switch(digit) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '*':
+ case '#':
+ sprintf(buf, "AT+VTS=%c\r", digit);
+ rfcomm_write(pvt, buf);
+ break;
+ default:
+ ast_log(LOG_WARNING, "Unknown digit '%c'\n", digit);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+static struct ast_frame *mbl_read(struct ast_channel *ast)
+{
+
+ struct mbl_pvt *pvt = ast->tech_pvt;
+ struct ast_frame *f;
+
+ if (!pvt->owner) {
+ return &ast_null_frame;
+ }
+
+ if (pvt->state == MBL_STATE_HANGUP) {
+ return &ast_null_frame;
+ }
+
+ if (pvt->sco_socket == -1) {
+ return &ast_null_frame;
+ }
+
+ pvt->fr.frametype = AST_FRAME_VOICE;
+ pvt->fr.subclass = AST_FORMAT_SLINEAR;
+ pvt->fr.data = pvt->sco_in_buf + AST_FRIENDLY_OFFSET;
+
+ if (sco_read(pvt->sco_socket, pvt->sco_in_buf + AST_FRIENDLY_OFFSET, 48)) {
+ if ((pvt->type == MBL_TYPE_PHONE) && (pvt->skip_frames == 0)) {
+ f = ast_dsp_process(0, pvt->dsp, &pvt->fr);
+ if (f && (f->frametype == AST_FRAME_DTMF_END)) {
+ pvt->fr.frametype = AST_FRAME_DTMF_END;
+ pvt->fr.subclass = f->subclass;
+ pvt->skip_frames = pvt->dtmf_skip;
+ }
+ } else {
+ pvt->skip_frames--;
+ }
+ return &pvt->fr;
+ }
+
+ return &ast_null_frame;
+
+}
+
+static int mbl_write(struct ast_channel *ast, struct ast_frame *frame)
+{
+
+ struct mbl_pvt *pvt = ast->tech_pvt;
+ int num_frames, i, sco_need = 0;
+ char *pfr;
+
+ if (frame->frametype != AST_FRAME_VOICE) {
+ return 0;
+ }
+ if (pvt->sco_socket == -1) {
+ return 0;
+ }
+ if (ast->_state != AST_STATE_UP) {
+ return 0;
+ }
+ if (pvt->state == MBL_STATE_HANGUP) {
+ return 0;
+ }
+
+ if (pvt->sco_save_len > 0) {
+ sco_need = 48 - pvt->sco_save_len;
+ memcpy(pvt->sco_save_buf + pvt->sco_save_len, frame->data, sco_need);
+ sco_write(pvt->sco_socket, pvt->sco_save_buf, 48);
+ }
+ num_frames = (frame->datalen - sco_need) / 48;
+ pfr = frame->data + sco_need;
+ for (i=0; i<num_frames; i++) {
+ sco_write(pvt->sco_socket, pfr, 48);
+ pfr += 48;
+ }
+ pvt->sco_save_len = (frame->datalen - sco_need) - (num_frames * 48);
+ if (pvt->sco_save_len > 0) {
+ memcpy(pvt->sco_save_buf, pfr, pvt->sco_save_len);
+ }
+ return 0;
+
+}
+
+static int mbl_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
+{
+
+ struct mbl_pvt *pvt = oldchan->tech_pvt;
+
+ if (pvt && pvt->owner == oldchan)
+ pvt->owner = newchan;
+
+ return 0;
+
+}
+
+static int mbl_devicestate(void *data)
+{
+
+ char *device;
+ int res = AST_DEVICE_INVALID;
+ struct mbl_pvt *pvt;
+
+ device = ast_strdupa(S_OR(data, ""));
+
+ ast_debug(1, "Checking device state for device %s\n", device);
+
+ AST_LIST_TRAVERSE(&devices, pvt, entry) {
+ if (!strcmp(pvt->id, device))
+ break;
+ }
+
+ if (pvt) {
+ if (pvt->connected) {
+ if (pvt->owner)
+ res = AST_DEVICE_INUSE;
+ else
+ res = AST_DEVICE_NOT_INUSE;
+ }
+ }
+
+ return res;
+
+}
+
+/*
+
+ rfcomm helpers
+
+*/
static int rfcomm_connect(bdaddr_t src, bdaddr_t dst, int remote_channel) {
@@ -837,10 +843,10 @@
}
memset(&addr, 0, sizeof(addr));
- addr.rc_family = AF_BLUETOOTH;
- bacpy(&addr.rc_bdaddr, &src);
- addr.rc_channel = (uint8_t) 1;
- if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ addr.rc_family = AF_BLUETOOTH;
+ bacpy(&addr.rc_bdaddr, &src);
+ addr.rc_channel = (uint8_t) 1;
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
ast_debug(1, "bind() failed (%d).\n", errno);
close(s);
return -1;
@@ -949,6 +955,12 @@
}
+/*
+
+ sco helpers
+
+*/
+
static int sco_connect(bdaddr_t src, bdaddr_t dst)
{
@@ -961,9 +973,9 @@
}
memset(&addr, 0, sizeof(addr));
- addr.sco_family = AF_BLUETOOTH;
- bacpy(&addr.sco_bdaddr, &src);
- if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ addr.sco_family = AF_BLUETOOTH;
+ bacpy(&addr.sco_bdaddr, &src);
+ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
ast_debug(1, "bind() failed (%d).\n", errno);
close(s);
return -1;
@@ -982,12 +994,6 @@
return s;
}
-
-/*
-
- sco_write()
-
-*/
static int sco_write(int s, char *buf, int len)
{
@@ -1016,12 +1022,6 @@
return 1;
}
-
-/*
-
- sco_read()
-
-*/
static int sco_read(int s, char *buf, int len)
{
@@ -1041,12 +1041,6 @@
}
-/*
-
- sco_set_options()
-
-*/
-
static int sco_set_options(int s)
{
@@ -1070,8 +1064,7 @@
/*
- sdp_search() performs a service discovery on the given device to determine whether
- or not it supports the Handsfree Profile.
+ sdp helpers
*/
@@ -1115,7 +1108,6 @@
} else
ast_debug(1, "sdp_service_search_attr_req() failed on device %s.\n", addr);
-
sdp_list_free(search_list, 0);
sdp_list_free(attrid_list, 0);
sdp_close(session);
@@ -1123,16 +1115,6 @@
return port;
}
-
-/*
-
- sdp_register()
-
- Register GENERIC_AUDIO & HEADSET with the SDP daemon on the Asterisk Box.
- This assists connections to phones/pda's with dud bluetooth stacks like the IMate Jasjam
- and some Nokia's
-
-*/
static sdp_session_t *sdp_register(void)
{
@@ -1198,11 +1180,7 @@
/*
- Phone Monitor Thread
-
- This thread is spun once a phone device is discovered and considered capable of being used, i.e. supports Handsfree Profile,
- and its configured in mobile.conf.
- The thread lives for the lifetime of the bluetooth connection, and handles the 'control' side of all calls.
+ Thread routines
*/
@@ -1247,7 +1225,7 @@
case MBL_STATE_INIT:
if (strstr(buf, "+BRSF:")) {
brsf = 1;
- } else if (strstr(buf, "ERROR") && !nsmode) { /* Hmmm, Non-Standard Phone, just continue */
+ } else if (strstr(buf, "ERROR") && !nsmode) { /* Hmmm, Non-Standard Phone, just continue */
rfcomm_write(pvt, "AT+CIND=?\r");
pvt->state++;
nsmode = 1;
@@ -1315,7 +1293,7 @@
}
break;
case MBL_STATE_INIT5:
- if (strstr(buf, "ERROR")) { /* No SMS Support ! */
+ if (strstr(buf, "ERROR")) { /* No SMS Support ! */
pvt->state = MBL_STATE_PREIDLE;
} else if (strstr(buf, "OK")) {
rfcomm_write(pvt, "AT+CNMI=2,1,0,1,0\r");
@@ -1323,7 +1301,7 @@
}
break;
case MBL_STATE_INIT6:
- if (strstr(buf, "OK")) { /* We have SMS Support */
+ if (strstr(buf, "OK")) { /* We have SMS Support */
pvt->has_sms = 1;
pvt->state = MBL_STATE_PREIDLE;
} else if (strstr(buf, "ERROR")) {
@@ -1340,8 +1318,8 @@
pvt->state = MBL_STATE_RING;
} else if (strstr(buf, "+CIEV:")) {
if (strstr(buf, pvt->ciev_callsetup_3)) { /* User has dialed out on handset */
- monitor = 0; /* We disconnect now, as he is */
- } /* probably leaving BT range... */
+ monitor = 0; /* We disconnect now, as he is */
+ } /* probably leaving BT range... */
}
break;
case MBL_STATE_DIAL: /* Nothing handled here, we need to wait for a timeout */
@@ -1560,16 +1538,6 @@
}
-/*
-
- Headset Monitor Thread
-
- This thread is spun once a headset device is discovered and considered capable of being used, i.e. supports Headset Profile,
- and its configured in mobile.conf.
- The thread lives for the lifetime of the bluetooth connection, and handles the 'control' side of all calls.
-
-*/
-
static void *do_monitor_headset(void *data)
{
@@ -1678,18 +1646,6 @@
}
-/*
-
- Device Discovery Thread.
-
- This thread wakes every 'discovery_interval' seconds and trys to connect to
- those configured devices which are not connected. This saves the user from having
- to manually connect his/her cell phone to the asterisk box. Once a successful
- connection is made, a monitor thread is spun on the device which lives for the
- lifetime of the connection.
-
-*/
-
static void *do_discovery(void *data)
{
@@ -1721,16 +1677,6 @@
return NULL;
}
-/*
-
- This thread listens for incoming sco connections.
- Although the Bluetooth Handsfree Profile Specification says that either end may initiate the audio connection,
- in practice some devices (LG TU500) get upset unless they initiate the connection.
- We leave all sco initiation to the device.
- On an inbound sco connection, we need to find the appropriate device, and set the channel fd accordingly.
-
-*/
-
static void *do_sco_listen(void *data)
{
@@ -1767,10 +1713,11 @@
return NULL;
}
while (1) {
+ ast_debug(1, "About to accept() socket.\n");
addrlen = sizeof(struct sockaddr_sco);
- ast_log(LOG_NOTICE, "About to accept the sco_socket...\n");
if ((ns = accept(adapter->sco_socket, (struct sockaddr *)&addr, &addrlen)) > -1) {
- ast_log(LOG_NOTICE, "sco_socket returns %d...\n",ns);
+
+ ast_debug(1, "accept()ed socket.\n");
sco_set_options(ns);
@@ -1786,7 +1733,6 @@
break;
}
if (pvt) {
- ast_log(LOG_NOTICE,"about to close the pvt-sco_socket and set it ns\n");
if (pvt->sco_socket != -1)
close(pvt->sco_socket);
pvt->sco_socket = ns;
@@ -1797,13 +1743,20 @@
}
} else
ast_debug(1, "Could not find device for incoming Audio Connection.\n");
+ } else {
+ ast_log(LOG_ERROR, "accept() failed %d\n", errno);
}
- else ast_log(LOG_NOTICE, "Accept got a -1....");
}
return NULL;
}
+
+/*
+
+ Module
+
+*/
static int mbl_load_config(void)
{
More information about the asterisk-addons-commits
mailing list