• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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