1 /*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2008-2009 Texas Instruments, Inc.
6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7 * Copyright (C) 2002-2008 Marcel Holtmann <marcel@holtmann.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #include <errno.h>
32 #include <ctype.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <getopt.h>
36 #include <syslog.h>
37 #include <signal.h>
38 #include <sys/time.h>
39 #include <sys/socket.h>
40
41 #include <bluetooth/bluetooth.h>
42 #include <bluetooth/hci.h>
43 #include <bluetooth/hci_lib.h>
44 #include <bluetooth/sco.h>
45
46 /* Static Local variables */
47
48 /* BD Address of the BT head set */
49 static bdaddr_t bdaddr;
50
51 /* Buffer to receive data feom headset */
52 static unsigned char *buffer;
53
54 /* Default data size */
55 static long data_size = 672;
56
57 /* Handling termination of process through signals */
58 static volatile int terminate = 0;
59
60 /* Static functions declerations */
61 static void send_hciCmd(int dev_id, int command_length, char **command);
62
63
64 /** Function to handle signal terminations */
sig_term(int sig)65 static void sig_term(int sig) {
66 terminate = 1;
67 }
68
69 /** do_connect Function
70 * This function Creates the SCO connection to the BT headset
71 *
72 * Parameters :
73 * @ svr : BD address of headset
74 * Returns SCO socket id on success
75 * suitable error code
76 */
do_connect(char * svr)77 static int do_connect(char *svr)
78 {
79 struct sockaddr_sco addr;
80 struct sco_conninfo conn;
81 socklen_t optlen;
82 int sk;
83
84 /* Create socket */
85 sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
86 if (sk < 0) {
87 syslog(LOG_ERR, "Can't create socket: %s (%d)",
88 strerror(errno), errno);
89 return -1;
90 }
91
92 /* Bind to local address */
93 memset(&addr, 0, sizeof(addr));
94 addr.sco_family = AF_BLUETOOTH;
95 bacpy(&addr.sco_bdaddr, &bdaddr);
96
97 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
98 syslog(LOG_ERR, "Can't bind socket: %s (%d)",
99 strerror(errno), errno);
100 goto error;
101 }
102
103 /* Connect to remote device */
104 memset(&addr, 0, sizeof(addr));
105 addr.sco_family = AF_BLUETOOTH;
106 str2ba(svr, &addr.sco_bdaddr);
107
108 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
109 syslog(LOG_ERR, "Can't connect: %s (%d)",
110 strerror(errno), errno);
111 goto error;
112 }
113
114 /* Get connection information */
115 memset(&conn, 0, sizeof(conn));
116 optlen = sizeof(conn);
117
118 if (getsockopt(sk, SOL_SCO, SCO_CONNINFO, &conn, &optlen) < 0) {
119 syslog(LOG_ERR, "Can't get SCO connection information: %s (%d)",
120 strerror(errno), errno);
121 goto error;
122 }
123
124 syslog(LOG_INFO, "Connected [handle %d, class 0x%02x%02x%02x]",
125 conn.hci_handle,
126 conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]);
127
128 return sk;
129
130 error:
131 close(sk);
132 return -1;
133 }
134
135 /** dump_mode Function
136 * This function waits till disconnection is intiated from headset or from
137 * the application.
138 *
139 * Parameters :
140 * @ sk : SCO socket id
141 * Returns VOID
142 */
dump_mode(int sk)143 static void dump_mode(int sk)
144 {
145 int len;
146
147 /* Wait till disconnect is issued from the headset OR
148 * IF the application is killed using signals
149 */
150 while ( ((len = read(sk, buffer, data_size)) > 0) && (!terminate) )
151 syslog(LOG_INFO, "Recevied %d bytes", len);
152 }
153
154 /** send_hciCmd Function
155 * This function takes the hci commands for the BT chip configurations, creates
156 * a hci channel to send the commadns through UART to configure BT chip
157 *
158 * Parameters :
159 * @ dev_id : HCI device ID
160 * @ command_length : Number of arguments of the command
161 * @ command : Pointer to command list
162 * Returns 0 upon success
163 * , different error messages depending upon the error.
164 */
send_hciCmd(int dev_id,int command_length,char ** command)165 static void send_hciCmd(int dev_id, int command_length, char **command)
166 {
167 unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr = buf;
168 struct hci_filter flt;
169 hci_event_hdr *hdr;
170 int i, opt, len, dd;
171 uint16_t ocf;
172 uint8_t ogf;
173
174 if (dev_id < 0)
175 dev_id = hci_get_route(NULL);
176
177 errno = 0;
178 ogf = strtol(command[0], NULL, 16);
179 ocf = strtol(command[1], NULL, 16);
180
181 for (i = 2, len = 0; i < command_length && len < sizeof(buf); i++, len++)
182 *ptr++ = (uint8_t) strtol(command[i], NULL, 16);
183
184 dd = hci_open_dev(dev_id);
185 if (dd < 0) {
186 perror("Device open failed");
187 return;
188 }
189
190 /* Setup filter */
191 hci_filter_clear(&flt);
192 hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
193 hci_filter_all_events(&flt);
194 if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
195 perror("HCI filter setup failed");
196 return;
197 }
198
199 /* Send the BT chip configuration commands */
200 if (hci_send_cmd(dd, ogf, ocf, len, buf) < 0) {
201 perror("Send failed");
202 return;
203 }
204
205 /* Wait for the command completion event */
206 len = read(dd, buf, sizeof(buf));
207 if (len < 0) {
208 perror("Read failed");
209 return;
210 }
211
212 hdr = (void *)(buf + 1);
213 ptr = buf + (1 + HCI_EVENT_HDR_SIZE);
214 len -= (1 + HCI_EVENT_HDR_SIZE);
215
216 hci_close_dev(dd);
217 }
218
219 /** USAGE Function
220 * This function displays the usage of the bt_sco_app application.
221 *
222 * Parameters :
223 * @ VOID
224 * Returns VOID
225 */
usage(void)226 static void usage(void)
227 {
228 printf("bt_scoapp\n"
229 "Usage:\n");
230 printf("\tbt_scoapp [bd_addr]\n");
231 }
232
233 /** Main Function
234 * The main function takes the command line BD adress of headset as inputs ,
235 * Calls the hci send configuration function and then creates a SCO connection.
236 *
237 * Parameters :
238 * @ argc : Number of arguments on the command line
239 * @ argv : Pointer to argument list - BD addr is the only valid argument.
240 * Returns 0 upon success
241 * , different error messages depending upon the error.
242 */
main(int argc,char * argv[])243 int main(int argc ,char *argv[])
244 {
245 struct sigaction sa;
246 int opt, i = 0, sk;
247
248 /* BT PCM configurations commands */
249 char *command[] = { "0x3f", "0x106", /* OCF and OGF */
250 "0x80", "0x00", /* Bit clock - 128KHz*/
251 "0x00", /* BT chip as Master*/
252 "0x40", "0x1f", "0x00", "0x00", /* Sampling rate - 8KHz*/
253 "0x01", "0x00", /* 50% Duty cycle*/
254 "0x00", /* Frame sync at falling edge*/
255 "0x00", /* FS Active high polarity*/
256 "0x00", /* FS direction - [Reserved]*/
257 "0x10", "0x00", /* CH1 16 -bit OUT size*/
258 "0x01", "0x00", /* One Clock delay */
259 "0x00", /* Data driven at rising edge*/
260 "0x10", "0x00", /* CH1 16 -bit IN size */
261 "0x01", "0x00", /* CH1 DAta IN One Clock delay*/
262 "0x00", /* Data driven at sampling edge*/
263 "0x00", /* Reserved bit*/
264 "0x10", "0x00", /* CH2 16 -bit OUT size*/
265 "0x11", "0x00", /* CH2 data OUT off set*/
266 "0x00", /* Data driven at rising edge*/
267 "0x10", "0x00", /* CH2 16 -bit IN size*/
268 "0x11", "0x00", /* CH2 data IN off set*/
269 "0x00", /* Data Sampled at rising edge*/
270 "0x00" /* Reserved bit*/
271 };
272 int command_length = 36; /* Length of the BT configuration commands */
273
274 /* Check if the number of arguemts mentioned is 2 */
275 if (argc != 2)
276 {
277 printf("\n Wrong input - No BD headset address specified");
278 usage();
279 exit(1);
280 }
281
282 memset(&sa, 0, sizeof(sa));
283 sa.sa_flags = SA_NOCLDSTOP;
284 sa.sa_handler = sig_term;
285 sigaction(SIGTERM, &sa, NULL);
286 sigaction(SIGINT, &sa, NULL);
287 sigaction(SIGCHLD, &sa, NULL);
288 sigaction(SIGPIPE, &sa, NULL);
289
290 openlog("bt_sco_app", LOG_PERROR | LOG_PID, LOG_LOCAL0);
291
292 /* Allocate memory for the buffer */
293 if (!(buffer = malloc(data_size))) {
294 perror("Can't allocate data buffer");
295 exit(1);
296 }
297 /* send the BT configuration commands */
298 send_hciCmd(-1,command_length,command);
299
300 sleep(2); /* wait for some time while BT chip is configured */
301
302 sk = do_connect(argv[1]);
303 if (sk < 0)
304 exit(1);
305 dump_mode(sk);
306
307 syslog(LOG_INFO, "Exit");
308
309 closelog();
310
311 return 0;
312 }
313