Fix build break for rpm
[framework/connectivity/bluez.git] / test / hstest.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <signal.h>
34 #include <termios.h>
35 #include <sys/wait.h>
36 #include <sys/time.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39
40 #include <bluetooth/bluetooth.h>
41 #include <bluetooth/hci.h>
42 #include <bluetooth/hci_lib.h>
43 #include <bluetooth/sco.h>
44 #include <bluetooth/rfcomm.h>
45
46 static volatile int terminate = 0;
47
48 static void sig_term(int sig) {
49         terminate = 1;
50 }
51
52 static int rfcomm_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t channel)
53 {
54         struct sockaddr_rc addr;
55         int s;
56
57         if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
58                 return -1;
59         }
60
61         memset(&addr, 0, sizeof(addr));
62         addr.rc_family = AF_BLUETOOTH;
63         bacpy(&addr.rc_bdaddr, src);
64         addr.rc_channel = 0;
65         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
66                 close(s);
67                 return -1;
68         }
69
70         memset(&addr, 0, sizeof(addr));
71         addr.rc_family = AF_BLUETOOTH;
72         bacpy(&addr.rc_bdaddr, dst);
73         addr.rc_channel = channel;
74         if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
75                 close(s);
76                 return -1;
77         }
78
79         return s;
80 }
81
82 static int sco_connect(bdaddr_t *src, bdaddr_t *dst, uint16_t *handle, uint16_t *mtu)
83 {
84         struct sockaddr_sco addr;
85         struct sco_conninfo conn;
86         struct sco_options opts;
87         socklen_t size;
88         int s;
89
90         if ((s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO)) < 0) {
91                 return -1;
92         }
93
94         memset(&addr, 0, sizeof(addr));
95         addr.sco_family = AF_BLUETOOTH;
96         bacpy(&addr.sco_bdaddr, src);
97
98         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
99                 close(s);
100                 return -1;
101         }
102
103         memset(&addr, 0, sizeof(addr));
104         addr.sco_family = AF_BLUETOOTH;
105         bacpy(&addr.sco_bdaddr, dst);
106
107         if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
108                 close(s);
109                 return -1;
110         }
111
112         memset(&conn, 0, sizeof(conn));
113         size = sizeof(conn);
114
115         if (getsockopt(s, SOL_SCO, SCO_CONNINFO, &conn, &size) < 0) {
116                 close(s);
117                 return -1;
118         }
119
120         memset(&opts, 0, sizeof(opts));
121         size = sizeof(opts);
122
123         if (getsockopt(s, SOL_SCO, SCO_OPTIONS, &opts, &size) < 0) {
124                 close(s);
125                 return -1;
126         }
127
128         if (handle)
129                 *handle = conn.hci_handle;
130
131         if (mtu)
132                 *mtu = opts.mtu;
133
134         return s;
135 }
136
137 static void usage(void)
138 {
139         printf("Usage:\n"
140                 "\thstest play   <file> <bdaddr> [channel]\n"
141                 "\thstest record <file> <bdaddr> [channel]\n");
142 }
143
144 #define PLAY    1
145 #define RECORD  2
146
147 int main(int argc, char *argv[])
148 {
149         struct sigaction sa;
150
151         fd_set rfds;
152         struct timeval timeout;
153         unsigned char buf[2048], *p;
154         int maxfd, sel, rlen, wlen;
155
156         bdaddr_t local;
157         bdaddr_t bdaddr;
158         uint8_t channel;
159
160         char *filename;
161         mode_t filemode;
162         int mode = 0;
163         int dd, rd, sd, fd;
164         uint16_t sco_handle, sco_mtu, vs;
165
166         switch (argc) {
167         case 4:
168                 str2ba(argv[3], &bdaddr);
169                 channel = 6;
170                 break;
171         case 5:
172                 str2ba(argv[3], &bdaddr);
173                 channel = atoi(argv[4]);
174                 break;
175         default:
176                 usage();
177                 exit(-1);
178         }
179
180         if (strncmp(argv[1], "play", 4) == 0) {
181                 mode = PLAY;
182                 filemode = O_RDONLY;
183         } else if (strncmp(argv[1], "rec", 3) == 0) {
184                 mode = RECORD;
185                 filemode = O_WRONLY | O_CREAT | O_TRUNC;
186         } else {
187                 usage();
188                 exit(-1);
189         }
190
191         filename = argv[2];
192
193         hci_devba(0, &local);
194         dd = hci_open_dev(0);
195         hci_read_voice_setting(dd, &vs, 1000);
196         vs = htobs(vs);
197         fprintf(stderr, "Voice setting: 0x%04x\n", vs);
198         close(dd);
199         if (vs != 0x0060) {
200                 fprintf(stderr, "The voice setting must be 0x0060\n");
201                 return -1;
202         }
203
204         if (strcmp(filename, "-") == 0) {
205                 switch (mode) {
206                 case PLAY:
207                         fd = 0;
208                         break;
209                 case RECORD:
210                         fd = 1;
211                         break;
212                 default:
213                         return -1;
214                 }
215         } else {
216                 if ((fd = open(filename, filemode)) < 0) {
217                         perror("Can't open input/output file");
218                         return -1;
219                 }
220         }
221
222         memset(&sa, 0, sizeof(sa));
223         sa.sa_flags = SA_NOCLDSTOP;
224         sa.sa_handler = sig_term;
225         sigaction(SIGTERM, &sa, NULL);
226         sigaction(SIGINT,  &sa, NULL);
227
228         sa.sa_handler = SIG_IGN;
229         sigaction(SIGCHLD, &sa, NULL);
230         sigaction(SIGPIPE, &sa, NULL);
231
232         if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {
233                 perror("Can't connect RFCOMM channel");
234                 return -1;
235         }
236
237         fprintf(stderr, "RFCOMM channel connected\n");
238
239         if ((sd = sco_connect(&local, &bdaddr, &sco_handle, &sco_mtu)) < 0) {
240                 perror("Can't connect SCO audio channel");
241                 close(rd);
242                 return -1;
243         }
244
245         fprintf(stderr, "SCO audio channel connected (handle %d, mtu %d)\n", sco_handle, sco_mtu);
246
247         if (mode == RECORD) {
248                 if (write(rd, "RING\r\n", 6) < 0)
249                         return -errno;
250         }
251
252         maxfd = (rd > sd) ? rd : sd;
253
254         while (!terminate) {
255
256                 FD_ZERO(&rfds);
257                 FD_SET(rd, &rfds);
258                 FD_SET(sd, &rfds);
259
260                 timeout.tv_sec = 0;
261                 timeout.tv_usec = 10000;
262
263                 if ((sel = select(maxfd + 1, &rfds, NULL, NULL, &timeout)) > 0) {
264
265                         if (FD_ISSET(rd, &rfds)) {
266                                 memset(buf, 0, sizeof(buf));
267                                 rlen = read(rd, buf, sizeof(buf));
268                                 if (rlen > 0) {
269                                         fprintf(stderr, "%s\n", buf);
270                                         wlen = write(rd, "OK\r\n", 4);
271                                 }
272                         }
273
274                         if (FD_ISSET(sd, &rfds)) {
275                                 memset(buf, 0, sizeof(buf));
276                                 rlen = read(sd, buf, sizeof(buf));
277                                 if (rlen > 0)
278                                         switch (mode) {
279                                         case PLAY:
280                                                 rlen = read(fd, buf, rlen);
281
282                                                 wlen = 0;
283                                                 p = buf;
284                                                 while (rlen > sco_mtu) {
285                                                         wlen += write(sd, p, sco_mtu);
286                                                         rlen -= sco_mtu;
287                                                         p += sco_mtu;
288                                                 }
289                                                 wlen += write(sd, p, rlen);
290                                                 break;
291                                         case RECORD:
292                                                 wlen = write(fd, buf, rlen);
293                                                 break;
294                                         default:
295                                                 break;
296                                         }
297                         }
298
299                 }
300
301         }
302
303         close(sd);
304         sleep(5);
305         close(rd);
306
307         close(fd);
308
309         return 0;
310 }