• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
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 <config.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <getopt.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 
35 #include <bluetooth/bluetooth.h>
36 #include <bluetooth/hci.h>
37 #include <bluetooth/hci_lib.h>
38 
39 #include "oui.h"
40 
41 static int transient = 0;
42 
generic_reset_device(int dd)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 
ericsson_write_bd_addr(int dd,bdaddr_t * bdaddr)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 
ericsson_store_in_flash(int dd,uint8_t user_id,uint8_t flash_length,uint8_t * flash_data)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 
csr_write_bd_addr(int dd,bdaddr_t * bdaddr)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 
csr_reset_device(int dd)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 
ti_write_bd_addr(int dd,bdaddr_t * bdaddr)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 
bcm_write_bd_addr(int dd,bdaddr_t * bdaddr)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_ZEEVO_WRITE_BD_ADDR		0x0001
254 typedef struct {
255 	bdaddr_t	bdaddr;
256 } __attribute__ ((packed)) zeevo_write_bd_addr_cp;
257 #define ZEEVO_WRITE_BD_ADDR_CP_SIZE 6
258 
zeevo_write_bd_addr(int dd,bdaddr_t * bdaddr)259 static int zeevo_write_bd_addr(int dd, bdaddr_t *bdaddr)
260 {
261 	struct hci_request rq;
262 	zeevo_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_ZEEVO_WRITE_BD_ADDR;
270 	rq.cparam = &cp;
271 	rq.clen   = ZEEVO_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 
st_write_bd_addr(int dd,bdaddr_t * bdaddr)281 static int st_write_bd_addr(int dd, bdaddr_t *bdaddr)
282 {
283 	return ericsson_store_in_flash(dd, 0xfe, 6, (uint8_t *) bdaddr);
284 }
285 
286 static struct {
287 	uint16_t compid;
288 	int (*write_bd_addr)(int dd, bdaddr_t *bdaddr);
289 	int (*reset_device)(int dd);
290 } vendor[] = {
291 	{ 0,		ericsson_write_bd_addr,	NULL			},
292 	{ 10,		csr_write_bd_addr,	csr_reset_device	},
293 	{ 13,		ti_write_bd_addr,	NULL			},
294 	{ 15,		bcm_write_bd_addr,	generic_reset_device	},
295 	{ 18,		zeevo_write_bd_addr,	NULL			},
296 	{ 48,		st_write_bd_addr,	generic_reset_device	},
297 	{ 57,		ericsson_write_bd_addr,	generic_reset_device	},
298 	{ 65535,	NULL,			NULL			},
299 };
300 
usage(void)301 static void usage(void)
302 {
303 	printf("bdaddr - Utility for changing the Bluetooth device address\n\n");
304 	printf("Usage:\n"
305 		"\tbdaddr [-i <dev>] [-r] [-t] [new bdaddr]\n");
306 }
307 
308 static struct option main_options[] = {
309 	{ "device",	1, 0, 'i' },
310 	{ "reset",	0, 0, 'r' },
311 	{ "transient",	0, 0, 't' },
312 	{ "help",	0, 0, 'h' },
313 	{ 0, 0, 0, 0 }
314 };
315 
main(int argc,char * argv[])316 int main(int argc, char *argv[])
317 {
318 	struct hci_dev_info di;
319 	struct hci_version ver;
320 	bdaddr_t bdaddr;
321 	char addr[18], oui[9], *comp;
322 	int i, dd, opt, dev = 0, reset = 0;
323 
324 	bacpy(&bdaddr, BDADDR_ANY);
325 
326 	while ((opt=getopt_long(argc, argv, "+i:rth", main_options, NULL)) != -1) {
327 		switch (opt) {
328 		case 'i':
329 			dev = hci_devid(optarg);
330 			if (dev < 0) {
331 				perror("Invalid device");
332 				exit(1);
333 			}
334 			break;
335 
336 		case 'r':
337 			reset = 1;
338 			break;
339 
340 		case 't':
341 			transient = 1;
342 			break;
343 
344 		case 'h':
345 		default:
346 			usage();
347 			exit(0);
348 		}
349 	}
350 
351 	argc -= optind;
352 	argv += optind;
353 	optind = 0;
354 
355 	dd = hci_open_dev(dev);
356 	if (dd < 0) {
357 		fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
358 						dev, strerror(errno), errno);
359 		exit(1);
360 	}
361 
362 	if (hci_devinfo(dev, &di) < 0) {
363 		fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n",
364 						dev, strerror(errno), errno);
365 		hci_close_dev(dd);
366 		exit(1);
367 	}
368 
369 	if (hci_read_local_version(dd, &ver, 1000) < 0) {
370 		fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n",
371 						dev, strerror(errno), errno);
372 		hci_close_dev(dd);
373 		exit(1);
374 	}
375 
376 	if (!bacmp(&di.bdaddr, BDADDR_ANY)) {
377 		if (hci_read_bd_addr(dd, &bdaddr, 1000) < 0) {
378 			fprintf(stderr, "Can't read address for hci%d: %s (%d)\n",
379 						dev, strerror(errno), errno);
380 			hci_close_dev(dd);
381 			exit(1);
382 		}
383 	} else
384 		bacpy(&bdaddr, &di.bdaddr);
385 
386 	printf("Manufacturer:   %s (%d)\n",
387 			bt_compidtostr(ver.manufacturer), ver.manufacturer);
388 
389 	ba2oui(&bdaddr, oui);
390 	comp = ouitocomp(oui);
391 
392 	ba2str(&bdaddr, addr);
393 	printf("Device address: %s", addr);
394 
395 	if (comp) {
396 		printf(" (%s)\n", comp);
397 		free(comp);
398 	} else
399 		printf("\n");
400 
401 	if (argc < 1) {
402 		hci_close_dev(dd);
403 		exit(0);
404 	}
405 
406 	str2ba(argv[0], &bdaddr);
407 	if (!bacmp(&bdaddr, BDADDR_ANY)) {
408 		hci_close_dev(dd);
409 		exit(0);
410 	}
411 
412 	for (i = 0; vendor[i].compid != 65535; i++)
413 		if (ver.manufacturer == vendor[i].compid) {
414 			ba2oui(&bdaddr, oui);
415 			comp = ouitocomp(oui);
416 
417 			ba2str(&bdaddr, addr);
418 			printf("New BD address: %s", addr);
419 
420 			if (comp) {
421 				printf(" (%s)\n\n", comp);
422 				free(comp);
423 			} else
424 				printf("\n\n");
425 
426 
427 			if (vendor[i].write_bd_addr(dd, &bdaddr) < 0) {
428 				fprintf(stderr, "Can't write new address\n");
429 				hci_close_dev(dd);
430 				exit(1);
431 			}
432 
433 			printf("Address changed - ");
434 
435 			if (reset && vendor[i].reset_device) {
436 				if (vendor[i].reset_device(dd) < 0) {
437 					printf("Reset device manually\n");
438 				} else {
439 					ioctl(dd, HCIDEVRESET, dev);
440 					printf("Device reset successully\n");
441 				}
442 			} else {
443 				printf("Reset device now\n");
444 			}
445 
446 			//ioctl(dd, HCIDEVRESET, dev);
447 			//ioctl(dd, HCIDEVDOWN, dev);
448 			//ioctl(dd, HCIDEVUP, dev);
449 
450 			hci_close_dev(dd);
451 			exit(0);
452 		}
453 
454 	hci_close_dev(dd);
455 
456 	printf("\n");
457 	fprintf(stderr, "Unsupported manufacturer\n");
458 
459 	exit(1);
460 }
461