diff options
| -rw-r--r-- | acinclude.m4 | 7 | ||||
| -rw-r--r-- | tools/Makefile.am | 20 | ||||
| -rw-r--r-- | tools/dfubabel.1 | 38 | ||||
| -rw-r--r-- | tools/dfubabel.c | 211 | 
4 files changed, 273 insertions, 3 deletions
| diff --git a/acinclude.m4 b/acinclude.m4 index 5797add0..8eb0effc 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -187,6 +187,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [  	avctrl_enable=no  	hid2hci_enable=${usb_found}  	dfutool_enable=no +	dfubabel_enable=no  	AC_ARG_ENABLE(fortify, AC_HELP_STRING([--disable-fortify], [disable compile time buffer checks]), [  		fortify_enable=${enableval} @@ -218,6 +219,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [  		avctrl_enable=${enableval}  		hid2hci_enable=${enableval}  		dfutool_enable=${enableval} +		dfubabel_enable=${enableval}  	])  	AC_ARG_ENABLE(inotify, AC_HELP_STRING([--enable-inotify], [enable inotify support]), [ @@ -332,6 +334,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [  		dfutool_enable=${enableval}  	]) +	AC_ARG_ENABLE(dfubabel, AC_HELP_STRING([--enable-dfubabel], [install Babel DFU mode switching utility]), [ +		dfubabel_enable=${enableval} +	]) +  	if (test "${fortify_enable}" = "yes"); then  		CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2"  	fi @@ -394,4 +400,5 @@ AC_DEFUN([AC_ARG_BLUEZ], [  	AM_CONDITIONAL(AVCTRL, test "${avctrl_enable}" = "yes" && test "${usb_found}" = "yes")  	AM_CONDITIONAL(HID2HCI, test "${hid2hci_enable}" = "yes" && test "${usb_found}" = "yes")  	AM_CONDITIONAL(DFUTOOL, test "${dfutool_enable}" = "yes" && test "${usb_found}" = "yes") +	AM_CONDITIONAL(DFUBABEL, test "${dfubabel_enable}" = "yes" && test "${usb_found}" = "yes")  ]) diff --git a/tools/Makefile.am b/tools/Makefile.am index 880036ea..2e5ecd68 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -31,9 +31,17 @@ dfutool_programs =  dfutool_manfiles =  endif +if DFUBABEL +dfubabel_programs = dfubabel +dfubabel_manfiles = dfubabel.1 +else +dfubabel_programs = +dfubabel_manfiles = +endif +  sbin_PROGRAMS = hciattach hciconfig $(bccmd_programs) $(avctrl_programs) $(hid2hci_programs) -bin_PROGRAMS = hcitool l2ping sdptool ciptool $(dfutool_programs) +bin_PROGRAMS = hcitool l2ping sdptool ciptool $(dfutool_programs) $(dfubabel_programs)  noinst_PROGRAMS = hcisecfilter ppporc @@ -76,16 +84,22 @@ dfutool_SOURCES = dfutool.c dfu.h dfu.c  dfutool_LDADD = @USB_LIBS@  endif +if DFUBABEL +dfubabel_SOURCES = dfubabel.c +dfubabel_LDADD = @USB_LIBS@ +endif +  AM_CFLAGS = @BLUEZ_CFLAGS@ @USB_CFLAGS@  INCLUDES = -I$(top_srcdir)/common  if MANPAGES  man_MANS = hciattach.8 hciconfig.8 hcitool.1 l2ping.1 sdptool.1 ciptool.1 \ -		$(bccmd_manfiles) $(avctrl_manfiles) $(hid2hci_manfiles) $(dfutool_manfiles) +		$(bccmd_manfiles) $(avctrl_manfiles) $(hid2hci_manfiles) \ +		$(dfutool_manfiles) $(dfubabel_manfiles)  endif  EXTRA_DIST = hciattach.8 hciconfig.8 hcitool.1 l2ping.1 sdptool.1 ciptool.1 \ -		 bccmd.8 avctrl.8 hid2hci.8 dfutool.1 example.psr +		 bccmd.8 avctrl.8 hid2hci.8 dfutool.1 dfubabel.1 example.psr  MAINTAINERCLEANFILES = Makefile.in diff --git a/tools/dfubabel.1 b/tools/dfubabel.1 new file mode 100644 index 00000000..5e0f805f --- /dev/null +++ b/tools/dfubabel.1 @@ -0,0 +1,38 @@ +.\" +.\"	This program is free software; you can redistribute it and/or modify +.\"	it under the terms of the GNU General Public License as published by +.\"	the Free Software Foundation; either version 2 of the License, or +.\"	(at your option) any later version. +.\" +.\"	This program is distributed in the hope that it will be useful, +.\"	but WITHOUT ANY WARRANTY; without even the implied warranty of +.\"	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +.\"	GNU General Public License for more details. +.\" +.\"	You should have received a copy of the GNU General Public License +.\"	along with this program; if not, write to the Free Software +.\"	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.\" +.TH DFUBABEL 8 "JUNE 6, 2005" "" "" + +.SH NAME +dfubabel \- Babel DFU mode switching utility +.SH SYNOPSIS +.BR "dfubabel +[ +.I options +] +.SH DESCRIPTION +.B dfubabel +is used to switch Babel devices into DFU mode. +.SH OPTIONS +.TP +.BI -h +Gives a list of possible options. +.TP +.BI -q +Don't display any messages. +.SH AUTHOR +Written by Marcel Holtmann <marcel@holtmann.org>. +.br diff --git a/tools/dfubabel.c b/tools/dfubabel.c new file mode 100644 index 00000000..ffcded90 --- /dev/null +++ b/tools/dfubabel.c @@ -0,0 +1,211 @@ +/* + * + *  BlueZ - Bluetooth protocol stack for Linux + * + *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org> + * + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <string.h> +#include <getopt.h> + +#include <usb.h> + +#ifdef NEED_USB_GET_BUSSES +static inline struct usb_bus *usb_get_busses(void) +{ +	return usb_busses; +} +#endif + +struct device_info; + +struct device_id { +	uint16_t vendor; +	uint16_t product; +	int (*func)(struct device_info *dev, int argc, char *argv[]); +}; + +struct device_info { +	struct usb_device *dev; +	struct device_id *id; +}; + +static int switch_babel(struct device_info *devinfo, int argc, char *argv[]) +{ +	char buf[3]; +	struct usb_dev_handle *udev; +	int err; + +	memset(buf, 0, sizeof(buf)); + +	buf[0] = 0x00; +	buf[1] = 0x06; +	buf[2] = 0x00; + +	udev = usb_open(devinfo->dev); +	if (!udev) +		return -errno; + +	if (usb_claim_interface(udev, 0) < 0) { +		err = -errno; +		usb_close(udev); +		return err; +	} + +	err = usb_bulk_write(udev, 0x02, buf, sizeof(buf), 10000); + +	if (err == 0) { +		err = -1; +		errno = EALREADY; +	} else { +		if (errno == ETIMEDOUT) +			err = 0; +	} + +	usb_release_interface(udev, 0); +	usb_close(udev); + +	return err; +} + +static struct device_id device_list[] = { +	{ 0x0a12, 0x0042, switch_babel }, +	{ -1 } +}; + +static struct device_id *match_device(uint16_t vendor, uint16_t product) +{ +	int i; + +	for (i = 0; device_list[i].func; i++) { +		if (vendor == device_list[i].vendor && +				product == device_list[i].product) +			return &device_list[i]; +	} + +	return NULL; +} + +static int find_devices(struct device_info *devinfo, size_t size) +{ +	struct usb_bus *bus; +	struct usb_device *dev; +	struct device_id *id; +	int count = 0; + +	usb_find_busses(); +	usb_find_devices(); + +	for (bus = usb_get_busses(); bus; bus = bus->next) +		for (dev = bus->devices; dev; dev = dev->next) { +			id = match_device(dev->descriptor.idVendor, +						dev->descriptor.idProduct); +			if (!id) +				continue; + +			if (count < size) { +				devinfo[count].dev = dev; +				devinfo[count].id = id; +				count++; +			} +		} + +	return count; +} + +static void usage(void) +{ +	printf("dfubabel - Babel DFU mode switching utility\n\n"); + +	printf("Usage:\n" +		"\tdfubabel [options]\n" +		"\n"); + +	printf("Options:\n" +		"\t-h, --help           Display help\n" +		"\t-q, --quiet          Don't display any messages\n" +		"\n"); +} + +static struct option main_options[] = { +	{ "help",	0, 0, 'h' }, +	{ "quiet",	0, 0, 'q' }, +	{ 0, 0, 0, 0 } +}; + +int main(int argc, char *argv[]) +{ +	struct device_info dev[16]; +	int i, opt, num, quiet = 0; + +	while ((opt = getopt_long(argc, argv, "+qh", main_options, NULL)) != -1) { +		switch (opt) { +		case 'q': +			quiet = 1; +			break; +		case 'h': +			usage(); +			exit(0); +		default: +			exit(0); +		} +	} + +	argc -= optind; +	argv += optind; +	optind = 0; + +	usb_init(); + +	num = find_devices(dev, sizeof(dev) / sizeof(dev[0])); +	if (num <= 0) { +		if (!quiet) +			fprintf(stderr, "No Babel devices found\n"); +		exit(1); +	} + +	for (i = 0; i < num; i++) { +		struct device_id *id = dev[i].id; +		int err; + +		if (!quiet) +			printf("Switching device %04x:%04x ", +						id->vendor, id->product); +		fflush(stdout); + +		err = id->func(&dev[i], argc, argv); +		if (err < 0) { +			if (!quiet) +				printf("failed (%s)\n", strerror(-err)); +		} else { +			if (!quiet) +				printf("was successful\n"); +		} +	} + +	return 0; +} | 
