[svn-commits] dcb: trunk r431 - /trunk/chan_mobile.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Sat Aug 25 23:23:33 CDT 2007
Author: dcb
Date: Sat Aug 25 23:23:31 2007
New Revision: 431
URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=431
Log:
* Changes to take advantage of kernel sco flow control patch.
* Removed hard coded 20ms frame size dependance.
* Configure adapters to master mode by default.
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=431&r1=430&r2=431
==============================================================================
--- trunk/chan_mobile.c (original)
+++ trunk/chan_mobile.c Sat Aug 25 23:23:31 2007
@@ -52,6 +52,7 @@
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sco.h>
+#include <bluetooth/l2cap.h>
#include <asterisk/lock.h>
#include <asterisk/channel.h>
@@ -134,9 +135,8 @@
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_out_buf[352];
- char *sco_out_ptr;
- int sco_out_len;
+ 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 */
@@ -178,7 +178,6 @@
static int do_show_devices(int, int, char **);
static int do_search_devices(int, int, char **);
static int do_send_rfcomm(int, int, char **);
-static void *do_sco_listen(void *data);
static struct ast_cli_entry mbl_cli[] = {
{{"mobile", "show", "devices", NULL}, do_show_devices, "Show Bluetooth Cell / Mobile devices", show_usage},
@@ -218,6 +217,10 @@
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);
static const struct ast_channel_tech mbl_tech = {
@@ -654,7 +657,7 @@
struct mbl_pvt *pvt = ast->tech_pvt;
int r;
struct ast_frame *f;
-
+
if (!pvt->owner) {
return &ast_null_frame;
}
@@ -671,8 +674,8 @@
pvt->fr.subclass = AST_FORMAT_SLINEAR;
pvt->fr.data = pvt->sco_in_buf + AST_FRIENDLY_OFFSET;
- if ((r = recv(pvt->sco_socket, pvt->fr.data, 48, MSG_DONTWAIT)) == 48) {
- if (pvt->skip_frames == 0) {
+ 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;
@@ -683,17 +686,6 @@
pvt->skip_frames--;
}
return &pvt->fr;
- } else if (r == -1) {
- if (errno != EAGAIN) {
- ast_log(LOG_ERROR, "mbl_read() read error %d.\n", errno);
- close(pvt->sco_socket);
- pvt->sco_socket = -1;
- ast_channel_lock(ast);
- ast_channel_set_fd(ast, 0, -1);
- ast_channel_unlock(ast);
- }
- } else {
- ast_debug(1, "mbl_read() read short frame. (%d)\n", r);
}
return &ast_null_frame;
@@ -711,45 +703,37 @@
{
struct mbl_pvt *pvt = ast->tech_pvt;
- int num_frames, i, r;
+ 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 (frame->datalen > sizeof(pvt->sco_out_buf) - pvt->sco_out_len) {
- frame->datalen = sizeof(pvt->sco_out_buf) - pvt->sco_out_len;
- ast_debug(1, "Overrun on sco_out_buf detected.\n");
- }
-
- memmove(pvt->sco_out_ptr, frame->data, frame->datalen);
- pvt->sco_out_len += frame->datalen;
- num_frames = pvt->sco_out_len / 48;
-
- pfr = pvt->sco_out_buf;
+
+ 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++) {
- if ((r = send(pvt->sco_socket, pfr, 48, MSG_DONTWAIT)) == -1) {
- if (errno != EAGAIN) {
- ast_debug(1, "write error on sco_socket %d.\n", errno);
- close(pvt->sco_socket);
- pvt->sco_socket = -1;
- }
- }
+ sco_write(pvt->sco_socket, pfr, 48);
pfr += 48;
}
-
- pvt->sco_out_len = pvt->sco_out_len - (num_frames * 48);
- memmove(pvt->sco_out_buf, pfr, pvt->sco_out_len);
- pvt->sco_out_ptr = pvt->sco_out_buf + pvt->sco_out_len;
-
+ 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;
}
@@ -810,11 +794,10 @@
pvt->fr.delivery.tv_sec = 0;
pvt->fr.delivery.tv_usec = 0;
pvt->fr.data = pvt->sco_in_buf + AST_FRIENDLY_OFFSET;
- pvt->sco_out_ptr = pvt->sco_out_buf;
- pvt->sco_out_len = 0;
+ pvt->sco_save_len = 0;
pvt->sent_answer = 0;
pvt->skip_frames = 0;
-
+
chn = ast_channel_alloc(1, state, cid_num, pvt->id, 0, 0, pvt->context, 0, "Mobile/%s-%04lx", pvt->id, ast_random() & 0xffff);
if (chn) {
chn->tech = &mbl_tech;
@@ -965,7 +948,7 @@
struct sockaddr_sco addr;
int s;
-
+
if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
ast_debug(1, "socket() failed (%d).\n", errno);
return -1;
@@ -991,6 +974,91 @@
}
return s;
+
+}
+
+/*
+
+ sco_write()
+
+*/
+
+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);
+ return 0;
+ }
+
+ if (pfd.revents != POLLOUT)
+ ast_debug(1, "pfd.revents = %d\n", pfd.revents);
+
+ r = write(s, buf, len);
+ if (r == -1) {
+ ast_debug(1, "sco write error %d\n", errno);
+ return 0;
+ }
+
+ return 1;
+
+}
+
+/*
+
+ sco_read()
+
+*/
+
+static int sco_read(int s, char *buf, int len)
+{
+
+ int r;
+
+ 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");
+ return 0;
+ }
+
+ return 1;
+
+}
+
+/*
+
+ sco_set_options()
+
+*/
+
+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;
}
@@ -1549,6 +1617,7 @@
} 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;
@@ -1697,6 +1766,8 @@
if ((ns = accept(adapter->sco_socket, (struct sockaddr *)&addr, &addrlen)) > -1) {
ast_log(LOG_NOTICE, "sco_socket returns %d...\n",ns);
+ sco_set_options(ns);
+
len = sizeof(so);
getsockopt(ns, SOL_SCO, SCO_OPTIONS, &so, &len);
@@ -1738,6 +1809,7 @@
struct mbl_pvt *pvt;
struct adapter_pvt *adapter;
uint16_t vs;
+ struct hci_dev_req dr;
char nadapters = 0;
struct ast_flags config_flags = { 0 };
@@ -1769,6 +1841,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);
+ }
+ }
hci_read_voice_setting(adapter->hci_socket, &vs, 1000);
vs = htobs(vs);
if (vs != 0x0060) {
More information about the svn-commits
mailing list