17490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann/* 27490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * 3b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann * BlueZ - Bluetooth protocol stack for Linux 47490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * 59184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org> 67490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * 77490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * 87490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * This program is free software; you can redistribute it and/or modify 9632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * it under the terms of the GNU General Public License as published by 10632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * the Free Software Foundation; either version 2 of the License, or 11632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * (at your option) any later version. 127490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * 13632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * This program is distributed in the hope that it will be useful, 14632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 15632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * GNU General Public License for more details. 177490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * 18632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * You should have received a copy of the GNU General Public License 19632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * along with this program; if not, write to the Free Software 20632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 217490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann * 227490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann */ 237490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 24b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann#ifdef HAVE_CONFIG_H 25b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann#include <config.h> 26b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann#endif 27b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann 287490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <stdio.h> 297490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <errno.h> 307490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <fcntl.h> 317490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <unistd.h> 327490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <stdlib.h> 337490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <signal.h> 347490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <termios.h> 357490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <sys/wait.h> 367490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <sys/time.h> 377490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <sys/ioctl.h> 387490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <sys/socket.h> 397490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 407490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <bluetooth/bluetooth.h> 417490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <bluetooth/hci.h> 427490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <bluetooth/hci_lib.h> 437490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <bluetooth/sco.h> 447490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#include <bluetooth/rfcomm.h> 457490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 467490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmannstatic volatile int terminate = 0; 477490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 487490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmannstatic void sig_term(int sig) { 497490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann terminate = 1; 507490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann} 517490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 527490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmannstatic int rfcomm_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t channel) 537490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann{ 547490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann struct sockaddr_rc addr; 557490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann int s; 567490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 577490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) { 587490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 597490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 607490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 617490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann memset(&addr, 0, sizeof(addr)); 627490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann addr.rc_family = AF_BLUETOOTH; 637490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann bacpy(&addr.rc_bdaddr, src); 647490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann addr.rc_channel = 0; 657490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 667490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(s); 677490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 687490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 697490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 707490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann memset(&addr, 0, sizeof(addr)); 717490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann addr.rc_family = AF_BLUETOOTH; 727490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann bacpy(&addr.rc_bdaddr, dst); 737490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann addr.rc_channel = channel; 747490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){ 757490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(s); 767490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 777490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 787490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 797490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return s; 807490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann} 817490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 827490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmannstatic int sco_connect(bdaddr_t *src, bdaddr_t *dst, uint16_t *handle, uint16_t *mtu) 837490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann{ 847490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann struct sockaddr_sco addr; 857490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann struct sco_conninfo conn; 867490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann struct sco_options opts; 871f422e5f2b343d35a8c77ce4be16f74b2819b2bfMarcel Holtmann socklen_t size; 881f422e5f2b343d35a8c77ce4be16f74b2819b2bfMarcel Holtmann int s; 897490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 907490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) { 917490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 927490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 937490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 947490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann memset(&addr, 0, sizeof(addr)); 957490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann addr.sco_family = AF_BLUETOOTH; 967490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann bacpy(&addr.sco_bdaddr, src); 97bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann 987490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 997490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(s); 1007490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 1017490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 1027490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1037490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann memset(&addr, 0, sizeof(addr)); 1047490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann addr.sco_family = AF_BLUETOOTH; 1057490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann bacpy(&addr.sco_bdaddr, dst); 106bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann 1077490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){ 1087490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(s); 1097490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 1107490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 1117490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 112bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann memset(&conn, 0, sizeof(conn)); 1137490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann size = sizeof(conn); 114bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann 1157490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (getsockopt(s, SOL_SCO, SCO_CONNINFO, &conn, &size) < 0) { 1167490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(s); 1177490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 1187490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 1197490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 120bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann memset(&opts, 0, sizeof(opts)); 1217490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann size = sizeof(opts); 122bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann 1237490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (getsockopt(s, SOL_SCO, SCO_OPTIONS, &opts, &size) < 0) { 1247490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(s); 1257490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 1267490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 1277490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1287490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (handle) 1297490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann *handle = conn.hci_handle; 1307490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1317490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (mtu) 1327490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann *mtu = opts.mtu; 1337490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1347490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return s; 1357490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann} 1367490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1377490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmannstatic void usage(void) 1387490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann{ 1397490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann printf("Usage:\n" 1407490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann "\thstest play <file> <bdaddr> [channel]\n" 1417490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann "\thstest record <file> <bdaddr> [channel]\n"); 1427490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann} 1437490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1447490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#define PLAY 1 1457490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann#define RECORD 2 1467490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1477490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmannint main(int argc, char *argv[]) 1487490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann{ 1497490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann struct sigaction sa; 1507490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1517490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann fd_set rfds; 1527490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann struct timeval timeout; 15367f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann unsigned char buf[2048], *p; 1547490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann int maxfd, sel, rlen, wlen; 1557490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1567490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann bdaddr_t local; 1577490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann bdaddr_t bdaddr; 1587490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann uint8_t channel; 1597490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1607490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann char *filename; 1617490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann mode_t filemode; 1622076574365b22a211b569a4dcc9a4df6f924f41cJohan Hedberg int mode = 0; 1637490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann int dd, rd, sd, fd; 1647490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann uint16_t sco_handle, sco_mtu, vs; 1657490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1667490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann switch (argc) { 1677490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann case 4: 1687490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann str2ba(argv[3], &bdaddr); 1697490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann channel = 6; 1707490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann break; 1717490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann case 5: 1727490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann str2ba(argv[3], &bdaddr); 1737490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann channel = atoi(argv[4]); 1747490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann break; 1757490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann default: 1767490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann usage(); 1777490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann exit(-1); 1787490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 1797490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1807490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (strncmp(argv[1], "play", 4) == 0) { 1817490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann mode = PLAY; 1827490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann filemode = O_RDONLY; 1837490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } else if (strncmp(argv[1], "rec", 3) == 0) { 1847490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann mode = RECORD; 1857490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann filemode = O_WRONLY | O_CREAT | O_TRUNC; 1867490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } else { 1877490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann usage(); 1887490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann exit(-1); 1897490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 1907490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1917490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann filename = argv[2]; 1927490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 1937490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann hci_devba(0, &local); 1947490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann dd = hci_open_dev(0); 1957490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann hci_read_voice_setting(dd, &vs, 1000); 196499f43343f20d5a562ee041d950086df01fb4868Marcel Holtmann vs = htobs(vs); 1977490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann fprintf(stderr, "Voice setting: 0x%04x\n", vs); 1987490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(dd); 199693d345b0cc02c961748aad2074a2ca64934c9f5Marcel Holtmann if (vs != 0x0060) { 200693d345b0cc02c961748aad2074a2ca64934c9f5Marcel Holtmann fprintf(stderr, "The voice setting must be 0x0060\n"); 2017490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 2027490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2037490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2047490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (strcmp(filename, "-") == 0) { 2057490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann switch (mode) { 2067490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann case PLAY: 2077490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann fd = 0; 2087490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann break; 2097490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann case RECORD: 2107490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann fd = 1; 2117490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann break; 2127490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann default: 2137490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 2147490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2157490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } else { 2167490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if ((fd = open(filename, filemode)) < 0) { 2177490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann perror("Can't open input/output file"); 2187490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 2197490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2207490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2217490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2227490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann memset(&sa, 0, sizeof(sa)); 2237490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sa.sa_flags = SA_NOCLDSTOP; 2247490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sa.sa_handler = sig_term; 2257490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sigaction(SIGTERM, &sa, NULL); 2267490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sigaction(SIGINT, &sa, NULL); 2277490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2287490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sa.sa_handler = SIG_IGN; 2297490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sigaction(SIGCHLD, &sa, NULL); 2307490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sigaction(SIGPIPE, &sa, NULL); 2317490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2327490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) { 2337490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann perror("Can't connect RFCOMM channel"); 2347490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 2357490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2367490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2377490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann fprintf(stderr, "RFCOMM channel connected\n"); 2387490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2397490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) { 2407490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann perror("Can't connect SCO audio channel"); 2417490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(rd); 2427490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return -1; 2437490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2447490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2457490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann fprintf(stderr, "SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu); 2467490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2472076574365b22a211b569a4dcc9a4df6f924f41cJohan Hedberg if (mode == RECORD) { 2482076574365b22a211b569a4dcc9a4df6f924f41cJohan Hedberg if (write(rd, "RING\r\n", 6) < 0) 2492076574365b22a211b569a4dcc9a4df6f924f41cJohan Hedberg return -errno; 2502076574365b22a211b569a4dcc9a4df6f924f41cJohan Hedberg } 2517490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2527490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann maxfd = (rd > sd) ? rd : sd; 2537490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2547490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann while (!terminate) { 2557490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2567490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann FD_ZERO(&rfds); 2577490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann FD_SET(rd, &rfds); 2587490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann FD_SET(sd, &rfds); 2597490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2607490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann timeout.tv_sec = 0; 2617490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann timeout.tv_usec = 10000; 2627490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2637490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if ((sel = select(maxfd + 1, &rfds, NULL, NULL, &timeout)) > 0) { 2647490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2657490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (FD_ISSET(rd, &rfds)) { 2667490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann memset(buf, 0, sizeof(buf)); 2677490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann rlen = read(rd, buf, sizeof(buf)); 2687490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (rlen > 0) { 2697490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann fprintf(stderr, "%s\n", buf); 2707490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann wlen = write(rd, "OK\r\n", 4); 2717490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2727490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2737490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2747490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (FD_ISSET(sd, &rfds)) { 2757490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann memset(buf, 0, sizeof(buf)); 2767490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann rlen = read(sd, buf, sizeof(buf)); 2777490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann if (rlen > 0) 2787490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann switch (mode) { 2797490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann case PLAY: 2807490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann rlen = read(fd, buf, rlen); 28167f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann 2826968c52091ad2f85038e5b2903b61cc78f3d29c9José Antonio Santos Cadenas wlen = 0; 28367f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann p = buf; 28467f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann while (rlen > sco_mtu) { 28567f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann wlen += write(sd, p, sco_mtu); 28667f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann rlen -= sco_mtu; 28767f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann p += sco_mtu; 28867f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann } 28967f9a013ade0649d032b9b25e694567a089237d1Marcel Holtmann wlen += write(sd, p, rlen); 2907490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann break; 2917490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann case RECORD: 2927490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann wlen = write(fd, buf, rlen); 2937490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann break; 2947490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann default: 2957490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann break; 2967490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2977490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 2987490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 2997490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 3007490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 3017490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann } 3027490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 3037490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(sd); 3047490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann sleep(5); 3057490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(rd); 3067490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 3077490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann close(fd); 3087490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann 3097490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann return 0; 3107490b6c61bfa0b581ff7a15f6482787973cf7e3fMarcel Holtmann} 311