1#!/usr/bin/env python 2# BlueKitchen GmbH (c) 2012-2014 3 4# documentation for TI Vendor Specific commands: 5# http://processors.wiki.ti.com/index.php/CC256x_VS_HCI_Commands 6 7import glob 8import re 9import sys 10import os 11 12print ''' 13CC256x init script conversion tool for use with BTstack, v0.1 14Copyright 2012-2014 BlueKitchen GmbH 15''' 16 17usage = '''This script perpares init scripts for TI's 18CC256x chipsets for use with BTstack . 19 20Please download the Service Pack for your module from http://processors.wiki.ti.com/index.php/CC256x_Downloads 21Then, unzip it and copy the *.bts file into this folder and start the script again. 22''' 23 24fartext = ''' 25#if defined(__GNUC__) && defined(__MSP430X__) && (__MSP430X__ > 0) 26__attribute__((section (".fartext"))) 27#endif 28#ifdef __AVR__ 29__attribute__((__progmem__)) 30#endif 31''' 32 33data_indent = ' ' 34 35def read_little_endian_16(f): 36 low = f.read(1) 37 if low == "": 38 return -1 39 high = f.read(1) 40 return ord(high) << 8 | ord(low) 41 42def append_power_vector_gfsk(additions, str_list, data_indent): 43 additions.append("- added HCI_VS_SET_POWER_VECTOR(GFSK) template") 44 str_list.append(data_indent) 45 str_list.append('// BTstack: added HCI_VS_SET_POWER_VECTOR(GFSK) 0xFD82 template\n'); 46 str_list.append(data_indent) 47 str_list.append("0x01, 0x82, 0xfd, 0x14, 0x00, 0x9c, 0x18, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xdc,\n"); 48 str_list.append(data_indent) 49 str_list.append("0xe6, 0xf0, 0xfa, 0x04, 0x0e, 0x18, 0xff, 0x00, 0x00,\n\n"); 50 return 25 51 52def append_power_vector_edr2(additions, str_list, data_indent): 53 additions.append("- added HCI_VS_SET_POWER_VECTOR(EDR2) template") 54 str_list.append(data_indent) 55 str_list.append('// BTstack: added HCI_VS_SET_POWER_VECTOR(EDR2) 0xFD82 template\n'); 56 str_list.append(data_indent) 57 str_list.append("0x01, 0x82, 0xfd, 0x14, 0x01, 0x9c, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xd8, \n"); 58 str_list.append(data_indent) 59 str_list.append("0xe2, 0xec, 0xf6, 0x00, 0x0a, 0x14, 0xff, 0x00, 0x00,\n\n"); 60 return 25 61 62def append_power_vector_edr3(additions, str_list, data_indent): 63 additions.append("- added HCI_VS_SET_POWER_VECTOR(EDR3) template") 64 str_list.append(data_indent) 65 str_list.append('// BTstack: added HCI_VS_SET_POWER_VECTOR(EDR3) 0xFD82 for EDR3 template\n'); 66 str_list.append(data_indent) 67 str_list.append("0x01, 0x82, 0xfd, 0x14, 0x02, 0x9c, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce, 0xd8,\n"); 68 str_list.append(data_indent) 69 str_list.append("0xe2, 0xec, 0xf6, 0x00, 0x0a, 0x14, 0xff, 0x00, 0x00,\n\n"); 70 return 25 71 72def append_class2_single_power(additions, str_list, data_indent): 73 additions.append("- added HCI_VS_SET_CLASS2_SINGLE_POWER template") 74 str_list.append(data_indent) 75 str_list.append('// BTstack: added HCI_VS_SET_CLASS2_SINGLE_POWER 0xFD87 template\n'); 76 str_list.append(data_indent) 77 str_list.append("0x01, 0x87, 0xfd, 0x03, 0x0d, 0x0d, 0x0d,\n\n"); 78 return 7 79 80def append_ehcill(additions, str_list, data_indent): 81 additions.append("- added eHCILL template") 82 str_list.append('\n') 83 str_list.append(data_indent) 84 str_list.append('// BTstack: added HCI_VS_Sleep_Mode_Configurations 0xFD0C template for eHCILL\n'); 85 str_list.append(data_indent) 86 str_list.append('0x01, 0x0c, 0xfd, 9 , 1, 0, 0, 0xff, 0xff, 0xff, 0xff, 100, 0,\n\n'); 87 return 13 88 89def append_calibration_sequence(additions, str_list, data_indent): 90 additions.append("- added calibration sequence") 91 str_list.append(data_indent) 92 str_list.append("// BTstack: added calibration sequence\n") 93 str_list.append(data_indent) 94 str_list.append("0x01, 0x80, 0xfd, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,\n") 95 str_list.append(data_indent) 96 str_list.append("0x01, 0x80, 0xfd, 0x06, 0x3c, 0xf0, 0x5f, 0x00, 0x00, 0x00,\n\n") 97 return 20 98 99def convert_bts(main_bts_file, bts_add_on): 100 array_name = 'cc256x' 101 c_file = main_bts_file.replace('bts', 'c') 102 103 input_files = [ main_bts_file ] 104 if bts_add_on != "": 105 input_files.append(bts_add_on) 106 107 with open(c_file, 'w') as fout: 108 109 # assert script contains templates for configuration by BTstack 110 have_eHCILL = False 111 have_power_vector_gfsk = False; 112 have_power_vector_edr2 = False; 113 have_power_vector_edr3 = False; 114 have_class2_single_power = False; 115 116 print "Creating {0}".format(c_file) 117 118 part_size = 0 119 120 parts = 0 121 str_list = [] 122 part_strings = [] 123 part_sizes = [] 124 additions = [] 125 126 for bts_file in input_files: 127 128 with open (bts_file, 'rb') as fin: 129 130 print "- parsing {0:32}".format(bts_file) 131 132 header = fin.read(32) 133 if header[0:4] != 'BTSB': 134 print 'Error', bts_file, 'is not a valid .BTS file' 135 sys.exit(1) 136 137 138 while True: 139 action_type = read_little_endian_16(fin) 140 action_size = read_little_endian_16(fin) 141 action_data = fin.read(action_size) 142 143 if (action_type == 1): # hci command 144 145 opcode = (ord(action_data[2]) << 8) | ord(action_data[1]) 146 if opcode == 0xFF36: 147 continue # skip baud rate command 148 if opcode == 0xFD0C: 149 have_eHCILL = True 150 if opcode == 0xFD82: 151 modulation_type = ord(action_data[4]) 152 if modulation_type == 0: 153 have_power_vector_gfsk = True 154 elif modulation_type == 1: 155 have_power_vector_edr2 + True 156 elif modulation_type == 2: 157 have_power_vector_edr3 = True 158 if opcode == 0xFD80: 159 # add missing power command templates 160 if not have_power_vector_gfsk: 161 part_size += append_power_vector_gfsk(additions, str_list, data_indent) 162 have_power_vector_gfsk = True; 163 if not have_power_vector_edr2: 164 part_size += append_power_vector_edr2(additions, str_list, data_indent) 165 have_power_vector_edr2 = True; 166 if not have_power_vector_edr3: 167 part_size += append_power_vector_edr2(additions, str_list, data_indent) 168 have_power_vector_edr3 = True; 169 if not have_class2_single_power: 170 part_size += append_class2_single_power(additions, str_list, data_indent) 171 have_class2_single_power = True; 172 173 counter = 0 174 str_list.append(data_indent) 175 for byte in action_data: 176 str_list.append("0x{0:02x}, ".format(ord(byte))) 177 counter = counter + 1 178 if (counter != 15): 179 continue 180 counter = 0 181 str_list.append("\n") 182 str_list.append(data_indent) 183 str_list.append("\n\n") 184 185 part_size = part_size + action_size 186 187 # 30 kB chunks 188 if part_size < 30 * 1024: 189 continue 190 191 part_strings.append(''.join(str_list)) 192 part_sizes.append(part_size) 193 parts += 1 194 195 str_list = [] 196 part_size = 0 197 198 if (action_type == 6): # comment 199 action_data = action_data.rstrip('\0') 200 str_list.append(data_indent) 201 str_list.append("// " + action_data + "\n") 202 203 if (action_type < 0): # EOF 204 break; 205 206 207 if not have_eHCILL: 208 part_size += append_ehcill(additions, str_list, data_indent) 209 210 # append calibration step, if missing so far 211 all_power_commands_provided = have_power_vector_gfsk and have_power_vector_edr2 and have_power_vector_edr3 and have_class2_single_power 212 if not all_power_commands_provided: 213 str_list.append("\n" + data_indent + "// BTstack: no calibration sequence found, adding power commands and calibration\n\n") 214 part_size += append_power_vector_gfsk(additions, str_list, data_indent) 215 part_size += append_power_vector_edr2(additions, str_list, data_indent) 216 part_size += append_power_vector_edr2(additions, str_list, data_indent) 217 part_size += append_class2_single_power(additions, str_list, data_indent) 218 part_size += append_calibration_sequence(additions, str_list, data_indent) 219 220 part_strings.append(''.join(str_list)) 221 part_sizes.append(part_size) 222 parts += 1 223 224 fout.write( '// init script created from\n') 225 fout.write( '// - {0}\n'.format(main_bts_file)) 226 if bts_add_on != "": 227 fout.write( '// - {0}\n'.format(bts_add_on)) 228 fout.write( '#include <stdint.h>\n') 229 230 part = 0 231 size = 0 232 for part_size in part_sizes: 233 part += 1 234 size += part_size 235 print "- part", part, "size", part_size 236 237 print '- total size', size 238 239 print "\n".join(additions) 240 241 242 part = 0 243 for part_text in part_strings: 244 part += 1 245 suffix = '' 246 247 if part == 1: 248 fout.write( fartext ) 249 250 if (part > 1): 251 suffix = '_{0}'.format(part) 252 fout.write('#if defined(__GNUC__) && defined(__GNUC__) && (__MSP430X__ > 0)\n') 253 fout.write('};\n') 254 fout.write('__attribute__((section (".fartext")))\n') 255 256 fout.write('const uint8_t {0}_init_script{1}[] = {2}\n\n'.format(array_name, suffix, '{')) 257 258 if (part > 1): 259 fout.write('#endif\n') 260 261 fout.write(part_text) 262 263 264 fout.write('};\n\n') 265 266 fout.write('const uint32_t {0}_init_script_size = {1};\n\n'.format(array_name,size)); 267 # fout.write('void main() {0} printf("size {1}\\n", {2}_init_script_size); {3}'.format('{', '%u', array_name,'}')); 268 269# get list of *.bts files 270files = glob.glob('*.bts') 271if not files: 272 print usage 273 sys.exit(1) 274 275# convert each of them 276for name in files: 277 name_lower = name.lower() 278 # skip BLE and AVRP add-ons 279 if name_lower.startswith('ble_init_cc'): 280 print "Skipping BLE add-on", name 281 continue 282 if name_lower.startswith('avpr_init_cc'): 283 print "Skipping AVPR add-on", name 284 continue 285 if re.match("initscripts_tiinit_.*_ble_add-on.bts", name_lower): 286 print "Skipping BLE add-on", name 287 continue 288 if re.match("initscripts_tiinit_.*_avpr_add-on.bts", name_lower): 289 print "Skipping AVPR add-on", name 290 291 # check for BLE add-on 292 add_on = "" 293 name_parts = re.match('bluetooth_init_(.....+_...)_.*.bts', name) 294 if name_parts: 295 potential_add_on = 'BLE_init_%s.bts' % name_parts.group(1) 296 if os.path.isfile(potential_add_on): 297 add_on = potential_add_on 298 print "Found", add_on, "add on for", name 299 300 name_parts = re.match('initscripts_TIInit_(\d*\.\d*\.\d*)_.*.bts', name) 301 if name_parts: 302 potential_add_on = 'initscripts_TIInit_%s_ble_add-on.bts' % name_parts.group(1) 303 if os.path.isfile(potential_add_on): 304 add_on = potential_add_on 305 print "Found", add_on, "add on for", name 306 307 convert_bts(name, add_on) 308 309# done 310print '\nConversion(s) successful!\n' 311 312 313 314