⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btsco.c

📁 蓝牙blue tooth sco协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Userspace management of snd-bt-sco * *  Copyright (c) 2003 by Jonathan Paisley <jp@dcs.gla.ac.uk> *  *  Daemon enhancements (c) 2004 by Lars Grunewaldt <lgw@dark-reality.de> * *  Based on sb16_csp/cspctl.c and hstest.c from bluez-utils/test. * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#include <getopt.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <assert.h>#include <string.h>#include <errno.h>#include <regex.h>#include <ctype.h>#include <sys/wait.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/poll.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/sco.h>#include <bluetooth/rfcomm.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <alsa/asoundlib.h>#define SNDRV_BT_SCO_IOCTL_SET_SCO_SOCKET _IOW ('H', 0x10, int)#define SNDRV_BT_SCO_IOCTL_REQ_INFO _IO ('H', 0x11)#ifndef SND_HWDEP_IFACE_EMUX_WAVETABLE#define SND_HWDEP_IFACE_EMUX_WAVETABLE (SND_HWDEP_IFACE_USX2Y + 1)#endif#ifndef SND_HWDEP_IFACE_BLUETOOTH#define SND_HWDEP_IFACE_BLUETOOTH (SND_HWDEP_IFACE_EMUX_WAVETABLE + 1)#endif#ifndef SNDRV_HWDEP_IFACE_BT_SCO#define SNDRV_HWDEP_IFACE_BT_SCO (SND_HWDEP_IFACE_BLUETOOTH + 1)#endif#define NOT_CONNECTED 0#define CONNECTED 1typedef struct snd_card_bt_sco_info {	int mixer_volume[2];	int playback_count, capture_count;} snd_card_bt_sco_info_t;struct action {	struct action *next;	regex_t regex;	char *cmd;};static volatile int terminate = 0, ring = 0, hupped = 0;static int verbose = 0;static void sig_term(int sig){	terminate = 1;}static void sig_ring(int sig){	ring = 1;}static void sig_hup(int sig){	hupped = 1;}static int rfcomm_connect(bdaddr_t * src, bdaddr_t * dst, uint8_t channel){	struct sockaddr_rc addr;	int s;	if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {		return -1;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	bacpy(&addr.rc_bdaddr, src);	addr.rc_channel = 0;	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {		close(s);		return -1;	}	memset(&addr, 0, sizeof(addr));	addr.rc_family = AF_BLUETOOTH;	bacpy(&addr.rc_bdaddr, dst);	addr.rc_channel = channel;	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {		close(s);		return -1;	}	return s;}static int sco_connect(bdaddr_t * src, bdaddr_t * dst, uint16_t * handle,		       uint16_t * mtu){	struct sockaddr_sco addr;	struct sco_conninfo conn;	struct sco_options opts;	int s, size;	if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {		return -1;	}	memset(&addr, 0, sizeof(addr));	addr.sco_family = AF_BLUETOOTH;	bacpy(&addr.sco_bdaddr, src);	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {		close(s);		return -1;	}	memset(&addr, 0, sizeof(addr));	addr.sco_family = AF_BLUETOOTH;	bacpy(&addr.sco_bdaddr, dst);	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {		close(s);		return -1;	}	size = sizeof(conn);	if (getsockopt(s, SOL_SCO, SCO_CONNINFO, &conn, &size) < 0) {		close(s);		return -1;	}	size = sizeof(opts);	if (getsockopt(s, SOL_SCO, SCO_OPTIONS, &opts, &size) < 0) {		close(s);		return -1;	}	if (handle)		*handle = conn.hci_handle;	if (mtu)		*mtu = opts.mtu;	return s;}static void error(const char *fmt, ...){	va_list va;	va_start(va, fmt);	fprintf(stderr, "Error: ");	vfprintf(stderr, fmt, va);	fprintf(stderr, "\n");	va_end(va);}static int bt_sco_set_fd(snd_hwdep_t * handle, int sco_fd){	if (snd_hwdep_ioctl	    (handle, SNDRV_BT_SCO_IOCTL_SET_SCO_SOCKET, (void *)sco_fd) < 0) {		error("unable to set fd");		return 1;	}	return 0;}int find_hwdep_device(int *cardP, int *devP){	snd_ctl_t *ctl_handle;	snd_ctl_card_info_t *card_info;	snd_hwdep_info_t *hwdep_info;	int card;	int dev;	int err;	char card_id[32];	ctl_handle = NULL;	snd_ctl_card_info_alloca(&card_info);	snd_hwdep_info_alloca(&hwdep_info);	for (card = 0; card < 7; card++) {		*cardP = card;		if (ctl_handle) {			snd_ctl_close(ctl_handle);			ctl_handle = NULL;		}		// Get control handle for selected card		sprintf(card_id, "hw:%i", card);		if ((err = snd_ctl_open(&ctl_handle, card_id, 0)) < 0) {			error("control open (%s): %s", card_id,			      snd_strerror(err));			return -1;		}		// Read control hardware info from card		if ((err = snd_ctl_card_info(ctl_handle, card_info)) < 0) {			error("control hardware info (%s): %s", card_id,			      snd_strerror(err));			continue;		}		//if (strcmp(snd_ctl_card_info_get_driver(card_info),"BT SCO (d)"))		//    continue;		dev = -1;		err = 1;		while (1) {			if (snd_ctl_hwdep_next_device(ctl_handle, &dev) < 0)				error("hwdep next device (%s): %s",				      card_id, snd_strerror(err));			if (dev < 0)				break;			snd_hwdep_info_set_device(hwdep_info, dev);			if (snd_ctl_hwdep_info(ctl_handle, hwdep_info) < 0) {				if (err != -ENOENT)					error					    ("control hwdep info (%s): %s",					     card_id, snd_strerror(err));				continue;			}			if (snd_hwdep_info_get_iface(hwdep_info) ==			    SNDRV_HWDEP_IFACE_BT_SCO) {				snd_ctl_close(ctl_handle);				*devP = dev;				return 0;			}		}	}	if (ctl_handle)		snd_ctl_close(ctl_handle);	return -1;}static void usage(void){	printf("\nbtsco bluetooth audio handler\n");	printf("Usage:\n" "\tbtsco [options] <bdaddr> [channel]\n");	printf("Options:\n");	printf(" -v print verbose output\n");	printf(" -f fork and run as a daemon\n");	printf(" -c clear filehandle and exit\n");	printf(" -h print this usage and exit\n");	printf("\nThe headset channel will be automatically detected if not specified\n\n");}int detect_channel(bdaddr_t * bdaddr){	// equivalent to running:	// sdptool search --bdaddr 00:0A:D9:74:B4:EA 0x1108	// and parsing out the channel number	uuid_t group;	bdaddr_t interface;	sdp_list_t *attrid, *search, *seq, *next;	uint32_t range = 0x0000ffff;	sdp_session_t *sess;	int channel = 2;	int searchresult;	bacpy(&interface, BDADDR_ANY);	sdp_uuid16_create(&group, 0x1108);	sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);	if (!sess) {		error		    ("Failed to connect to SDP server: %s\nAssuming channel %d\n",		     strerror(errno), channel);		return channel;	}	attrid = sdp_list_append(0, &range);	search = sdp_list_append(0, &group);	searchresult =	    sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE,					attrid, &seq);	sdp_list_free(attrid, 0);	sdp_list_free(search, 0);	if (searchresult) {		error("Service Search failed: %s\nAssuming channel %d\n",		       strerror(errno), channel);		sdp_close(sess);		return channel;	}	for (; seq; seq = next) {		sdp_record_t *rec = (sdp_record_t *) seq->data;		sdp_list_t *list = 0;		if (sdp_get_access_protos(rec, &list) == 0) {			channel = sdp_get_proto_port(list, RFCOMM_UUID);		}		next = seq->next;		free(seq);		sdp_record_free(rec);	}	sdp_close(sess);	return channel;}static void free_actions(struct action *list){	struct action *cur;		while(list != NULL) {		cur = list;		list = cur->next;		regfree(&cur->regex);		free(cur->cmd);		free(cur);	}}static struct action *read_actions(void){	int state, retval, len;	struct action *ret, *cur, *new;	char buf[1024];	char *p;	FILE *cf;		ret = NULL;	cur = NULL;	new = NULL;	if(getenv("HOME") == NULL)		return(NULL);	snprintf(buf, sizeof(buf), "%s/.btscorc", getenv("HOME"));	if((cf = fopen(buf, "r")) == NULL) {		if(errno != ENOENT)			perror(buf);		return(NULL);	}	state = 0;	while(!feof(cf)) {		if(fgets(buf, sizeof(buf), cf) == NULL) {			if(ferror(cf)) {				error("reading cf: %s", strerror(ferror(cf)));				free_actions(ret);				return(NULL);			} else {				continue;			}		}				if(buf[0] == '#')			continue;		for(p = buf; isspace(*p); p++);		memmove(buf, p, strlen(buf) + 1 - (p - buf));		if(strlen(buf) == 0)			continue;		for(p = buf + strlen(buf) - 1; isspace(*p); p--);		p[1] = 0;				switch(state) {		case 0:			new = malloc(sizeof(*new));			new->next = NULL;			new->cmd = NULL;			if((retval = regcomp(&new->regex, buf, REG_EXTENDED)) != 0) {				error("could not compile regex `%s'", buf);				free_actions(ret);				free(new);				return(NULL);			}			state = 1;			break;		case 1:			len = strlen(buf);			if(buf[len - 1] == '\\') {				buf[len - 1] = 0;			} else {				state = 0;				if(ret == NULL) {					ret = cur = new;				} else {					cur->next = new;					cur = new;				}			}			if(new->cmd == NULL) {				new->cmd = strdup(buf);			} else {				len = strlen(new->cmd);				new->cmd = realloc(new->cmd, len + strlen(buf) + 1);				memcpy(new->cmd + len, buf, strlen(buf));				new->cmd[len + strlen(buf)] = 0;			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -