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

📄 btsco.c

📁 蓝牙blue tooth sco协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
			break;		}	}	fclose(cf);	return(ret);}int main(int argc, char *argv[]){	int dev;	int card;	int ret;	int fork, clear;	struct sigaction sa;	//struct timeval timeout;	unsigned char buf[2048];	//int sel, rlen, wlen;	int rlen, wlen;	bdaddr_t local;	bdaddr_t bdaddr;	uint8_t channel;	//char *filename;	//mode_t filemode;	//int mode = 0;	int dd;	int rd;			// rfcomm handle	int sd;			//sco handle	uint16_t sco_handle, sco_mtu, vs;	char line[100];	int last_volumes[2];	int dr_usage, force_sco;	// sco_mode is our running mode. 0 => not connect, 1 => connected	// see NOT_CONNECTED,CONNECTED :)	int sco_mode;	struct pollfd pfds[10];	int nfds;	int i, err;	snd_hwdep_t *handle;	char hwdep_name[16];	snd_card_bt_sco_info_t infobuf;	struct action *actions;	fork = 0;	clear = 0;	while((i = getopt(argc, argv, "fcvh")) >= 0) {		switch(i) {		case 'v':			verbose++;			break;		case 'f':			fork = 1;			break;		case 'c':			clear = 1;			break;		case 'h':		case '?':		case ':':		default:			usage();			exit((i == 'h')?0:1);		}	}	if(verbose)		printf("btsco v0.4\n");		actions = read_actions();		/* detect the audio device */	if (find_hwdep_device(&card, &dev)) {		error("Can't find device. Bail");		return 1;	}	if(verbose)		printf("Device is %d:%d\n", card, dev);	sprintf(hwdep_name, "hw:%i,%i", card, dev);	/* open hwdep on audio device */	if ((err = snd_hwdep_open(&handle, hwdep_name, O_RDWR)) < 0) {		error("btsco open (%i-%i): %s\n", card, dev, snd_strerror(err));		return -1;	}	if (clear) {		if(verbose)			printf("Clearing fd\n");		bt_sco_set_fd(handle, 1);		return 1;	}	/* find bdaddr */	switch (argc - optind) {	case 1:		str2ba(argv[optind], &bdaddr);		channel = detect_channel(&bdaddr);		break;	case 2:		str2ba(argv[optind], &bdaddr);		channel = atoi(argv[optind + 1]);		break;	default:		usage();		exit(-1);	}	/* check voice settings. in this version we only support mu-law */	hci_devba(0, &local);	dd = hci_open_dev(0);	hci_read_voice_setting(dd, &vs, 1000);	vs = htobs(vs);	if(verbose)		printf("Voice setting: 0x%04x\n", vs);	close(dd);	/*	   MU_LAW	   if (vs != 0x0140) {	   fprintf(stderr, "The voice setting must be 0x0140\n");	   return -1;	   }	 */	// 16bit	if (vs != 0x060) {		error("The voice setting must be 0x060\n");		return -1;	}	/* setup sigterm handler. we must make sure to do a clean disconnect */	memset(&sa, 0, sizeof(sa));	sa.sa_flags = SA_NOCLDSTOP;	sa.sa_handler = sig_term;	sigaction(SIGTERM, &sa, NULL);	sigaction(SIGINT, &sa, NULL);		sa.sa_handler = sig_ring;	sigaction(SIGUSR1, &sa, NULL);	sa.sa_handler = sig_hup;	sigaction(SIGHUP, &sa, NULL);	sa.sa_handler = SIG_IGN;	sigaction(SIGCHLD, &sa, NULL);	sigaction(SIGPIPE, &sa, NULL);	/* connect rfcomm control channel */	if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {		perror("Can't connect RFCOMM channel");		return -1;	}	if(verbose)		printf("RFCOMM channel %i connected\n", channel);	i = 0;	/* set up data polling description */	nfds = 0;	/* polling data from rfcomm */	pfds[nfds].fd = rd;	pfds[nfds++].events = POLLIN;	// polling data from command line - unused now//      pfds[nfds].fd = 0;//      pfds[nfds++].events = POLLIN;	/* polling data from hwdep interface */	nfds += snd_hwdep_poll_descriptors(handle, &pfds[nfds], 1);	last_volumes[0] = last_volumes[1] = 0;	snd_hwdep_ioctl(handle, SNDRV_BT_SCO_IOCTL_REQ_INFO, NULL);	if(snd_hwdep_read(handle, &infobuf, sizeof(infobuf)) < 0) {		perror("read info");		exit(1);	}	dr_usage = infobuf.playback_count || infobuf.capture_count;	force_sco = -1;		if (fork)		daemon(0, 0);		/* we are not yet connected */	sco_mode = NOT_CONNECTED;	sd = -1;	while (!terminate) {		/*printf("outer loop\n"); */				ret = poll(pfds, nfds, -1);		if ((ret < 0) && (errno != EINTR)) {			perror("poll");			sleep(1); /* Don't steal the CPU in case of non-transient errors. */		} else if (ret > 0) {			short revents;			/*printf("inner loop\n"); */			/* Volume polling (sound card) */			if (!snd_hwdep_poll_descriptors_revents			    (handle, &pfds[nfds - 1], 1, &revents)) {				if (revents & POLLIN) {					int len;										len = snd_hwdep_read(handle, &infobuf, sizeof(infobuf));					if (len == sizeof(infobuf)) {						if(verbose)							printf ("speaker volume: %d mic volume: %d\n",								infobuf.mixer_volume[0], infobuf.mixer_volume[1]);						if (infobuf.mixer_volume[0] != last_volumes[0]) {							sprintf(line, "AT+VGS=%d\r",								infobuf.mixer_volume[0]);							write(rd, line, strlen(line));						}						if (infobuf.mixer_volume[1] != last_volumes[1]) {							sprintf(line, "AT+VGM=%d\r",								infobuf.mixer_volume[1]);							write(rd, line, strlen(line));						}						memcpy(last_volumes, infobuf.mixer_volume,						       sizeof(infobuf.mixer_volume));						dr_usage = infobuf.playback_count || infobuf.capture_count;					}				}			}						if ((pfds[0].revents & POLLHUP) || (pfds[0].revents & POLLERR)) {			    /* RFCOMM channel lost.			     * For now, exit. */			    if(verbose)				printf("RFCOMM channel lost\n");			    terminate = 1;			}						// control transmission events for volume and channel control			if (pfds[0].revents & POLLIN) {				memset(buf, 0, sizeof(buf));				rlen = read(rd, buf, sizeof(buf) - 1);				if (rlen > 0) {					struct action *cur;										if(verbose)						printf("recieved %s\n", buf);					/* tell them we recieved */					wlen = write(rd, "\r\nOK\r\n", 6);					for(cur = actions; cur != NULL; cur = cur->next) {						regmatch_t matches[10];						char *cmdbuf, *args;						int match;												if(regexec(&cur->regex, buf, 10, matches, 0))							continue;						cmdbuf = strdup(cur->cmd);						if((args = strchr(cmdbuf, ' ')) != NULL)							*(args++) = 0;						if(!strcmp(cmdbuf, "system")) {							char *subst;							char *sysbuf;							int substl = 0;														subst = NULL;							sysbuf = strdup(args);							for(i = 0; sysbuf[i]; i++) {								if((sysbuf[i] == '\\') && (sysbuf[i + 1] >= '0') && (sysbuf[i + 1] <= '9')) {									match = sysbuf[i + 1] - '0';									if(matches[match].rm_so == -1)										continue;									substl = matches[match].rm_eo - matches[match].rm_so;									subst = memcpy(malloc(substl), buf + matches[match].rm_so, substl);								}								if((sysbuf[i] == '\\') && (sysbuf[i + 1] == 'p')) {									subst = malloc(11); /* For potentially 32-bit PIDs */									substl = snprintf(subst, 11, "%i", getpid());								}								if(subst != NULL) {									sysbuf = realloc(sysbuf, strlen(sysbuf) + substl - 1);									memmove(sysbuf + i + substl, sysbuf + i + 2, strlen(sysbuf) - i - 1);									memmove(sysbuf + i, subst, substl);									free(subst);									subst = NULL;									i += substl - 1;								}							}							if(verbose)								printf("running %s\n", sysbuf);							system(sysbuf);							free(sysbuf);						} else if(!strcmp(cmdbuf, "sco-toggle")) {							int target;							char *p;														target = 1;							p = NULL;							if(args != NULL) {								if((p = strchr(args, ' ')) != NULL)									*(p++) = 0;								if(!strcmp(args, "on"))									target = 1;								else if(!strcmp(args, "off"))									target = 0;								else if(!strcmp(args, "none"))									target = -1;							}							if(force_sco == target) {								force_sco = -1;								if(p != NULL) {									if(!strcmp(p, "on"))										force_sco = 1;									else if(!strcmp(p, "off"))										force_sco = 0;									else if(!strcmp(p, "none"))										force_sco = -1;								}							} else {								force_sco = target;							}						} else if(!strcmp(cmdbuf, "sco-force")) {							if(args != NULL) {								if(!strcmp(args, "on"))									force_sco = 1;								else if(!strcmp(args, "off"))									force_sco = 0;								else if(!strcmp(args, "none"))									force_sco = -1;							}						}						free(cmdbuf);					}										if (sscanf					    (buf, "AT+VGS=%d",					     &infobuf.mixer_volume[0]) == 1) {						if(verbose)							printf("Sending up speaker change %d\n", infobuf.mixer_volume[0]);						snd_hwdep_write(handle,								infobuf.mixer_volume,								sizeof								(infobuf.mixer_volume));					}					if (sscanf					    (buf, "AT+VGM=%d",					     &infobuf.mixer_volume[1]) == 1) {						if(verbose)							printf("Sending up microphone change %d\n", infobuf.mixer_volume[1]);						snd_hwdep_write(handle,								infobuf.mixer_volume,								sizeof								(infobuf.mixer_volume));					}				}			}		}		if(((dr_usage && (force_sco != 0)) || (force_sco == 1)) && (sco_mode == NOT_CONNECTED)) {			if(verbose)				printf("driver is in use\n");			/* connect sco stream */			if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) {				perror ("Can't connect SCO audio channel\n");			} else {				if(verbose)					printf("connected SCO channel\n");				bt_sco_set_fd (handle, sd);								if(verbose)					printf ("Done setting sco fd\n");				sco_mode = CONNECTED;			}					}		if(((!dr_usage && (force_sco != 1)) || (force_sco == 0)) && (sco_mode == CONNECTED)) {			if(verbose)				printf("driver is not in use\n");			/* close bt_sco audio handle */			bt_sco_set_fd(handle, -1);			/* disconnect SCO stream */			close(sd);			if(verbose)				printf("disconnected SCO channel\n");						sco_mode = NOT_CONNECTED;					}				if (ring) {			write(rd, "\r\nRING\r\n", 8);			ring = 0;		}				if (hupped) {			free_actions(actions);			actions = read_actions();			hupped = 0;		}	}	if (sco_mode == CONNECTED) {		close(sd);		bt_sco_set_fd(handle, -1);	}	sleep(1);	close(rd);	snd_hwdep_close(handle);	return 0;}

⌨️ 快捷键说明

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