├── Makefile ├── .gitignore ├── oui.h ├── oui.c ├── README.md └── bdaddr.c /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | LINK_OPT=-lbluetooth 3 | RM=rm 4 | 5 | default: bdaddr 6 | 7 | bdaddr: bdaddr.o oui.o 8 | $(CC) -o bdaddr bdaddr.o oui.o $(LINK_OPT) 9 | 10 | bdaddr.o: bdaddr.c 11 | $(CC) -c bdaddr.c 12 | 13 | oui.o: oui.c 14 | $(CC) -c oui.c 15 | 16 | clean: 17 | $(RM) -f *.o 18 | $(RM) -f bdaddr 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /oui.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * BlueZ - Bluetooth protocol stack for Linux 4 | * 5 | * Copyright (C) 2004-2006 Marcel Holtmann 6 | * 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | * 22 | */ 23 | 24 | char *ouitocomp(const char *oui); 25 | int oui2comp(const char *oui, char *comp, size_t size); 26 | -------------------------------------------------------------------------------- /oui.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * BlueZ - Bluetooth protocol stack for Linux 4 | * 5 | * Copyright (C) 2004-2006 Marcel Holtmann 6 | * 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | * 22 | */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | #include 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "oui.h" 38 | 39 | /* http://standards.ieee.org/regauth/oui/oui.txt */ 40 | 41 | #define OUIFILE "/var/lib/misc/oui.txt" 42 | 43 | char *ouitocomp(const char *oui) 44 | { 45 | struct stat st; 46 | char *str, *map, *off, *end; 47 | int fd; 48 | 49 | fd = open("oui.txt", O_RDONLY); 50 | if (fd < 0) { 51 | fd = open(OUIFILE, O_RDONLY); 52 | if (fd < 0) { 53 | fd = open("/usr/share/misc/oui.txt", O_RDONLY); 54 | if (fd < 0) 55 | return NULL; 56 | } 57 | } 58 | 59 | if (fstat(fd, &st) < 0) { 60 | close(fd); 61 | return NULL; 62 | } 63 | 64 | str = malloc(128); 65 | if (!str) { 66 | close(fd); 67 | return NULL; 68 | } 69 | 70 | memset(str, 0, 128); 71 | 72 | map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); 73 | if (!map || map == MAP_FAILED) { 74 | free(str); 75 | close(fd); 76 | return NULL; 77 | } 78 | 79 | off = strstr(map, oui); 80 | if (off) { 81 | off += 18; 82 | end = strpbrk(off, "\r\n"); 83 | strncpy(str, off, end - off); 84 | } else { 85 | free(str); 86 | str = NULL; 87 | } 88 | 89 | munmap(map, st.st_size); 90 | 91 | close(fd); 92 | 93 | return str; 94 | } 95 | 96 | int oui2comp(const char *oui, char *comp, size_t size) 97 | { 98 | char *tmp; 99 | 100 | tmp = ouitocomp(oui); 101 | if (!tmp) 102 | return -1; 103 | 104 | snprintf(comp, size, "%s", tmp); 105 | 106 | free(tmp); 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bdaddr 2 | Updated version of the bluez bdaddr tool 3 | 4 | NAME 5 | ==== 6 | 7 | **bdaddr** \- Utility for changing the Bluetooth device address 8 | 9 | SYNOPSIS 10 | ======== 11 | 12 | **bdaddr** 13 | 14 | **bdaddr** -h 15 | 16 | **bdaddr** [-i ] [-r] [-t] [new bdaddr] 17 | 18 | DESCRIPTION 19 | =========== 20 | 21 | **bdaddr** is used to query or set the local Bluetooth device address (BD_ADDR). 22 | 23 | If run with no arguments, bdaddr prints the chip manufacturer's name, and the current BD_ADDR. 24 | 25 | If the IEEE OUI index file "oui.txt" is installed on the system, the BD_ADDR owner will be 26 | displayed. 27 | 28 | If the optional [new bdaddr] argument is given, the device will be reprogrammed with that address. 29 | This can either be permanent or temporary, as specified by the -t flag. 30 | 31 | In both cases, the device must be reset before the new address will become active. 32 | This can be done with a 'soft' reset by 33 | specifying the -r flag, or a 'hard' reset by removing and replugging the 34 | device. A 'hard' reset will cause the address to revert to the current 35 | non-volatile value. 36 | The command `hciconfig hci0 reset` can be used in most cases to reset manually. 37 | 38 | >bdaddr 39 | uses manufacturer specific commands to set the address, and is therefore 40 | device specific. 41 | >For this reason, not all devices are supported, and not all 42 | options are supported on all devices. 43 | 44 | Supported manufacturers in this fork are: 45 | 46 | * Ericsson 47 | * Cambridge Silicon Radio (CSR) 48 | * Texas Instruments (TI) 49 | * Zeevo 50 | * ST Microelectronics (ST) 51 | * Cypress Semiconductors (found in Raspberry Pi 4) 52 | * some Intel Corporation chips 53 | 54 | 55 | Options 56 | ------- 57 | 58 | ``` 59 | -h 60 | Gives a list of possible commands. 61 | 62 | -i 63 | Specify a particular device to operate on. If not specified, default is the 64 | first available device. 65 | 66 | -r 67 | Reset device and make new BD_ADDR active. 68 | 69 | CSR devices only : 70 | 71 | -t 72 | Temporary change. Do not write to non-volatile memory. 73 | ``` 74 | FILES 75 | ===== 76 | 77 | */usr/share/misc/oui.txt* 78 | 79 | IEEE Organizationally Unique Identifier master file. 80 | Manually update it on your system from: http://standards.ieee.org/regauth/oui/oui.txt 81 | (optional) 82 | 83 | BUILD 84 | ===== 85 | 86 | libbluetooth-dev package must be installed. 87 | 88 | To build, just type ```make``` in the source directory. 89 | 90 | BUGS 91 | ==== 92 | 93 | See GitHub Issues: 94 | 95 | AUTHORS 96 | ======= 97 | 98 | Orginal 99 | Written by Marcel Holtmann , 100 | man page by Adam Laurie 101 | 102 | Updated by thxomas 103 | ~ 104 | 105 | -------------------------------------------------------------------------------- /bdaddr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * BlueZ - Bluetooth protocol stack for Linux 4 | * 5 | * Copyright (C) 2004-2006 Marcel Holtmann 6 | * 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; either version 2 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 | * 22 | */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | #include 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "oui.h" 40 | 41 | static int transient = 0; 42 | 43 | static int generic_reset_device(int dd) 44 | { 45 | bdaddr_t bdaddr; 46 | int err; 47 | 48 | err = hci_send_cmd(dd, 0x03, 0x0003, 0, NULL); 49 | if (err < 0) 50 | return err; 51 | 52 | return hci_read_bd_addr(dd, &bdaddr, 10000); 53 | } 54 | 55 | #define OCF_ERICSSON_WRITE_BD_ADDR 0x000d 56 | typedef struct { 57 | bdaddr_t bdaddr; 58 | } __attribute__ ((packed)) ericsson_write_bd_addr_cp; 59 | #define ERICSSON_WRITE_BD_ADDR_CP_SIZE 6 60 | 61 | static int ericsson_write_bd_addr(int dd, bdaddr_t *bdaddr) 62 | { 63 | struct hci_request rq; 64 | ericsson_write_bd_addr_cp cp; 65 | 66 | memset(&cp, 0, sizeof(cp)); 67 | bacpy(&cp.bdaddr, bdaddr); 68 | 69 | memset(&rq, 0, sizeof(rq)); 70 | rq.ogf = OGF_VENDOR_CMD; 71 | rq.ocf = OCF_ERICSSON_WRITE_BD_ADDR; 72 | rq.cparam = &cp; 73 | rq.clen = ERICSSON_WRITE_BD_ADDR_CP_SIZE; 74 | rq.rparam = NULL; 75 | rq.rlen = 0; 76 | 77 | if (hci_send_req(dd, &rq, 1000) < 0) 78 | return -1; 79 | 80 | return 0; 81 | } 82 | 83 | #define OCF_ERICSSON_STORE_IN_FLASH 0x0022 84 | typedef struct { 85 | uint8_t user_id; 86 | uint8_t flash_length; 87 | uint8_t flash_data[253]; 88 | } __attribute__ ((packed)) ericsson_store_in_flash_cp; 89 | #define ERICSSON_STORE_IN_FLASH_CP_SIZE 255 90 | 91 | static int ericsson_store_in_flash(int dd, uint8_t user_id, uint8_t flash_length, uint8_t *flash_data) 92 | { 93 | struct hci_request rq; 94 | ericsson_store_in_flash_cp cp; 95 | 96 | memset(&cp, 0, sizeof(cp)); 97 | cp.user_id = user_id; 98 | cp.flash_length = flash_length; 99 | if (flash_length > 0) 100 | memcpy(cp.flash_data, flash_data, flash_length); 101 | 102 | memset(&rq, 0, sizeof(rq)); 103 | rq.ogf = OGF_VENDOR_CMD; 104 | rq.ocf = OCF_ERICSSON_STORE_IN_FLASH; 105 | rq.cparam = &cp; 106 | rq.clen = ERICSSON_STORE_IN_FLASH_CP_SIZE; 107 | rq.rparam = NULL; 108 | rq.rlen = 0; 109 | 110 | if (hci_send_req(dd, &rq, 1000) < 0) 111 | return -1; 112 | 113 | return 0; 114 | } 115 | 116 | static int csr_write_bd_addr(int dd, bdaddr_t *bdaddr) 117 | { 118 | unsigned char cmd[] = { 0x02, 0x00, 0x0c, 0x00, 0x11, 0x47, 0x03, 0x70, 119 | 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 120 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 121 | 122 | unsigned char cp[254], rp[254]; 123 | struct hci_request rq; 124 | 125 | if (transient) 126 | cmd[14] = 0x08; 127 | 128 | cmd[16] = bdaddr->b[2]; 129 | cmd[17] = 0x00; 130 | cmd[18] = bdaddr->b[0]; 131 | cmd[19] = bdaddr->b[1]; 132 | cmd[20] = bdaddr->b[3]; 133 | cmd[21] = 0x00; 134 | cmd[22] = bdaddr->b[4]; 135 | cmd[23] = bdaddr->b[5]; 136 | 137 | memset(&cp, 0, sizeof(cp)); 138 | cp[0] = 0xc2; 139 | memcpy(cp + 1, cmd, sizeof(cmd)); 140 | 141 | memset(&rq, 0, sizeof(rq)); 142 | rq.ogf = OGF_VENDOR_CMD; 143 | rq.ocf = 0x00; 144 | rq.event = EVT_VENDOR; 145 | rq.cparam = cp; 146 | rq.clen = sizeof(cmd) + 1; 147 | rq.rparam = rp; 148 | rq.rlen = sizeof(rp); 149 | 150 | if (hci_send_req(dd, &rq, 2000) < 0) 151 | return -1; 152 | 153 | if (rp[0] != 0xc2) { 154 | errno = EIO; 155 | return -1; 156 | } 157 | 158 | if ((rp[9] + (rp[10] << 8)) != 0) { 159 | errno = ENXIO; 160 | return -1; 161 | } 162 | 163 | return 0; 164 | } 165 | 166 | static int csr_reset_device(int dd) 167 | { 168 | unsigned char cmd[] = { 0x02, 0x00, 0x09, 0x00, 169 | 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 170 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 171 | 172 | unsigned char cp[254], rp[254]; 173 | struct hci_request rq; 174 | 175 | if (transient) 176 | cmd[6] = 0x02; 177 | 178 | memset(&cp, 0, sizeof(cp)); 179 | cp[0] = 0xc2; 180 | memcpy(cp + 1, cmd, sizeof(cmd)); 181 | 182 | memset(&rq, 0, sizeof(rq)); 183 | rq.ogf = OGF_VENDOR_CMD; 184 | rq.ocf = 0x00; 185 | rq.event = EVT_VENDOR; 186 | rq.cparam = cp; 187 | rq.clen = sizeof(cmd) + 1; 188 | rq.rparam = rp; 189 | rq.rlen = sizeof(rp); 190 | 191 | if (hci_send_req(dd, &rq, 2000) < 0) 192 | return -1; 193 | 194 | return 0; 195 | } 196 | 197 | #define OCF_TI_WRITE_BD_ADDR 0x0006 198 | typedef struct { 199 | bdaddr_t bdaddr; 200 | } __attribute__ ((packed)) ti_write_bd_addr_cp; 201 | #define TI_WRITE_BD_ADDR_CP_SIZE 6 202 | 203 | static int ti_write_bd_addr(int dd, bdaddr_t *bdaddr) 204 | { 205 | struct hci_request rq; 206 | ti_write_bd_addr_cp cp; 207 | 208 | memset(&cp, 0, sizeof(cp)); 209 | bacpy(&cp.bdaddr, bdaddr); 210 | 211 | memset(&rq, 0, sizeof(rq)); 212 | rq.ogf = OGF_VENDOR_CMD; 213 | rq.ocf = OCF_TI_WRITE_BD_ADDR; 214 | rq.cparam = &cp; 215 | rq.clen = TI_WRITE_BD_ADDR_CP_SIZE; 216 | rq.rparam = NULL; 217 | rq.rlen = 0; 218 | 219 | if (hci_send_req(dd, &rq, 1000) < 0) 220 | return -1; 221 | 222 | return 0; 223 | } 224 | 225 | #define OCF_BCM_WRITE_BD_ADDR 0x0001 226 | typedef struct { 227 | bdaddr_t bdaddr; 228 | } __attribute__ ((packed)) bcm_write_bd_addr_cp; 229 | #define BCM_WRITE_BD_ADDR_CP_SIZE 6 230 | 231 | static int bcm_write_bd_addr(int dd, bdaddr_t *bdaddr) 232 | { 233 | struct hci_request rq; 234 | bcm_write_bd_addr_cp cp; 235 | 236 | memset(&cp, 0, sizeof(cp)); 237 | bacpy(&cp.bdaddr, bdaddr); 238 | 239 | memset(&rq, 0, sizeof(rq)); 240 | rq.ogf = OGF_VENDOR_CMD; 241 | rq.ocf = OCF_BCM_WRITE_BD_ADDR; 242 | rq.cparam = &cp; 243 | rq.clen = BCM_WRITE_BD_ADDR_CP_SIZE; 244 | rq.rparam = NULL; 245 | rq.rlen = 0; 246 | 247 | if (hci_send_req(dd, &rq, 1000) < 0) 248 | return -1; 249 | 250 | return 0; 251 | } 252 | 253 | #define OCF_INTEL_WRITE_BD_ADDR 0x0031 254 | typedef struct { 255 | bdaddr_t bdaddr; 256 | } __attribute__ ((packed)) intel_write_bd_addr_cp; 257 | #define INTEL_WRITE_BD_ADDR_CP_SIZE 6 258 | 259 | static int intel_write_bd_addr(int dd, bdaddr_t *bdaddr) 260 | { 261 | struct hci_request rq; 262 | intel_write_bd_addr_cp cp; 263 | 264 | memset(&cp, 0, sizeof(cp)); 265 | bacpy(&cp.bdaddr, bdaddr); 266 | 267 | memset(&rq, 0, sizeof(rq)); 268 | rq.ogf = OGF_VENDOR_CMD; 269 | rq.ocf = OCF_INTEL_WRITE_BD_ADDR; 270 | rq.cparam = &cp; 271 | rq.clen = INTEL_WRITE_BD_ADDR_CP_SIZE; 272 | rq.rparam = NULL; 273 | rq.rlen = 0; 274 | 275 | if (hci_send_req(dd, &rq, 1000) < 0) 276 | return -1; 277 | 278 | return 0; 279 | } 280 | 281 | static int intel_reset_device(int dd) 282 | { 283 | return -1; // request Manual reset 284 | } 285 | 286 | #define OCF_CYS_WRITE_BD_ADDR 0x001 287 | typedef struct { 288 | bdaddr_t bdaddr; 289 | } __attribute__ ((packed)) cys_write_bd_addr_cp; 290 | #define CYS_WRITE_BD_ADDR_CP_SIZE 6 291 | 292 | static int cys_write_bd_addr(int dd, bdaddr_t *bdaddr) 293 | { 294 | struct hci_request rq; 295 | cys_write_bd_addr_cp cp; 296 | 297 | memset(&cp, 0, sizeof(cp)); 298 | bacpy(&cp.bdaddr, bdaddr); 299 | 300 | memset(&rq, 0, sizeof(rq)); 301 | rq.ogf = OGF_VENDOR_CMD; 302 | rq.ocf = OCF_CYS_WRITE_BD_ADDR; 303 | rq.cparam = &cp; 304 | rq.clen = CYS_WRITE_BD_ADDR_CP_SIZE; 305 | rq.rparam = NULL; 306 | rq.rlen = 0; 307 | 308 | if (hci_send_req(dd, &rq, 1000) < 0) 309 | return -1; 310 | 311 | return 0; 312 | } 313 | 314 | static int cys_reset_device(int dd) 315 | { 316 | return -1; // request Manual reset 317 | } 318 | 319 | 320 | #define OCF_ZEEVO_WRITE_BD_ADDR 0x0001 321 | typedef struct { 322 | bdaddr_t bdaddr; 323 | } __attribute__ ((packed)) zeevo_write_bd_addr_cp; 324 | #define ZEEVO_WRITE_BD_ADDR_CP_SIZE 6 325 | 326 | static int zeevo_write_bd_addr(int dd, bdaddr_t *bdaddr) 327 | { 328 | struct hci_request rq; 329 | zeevo_write_bd_addr_cp cp; 330 | 331 | memset(&cp, 0, sizeof(cp)); 332 | bacpy(&cp.bdaddr, bdaddr); 333 | 334 | memset(&rq, 0, sizeof(rq)); 335 | rq.ogf = OGF_VENDOR_CMD; 336 | rq.ocf = OCF_ZEEVO_WRITE_BD_ADDR; 337 | rq.cparam = &cp; 338 | rq.clen = ZEEVO_WRITE_BD_ADDR_CP_SIZE; 339 | rq.rparam = NULL; 340 | rq.rlen = 0; 341 | 342 | if (hci_send_req(dd, &rq, 1000) < 0) 343 | return -1; 344 | 345 | return 0; 346 | } 347 | 348 | static int st_write_bd_addr(int dd, bdaddr_t *bdaddr) 349 | { 350 | return ericsson_store_in_flash(dd, 0xfe, 6, (uint8_t *) bdaddr); 351 | } 352 | 353 | static struct { 354 | uint16_t compid; 355 | int (*write_bd_addr)(int dd, bdaddr_t *bdaddr); 356 | int (*reset_device)(int dd); 357 | } vendor[] = { 358 | { 0, ericsson_write_bd_addr, NULL }, 359 | { 2, intel_write_bd_addr, intel_reset_device }, 360 | { 10, csr_write_bd_addr, csr_reset_device }, 361 | { 13, ti_write_bd_addr, NULL }, 362 | { 15, bcm_write_bd_addr, generic_reset_device }, 363 | { 18, zeevo_write_bd_addr, NULL }, 364 | { 48, st_write_bd_addr, generic_reset_device }, 365 | { 57, ericsson_write_bd_addr, generic_reset_device }, 366 | { 305, cys_write_bd_addr, cys_reset_device }, 367 | { 65535, NULL, NULL }, 368 | }; 369 | 370 | static void usage(void) 371 | { 372 | printf("bdaddr - Utility for changing the Bluetooth device address\n\n"); 373 | printf("Usage:\n" 374 | "\tbdaddr [-i ] [-r] [-t] [new bdaddr]\n"); 375 | } 376 | 377 | static struct option main_options[] = { 378 | { "device", 1, 0, 'i' }, 379 | { "reset", 0, 0, 'r' }, 380 | { "transient", 0, 0, 't' }, 381 | { "help", 0, 0, 'h' }, 382 | { 0, 0, 0, 0 } 383 | }; 384 | 385 | int main(int argc, char *argv[]) 386 | { 387 | struct hci_dev_info di; 388 | struct hci_version ver; 389 | bdaddr_t bdaddr; 390 | char addr[18], oui[9], *comp; 391 | int i, dd, opt, dev = 0, reset = 0; 392 | 393 | bacpy(&bdaddr, BDADDR_ANY); 394 | 395 | while ((opt=getopt_long(argc, argv, "+i:rth", main_options, NULL)) != -1) { 396 | switch (opt) { 397 | case 'i': 398 | dev = hci_devid(optarg); 399 | if (dev < 0) { 400 | perror("Invalid device"); 401 | exit(1); 402 | } 403 | break; 404 | 405 | case 'r': 406 | reset = 1; 407 | break; 408 | 409 | case 't': 410 | transient = 1; 411 | break; 412 | 413 | case 'h': 414 | default: 415 | usage(); 416 | exit(0); 417 | } 418 | } 419 | 420 | argc -= optind; 421 | argv += optind; 422 | optind = 0; 423 | 424 | dd = hci_open_dev(dev); 425 | if (dd < 0) { 426 | fprintf(stderr, "Can't open device hci%d: %s (%d)\n", 427 | dev, strerror(errno), errno); 428 | exit(1); 429 | } 430 | 431 | if (hci_devinfo(dev, &di) < 0) { 432 | fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n", 433 | dev, strerror(errno), errno); 434 | hci_close_dev(dd); 435 | exit(1); 436 | } 437 | 438 | if (hci_read_local_version(dd, &ver, 1000) < 0) { 439 | fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n", 440 | dev, strerror(errno), errno); 441 | hci_close_dev(dd); 442 | exit(1); 443 | } 444 | 445 | if (!bacmp(&di.bdaddr, BDADDR_ANY)) { 446 | if (hci_read_bd_addr(dd, &bdaddr, 1000) < 0) { 447 | fprintf(stderr, "Can't read address for hci%d: %s (%d)\n", 448 | dev, strerror(errno), errno); 449 | hci_close_dev(dd); 450 | exit(1); 451 | } 452 | } else 453 | bacpy(&bdaddr, &di.bdaddr); 454 | 455 | printf("Manufacturer: %s (%d)\n", 456 | bt_compidtostr(ver.manufacturer), ver.manufacturer); 457 | 458 | ba2oui(&bdaddr, oui); 459 | comp = (char *)ouitocomp(oui); 460 | 461 | ba2str(&bdaddr, addr); 462 | printf("Device address: %s", addr); 463 | 464 | if (comp) { 465 | printf(" (%s)\n", comp); 466 | free(comp); 467 | } else 468 | printf("\n"); 469 | 470 | if (argc < 1) { 471 | hci_close_dev(dd); 472 | exit(0); 473 | } 474 | 475 | str2ba(argv[0], &bdaddr); 476 | if (!bacmp(&bdaddr, BDADDR_ANY)) { 477 | hci_close_dev(dd); 478 | exit(0); 479 | } 480 | 481 | for (i = 0; vendor[i].compid != 65535; i++) 482 | if (ver.manufacturer == vendor[i].compid) { 483 | ba2oui(&bdaddr, oui); 484 | comp = (char *)ouitocomp(oui); 485 | 486 | ba2str(&bdaddr, addr); 487 | printf("New BD address: %s", addr); 488 | 489 | if (comp) { 490 | printf(" (%s)\n\n", comp); 491 | free(comp); 492 | } else 493 | printf("\n\n"); 494 | 495 | 496 | if (vendor[i].write_bd_addr(dd, &bdaddr) < 0) { 497 | fprintf(stderr, "Can't write new address\n"); 498 | hci_close_dev(dd); 499 | exit(1); 500 | } 501 | 502 | printf("Address changed - "); 503 | 504 | if (reset && vendor[i].reset_device) { 505 | if (vendor[i].reset_device(dd) < 0) { 506 | printf("Reset device manually\n"); 507 | } else { 508 | ioctl(dd, HCIDEVRESET, dev); 509 | printf("Device reset successully\n"); 510 | } 511 | } else { 512 | printf("Reset device now\n"); 513 | } 514 | 515 | //ioctl(dd, HCIDEVRESET, dev); 516 | //ioctl(dd, HCIDEVDOWN, dev); 517 | //ioctl(dd, HCIDEVUP, dev); 518 | 519 | hci_close_dev(dd); 520 | exit(0); 521 | } 522 | 523 | hci_close_dev(dd); 524 | 525 | printf("\n"); 526 | fprintf(stderr, "Unsupported manufacturer\n"); 527 | 528 | exit(1); 529 | } 530 | --------------------------------------------------------------------------------