brcm_patchram_plus.c revision ac8c432d8eea5f875f672c2a7755c40a76a3c8cd
1ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly/**
2ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * brcm_patchram_plus.c
3ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly *
4ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * Copyright (C) 2009 Broadcom Corporation.
5ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly *
6ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * This software is licensed under the terms of the GNU General Public License,
7ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * version 2, as published by the Free Software Foundation (the "GPL"), and may
8ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * be copied, distributed, and modified under those terms.
9ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly *
10ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * This program is distributed in the hope that it will be useful, but WITHOUT
11ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * FITNESS FOR A PARTICULAR PURPOSE. See the GPL for more details.
13ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly *
14ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
15ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * or by writing to the Free Software Foundation, Inc.,
16ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
17ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly */
18ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
19ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
20ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly/*****************************************************************************
21ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
22ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**  Name:          brcm_patchram_plus.c
23ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
24ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**  Description:   This program downloads a patchram files in the HCD format
25ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 to Broadcom Bluetooth based silicon and combo chips and
26ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**				   and other utility functions.
27ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
28ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 It can be invoked from the command line in the form
29ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<-d> to print a debug log
30ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--patchram patchram_file>
31ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--baudrate baud_rate>
32ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--bd_addr bd_address>
33ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--enable_lpm>
34ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						<--enable_hci>
35ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						uart_device_name
36ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
37ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 For example:
38ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
39ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 brcm_patchram_plus -d --patchram  \
40ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**						BCM2045B2_002.002.011.0348.0349.hcd /dev/ttyHS0
41ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
42ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 It will return 0 for success and a number greater than 0
43ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 for any errors.
44ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
45ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 For Android, this program invoked using a
46ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 "system(2)" call from the beginning of the bt_enable
47ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 function inside the file
48ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**                 mydroid/system/bluetooth/bluedroid/bluetooth.c.
49ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
50ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly**
51ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly******************************************************************************/
52ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
53ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly// TODO: Integrate BCM support into Bluez hciattach
54ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
55ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <stdio.h>
56ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <getopt.h>
57ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <errno.h>
58ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
59ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/types.h>
60ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/stat.h>
61ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <fcntl.h>
62ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
63ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <stdlib.h>
64ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
65ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifdef ANDROID
66ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <termios.h>
67ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#else
68ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/termios.h>
69ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
70ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
71ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <string.h>
72ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <signal.h>
73ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
74ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef N_HCI
75ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define N_HCI	15
76ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
77ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
78ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTSETPROTO		_IOW('U', 200, int)
79ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTGETPROTO		_IOR('U', 201, int)
80ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTGETDEVICE	_IOR('U', 202, int)
81ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
82ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_H4		0
83ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_BCSP	1
84ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_3WIRE	2
85ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_H4DS	3
86ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_LL		4
87ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
88ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
89ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint uart_fd = -1;
90ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint hcdfile_fd = -1;
91ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint termios_baudrate = 0;
92ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint bdaddr_flag = 0;
93ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint enable_lpm = 0;
94ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint enable_hci = 0;
95ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint debug = 0;
96ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
97ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellystruct termios termios;
98ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char buffer[1024];
99ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
100ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
101ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
102ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_download_minidriver[] = { 0x01, 0x2e, 0xfc, 0x00 };
103ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
104ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00,
105ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	0x00, 0x00, 0x00, 0x00 };
106ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
107ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_write_bd_addr[] = { 0x01, 0x01, 0xfc, 0x06,
108ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	0x00 };
110ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
111ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc, 0x0c,
112ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
113ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	0x00, 0x00 };
114ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
115ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
116ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_patchram(char *optarg)
117ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
118ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	char *p;
119ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
120ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (!(p = strrchr(optarg, '.'))) {
121ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "file %s not an HCD file\n", optarg);
122ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(3);
123ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
124ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
125ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	p++;
126ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
127ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (strcasecmp("hcd", p) != 0) {
128ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "file %s not an HCD file\n", optarg);
129ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(4);
130ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
131ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
132ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if ((hcdfile_fd = open(optarg, O_RDONLY)) == -1) {
133ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "file %s could not be opened, error %d\n", optarg, errno);
134ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(5);
135ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
136ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
137ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
138ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
139ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
140ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
141ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick PellyBRCM_encode_baud_rate(uint baud_rate, unsigned char *encoded_baud)
142ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
143ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if(baud_rate == 0 || encoded_baud == NULL) {
144ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Baudrate not supported!");
145ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		return;
146ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
147ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
148ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[3] = (unsigned char)(baud_rate >> 24);
149ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[2] = (unsigned char)(baud_rate >> 16);
150ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[1] = (unsigned char)(baud_rate >> 8);
151ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	encoded_baud[0] = (unsigned char)(baud_rate & 0xFF);
152ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
153ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
154ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellytypedef struct {
155ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int baud_rate;
156ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int termios_value;
157ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} tBaudRates;
158ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
159ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick PellytBaudRates baud_rates[] = {
160ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 115200, B115200 },
161ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 230400, B230400 },
162ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 460800, B460800 },
163ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 500000, B500000 },
164ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 576000, B576000 },
165ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 921600, B921600 },
166ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 1000000, B1000000 },
167ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 1152000, B1152000 },
168ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 1500000, B1500000 },
169ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 2000000, B2000000 },
170ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 2500000, B2500000 },
171ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 3000000, B3000000 },
172ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef __CYGWIN__
173ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 3500000, B3500000 },
174ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	{ 4000000, B4000000 }
175ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
176ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly};
177ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
178ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
179ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvalidate_baudrate(int baud_rate, int *value)
180ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
181ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	unsigned int i;
182ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
183ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	for (i = 0; i < (sizeof(baud_rates) / sizeof(tBaudRates)); i++) {
184ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		if (baud_rates[i].baud_rate == baud_rate) {
185ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			*value = baud_rates[i].termios_value;
186ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			return(1);
187ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
188ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
189ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
190ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
191ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
192ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
193ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
194ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_baudrate(char *optarg)
195ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
196ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int baudrate = atoi(optarg);
197ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
198ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (validate_baudrate(baudrate, &termios_baudrate)) {
199ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		BRCM_encode_baud_rate(baudrate, &hci_update_baud_rate[6]);
200ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
201ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
202ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
203ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
204ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
205ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
206ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_bdaddr(char *optarg)
207ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
208ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int bd_addr[6];
209ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i;
210ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
211ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	sscanf(optarg, "%02x%02x%02x%02x%02x%02x",
212ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		&bd_addr[0], &bd_addr[1], &bd_addr[2],
213ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		&bd_addr[3], &bd_addr[4], &bd_addr[5]);
214ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
215ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	for (i = 0; i < 6; i++) {
216ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		hci_write_bd_addr[4 + i] = bd_addr[i];
217ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
218ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
219ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	bdaddr_flag = 1;
220ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
221ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
222ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
223ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
224ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
225ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_enable_lpm(char *optarg)
226ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
227ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	enable_lpm = 1;
228ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
229ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
230ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
231ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
232ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_enable_hci(char *optarg)
233ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
234ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	enable_hci = 1;
235ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
236ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
237ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
238ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
239ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_cmd_line(int argc, char **argv)
240ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
241ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int c;
242ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int digit_optind = 0;
243ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
244ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	typedef int (*PFI)();
245ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
246ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	PFI parse_param[] = { parse_patchram, parse_baudrate,
247ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		parse_bdaddr, parse_enable_lpm, parse_enable_hci };
248ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
249ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly    while (1)
250ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly    {
251ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly    	int this_option_optind = optind ? optind : 1;
252ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly        int option_index = 0;
253ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
254ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       	static struct option long_options[] = {
255ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly         {"patchram", 1, 0, 0},
256ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly         {"baudrate", 1, 0, 0},
257ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly         {"bd_addr", 1, 0, 0},
258ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly         {"enable_lpm", 0, 0, 0},
259ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly         {"enable_hci", 0, 0, 0},
260ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly         {0, 0, 0, 0}
261ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       	};
262ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
263ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       	c = getopt_long_only (argc, argv, "d", long_options, &option_index);
264ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
265ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       	if (c == -1) {
266ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly      		break;
267ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
268ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
269ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       	switch (c) {
270ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly        case 0:
271ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly        	printf ("option %s", long_options[option_index].name);
272ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
273ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly        	if (optarg) {
274ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly           		printf (" with arg %s", optarg);
275ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			}
276ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
277ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly           	printf ("\n");
278ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
279ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			(*parse_param[option_index])(optarg);
280ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		break;
281ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
282ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		case 'd':
283ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			debug = 1;
284ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		break;
285ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
286ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly        case '?':
287ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			//nobreak
288ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly        default:
289ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
290ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("Usage %s:\n", argv[0]);
291ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("\t<-d> to print a debug log\n");
292ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("\t<--patchram patchram_file>\n");
293ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("\t<--baudrate baud_rate>\n");
294ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("\t<--bd_addr bd_address>\n");
295ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("\t<--enable_lpm\n");
296ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("\t<--enable_hci\n");
297ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			printf("\tuart_device_name\n");
298ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly           	break;
299ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
300ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly        }
301ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
302ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
303ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly   	if (optind < argc) {
304ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       	if (optind < argc) {
305ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       		printf ("%s ", argv[optind]);
306ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
307ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			if ((uart_fd = open(argv[optind], O_RDWR | O_NOCTTY)) == -1) {
308ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly				fprintf(stderr, "port %s could not be opened, error %d\n", argv[2], errno);
309ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			}
310ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
311ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
312ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly       	printf ("\n");
313ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly    }
314ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
315ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return(0);
316ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
317ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
318ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
319ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyinit_uart()
320ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
321ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
322ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcgetattr(uart_fd, &termios);
323ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
324ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef __CYGWIN__
325ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfmakeraw(&termios);
326ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#else
327ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
328ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly                | INLCR | IGNCR | ICRNL | IXON);
329ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_oflag &= ~OPOST;
330ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
331ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_cflag &= ~(CSIZE | PARENB);
332ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_cflag |= CS8;
333ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif
334ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
335ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	termios.c_cflag |= CRTSCTS;
336ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
337ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
338ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
339ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
340ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcflush(uart_fd, TCIOFLUSH);
341ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetospeed(&termios, B115200);
342ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetispeed(&termios, B115200);
343ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
344ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
345ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
346ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
347ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellydump(unsigned char *out, int len)
348ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
349ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i;
350ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
351ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	for (i = 0; i < len; i++) {
352ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		if (i && !(i % 16)) {
353ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			fprintf(stderr, "\n");
354ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
355ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
356ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "%02x ", out[i]);
357ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
358ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
359ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	fprintf(stderr, "\n");
360ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
361ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
362ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
363ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyread_event(int fd, unsigned char *buffer)
364ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
365ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i = 0;
366ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int len = 3;
367ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int count;
368ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
369ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	while ((count = read(fd, &buffer[i], len)) < len) {
370ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		i += count;
371ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		len -= count;
372ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
373ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
374ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	i += count;
375ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	len = buffer[2];
376ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
377ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	while ((count = read(fd, &buffer[i], len)) < len) {
378ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		i += count;
379ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		len -= count;
380ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
381ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
382ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (debug) {
383ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		count += i;
384ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
385ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "received %d\n", count);
386ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		dump(buffer, count);
387ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
388ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
389ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
390ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
391ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyhci_send_cmd(unsigned char *buf, int len)
392ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
393ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (debug) {
394ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "writing\n");
395ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		dump(buf, len);
396ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
397ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
398ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	write(uart_fd, buf, len);
399ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
400ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
401ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
402ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyexpired(int sig)
403ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
404ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_reset, sizeof(hci_reset));
405ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	alarm(4);
406ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
407ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
408ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
409ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_reset()
410ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
411ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	signal(SIGALRM, expired);
412ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
413ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
414ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_reset, sizeof(hci_reset));
415ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
416ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	alarm(4);
417ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
418ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
419ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
420ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	alarm(0);
421ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
422ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
423ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
424ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_patchram()
425ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
426ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int len;
427ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
428ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_download_minidriver, sizeof(hci_download_minidriver));
429ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
430ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
431ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
432ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read(uart_fd, &buffer[0], 2);
433ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
434ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	while (read(hcdfile_fd, &buffer[1], 3)) {
435ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		buffer[0] = 0x01;
436ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
437ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		len = buffer[3];
438ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
439ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		read(hcdfile_fd, &buffer[4], len);
440ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
441ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		hci_send_cmd(buffer, len + 4);
442ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
443ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		read_event(uart_fd, buffer);
444ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
445ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
446ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	proc_reset();
447ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
448ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
449ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
450ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_baudrate()
451ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
452ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_update_baud_rate, sizeof(hci_update_baud_rate));
453ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
454ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
455ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
456ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetospeed(&termios, termios_baudrate);
457ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	cfsetispeed(&termios, termios_baudrate);
458ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	tcsetattr(uart_fd, TCSANOW, &termios);
459ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
460ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (debug) {
461ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Done setting baudrate\n");
462ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
463ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
464ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
465ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
466ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_bdaddr()
467ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
468ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_write_bd_addr, sizeof(hci_write_bd_addr));
469ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
470ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
471ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
472ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
473ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
474ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_enable_lpm()
475ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
476ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	hci_send_cmd(hci_write_sleep_mode, sizeof(hci_write_sleep_mode));
477ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
478ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	read_event(uart_fd, buffer);
479ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
480ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
481ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid
482ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_enable_hci()
483ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
484ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int i = N_HCI;
485ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	int proto = HCI_UART_H4;
486ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (enable_lpm) {
487ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proto = HCI_UART_LL;
488ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
489ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (ioctl(uart_fd, TIOCSETD, &i) < 0) {
490ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Can't set line discipline\n");
491ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		return;
492ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
493ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
494ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (ioctl(uart_fd, HCIUARTSETPROTO, proto) < 0) {
495ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		fprintf(stderr, "Can't set hci protocol\n");
496ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		return;
497ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
498ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	fprintf(stderr, "Done setting line discpline\n");
499ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	return;
500ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
501ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
502ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint
503ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellymain (int argc, char **argv)
504ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{
505ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	parse_cmd_line(argc, argv);
506ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
507ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (uart_fd < 0) {
508ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		exit(1);
509ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
510ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
511ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	init_uart();
512ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
513ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	proc_reset();
514ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
515ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (hcdfile_fd > 0) {
516ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proc_patchram();
517ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
518ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
519ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (termios_baudrate) {
520ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proc_baudrate();
521ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
522ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
523ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (bdaddr_flag) {
524ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proc_bdaddr();
525ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
526ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
527ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (enable_hci) {
528ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proc_enable_hci();
529ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
530ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
531ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (enable_lpm) {
532ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		proc_enable_lpm();
533ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
534ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
535ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	if (enable_hci) {
536ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		while (1) {
537ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly			sleep(UINT_MAX);
538ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly		}
539ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	}
540ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly
541ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly	exit(0);
542ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}
543