1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2004-2009  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
41static int transient = 0;
42
43static 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
56typedef struct {
57	bdaddr_t	bdaddr;
58} __attribute__ ((packed)) ericsson_write_bd_addr_cp;
59#define ERICSSON_WRITE_BD_ADDR_CP_SIZE 6
60
61static 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
84typedef 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
91static 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
116static 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
166static 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
198typedef struct {
199	bdaddr_t	bdaddr;
200} __attribute__ ((packed)) ti_write_bd_addr_cp;
201#define TI_WRITE_BD_ADDR_CP_SIZE 6
202
203static 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
226typedef struct {
227	bdaddr_t	bdaddr;
228} __attribute__ ((packed)) bcm_write_bd_addr_cp;
229#define BCM_WRITE_BD_ADDR_CP_SIZE 6
230
231static 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
254typedef struct {
255	bdaddr_t	bdaddr;
256} __attribute__ ((packed)) zeevo_write_bd_addr_cp;
257#define ZEEVO_WRITE_BD_ADDR_CP_SIZE 6
258
259static 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
281static 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
286static 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
301static 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
308static 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
316int 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