brcm_patchram_plus.c revision fd8ee4744176894d5a8ee28645fa342b859f4893
1fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte/*******************************************************************************
2ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly *
3fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  Copyright (C) 2009-2011 Broadcom Corporation
4ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly *
5fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  Licensed under the Apache License, Version 2.0 (the "License");
6fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  you may not use this file except in compliance with the License.
7fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  You may obtain a copy of the License at
8fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *
9fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *      http://www.apache.org/licenses/LICENSE-2.0
10fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *
11fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  Unless required by applicable law or agreed to in writing, software
12fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  distributed under the License is distributed on an "AS IS" BASIS,
13fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  See the License for the specific language governing permissions and
15fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *  limitations under the License.
16fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte *
17fd8ee4744176894d5a8ee28645fa342b859f4893Howard M. Harte ******************************************************************************/
18ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
19ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly/*****************************************************************************
20ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
21ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**  Name:          brcm_patchram_plus.c
22ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
23ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**  Description:   This program downloads a patchram files in the HCD format
24ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 to Broadcom Bluetooth based silicon and combo chips and
25ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**				   and other utility functions.
26ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
27ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 It can be invoked from the command line in the form
28ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<-d> to print a debug log
29ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--patchram patchram_file>
30ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--baudrate baud_rate>
31ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--bd_addr bd_address>
32ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--enable_lpm>
33ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--enable_hci>
341725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries**                                              <--pcm_role master|slave>
35fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh**						<--use_baudrate_for_download>
36ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						uart_device_name
37ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
38ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 For example:
39ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
40ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 brcm_patchram_plus -d --patchram  \
41ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						BCM2045B2_002.002.011.0348.0349.hcd /dev/ttyHS0
42ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
43ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 It will return 0 for success and a number greater than 0
44ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 for any errors.
45ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
46ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 For Android, this program invoked using a
47ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 "system(2)" call from the beginning of the bt_enable
48ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 function inside the file
49db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly**                 system/bluetooth/bluedroid/bluetooth.c.
50ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
51db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly**                 If the Android system property "ro.bt.bcm_bdaddr_path" is
52db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly**                 set, then the bd_addr will be read from this path.
53db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly**                 This is overridden by --bd_addr on the command line.
54ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
55ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly******************************************************************************/
56ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
57ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly// TODO: Integrate BCM support into Bluez hciattach
58ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
59ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <stdio.h>
60ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <getopt.h>
61ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <errno.h>
62ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
63ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/types.h>
64ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/stat.h>
65ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <fcntl.h>
66ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
67ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <stdlib.h>
68ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
69ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifdef ANDROID
70ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <termios.h>
71ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#else
72ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/termios.h>
73ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
74ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
75ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <string.h>
76ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <signal.h>
77ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
78db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly#include <cutils/properties.h>
79db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly
801725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#ifdef ANDROID
811725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#define LOG_TAG "brcm_patchram_plus"
821725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#include <cutils/log.h>
831725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#undef printf
841725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#define printf LOGD
851725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#undef fprintf
861725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#define fprintf(x, ...) \
871725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries  { if(x==stderr) LOGE(__VA_ARGS__); else fprintf(x, __VA_ARGS__); }
881725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries
891725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries#endif //ANDROID
901725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries
91ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef N_HCI
92ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define N_HCI	15
93ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
94ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
95ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTSETPROTO		_IOW('U', 200, int)
96ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTGETPROTO		_IOR('U', 201, int)
97ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTGETDEVICE	_IOR('U', 202, int)
98ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
99ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_H4		0
100ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_BCSP	1
101ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_3WIRE	2
102ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_H4DS	3
103ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_LL		4
104ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
105ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
106ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint uart_fd = -1;
107ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint hcdfile_fd = -1;
108ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint termios_baudrate = 0;
109ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint bdaddr_flag = 0;
110ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint enable_lpm = 0;
111ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint enable_hci = 0;
1121725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesint pcm_slave = 0;
1131725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesint pcm_master = 0;
114fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganeshint use_baudrate_for_download = 0;
115ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint debug = 0;
116ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
117ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellystruct termios termios;
118ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char buffer[1024];
119ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
120ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
121ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
122ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_download_minidriver[] = { 0x01, 0x2e, 0xfc, 0x00 };
123ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
124ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00,
125ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	0x00, 0x00, 0x00, 0x00 };
126ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
127ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_write_bd_addr[] = { 0x01, 0x01, 0xfc, 0x06,
128db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
129ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
130ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc, 0x0c,
131d4397861e745c5b6ae99fe547b841df9babf3085Nick Pelly	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
132ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	0x00, 0x00 };
133ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
1341725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// HCI_COMMAND_PKT = 0x01
1351725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// unpacked ogf/ocf: 0x3F 0x1C
1361725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// ... ((ocf & 0x03ff)|(ogf << 10)) => 0xFC1C (0x1C 0xFC)
1371725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// packet data len: 0x5
1381725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// Data for the Write_SCO_PCM_Int_Param Message:
1391725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// 00 (Use PCM)
1401725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// 0x (02== 512 KHz bit clock, 03==1024 KHz bit clock, 04==2048 KHz)
1411725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// 01 (Long FS)
1421725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// 00 (Slave frame sync)
1431725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries// 00 (Slave bit clock)
1441725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesunsigned char hci_write_pcm_slave_mode[] =
1451725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	{ 0x01, 0x1C, 0xFC, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00 };
1461725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesunsigned char hci_write_pcm_master_mode[] =
1471725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	{ 0x01, 0x1C, 0xFC, 0x05, 0x00, 0x02, 0x00, 0x01, 0x01 };
1481725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries
149ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
150ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_patchram(char *optarg)
151ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
152ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	char *p;
153ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
154ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (!(p = strrchr(optarg, '.'))) {
155ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "file %s not an HCD file\n", optarg);
156ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(3);
157ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
158ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
159ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	p++;
160ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
161ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (strcasecmp("hcd", p) != 0) {
162ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "file %s not an HCD file\n", optarg);
163ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(4);
164ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
165ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
166ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if ((hcdfile_fd = open(optarg, O_RDONLY)) == -1) {
167ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "file %s could not be opened, error %d\n", optarg, errno);
168ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(5);
169ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
170ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
171ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
172ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
173ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
174ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
175ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick PellyBRCM_encode_baud_rate(uint baud_rate, unsigned char *encoded_baud)
176ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
177ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if(baud_rate == 0 || encoded_baud == NULL) {
178ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Baudrate not supported!");
179ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		return;
180ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
181ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
182ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[3] = (unsigned char)(baud_rate >> 24);
183ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[2] = (unsigned char)(baud_rate >> 16);
184ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[1] = (unsigned char)(baud_rate >> 8);
185ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[0] = (unsigned char)(baud_rate & 0xFF);
186ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
187ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
188ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellytypedef struct {
189ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int baud_rate;
190ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int termios_value;
191ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} tBaudRates;
192ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
193ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick PellytBaudRates baud_rates[] = {
194ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 115200, B115200 },
195ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 230400, B230400 },
196ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 460800, B460800 },
197ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 500000, B500000 },
198ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 576000, B576000 },
199ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 921600, B921600 },
200ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 1000000, B1000000 },
201ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 1152000, B1152000 },
202ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 1500000, B1500000 },
203ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 2000000, B2000000 },
204ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 2500000, B2500000 },
205ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 3000000, B3000000 },
206ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef __CYGWIN__
207ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 3500000, B3500000 },
208ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 4000000, B4000000 }
209ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
210ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly};
211ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
212ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
213ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvalidate_baudrate(int baud_rate, int *value)
214ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
215ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	unsigned int i;
216ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
217ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	for (i = 0; i < (sizeof(baud_rates) / sizeof(tBaudRates)); i++) {
218ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		if (baud_rates[i].baud_rate == baud_rate) {
219ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			*value = baud_rates[i].termios_value;
220ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			return(1);
221ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
222ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
223ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
224ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
225ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
226ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
227ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
228ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_baudrate(char *optarg)
229ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
230ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int baudrate = atoi(optarg);
231ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
232ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (validate_baudrate(baudrate, &termios_baudrate)) {
233ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		BRCM_encode_baud_rate(baudrate, &hci_update_baud_rate[6]);
234ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
235ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
236ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
237ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
238ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
239ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
240ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_bdaddr(char *optarg)
241ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
242ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int bd_addr[6];
243ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i;
244ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
245db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X",
246db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		&bd_addr[5], &bd_addr[4], &bd_addr[3],
247db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		&bd_addr[2], &bd_addr[1], &bd_addr[0]);
248ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
249ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	for (i = 0; i < 6; i++) {
250ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		hci_write_bd_addr[4 + i] = bd_addr[i];
251ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
252ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
253ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	bdaddr_flag = 1;
254ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
255ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
256ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
257ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
258ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
259ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_enable_lpm(char *optarg)
260ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
261ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	enable_lpm = 1;
262ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
263ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
264ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
265ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
266fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganeshparse_use_baudrate_for_download(char *optarg)
267fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh{
268fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh	use_baudrate_for_download = 1;
269fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh	return(0);
270fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh}
271fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh
272fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganeshint
273ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_enable_hci(char *optarg)
274ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
275ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	enable_hci = 1;
276ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
277ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
278ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
279ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
2801725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesparse_pcm_role(char *optarg) {
2811725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	if(!strcmp(optarg, "master")) {
2821725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		pcm_master = 1;
2831725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	} else if (!strcmp(optarg, "slave")) {
2841725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		pcm_slave = 1;
2851725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	} else {
2861725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		printf("Unknown PCM Role received: %s\n", optarg);
2871725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	}
2881725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	if (pcm_master && pcm_slave) {
2891725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		fprintf(stderr, "Illegal command line- pcm role master && slave\n");
2901725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		exit(6);
2911725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	}
2921725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	return(0);
2931725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries}
2941725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries
2951725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesint
296ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_cmd_line(int argc, char **argv)
297ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
298ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int c;
299ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int digit_optind = 0;
300ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
301ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	typedef int (*PFI)();
302ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
303ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	PFI parse_param[] = { parse_patchram, parse_baudrate,
3041725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		parse_bdaddr, parse_enable_lpm, parse_enable_hci,
305fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		parse_pcm_role, parse_use_baudrate_for_download};
306ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
307d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh   	while (1)
308d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh    	{
309d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		int this_option_optind = optind ? optind : 1;
310d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		int option_index = 0;
311d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh
312d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		static struct option long_options[] = {
313d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{"patchram", 1, 0, 0},
314d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{"baudrate", 1, 0, 0},
315d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{"bd_addr", 1, 0, 0},
316d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{"enable_lpm", 0, 0, 0},
317d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{"enable_hci", 0, 0, 0},
318d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{"pcm_role", 1, 0, 0},
319d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{"use_baudrate_for_download", 0, 0, 0},
320d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			{0, 0, 0, 0}
321d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		};
322d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh
323d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		c = getopt_long_only (argc, argv, "d", long_options,
324d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				&option_index);
325d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh
326d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		if (c == -1) {
327d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			break;
328ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
329ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
330d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		switch (c) {
331d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			case 0:
332d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				if (debug) {
333d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh					printf ("option %s",
334d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh						long_options[option_index].name);
335d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh					if (optarg)
336d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh						printf (" with arg %s", optarg);
337d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh					printf ("\n");
338d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				}
339d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				(*parse_param[option_index])(optarg);
340d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				break;
341d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			case 'd':
342d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				debug = 1;
343d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				break;
344d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh
345d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			case '?':
346d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				//nobreak
347d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			default:
348d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("Usage %s:\n", argv[0]);
349d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<-d> to print a debug log\n");
350d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<--patchram patchram_file>\n");
351d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<--baudrate baud_rate>\n");
352d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<--bd_addr bd_address>\n");
353d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<--enable_lpm>\n");
354d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<--enable_hci>\n");
355d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<--pcm_role slave|master>\n");
356d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\t<--use_baudrate_for_download> - Uses the\
357d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh						baudrate for downloading the\
358d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh						firmware\n");
359d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				printf("\tuart_device_name\n");
360d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh				break;
361d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		}
362ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
363d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	if (optind < argc) {
364d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		if (debug)
365d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			printf ("%s \n", argv[optind]);
366d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		if ((uart_fd = open(argv[optind], O_RDWR | O_NOCTTY)) == -1) {
367d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh			fprintf(stderr, "port %s could not be opened, error %d\n",
368d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh					argv[2], errno);
369ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
370d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	}
371ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
372ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
373ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
374ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
375ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
376ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyinit_uart()
377ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
378ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
379ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcgetattr(uart_fd, &termios);
380ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
381ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef __CYGWIN__
382ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfmakeraw(&termios);
383ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#else
384ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
385ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly                | INLCR | IGNCR | ICRNL | IXON);
386ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_oflag &= ~OPOST;
387ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
388ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_cflag &= ~(CSIZE | PARENB);
389ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_cflag |= CS8;
390ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
391ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
392ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_cflag |= CRTSCTS;
393ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
394ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
395ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
396ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
397ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
398ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetospeed(&termios, B115200);
399ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetispeed(&termios, B115200);
400ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
401ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
402ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
403ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
404ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellydump(unsigned char *out, int len)
405ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
406ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i;
407ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
408ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	for (i = 0; i < len; i++) {
409ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		if (i && !(i % 16)) {
410ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			fprintf(stderr, "\n");
411ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
412ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
413ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "%02x ", out[i]);
414ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
415ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
416ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	fprintf(stderr, "\n");
417ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
418ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
419ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
420ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyread_event(int fd, unsigned char *buffer)
421ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
422ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i = 0;
423ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int len = 3;
424ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int count;
425ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
426ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	while ((count = read(fd, &buffer[i], len)) < len) {
427ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		i += count;
428ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		len -= count;
429ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
430ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
431ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	i += count;
432ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	len = buffer[2];
433ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
434ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	while ((count = read(fd, &buffer[i], len)) < len) {
435ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		i += count;
436ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		len -= count;
437ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
438ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
439ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (debug) {
440ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		count += i;
441ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
442ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "received %d\n", count);
443ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		dump(buffer, count);
444ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
445ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
446ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
447ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
448ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyhci_send_cmd(unsigned char *buf, int len)
449ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
450ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (debug) {
451ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "writing\n");
452ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		dump(buf, len);
453ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
454ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
455ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	write(uart_fd, buf, len);
456ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
457ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
458ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
459ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyexpired(int sig)
460ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
461ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_reset, sizeof(hci_reset));
462ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	alarm(4);
463ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
464ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
465ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
466ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_reset()
467ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
468ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	signal(SIGALRM, expired);
469ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
470ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
471ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_reset, sizeof(hci_reset));
472ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
473ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	alarm(4);
474ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
475ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
476ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
477ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	alarm(0);
478ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
479ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
480ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
481ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_patchram()
482ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
483ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int len;
484ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
485ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_download_minidriver, sizeof(hci_download_minidriver));
486ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
487ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
488ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
489ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read(uart_fd, &buffer[0], 2);
490ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
491deaab6fa4a94c31494ebb6770dd0532198d0cbcaNick Pelly	usleep(50000);
492deaab6fa4a94c31494ebb6770dd0532198d0cbcaNick Pelly
493ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	while (read(hcdfile_fd, &buffer[1], 3)) {
494ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		buffer[0] = 0x01;
495ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
496ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		len = buffer[3];
497ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
498ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		read(hcdfile_fd, &buffer[4], len);
499ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
500ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		hci_send_cmd(buffer, len + 4);
501ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
502ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		read_event(uart_fd, buffer);
503ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
504ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
505ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	proc_reset();
506ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
507ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
508ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
509ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_baudrate()
510ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
511ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_update_baud_rate, sizeof(hci_update_baud_rate));
512ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
513ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
514ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
515ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetospeed(&termios, termios_baudrate);
516ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetispeed(&termios, termios_baudrate);
517ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
518ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
519ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (debug) {
520ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Done setting baudrate\n");
521ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
522ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
523ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
524ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
525ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_bdaddr()
526ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
527ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_write_bd_addr, sizeof(hci_write_bd_addr));
528ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
529ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
530ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
531ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
532ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
533ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_enable_lpm()
534ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
535ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_write_sleep_mode, sizeof(hci_write_sleep_mode));
536ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
537ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
538ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
539ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
540ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
5411725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesproc_pcm_slave()
5421725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries{
543d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	if (debug)
544d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		printf("Configuring PCM Interface as slave.\n");
5451725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	hci_send_cmd(hci_write_pcm_slave_mode, sizeof(hci_write_pcm_slave_mode));
5461725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries}
5471725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries
5481725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesvoid
5491725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesproc_pcm_master()
5501725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries{
551d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	if (debug)
552d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		printf("Configuring PCM Interface as master.\n");
5531725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	hci_send_cmd(hci_write_pcm_master_mode, sizeof(hci_write_pcm_master_mode));
5541725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries}
5551725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries
5561725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Friesvoid
557ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_enable_hci()
558ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
559ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i = N_HCI;
560ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int proto = HCI_UART_H4;
561ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (ioctl(uart_fd, TIOCSETD, &i) < 0) {
562ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Can't set line discipline\n");
563ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		return;
564ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
565ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
566ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (ioctl(uart_fd, HCIUARTSETPROTO, proto) < 0) {
567ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Can't set hci protocol\n");
568ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		return;
569ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
570ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	fprintf(stderr, "Done setting line discpline\n");
571ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return;
572ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
573ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
574db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pellyvoid
575db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pellyread_default_bdaddr()
576db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly{
577db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	int sz;
578db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	int fd;
579db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	char path[PROPERTY_VALUE_MAX];
580db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	char bdaddr[18];
581d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	int len = 17;
582d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	memset(bdaddr, 0, (len + 1) * sizeof(char));
583db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly
584db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	property_get("ro.bt.bdaddr_path", path, "");
585db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	if (path[0] == 0)
586db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		return;
587db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly
588db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	fd = open(path, O_RDONLY);
589db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	if (fd < 0) {
590db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		fprintf(stderr, "open(%s) failed: %s (%d)", path, strerror(errno),
591db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly				errno);
592db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		return;
593db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	}
594db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly
595d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	sz = read(fd, bdaddr, len);
596db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	if (sz < 0) {
597db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		fprintf(stderr, "read(%s) failed: %s (%d)", path, strerror(errno),
598db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly				errno);
599db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		close(fd);
600db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		return;
601d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	} else if (sz != len) {
602db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		fprintf(stderr, "read(%s) unexpected size %d", path, sz);
603db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		close(fd);
604db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly		return;
605db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	}
606db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly
607d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh	if (debug)
608d15a37448edcc1bd314873732ce5f3ea7ddad4baJaikumar Ganesh		printf("Read default bdaddr of %s\n", bdaddr);
609db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	parse_bdaddr(bdaddr);
610db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly}
611db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly
612ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
613ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellymain (int argc, char **argv)
614ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
615db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly	read_default_bdaddr();
616db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly
617ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	parse_cmd_line(argc, argv);
618ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
619ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (uart_fd < 0) {
620ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(1);
621ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
622ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
623ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	init_uart();
624ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
625ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	proc_reset();
626ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
627fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh	if (use_baudrate_for_download) {
628fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		if (termios_baudrate) {
629fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh			proc_baudrate();
630fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		}
631fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh
632fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		if (hcdfile_fd > 0) {
633fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh			proc_patchram();
634fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		}
635fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh	} else {
636fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		if (hcdfile_fd > 0) {
637fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh			proc_patchram();
638fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		}
639ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
640fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		if (termios_baudrate) {
641fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh			proc_baudrate();
642fff5ba85648ed4346d6feb3639aeafa6874bf640Jaikumar Ganesh		}
643ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
644ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
645ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (bdaddr_flag) {
646ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proc_bdaddr();
647ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
648ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
649ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (enable_lpm) {
650ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proc_enable_lpm();
651ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
652ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
6531725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	if (pcm_slave) {
6541725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		proc_pcm_slave();
6551725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	} else if (pcm_master) {
6561725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries		proc_pcm_master();
6571725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries	}
6581725ef80c89ba54e0b246d5d4d31e217496d01b5Chris Fries
659ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (enable_hci) {
660d4397861e745c5b6ae99fe547b841df9babf3085Nick Pelly		proc_enable_hci();
661ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		while (1) {
662ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			sleep(UINT_MAX);
663ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
664ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
665ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
666ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	exit(0);
667ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
668