Home | History | Annotate | Line # | Download | only in btdevctl
btdevctl.c revision 1.10
      1  1.10   joerg /*	$NetBSD: btdevctl.c,v 1.10 2011/08/27 22:24:14 joerg Exp $	*/
      2   1.1  plunky 
      3   1.1  plunky /*-
      4   1.1  plunky  * Copyright (c) 2006 Itronix Inc.
      5   1.1  plunky  * All rights reserved.
      6   1.1  plunky  *
      7   1.1  plunky  * Written by Iain Hibbert for Itronix Inc.
      8   1.1  plunky  *
      9   1.1  plunky  * Redistribution and use in source and binary forms, with or without
     10   1.1  plunky  * modification, are permitted provided that the following conditions
     11   1.1  plunky  * are met:
     12   1.1  plunky  * 1. Redistributions of source code must retain the above copyright
     13   1.1  plunky  *    notice, this list of conditions and the following disclaimer.
     14   1.1  plunky  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1  plunky  *    notice, this list of conditions and the following disclaimer in the
     16   1.1  plunky  *    documentation and/or other materials provided with the distribution.
     17   1.1  plunky  * 3. The name of Itronix Inc. may not be used to endorse
     18   1.1  plunky  *    or promote products derived from this software without specific
     19   1.1  plunky  *    prior written permission.
     20   1.1  plunky  *
     21   1.1  plunky  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
     22   1.1  plunky  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23   1.1  plunky  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24   1.1  plunky  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
     25   1.1  plunky  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26   1.1  plunky  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     27   1.1  plunky  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     28   1.1  plunky  * ON ANY THEORY OF LIABILITY, WHETHER IN
     29   1.1  plunky  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30   1.1  plunky  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31   1.1  plunky  * POSSIBILITY OF SUCH DAMAGE.
     32   1.1  plunky  */
     33   1.1  plunky 
     34   1.1  plunky #include <sys/cdefs.h>
     35   1.8  plunky __COPYRIGHT("@(#) Copyright (c) 2006 The NetBSD Foundation, Inc.\
     36   1.8  plunky   @(#) Copyright (c) 2006 Itronix, Inc.\
     37   1.8  plunky   All rights reserved.");
     38  1.10   joerg __RCSID("$NetBSD: btdevctl.c,v 1.10 2011/08/27 22:24:14 joerg Exp $");
     39   1.1  plunky 
     40   1.1  plunky #include <prop/proplib.h>
     41   1.2  plunky #include <sys/ioctl.h>
     42   1.1  plunky 
     43   1.2  plunky #include <bluetooth.h>
     44   1.2  plunky #include <ctype.h>
     45   1.1  plunky #include <err.h>
     46   1.1  plunky #include <fcntl.h>
     47   1.1  plunky #include <stdlib.h>
     48   1.1  plunky #include <string.h>
     49   1.1  plunky #include <unistd.h>
     50   1.1  plunky 
     51   1.2  plunky #include <dev/bluetooth/btdev.h>
     52   1.2  plunky 
     53   1.1  plunky #include "btdevctl.h"
     54   1.1  plunky 
     55   1.2  plunky #define BTHUB_PATH		"/dev/bthub"
     56   1.1  plunky 
     57  1.10   joerg __dead static void usage(void);
     58  1.10   joerg static char *uppercase(const char *);
     59  1.10   joerg static int bthub_pioctl(unsigned long, prop_dictionary_t);
     60   1.1  plunky 
     61   1.2  plunky int
     62   1.2  plunky main(int argc, char *argv[])
     63   1.1  plunky {
     64   1.2  plunky 	prop_dictionary_t dev;
     65   1.2  plunky 	prop_object_t obj;
     66   1.2  plunky 	bdaddr_t laddr, raddr;
     67   1.4  plunky 	const char *service, *mode;
     68   1.4  plunky 	int ch, query, verbose, attach, detach, set, none;
     69   1.2  plunky 
     70   1.2  plunky 	bdaddr_copy(&laddr, BDADDR_ANY);
     71   1.2  plunky 	bdaddr_copy(&raddr, BDADDR_ANY);
     72   1.2  plunky 	service = NULL;
     73   1.4  plunky 	mode = NULL;
     74   1.5   pavel 	query = false;
     75   1.5   pavel 	verbose = false;
     76   1.5   pavel 	attach = false;
     77   1.5   pavel 	detach = false;
     78   1.5   pavel 	set = false;
     79   1.5   pavel 	none = false;
     80   1.2  plunky 
     81   1.4  plunky 	while ((ch = getopt(argc, argv, "Aa:Dd:hm:qs:v")) != -1) {
     82   1.2  plunky 		switch (ch) {
     83   1.2  plunky 		case 'A': /* Attach device */
     84   1.5   pavel 			attach = true;
     85   1.2  plunky 			break;
     86   1.2  plunky 
     87   1.2  plunky 		case 'a': /* remote address */
     88   1.2  plunky 			if (!bt_aton(optarg, &raddr)) {
     89   1.2  plunky 				struct hostent  *he = NULL;
     90   1.2  plunky 
     91   1.2  plunky 				if ((he = bt_gethostbyname(optarg)) == NULL)
     92   1.2  plunky 					errx(EXIT_FAILURE, "%s: %s",
     93   1.2  plunky 						optarg, hstrerror(h_errno));
     94   1.2  plunky 
     95   1.2  plunky 				bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr);
     96   1.2  plunky 			}
     97   1.2  plunky 			break;
     98   1.2  plunky 
     99   1.2  plunky 		case 'D': /* Detach device */
    100   1.5   pavel 			detach = true;
    101   1.2  plunky 			break;
    102   1.2  plunky 
    103   1.2  plunky 		case 'd': /* local device address */
    104   1.2  plunky 			if (!bt_devaddr(optarg, &laddr))
    105   1.2  plunky 				err(EXIT_FAILURE, "%s", optarg);
    106   1.2  plunky 
    107   1.2  plunky 			break;
    108   1.2  plunky 
    109   1.4  plunky 		case 'm': /* link mode */
    110   1.4  plunky 			if (strcasecmp(optarg, "none") == 0)
    111   1.5   pavel 				none = true;
    112   1.4  plunky 			else if (strcasecmp(optarg, BTDEVauth) == 0)
    113   1.4  plunky 				mode = BTDEVauth;
    114   1.4  plunky 			else if (strcasecmp(optarg, BTDEVencrypt) == 0)
    115   1.4  plunky 				mode = BTDEVencrypt;
    116   1.4  plunky 			else if (strcasecmp(optarg, BTDEVsecure) == 0)
    117   1.4  plunky 				mode = BTDEVsecure;
    118   1.4  plunky 			else
    119   1.6  plunky 				errx(EXIT_FAILURE, "%s: unknown mode", optarg);
    120   1.4  plunky 
    121   1.4  plunky 			break;
    122   1.4  plunky 
    123   1.2  plunky 		case 'q':
    124   1.5   pavel 			query = true;
    125   1.2  plunky 			break;
    126   1.2  plunky 
    127   1.2  plunky 		case 's': /* service */
    128   1.2  plunky 			service = uppercase(optarg);
    129   1.2  plunky 			break;
    130   1.2  plunky 
    131   1.2  plunky 		case 'v': /* verbose */
    132   1.5   pavel 			verbose = true;
    133   1.2  plunky 			break;
    134   1.2  plunky 
    135   1.2  plunky 		case 'h':
    136   1.2  plunky 		default:
    137   1.2  plunky 			usage();
    138   1.2  plunky 		}
    139   1.2  plunky 	}
    140   1.2  plunky 
    141   1.2  plunky 	argc -= optind;
    142   1.2  plunky 	argv += optind;
    143   1.2  plunky 
    144   1.2  plunky 	if (argc > 0
    145   1.5   pavel 	    || (attach == true && detach == true)
    146   1.2  plunky 	    || bdaddr_any(&laddr)
    147   1.2  plunky 	    || bdaddr_any(&raddr)
    148   1.2  plunky 	    || service == NULL)
    149   1.2  plunky 		usage();
    150   1.2  plunky 
    151   1.5   pavel 	if (attach == false && detach == false)
    152   1.5   pavel 		verbose = true;
    153   1.2  plunky 
    154   1.2  plunky 	dev = db_get(&laddr, &raddr, service);
    155   1.5   pavel 	if (dev == NULL || query == true) {
    156   1.5   pavel 		if (verbose == true)
    157   1.2  plunky 			printf("Performing SDP query for service '%s'..\n", service);
    158   1.2  plunky 
    159   1.2  plunky 		dev = cfg_query(&laddr, &raddr, service);
    160   1.5   pavel 		set = true;
    161   1.2  plunky 	}
    162   1.2  plunky 
    163   1.4  plunky 	if (mode != NULL) {
    164   1.4  plunky 		obj = prop_string_create_cstring_nocopy(mode);
    165   1.4  plunky 		if (obj == NULL || !prop_dictionary_set(dev, BTDEVmode, obj))
    166   1.4  plunky 			errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVmode);
    167   1.4  plunky 
    168   1.4  plunky 		prop_object_release(obj);
    169   1.5   pavel 		set = true;
    170   1.4  plunky 	}
    171   1.4  plunky 
    172   1.5   pavel 	if (none == true) {
    173   1.4  plunky 		prop_dictionary_remove(dev, BTDEVmode);
    174   1.5   pavel 		set = true;
    175   1.4  plunky 	}
    176   1.4  plunky 
    177   1.5   pavel 	if (set == true && !db_set(dev, &laddr, &raddr, service))
    178   1.4  plunky 		errx(EXIT_FAILURE, "service store failed");
    179   1.4  plunky 
    180   1.2  plunky 	/* add binary local-bdaddr */
    181   1.2  plunky 	obj = prop_data_create_data(&laddr, sizeof(laddr));
    182   1.2  plunky 	if (obj == NULL || !prop_dictionary_set(dev, BTDEVladdr, obj))
    183   1.2  plunky 		errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVladdr);
    184   1.1  plunky 
    185   1.2  plunky 	prop_object_release(obj);
    186   1.1  plunky 
    187   1.2  plunky 	/* add binary remote-bdaddr */
    188   1.2  plunky 	obj = prop_data_create_data(&raddr, sizeof(raddr));
    189   1.2  plunky 	if (obj == NULL || !prop_dictionary_set(dev, BTDEVraddr, obj))
    190   1.2  plunky 		errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVraddr);
    191   1.1  plunky 
    192   1.2  plunky 	prop_object_release(obj);
    193   1.1  plunky 
    194   1.3  plunky 	/* add service name */
    195   1.3  plunky 	obj = prop_string_create_cstring(service);
    196   1.3  plunky 	if (obj == NULL || !prop_dictionary_set(dev, BTDEVservice, obj))
    197   1.3  plunky 		errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVservice);
    198   1.3  plunky 
    199   1.3  plunky 	prop_object_release(obj);
    200   1.3  plunky 
    201   1.5   pavel 	if (verbose == true)
    202   1.2  plunky 		cfg_print(dev);
    203   1.1  plunky 
    204   1.5   pavel 	if (attach == true)
    205   1.2  plunky 		bthub_pioctl(BTDEV_ATTACH, dev);
    206   1.1  plunky 
    207   1.5   pavel 	if (detach == true)
    208   1.2  plunky 		bthub_pioctl(BTDEV_DETACH, dev);
    209   1.1  plunky 
    210   1.2  plunky 	exit(EXIT_SUCCESS);
    211   1.1  plunky }
    212   1.1  plunky 
    213  1.10   joerg static void
    214   1.2  plunky usage(void)
    215   1.1  plunky {
    216   1.1  plunky 
    217   1.2  plunky 	fprintf(stderr,
    218   1.4  plunky 		"usage: %s [-A | -D] [-qv] [-m mode] -a address -d device -s service\n"
    219   1.2  plunky 		"Where:\n"
    220   1.2  plunky 		"\t-A           attach device\n"
    221   1.2  plunky 		"\t-a address   remote device address\n"
    222   1.2  plunky 		"\t-D           detach device\n"
    223   1.2  plunky 		"\t-d device    local device address\n"
    224   1.4  plunky 		"\t-m mode      link mode\n"
    225   1.2  plunky 		"\t-q           force SDP query\n"
    226   1.2  plunky 		"\t-s service   remote service\n"
    227   1.2  plunky 		"\t-v           verbose\n"
    228   1.2  plunky 		"", getprogname());
    229   1.1  plunky 
    230   1.2  plunky 	exit(EXIT_FAILURE);
    231   1.2  plunky }
    232   1.1  plunky 
    233  1.10   joerg static char *
    234   1.2  plunky uppercase(const char *arg)
    235   1.2  plunky {
    236   1.2  plunky 	char *str, *ptr;
    237   1.1  plunky 
    238   1.2  plunky 	str = strdup(arg);
    239   1.2  plunky 	if (str == NULL)
    240   1.2  plunky 		err(EXIT_FAILURE, "strdup");
    241   1.1  plunky 
    242   1.2  plunky 	for (ptr = str ; *ptr ; ptr++)
    243   1.2  plunky 		*ptr = (char)toupper((int)*ptr);
    244   1.1  plunky 
    245   1.2  plunky 	return str;
    246   1.1  plunky }
    247   1.1  plunky 
    248  1.10   joerg static int
    249   1.2  plunky bthub_pioctl(unsigned long cmd, prop_dictionary_t dict)
    250   1.1  plunky {
    251   1.1  plunky 	int fd;
    252   1.1  plunky 
    253   1.2  plunky 	fd = open(BTHUB_PATH, O_WRONLY, 0);
    254   1.1  plunky 	if (fd < 0)
    255   1.2  plunky 		err(EXIT_FAILURE, "%s", BTHUB_PATH);
    256   1.1  plunky 
    257   1.2  plunky 	if (prop_dictionary_send_ioctl(dict, fd, cmd))
    258   1.2  plunky 		err(EXIT_FAILURE, "%s", BTHUB_PATH);
    259   1.1  plunky 
    260   1.1  plunky 	close(fd);
    261   1.2  plunky 	return EXIT_SUCCESS;
    262   1.1  plunky }
    263