[svn-commits] dcb: trunk r441 - in /trunk: chan_mobile.c configs/mobile.conf.sample

SVN commits to the Digium repositories svn-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 svn-commits mailing list