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