brfpatch.c revision 7342a3e6a751116a193ff27d69b87eda478a5016
17342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project/* 27342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** Copyright 2007, The Android Open Source Project 37342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** 47342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 57342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** you may not use this file except in compliance with the License. 67342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** You may obtain a copy of the License at 77342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** 87342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 97342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** 107342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 117342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 127342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** See the License for the specific language governing permissions and 147342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project** limitations under the License. 157342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project*/ 167342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 177342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <stdio.h> 187342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <unistd.h> 197342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <stdlib.h> 207342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <string.h> 217342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <errno.h> 227342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <ctype.h> 237342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 247342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#define FAILIF(x, args...) do { \ 257342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project if (x) { \ 267342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project fprintf(stderr, ##args); \ 277342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project exit(1); \ 287342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project } \ 297342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project} while(0) 307342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 317342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic void usage() { 327342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project printf("Usage: brfpatch INPUT OUTPUT\n" 337342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "\n" 347342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "\tGenerates bluetooth firmware\n" 357342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "\n" 367342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "INPUT: Bluetooth script in ASCII format.\n" 377342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " For TI BRF chips this can be generated from .bts files using the TI Bluetooth\n" 387342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " script pad to save as .txt. This txt file can be used as input.\n" 397342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " Alternately, run strings on the .bts and manually edit to change decimal\n" 407342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " arguments into hex of the appropriate number of octets.\n" 417342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " FORMAT: Send_HCI_xxxx OPCODE DATA1 DATA2 DATA3 ...\n" 427342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " where OPCODE, DATA1 etc are one of:\n" 437342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " 0x12 (1 byte)\n" 447342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " 0x1234 (2 byte)\n" 457342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " 0x12345678 (4 byte)\n" 467342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " \"0123456789ABCDEF0123\" (multibyte)\n" 477342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " \"01:23:45:67:89:AB:CD:EF:01:23\" (multibyte)\n" 487342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "\n" 497342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "OUTPUT: Binary firmware\n" 507342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project " FORMAT: 0x01 OPCODE DATA_LEN DATA\n"); 517342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project exit(1); 527342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project} 537342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 547342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic void dump_record(FILE *fpo, unsigned short opcode, unsigned char len, 557342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project unsigned char *data) { 567342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 577342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project unsigned char prefix = 0x01; // H4 UART command packet 587342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project fwrite(&prefix, 1, 1, fpo); 597342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project fwrite(&opcode, 2, 1, fpo); // opcode 607342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project fwrite(&len, 1, 1, fpo); // data length 617342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project fwrite(data, len, 1, fpo); // data 627342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project} 637342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 647342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project// advance beyond next whitespace. Return -1 if end of string reached 657342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic int advance(char **buf) { 667342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project char *b = *buf; 677342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project while (*b && !isspace(*b)) 687342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project b++; 697342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project while (*b && isspace(*b)) 707342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project b++; 717342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project *buf = b; 727342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project if (!(*b)) 737342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project return -1; 747342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project return 0; 757342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project} 767342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 777342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic void process_line(FILE *file_out, char *buf, char *buffer) { 787342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(strncmp(buf, "Send_", 5) != 0, "Not expecting: %s\n", buffer); 797342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 807342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 817342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project unsigned int opcode; 827342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 837342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(advance(&buf), "Could not find opcode in: %s\n", buffer); 847342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(sscanf(buf, "0x%04x\n", &opcode) != 1, 857342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "Could not find opcode in: %s\n", buffer); 867342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 877342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 887342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project unsigned char data[1024]; 897342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project unsigned char *dp = data; 907342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 917342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project while (!advance(&buf)) { 927342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project switch (*buf) { 937342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case '"': 947342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf++; 957342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project while (*buf != '"' && *buf != 0) { 967342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(dp > data + sizeof(data), 977342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "Too much data: %s\n", buffer); 987342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(sscanf(buf, "%02x", (unsigned int *)dp) != 1, 997342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "Error parsing (%d): %s\n", __LINE__, buffer); 1007342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project dp++; 1017342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf += 2; 1027342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project if (*buf == ':') 1037342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf++; 1047342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project } 1057342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project break; 1067342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case '0': 1077342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf++; 1087342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(*buf != 'x', "Error parsing: %s\n", buffer); 1097342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf++; 1107342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1117342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project // find length of this piece of data 1127342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project char *end = buf; 1137342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project while (isalnum(*end)) 1147342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project end++; 1157342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1167342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project // switch on length 1177342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project switch ((unsigned int)end - (unsigned int)buf) { 1187342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case 2: 1197342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(sscanf(buf, "%02x", (unsigned int *)dp) != 1, 1207342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "Error parsing (%d): %s\n", __LINE__, buffer); 1217342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf += 2; 1227342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project dp += 1; 1237342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project break; 1247342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case 4: 1257342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(sscanf(buf, "%04x", (unsigned int *)dp) != 1, 1267342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "Error parsing (%d): %s\n", __LINE__, buffer); 1277342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf += 4; 1287342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project dp += 2; 1297342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project break; 1307342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case 8: 1317342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(sscanf(buf, "%08x", (unsigned int *)dp) != 1, 1327342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project "Error parsing (%d): %s\n", __LINE__, buffer); 1337342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf += 8; 1347342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project dp += 4; 1357342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project break; 1367342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project default: 1377342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(1, "Error parsing (%d): %s\n", __LINE__, buffer); 1387342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project } 1397342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project break; 1407342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project default: 1417342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(1, "Error parsing (%d): %s\n", __LINE__, buffer); 1427342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project } 1437342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project } 1447342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1457342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project dump_record(file_out, opcode, dp - data, data); 1467342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project} 1477342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1487342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1497342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectint main(int argc, char **argv) { 1507342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1517342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project if (argc != 3) 1527342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project usage(); 1537342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1547342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FILE *file_in = fopen(argv[1], "r"); 1557342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(!file_in, "Could not open %s: %s\n", argv[1], strerror(errno)); 1567342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1577342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FILE *file_out = fopen(argv[2], "w+"); 1587342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(!file_out, "Could not open %s: %s\n", argv[2], strerror(errno)); 1597342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1607342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project char buffer[1024]; 1617342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project char *buf; 1627342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1637342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project while (fgets(buffer, 1024, file_in) != NULL) { 1647342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf = buffer; 1657342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project while (*buf && isspace(*buf)) 1667342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project buf++; 1677342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project switch (*buf) { 1687342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case 'S': 1697342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project process_line(file_out, buf, buffer); 1707342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project break; 1717342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case 'W': // Wait_HCI_Command... meta-data, not needed 1727342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case '#': 1737342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project case 0: 1747342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project continue; 1757342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project default: 1767342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project FAILIF(1, "Don't know what to do with: %s\n", buffer); 1777342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project } 1787342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project } 1797342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1807342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project fclose(file_in); 1817342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project fclose(file_out); 1827342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project 1837342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project return 0; 1847342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project} 185