[asterisk-addons-commits] dcb: trunk r441 - in /trunk: chan_mobile.c configs/mobile.conf.sample
SVN commits to the Asterisk addons project
asterisk-addons-commits at lists.digium.com
Fri Sep 7 20:24:59 CDT 2007
Author: dcb
Date: Fri Sep 7 20:24:58 2007
New Revision: 441
URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=441
Log:
Modified audio handling methodology to align with SCO timing requirements.
Modified:
trunk/chan_mobile.c
trunk/configs/mobile.conf.sample
Modified: trunk/chan_mobile.c
URL: http://svn.digium.com/view/asterisk-addons/trunk/chan_mobile.c?view=diff&rev=441&r1=440&r2=441
==============================================================================
--- trunk/chan_mobile.c (original)
+++ trunk/chan_mobile.c Fri Sep 7 20:24:58 2007
@@ -72,7 +72,11 @@
#define MBL_CONFIG "mobile.conf"
-static int prefformat = AST_FORMAT_SLINEAR;
+#define DEVICE_FRAME_SIZE 48
+#define DEVICE_FRAME_FORMAT AST_FORMAT_SLINEAR
+#define CHANNEL_FRAME_SIZE 320
+
+static int prefformat = DEVICE_FRAME_FORMAT;
static int discovery_interval = 60; /* The device discovery interval, default 60 seconds. */
static pthread_t discovery_thread = AST_PTHREADT_NULL; /* The discovery thread */
@@ -132,13 +136,14 @@
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];
+ char io_save_buf[DEVICE_FRAME_SIZE];
+ int io_save_len;
+ int io_pipe[2];
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 */
- 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 */
int dial_timeout;
char ciev_call_0[4]; /* dynamically built reponse strings */
@@ -220,7 +225,6 @@
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);
@@ -467,17 +471,15 @@
struct ast_channel *chn;
- pvt->fr.frametype = AST_FRAME_VOICE;
- pvt->fr.subclass = AST_FORMAT_SLINEAR;
- pvt->fr.datalen = 48;
- pvt->fr.samples = 24;
- pvt->fr.src = "Mobile";
- pvt->fr.offset = AST_FRIENDLY_OFFSET;
- pvt->fr.mallocd = 0;
- pvt->fr.delivery.tv_sec = 0;
- pvt->fr.delivery.tv_usec = 0;
- pvt->fr.data = pvt->sco_in_buf + AST_FRIENDLY_OFFSET;
- pvt->sco_save_len = 0;
+ if (pipe(pvt->io_pipe) == -1) {
+ ast_log(LOG_ERROR, "Failed to create io_pipe.\n");
+ return NULL;
+ }
+
+ if (pvt->sco_socket != -1)
+ close(pvt->sco_socket);
+ pvt->sco_socket = -1;
+ pvt->io_save_len = 0;
pvt->sent_answer = 0;
pvt->skip_frames = 0;
@@ -489,8 +491,8 @@
chn->rawwriteformat = prefformat;
chn->writeformat = prefformat;
chn->readformat = prefformat;
- AST_LIST_HEAD_INIT_NOLOCK(&chn->readq);
chn->tech_pvt = pvt;
+ ast_channel_set_fd(chn, 0, pvt->io_pipe[0]);
if (state == AST_STATE_RING)
chn->rings = 1;
ast_string_field_set(chn, language, "en");
@@ -533,7 +535,7 @@
/* Find requested device and make sure its connected. */
AST_LIST_TRAVERSE(&devices, pvt, entry) {
- if ((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) {
+ if (((dest_dev[0] == 'g') || (dest_dev[0] == 'G')) && ((dest_dev[1] >= '0') && (dest_dev[1] <= '9'))) {
group = atoi(dest_dev+1);
if (pvt->group == group)
break;
@@ -574,7 +576,6 @@
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, '/');
@@ -587,7 +588,6 @@
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;
}
@@ -600,8 +600,6 @@
} else {
pvt->state = MBL_STATE_RING;
}
-
- ast_mutex_unlock(&pvt->owner->lock);
return 0;
@@ -620,9 +618,8 @@
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);
+ close(pvt->io_pipe[0]);
+ close(pvt->io_pipe[1]);
if (pvt->type == MBL_TYPE_HEADSET && pvt->sco_socket != -1) {
close(pvt->sco_socket);
@@ -711,38 +708,40 @@
struct mbl_pvt *pvt = ast->tech_pvt;
struct ast_frame *f;
+ int r;
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;
- }
-
+ memset(&pvt->fr, 0x00, sizeof(struct ast_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;
- }
+ pvt->fr.subclass = DEVICE_FRAME_FORMAT;
+ pvt->fr.datalen = CHANNEL_FRAME_SIZE;
+ pvt->fr.samples = CHANNEL_FRAME_SIZE / 2;
+ pvt->fr.src = "Mobile";
+ pvt->fr.offset = AST_FRIENDLY_OFFSET;
+ pvt->fr.mallocd = 0;
+ pvt->fr.delivery.tv_sec = 0;
+ pvt->fr.delivery.tv_usec = 0;
+ pvt->fr.data = pvt->io_buf + AST_FRIENDLY_OFFSET;
+
+ if ((r = read(pvt->io_pipe[0], pvt->fr.data, CHANNEL_FRAME_SIZE)) != CHANNEL_FRAME_SIZE) {
+ if (r == -1) {
+ ast_log(LOG_ERROR, "read error %d\n", errno);
+ return &ast_null_frame;
} else {
- pvt->skip_frames--;
- }
- return &pvt->fr;
- }
-
- return &ast_null_frame;
+ pvt->fr.datalen = r;
+ pvt->fr.samples = r / 2;
+ }
+ }
+
+ 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;
+ }
+
+ return &pvt->fr;
}
@@ -750,37 +749,40 @@
{
struct mbl_pvt *pvt = ast->tech_pvt;
- int num_frames, i, sco_need = 0;
- char *pfr;
-
+ int i, r, io_need, num_frames;
+ char *pfr, buf[DEVICE_FRAME_SIZE];
+
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;
+
+ io_need = 0;
+ if (pvt->io_save_len > 0) {
+ io_need = DEVICE_FRAME_SIZE - pvt->io_save_len;
+ memcpy(pvt->io_save_buf + pvt->io_save_len, frame->data, io_need);
+ sco_write(pvt->sco_socket, pvt->io_save_buf, DEVICE_FRAME_SIZE);
+ if ((r = sco_read(pvt->sco_socket, buf, DEVICE_FRAME_SIZE)))
+ sco_write(pvt->io_pipe[1], buf, r);
+ }
+
+ num_frames = (frame->datalen - io_need) / DEVICE_FRAME_SIZE;
+ pfr = frame->data + io_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);
- }
+ sco_write(pvt->sco_socket, pfr, DEVICE_FRAME_SIZE);
+ if ((r = sco_read(pvt->sco_socket, buf, DEVICE_FRAME_SIZE)))
+ sco_write(pvt->io_pipe[1], buf, r);
+ pfr += DEVICE_FRAME_SIZE;
+ }
+
+ pvt->io_save_len = (frame->datalen - io_need) - (num_frames * DEVICE_FRAME_SIZE);
+ if (pvt->io_save_len > 0) {
+ memcpy(pvt->io_save_buf, pfr, pvt->io_save_len);
+ }
+
return 0;
}
@@ -998,21 +1000,15 @@
static int sco_write(int s, char *buf, int len)
{
- struct pollfd pfd;
int r;
-
- pfd.fd = s;
- pfd.events = POLLOUT;
-
- if (( r = poll(&pfd, 1, -1)) != 1) {
- if (r == -1)
- ast_debug(1, "poll() returned errno %d\n", errno);
+
+ if (s == -1) {
+ ast_debug(2, "sco_write() not ready\n");
return 0;
}
-
- if (pfd.revents != POLLOUT)
- ast_debug(1, "pfd.revents = %d\n", pfd.revents);
-
+
+ ast_debug(2, "sco_write()\n");
+
r = write(s, buf, len);
if (r == -1) {
ast_debug(1, "sco write error %d\n", errno);
@@ -1027,39 +1023,22 @@
{
int r;
-
+
+ if (s == -1) {
+ ast_debug(2, "sco_read() not ready\n");
+ return 0;
+ }
+
+ ast_debug(2, "sco_read()\n");
+
r = read(s, buf, len);
- if (r != len) {
- if (r == -1)
- ast_debug(1, "sco_read() error %d\n", errno);
- else
- ast_debug(1, "sco_read() read short frame.\n");
+ if (r == -1) {
+ ast_debug(1, "sco_read() error %d\n", errno);
return 0;
}
- return 1;
-
-}
-
-static int sco_set_options(int s)
-{
-
- #define SCO_TXBUFS 0x03
- #define SCO_RXBUFS 0x04
-
- int arg;
- socklen_t arglen;
-
- arglen = sizeof(arg);
- arg = 100;
- if (setsockopt(s, SOL_SCO, SCO_TXBUFS, &arg, arglen) == -1)
- ast_debug(1, "error setting SCO_TXBUFS %d\n", errno);
-
- if (setsockopt(s, SOL_SCO, SCO_RXBUFS, &arg, arglen) == -1)
- ast_debug(1, "error setting SCO_RXBUFS %d\n", errno);
-
- return 0;
-
+ return r;
+
}
/*
@@ -1389,7 +1368,6 @@
pvt->state = MBL_STATE_INCOMING;
} else { /* User answered on handset!, disconnect */
pvt->state = MBL_STATE_IDLE;
- ast_log(LOG_NOTICE,"Closing the sco_socket in RING3 with CIEV\n");
if (pvt->sco_socket > -1)
close(pvt->sco_socket);
ast_queue_control(pvt->owner, AST_CONTROL_HANGUP);
@@ -1561,9 +1539,6 @@
switch (pvt->state) {
case MBL_STATE_RING2:
if (strstr(buf, "AT+CKPD=")) {
- ast_channel_lock(pvt->owner);
- ast_channel_set_fd(pvt->owner, 0, pvt->sco_socket);
- ast_channel_unlock(pvt->owner);
ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
pvt->state = MBL_STATE_INCOMING;
rfcomm_write(pvt, "\r\n+VGS=13\r\n");
@@ -1591,7 +1566,6 @@
} else if (pvt->state == MBL_STATE_RING) {
pvt->sco_socket = sco_connect(pvt->adapter->addr, pvt->addr);
if (pvt->sco_socket > -1) {
- sco_set_options(pvt->sco_socket);
ast_setstate(pvt->owner, AST_STATE_RINGING);
ast_queue_control(pvt->owner, AST_CONTROL_RINGING);
pvt->state = MBL_STATE_RING2;
@@ -1656,7 +1630,7 @@
AST_LIST_TRAVERSE(&adapters, adapter, entry) {
if (!adapter->inuse) {
AST_LIST_TRAVERSE(&devices, pvt, entry) {
- if (!pvt->connected && !strcmp(adapter->id, pvt->adapter->id)) {
+ if (!adapter->inuse && !pvt->connected && !strcmp(adapter->id, pvt->adapter->id)) {
if ((pvt->rfcomm_socket = rfcomm_connect(adapter->addr, pvt->addr, pvt->rfcomm_port)) > -1) {
pvt->state = 0;
if (start_monitor(pvt)) {
@@ -1716,11 +1690,7 @@
ast_debug(1, "About to accept() socket.\n");
addrlen = sizeof(struct sockaddr_sco);
if ((ns = accept(adapter->sco_socket, (struct sockaddr *)&addr, &addrlen)) > -1) {
-
ast_debug(1, "accept()ed socket.\n");
-
- sco_set_options(ns);
-
len = sizeof(so);
getsockopt(ns, SOL_SCO, SCO_OPTIONS, &so, &len);
@@ -1736,11 +1706,6 @@
if (pvt->sco_socket != -1)
close(pvt->sco_socket);
pvt->sco_socket = ns;
- if (pvt->owner) {
- ast_channel_lock(pvt->owner);
- ast_channel_set_fd(pvt->owner, 0, ns);
- ast_channel_unlock(pvt->owner);
- }
} else
ast_debug(1, "Could not find device for incoming Audio Connection.\n");
} else {
@@ -1764,7 +1729,7 @@
struct ast_config *cfg = NULL;
char *cat = NULL;
struct ast_variable *var;
- const char *id, *address, *useadapter, *port, *context, *type, *skip, *group;
+ const char *id, *address, *useadapter, *port, *context, *type, *skip, *group, *master;
struct mbl_pvt *pvt;
struct adapter_pvt *adapter;
uint16_t vs;
@@ -1787,6 +1752,7 @@
if (!strcasecmp(cat, "adapter")) {
id = ast_variable_retrieve(cfg, cat, "id");
address = ast_variable_retrieve(cfg, cat, "address");
+ master = ast_variable_retrieve(cfg, cat, "forcemaster");
ast_debug(1, "Loading adapter %s %s.\n", id, address);
if (id && address) {
if ((adapter = ast_malloc(sizeof(struct adapter_pvt)))) {
@@ -1800,10 +1766,12 @@
ast_log(LOG_ERROR, "Unable to open adapter %s. It wont be enabled.\n", adapter->id);
free(adapter);
} else {
- dr.dev_id = adapter->dev_id;
- if (hci_strtolm("master", &dr.dev_opt)) {
- if (ioctl(adapter->hci_socket, HCISETLINKMODE, (unsigned long) &dr) < 0) {
- ast_log(LOG_WARNING, "Unable to set adapter %s link mode to MASTER.\n", adapter->id);
+ if ((master) && (*master)) {
+ dr.dev_id = adapter->dev_id;
+ if (hci_strtolm("master", &dr.dev_opt)) {
+ if (ioctl(adapter->hci_socket, HCISETLINKMODE, (unsigned long) &dr) < 0) {
+ ast_log(LOG_WARNING, "Unable to set adapter %s link mode to MASTER.\n", adapter->id);
+ }
}
}
hci_read_voice_setting(adapter->hci_socket, &vs, 1000);
Modified: trunk/configs/mobile.conf.sample
URL: http://svn.digium.com/view/asterisk-addons/trunk/configs/mobile.conf.sample?view=diff&rev=441&r1=440&r2=441
==============================================================================
--- trunk/configs/mobile.conf.sample (original)
+++ trunk/configs/mobile.conf.sample Fri Sep 7 20:24:58 2007
@@ -4,7 +4,7 @@
;
[general]
-interval=10 ; Number of seconds between trying to connect to devices.
+interval=30 ; Number of seconds between trying to connect to devices.
; The following is a list of adapters we use.
; id must be unique and address is the bdaddr of the adapter from hciconfig.
@@ -14,6 +14,7 @@
[adapter]
id=blue
address=00:09:DD:60:01:A3
+;forcemaster=yes ; attempt to force adapter into master mode. default is no.
[adapter]
id=dlink
@@ -32,15 +33,15 @@
address=00:E0:91:7F:46:44 ; the address of the phone
port=4 ; the rfcomm port number (from mobile search)
context=incoming-mobile ; dialplan context for incoming calls
-adapter=dlink ; adapter to use
-group=1 ; this phone is in channel group 1
+adapter=dlink ; adapter to use
+group=1 ; this phone is in channel group 1
[6310i]
address=00:60:57:32:7E:B1
port=13
context=incoming-mobile
adapter=dlink
-group=1 ; this phone is in channel group 1 also.
+group=1 ; this phone is in channel group 1 also.
[headset]
address=00:0B:9E:11:AE:C6
More information about the asterisk-addons-commits
mailing list