[asterisk-addons-commits] dcb: trunk r431 - /trunk/chan_mobile.c

SVN commits to the Asterisk addons project asterisk-addons-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 asterisk-addons-commits mailing list