diff options
| -rw-r--r-- | acinclude.m4 | 17 | ||||
| -rw-r--r-- | tools/Makefile.am | 18 | ||||
| -rw-r--r-- | tools/avctrl.8 | 38 | ||||
| -rw-r--r-- | tools/avctrl.c | 233 | 
4 files changed, 298 insertions, 8 deletions
diff --git a/acinclude.m4 b/acinclude.m4 index 5c27b5a8..ed00a60e 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -265,10 +265,11 @@ AC_DEFUN([AC_ARG_BLUEZ], [  	cups_enable=no  	pcmcia_enable=no  	initscripts_enable=no -	bluepin_enable=yes +	avctrl_enable=${usb_found}  	hid2hci_enable=${usb_found}  	dfutool_enable=no  	bcm203x_enable=no +	bluepin_enable=yes  	AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [enable compiling with debugging information]), [  		debug_enable=${enableval} @@ -286,10 +287,11 @@ AC_DEFUN([AC_ARG_BLUEZ], [  		cups_enable=${enableval}  		pcmcia_enable=${enableval}  		initscripts_enable=${enableval} -		bluepin_enable=${enableval} +		avctrl_enable=${enableval}  		hid2hci_enable=${enableval}  		dfutool_enable=${enableval}  		bcm203x_enable=${enableval} +		bluepin_enable=${enableval}  	])  	AC_ARG_ENABLE(obex, AC_HELP_STRING([--enable-obex], [enable OBEX support]), [ @@ -320,8 +322,8 @@ AC_DEFUN([AC_ARG_BLUEZ], [  		initscripts_enable=${enableval}  	]) -	AC_ARG_ENABLE(bluepin, AC_HELP_STRING([--enable-bluepin], [install Python based PIN helper utility]), [ -		bluepin_enable=${enableval} +	AC_ARG_ENABLE(avctrl, AC_HELP_STRING([--enable-avctrl], [install Audio/Video control utility]), [ +		avctrl_enable=${enableval}  	])  	AC_ARG_ENABLE(hid2hci, AC_HELP_STRING([--enable-hid2hci], [install HID mode switching utility]), [ @@ -336,6 +338,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [  		bcm203x_enable=${enableval}  	]) +	AC_ARG_ENABLE(bluepin, AC_HELP_STRING([--enable-bluepin], [install Python based PIN helper utility]), [ +		bluepin_enable=${enableval} +	]) +  	if (test "${debug_enable}" = "yes" && test "${ac_cv_prog_cc_g}" = "yes"); then  		CFLAGS="$CFLAGS -g"  	fi @@ -352,8 +358,9 @@ AC_DEFUN([AC_ARG_BLUEZ], [  	AM_CONDITIONAL(CUPS, test "${cups_enable}" = "yes")  	AM_CONDITIONAL(PCMCIA, test "${pcmcia_enable}" = "yes")  	AM_CONDITIONAL(INITSCRIPTS, test "${initscripts_enable}" = "yes") -	AM_CONDITIONAL(BLUEPIN, test "${bluepin_enable}" = "yes") +	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(BCM203X, test "${bcm203x_enable}" = "yes" && test "${usb_found}" = "yes") +	AM_CONDITIONAL(BLUEPIN, test "${bluepin_enable}" = "yes")  ]) diff --git a/tools/Makefile.am b/tools/Makefile.am index 66839dd7..adff35b9 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -2,6 +2,14 @@  #  $Id$  # +if AVCTRL +avctrl_programs = avctrl +avctrl_manfiles = avctrl.8 +else +avctrl_programs = +avctrl_manfiles = +endif +  if HID2HCI  hid2hci_programs = hid2hci  hid2hci_manfiles = hid2hci.8 @@ -18,7 +26,7 @@ dfutool_programs =  dfutool_manfiles =  endif -sbin_PROGRAMS = hciattach hciconfig $(hid2hci_programs) +sbin_PROGRAMS = hciattach hciconfig $(avctrl_programs) $(hid2hci_programs)  bin_PROGRAMS = hcitool l2ping sdptool ciptool $(dfutool_programs) @@ -44,6 +52,10 @@ pskey_LDADD = @BLUEZ_LIBS@  bccmd_SOURCES = bccmd.c csr.h csr.c  bccmd_LDADD = @BLUEZ_LIBS@ +if AVCTRL +avctrl_LDADD = @USB_LIBS@ +endif +  if HID2HCI  hid2hci_LDADD = @USB_LIBS@  endif @@ -58,8 +70,8 @@ AM_CFLAGS = @BLUEZ_CFLAGS@ @USB_CFLAGS@  INCLUDES = -I$(top_srcdir)/common  man_MANS = hciattach.8 hciconfig.8 hcitool.1 l2ping.1 sdptool.1 ciptool.1 \ -		$(hid2hci_manfiles) $(dfutool_manfiles) +		$(avctrl_manfiles) $(hid2hci_manfiles) $(dfutool_manfiles) -EXTRA_DIST = $(man_MANS) hid2hci.8 dfutool.1 +EXTRA_DIST = $(man_MANS) avctrl.8 hid2hci.8 dfutool.1  MAINTAINERCLEANFILES = Makefile.in diff --git a/tools/avctrl.8 b/tools/avctrl.8 new file mode 100644 index 00000000..f791cf9e --- /dev/null +++ b/tools/avctrl.8 @@ -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 AVCTRL 8 "JUNE 6, 2005" "" "" + +.SH NAME +avctrl \- Bluetooth Audio/Video control utility +.SH SYNOPSIS +.BR "avctrl +[ +.I options +] +.SH DESCRIPTION +.B avctrl +is used to control the Audio/Video dongles. +.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/avctrl.c b/tools/avctrl.c new file mode 100644 index 00000000..120a382f --- /dev/null +++ b/tools/avctrl.c @@ -0,0 +1,233 @@ +/* + * + *  BlueZ - Bluetooth protocol stack for Linux + * + *  Copyright (C) 2004-2005  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 version 2 as + *  published by the Free Software Foundation; + * + *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + *  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + *  CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES  + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN  + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + *  ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,  + *  COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS  + *  SOFTWARE IS DISCLAIMED. + * + * + *  $Id$ + */ + +#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 + +#ifndef USB_DIR_OUT +#define USB_DIR_OUT	0x00 +#endif + +#ifndef USB_DIR_IN +#define USB_DIR_IN	0x80 +#endif + +#define HID_REQ_GET_REPORT	0x01 +#define HID_REQ_GET_IDLE	0x02 +#define HID_REQ_GET_PROTOCOL	0x03 +#define HID_REQ_SET_REPORT	0x09 +#define HID_REQ_SET_IDLE	0x0a +#define HID_REQ_SET_PROTOCOL	0x0b + +struct device_info; + +struct device_id { +	uint16_t vendor; +	uint16_t product; +	int (*func)(struct device_info *dev); +}; + +struct device_info { +	struct usb_device *dev; +	struct device_id *id; +}; + +#define GET_STATE		0x01 +#define GET_REMOTE_BDADDR	0x02 +#define DISCOVER		0x03 +#define SWITCH_TO_DFU		0x04 +#define READ_CODEC		0x05 + +static int dongle_csr(struct device_info *devinfo) +{ +	unsigned char buf[8]; +	struct usb_dev_handle *udev; +	int err, intf = 2; + +	udev = usb_open(devinfo->dev); +	if (!udev) +		return -errno; + +	if (usb_claim_interface(udev, intf) < 0) { +		err = -errno; +		usb_close(udev); +		return err; +	} + +	memset(buf, 0, sizeof(buf)); +	buf[0] = SWITCH_TO_DFU; + +	err = usb_control_msg(udev, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, +				HID_REQ_SET_REPORT, 0x03 << 8, intf, buf, sizeof(buf), 10000); + +	if (err == 0) { +		err = -1; +		errno = EALREADY; +	} else { +		if (errno == ETIMEDOUT) +			err = 0; +	} + +	usb_release_interface(udev, intf); +	usb_close(udev); + +	return err; +} + +static struct device_id device_list[] = { +	{ 0x0a12, 0x1004, dongle_csr }, +	{ -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("avctrl - Bluetooth Audio/Video control utility\n\n"); + +	printf("Usage:\n" +		"\tavctrl [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 Audio/Video devices found\n"); +		exit(1); +	} + +	for (i = 0; i < num; i++) { +		struct device_id *id = dev[i].id; + +		if (!quiet) +			printf("Switching device %04x:%04x ", +						id->vendor, id->product); +		fflush(stdout); + +		if (id->func(&dev[i]) < 0) { +			if (!quiet) +				printf("failed (%s)\n", strerror(errno)); +		} else { +			if (!quiet) +				printf("was successful\n"); +		} +	} + +	return 0; +}  | 
