brcm_patchram_plus.c revision d4397861e745c5b6ae99fe547b841df9babf3085
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 48db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly** system/bluetooth/bluedroid/bluetooth.c. 49ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly** 50db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly** If the Android system property "ro.bt.bcm_bdaddr_path" is 51db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly** set, then the bd_addr will be read from this path. 52db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly** This is overridden by --bd_addr on the command line. 53ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly** 54ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly******************************************************************************/ 55ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 56ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly// TODO: Integrate BCM support into Bluez hciattach 57ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 58ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <stdio.h> 59ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <getopt.h> 60ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <errno.h> 61ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 62ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/types.h> 63ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/stat.h> 64ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <fcntl.h> 65ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 66ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <stdlib.h> 67ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 68ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifdef ANDROID 69ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <termios.h> 70ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#else 71ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <sys/termios.h> 72ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif 73ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 74ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <string.h> 75ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#include <signal.h> 76ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 77db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly#include <cutils/properties.h> 78db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 79ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef N_HCI 80ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define N_HCI 15 81ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif 82ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 83ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTSETPROTO _IOW('U', 200, int) 84ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTGETPROTO _IOR('U', 201, int) 85ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCIUARTGETDEVICE _IOR('U', 202, int) 86ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 87ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_H4 0 88ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_BCSP 1 89ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_3WIRE 2 90ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_H4DS 3 91ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#define HCI_UART_LL 4 92ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 93ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 94ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint uart_fd = -1; 95ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint hcdfile_fd = -1; 96ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint termios_baudrate = 0; 97ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint bdaddr_flag = 0; 98ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint enable_lpm = 0; 99ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint enable_hci = 0; 100ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint debug = 0; 101ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 102ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellystruct termios termios; 103ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char buffer[1024]; 104ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 105ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 }; 106ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 107ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_download_minidriver[] = { 0x01, 0x2e, 0xfc, 0x00 }; 108ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 109ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_update_baud_rate[] = { 0x01, 0x18, 0xfc, 0x06, 0x00, 0x00, 110ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 0x00, 0x00, 0x00, 0x00 }; 111ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 112ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_write_bd_addr[] = { 0x01, 0x01, 0xfc, 0x06, 113db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 114ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 115ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyunsigned char hci_write_sleep_mode[] = { 0x01, 0x27, 0xfc, 0x0c, 116d4397861e745c5b6ae99fe547b841df9babf3085Nick Pelly 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 117ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 0x00, 0x00 }; 118ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 119ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 120ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_patchram(char *optarg) 121ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 122ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly char *p; 123ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 124ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (!(p = strrchr(optarg, '.'))) { 125ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "file %s not an HCD file\n", optarg); 126ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly exit(3); 127ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 128ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 129ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly p++; 130ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 131ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (strcasecmp("hcd", p) != 0) { 132ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "file %s not an HCD file\n", optarg); 133ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly exit(4); 134ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 135ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 136ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if ((hcdfile_fd = open(optarg, O_RDONLY)) == -1) { 137ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "file %s could not be opened, error %d\n", optarg, errno); 138ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly exit(5); 139ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 140ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 141ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(0); 142ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 143ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 144ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 145ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick PellyBRCM_encode_baud_rate(uint baud_rate, unsigned char *encoded_baud) 146ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 147ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if(baud_rate == 0 || encoded_baud == NULL) { 148ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "Baudrate not supported!"); 149ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return; 150ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 151ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 152ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly encoded_baud[3] = (unsigned char)(baud_rate >> 24); 153ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly encoded_baud[2] = (unsigned char)(baud_rate >> 16); 154ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly encoded_baud[1] = (unsigned char)(baud_rate >> 8); 155ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly encoded_baud[0] = (unsigned char)(baud_rate & 0xFF); 156ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 157ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 158ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellytypedef struct { 159ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int baud_rate; 160ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int termios_value; 161ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} tBaudRates; 162ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 163ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick PellytBaudRates baud_rates[] = { 164ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 115200, B115200 }, 165ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 230400, B230400 }, 166ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 460800, B460800 }, 167ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 500000, B500000 }, 168ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 576000, B576000 }, 169ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 921600, B921600 }, 170ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 1000000, B1000000 }, 171ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 1152000, B1152000 }, 172ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 1500000, B1500000 }, 173ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 2000000, B2000000 }, 174ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 2500000, B2500000 }, 175ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 3000000, B3000000 }, 176ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef __CYGWIN__ 177ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 3500000, B3500000 }, 178ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 4000000, B4000000 } 179ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif 180ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly}; 181ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 182ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 183ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvalidate_baudrate(int baud_rate, int *value) 184ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 185ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly unsigned int i; 186ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 187ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly for (i = 0; i < (sizeof(baud_rates) / sizeof(tBaudRates)); i++) { 188ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (baud_rates[i].baud_rate == baud_rate) { 189ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly *value = baud_rates[i].termios_value; 190ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(1); 191ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 192ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 193ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 194ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(0); 195ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 196ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 197ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 198ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_baudrate(char *optarg) 199ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 200ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int baudrate = atoi(optarg); 201ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 202ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (validate_baudrate(baudrate, &termios_baudrate)) { 203ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly BRCM_encode_baud_rate(baudrate, &hci_update_baud_rate[6]); 204ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 205ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 206ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(0); 207ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 208ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 209ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 210ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_bdaddr(char *optarg) 211ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 212ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int bd_addr[6]; 213ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int i; 214ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 215db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly sscanf(optarg, "%02X:%02X:%02X:%02X:%02X:%02X", 216db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly &bd_addr[5], &bd_addr[4], &bd_addr[3], 217db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly &bd_addr[2], &bd_addr[1], &bd_addr[0]); 218ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 219ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly for (i = 0; i < 6; i++) { 220ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_write_bd_addr[4 + i] = bd_addr[i]; 221ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 222ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 223ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly bdaddr_flag = 1; 224ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 225ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(0); 226ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 227ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 228ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 229ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_enable_lpm(char *optarg) 230ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 231ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly enable_lpm = 1; 232ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(0); 233ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 234ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 235ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 236ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_enable_hci(char *optarg) 237ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 238ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly enable_hci = 1; 239ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(0); 240ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 241ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 242ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 243ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyparse_cmd_line(int argc, char **argv) 244ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 245ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int c; 246ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int digit_optind = 0; 247ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 248ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly typedef int (*PFI)(); 249ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 250ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly PFI parse_param[] = { parse_patchram, parse_baudrate, 251ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly parse_bdaddr, parse_enable_lpm, parse_enable_hci }; 252ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 253ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly while (1) 254ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly { 255ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int this_option_optind = optind ? optind : 1; 256ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int option_index = 0; 257ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 258ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly static struct option long_options[] = { 259ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly {"patchram", 1, 0, 0}, 260ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly {"baudrate", 1, 0, 0}, 261ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly {"bd_addr", 1, 0, 0}, 262ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly {"enable_lpm", 0, 0, 0}, 263ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly {"enable_hci", 0, 0, 0}, 264ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly {0, 0, 0, 0} 265ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly }; 266ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 267ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly c = getopt_long_only (argc, argv, "d", long_options, &option_index); 268ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 269ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (c == -1) { 270ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly break; 271ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 272ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 273ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly switch (c) { 274ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly case 0: 275ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf ("option %s", long_options[option_index].name); 276ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 277ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (optarg) { 278ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf (" with arg %s", optarg); 279ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 280ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 281ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf ("\n"); 282ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 283ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly (*parse_param[option_index])(optarg); 284ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly break; 285ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 286ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly case 'd': 287ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly debug = 1; 288ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly break; 289ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 290ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly case '?': 291ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly //nobreak 292ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly default: 293ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 294ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("Usage %s:\n", argv[0]); 295ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("\t<-d> to print a debug log\n"); 296ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("\t<--patchram patchram_file>\n"); 297ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("\t<--baudrate baud_rate>\n"); 298ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("\t<--bd_addr bd_address>\n"); 299ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("\t<--enable_lpm\n"); 300ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("\t<--enable_hci\n"); 301ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf("\tuart_device_name\n"); 302ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly break; 303ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 304ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 305ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 306ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 307ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (optind < argc) { 308ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (optind < argc) { 309ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf ("%s ", argv[optind]); 310ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 311ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if ((uart_fd = open(argv[optind], O_RDWR | O_NOCTTY)) == -1) { 312ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "port %s could not be opened, error %d\n", argv[2], errno); 313ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 314ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 315ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 316ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly printf ("\n"); 317ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 318ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 319ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return(0); 320ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 321ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 322ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 323ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyinit_uart() 324ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 325ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcflush(uart_fd, TCIOFLUSH); 326ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcgetattr(uart_fd, &termios); 327ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 328ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#ifndef __CYGWIN__ 329ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly cfmakeraw(&termios); 330ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#else 331ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP 332ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly | INLCR | IGNCR | ICRNL | IXON); 333ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly termios.c_oflag &= ~OPOST; 334ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 335ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly termios.c_cflag &= ~(CSIZE | PARENB); 336ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly termios.c_cflag |= CS8; 337ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly#endif 338ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 339ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly termios.c_cflag |= CRTSCTS; 340ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcsetattr(uart_fd, TCSANOW, &termios); 341ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcflush(uart_fd, TCIOFLUSH); 342ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcsetattr(uart_fd, TCSANOW, &termios); 343ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcflush(uart_fd, TCIOFLUSH); 344ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcflush(uart_fd, TCIOFLUSH); 345ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly cfsetospeed(&termios, B115200); 346ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly cfsetispeed(&termios, B115200); 347ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcsetattr(uart_fd, TCSANOW, &termios); 348ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 349ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 350ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 351ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellydump(unsigned char *out, int len) 352ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 353ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int i; 354ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 355ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly for (i = 0; i < len; i++) { 356ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (i && !(i % 16)) { 357ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "\n"); 358ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 359ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 360ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "%02x ", out[i]); 361ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 362ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 363ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "\n"); 364ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 365ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 366ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 367ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyread_event(int fd, unsigned char *buffer) 368ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 369ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int i = 0; 370ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int len = 3; 371ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int count; 372ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 373ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly while ((count = read(fd, &buffer[i], len)) < len) { 374ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly i += count; 375ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly len -= count; 376ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 377ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 378ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly i += count; 379ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly len = buffer[2]; 380ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 381ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly while ((count = read(fd, &buffer[i], len)) < len) { 382ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly i += count; 383ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly len -= count; 384ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 385ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 386ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (debug) { 387ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly count += i; 388ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 389ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "received %d\n", count); 390ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly dump(buffer, count); 391ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 392ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 393ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 394ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 395ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyhci_send_cmd(unsigned char *buf, int len) 396ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 397ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (debug) { 398ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "writing\n"); 399ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly dump(buf, len); 400ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 401ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 402ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly write(uart_fd, buf, len); 403ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 404ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 405ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 406ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyexpired(int sig) 407ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 408ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_send_cmd(hci_reset, sizeof(hci_reset)); 409ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly alarm(4); 410ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 411ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 412ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 413ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_reset() 414ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 415ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly signal(SIGALRM, expired); 416ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 417ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 418ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_send_cmd(hci_reset, sizeof(hci_reset)); 419ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 420ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly alarm(4); 421ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 422ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read_event(uart_fd, buffer); 423ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 424ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly alarm(0); 425ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 426ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 427ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 428ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_patchram() 429ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 430ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int len; 431ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 432ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_send_cmd(hci_download_minidriver, sizeof(hci_download_minidriver)); 433ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 434ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read_event(uart_fd, buffer); 435ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 436ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read(uart_fd, &buffer[0], 2); 437ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 438ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly while (read(hcdfile_fd, &buffer[1], 3)) { 439ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly buffer[0] = 0x01; 440ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 441ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly len = buffer[3]; 442ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 443ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read(hcdfile_fd, &buffer[4], len); 444ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 445ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_send_cmd(buffer, len + 4); 446ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 447ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read_event(uart_fd, buffer); 448ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 449ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 450ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly proc_reset(); 451ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 452ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 453ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 454ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_baudrate() 455ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 456ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_send_cmd(hci_update_baud_rate, sizeof(hci_update_baud_rate)); 457ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 458ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read_event(uart_fd, buffer); 459ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 460ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly cfsetospeed(&termios, termios_baudrate); 461ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly cfsetispeed(&termios, termios_baudrate); 462ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly tcsetattr(uart_fd, TCSANOW, &termios); 463ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 464ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (debug) { 465ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "Done setting baudrate\n"); 466ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 467ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 468ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 469ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 470ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_bdaddr() 471ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 472ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_send_cmd(hci_write_bd_addr, sizeof(hci_write_bd_addr)); 473ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 474ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read_event(uart_fd, buffer); 475ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 476ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 477ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 478ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_enable_lpm() 479ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 480ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly hci_send_cmd(hci_write_sleep_mode, sizeof(hci_write_sleep_mode)); 481ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 482ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly read_event(uart_fd, buffer); 483ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 484ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 485ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyvoid 486ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyproc_enable_hci() 487ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 488ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int i = N_HCI; 489ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly int proto = HCI_UART_H4; 490ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (enable_lpm) { 491ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly proto = HCI_UART_LL; 492ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 493ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (ioctl(uart_fd, TIOCSETD, &i) < 0) { 494ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "Can't set line discipline\n"); 495ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return; 496ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 497ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 498ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (ioctl(uart_fd, HCIUARTSETPROTO, proto) < 0) { 499ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "Can't set hci protocol\n"); 500ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return; 501ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 502ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly fprintf(stderr, "Done setting line discpline\n"); 503ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly return; 504ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 505ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 506db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pellyvoid 507db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pellyread_default_bdaddr() 508db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly{ 509db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly int sz; 510db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly int fd; 511db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly char path[PROPERTY_VALUE_MAX]; 512db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly char bdaddr[18]; 513db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 514db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly property_get("ro.bt.bdaddr_path", path, ""); 515db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly if (path[0] == 0) 516db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly return; 517db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 518db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly fd = open(path, O_RDONLY); 519db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly if (fd < 0) { 520db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly fprintf(stderr, "open(%s) failed: %s (%d)", path, strerror(errno), 521db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly errno); 522db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly return; 523db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly } 524db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 525db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly sz = read(fd, bdaddr, sizeof(bdaddr)); 526db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly if (sz < 0) { 527db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly fprintf(stderr, "read(%s) failed: %s (%d)", path, strerror(errno), 528db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly errno); 529db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly close(fd); 530db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly return; 531db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly } else if (sz != sizeof(bdaddr)) { 532db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly fprintf(stderr, "read(%s) unexpected size %d", path, sz); 533db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly close(fd); 534db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly return; 535db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly } 536db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 537db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly printf("Read default bdaddr of %s\n", bdaddr); 538db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly parse_bdaddr(bdaddr); 539db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly} 540db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 541ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellyint 542ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pellymain (int argc, char **argv) 543ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly{ 544db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly read_default_bdaddr(); 545db5ccf71519a49fbb36b915dba551aa0b3fa0db8Nick Pelly 546ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly parse_cmd_line(argc, argv); 547ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 548ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (uart_fd < 0) { 549ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly exit(1); 550ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 551ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 552ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly init_uart(); 553ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 554ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly proc_reset(); 555ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 556ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (hcdfile_fd > 0) { 557ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly proc_patchram(); 558ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 559ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 560ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (termios_baudrate) { 561ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly proc_baudrate(); 562ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 563ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 564ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (bdaddr_flag) { 565ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly proc_bdaddr(); 566ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 567ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 568ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (enable_lpm) { 569ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly proc_enable_lpm(); 570ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 571ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 572ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly if (enable_hci) { 573d4397861e745c5b6ae99fe547b841df9babf3085Nick Pelly proc_enable_hci(); 574ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly while (1) { 575ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly sleep(UINT_MAX); 576ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 577ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly } 578ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly 579ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly exit(0); 580ac8c432d8eea5f875f672c2a7755c40a76a3c8cdNick Pelly} 581