Home | History | Annotate | Line # | Download | only in btdevctl
      1  1.11  thorpej /*	$NetBSD: btdevctl.c,v 1.11 2020/06/07 00:12:00 thorpej 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.11  thorpej __RCSID("$NetBSD: btdevctl.c,v 1.11 2020/06/07 00:12:00 thorpej 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 	bdaddr_t laddr, raddr;
     66   1.4   plunky 	const char *service, *mode;
     67   1.4   plunky 	int ch, query, verbose, attach, detach, set, none;
     68   1.2   plunky 
     69   1.2   plunky 	bdaddr_copy(&laddr, BDADDR_ANY);
     70   1.2   plunky 	bdaddr_copy(&raddr, BDADDR_ANY);
     71   1.2   plunky 	service = NULL;
     72   1.4   plunky 	mode = NULL;
     73   1.5    pavel 	query = false;
     74   1.5    pavel 	verbose = false;
     75   1.5    pavel 	attach = false;
     76   1.5    pavel 	detach = false;
     77   1.5    pavel 	set = false;
     78   1.5    pavel 	none = false;
     79   1.2   plunky 
     80   1.4   plunky 	while ((ch = getopt(argc, argv, "Aa:Dd:hm:qs:v")) != -1) {
     81   1.2   plunky 		switch (ch) {
     82   1.2   plunky 		case 'A': /* Attach device */
     83   1.5    pavel 			attach = true;
     84   1.2   plunky 			break;
     85   1.2   plunky 
     86   1.2   plunky 		case 'a': /* remote address */
     87   1.2   plunky 			if (!bt_aton(optarg, &raddr)) {
     88   1.2   plunky 				struct hostent  *he = NULL;
     89   1.2   plunky 
     90   1.2   plunky 				if ((he = bt_gethostbyname(optarg)) == NULL)
     91   1.2   plunky 					errx(EXIT_FAILURE, "%s: %s",
     92   1.2   plunky 						optarg, hstrerror(h_errno));
     93   1.2   plunky 
     94   1.2   plunky 				bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr);
     95   1.2   plunky 			}
     96   1.2   plunky 			break;
     97   1.2   plunky 
     98   1.2   plunky 		case 'D': /* Detach device */
     99   1.5    pavel 			detach = true;
    100   1.2   plunky 			break;
    101   1.2   plunky 
    102   1.2   plunky 		case 'd': /* local device address */
    103   1.2   plunky 			if (!bt_devaddr(optarg, &laddr))
    104   1.2   plunky 				err(EXIT_FAILURE, "%s", optarg);
    105   1.2   plunky 
    106   1.2   plunky 			break;
    107   1.2   plunky 
    108   1.4   plunky 		case 'm': /* link mode */
    109   1.4   plunky 			if (strcasecmp(optarg, "none") == 0)
    110   1.5    pavel 				none = true;
    111   1.4   plunky 			else if (strcasecmp(optarg, BTDEVauth) == 0)
    112   1.4   plunky 				mode = BTDEVauth;
    113   1.4   plunky 			else if (strcasecmp(optarg, BTDEVencrypt) == 0)
    114   1.4   plunky 				mode = BTDEVencrypt;
    115   1.4   plunky 			else if (strcasecmp(optarg, BTDEVsecure) == 0)
    116   1.4   plunky 				mode = BTDEVsecure;
    117   1.4   plunky 			else
    118   1.6   plunky 				errx(EXIT_FAILURE, "%s: unknown mode", optarg);
    119   1.4   plunky 
    120   1.4   plunky 			break;
    121   1.4   plunky 
    122   1.2   plunky 		case 'q':
    123   1.5    pavel 			query = true;
    124   1.2   plunky 			break;
    125   1.2   plunky 
    126   1.2   plunky 		case 's': /* service */
    127   1.2   plunky 			service = uppercase(optarg);
    128   1.2   plunky 			break;
    129   1.2   plunky 
    130   1.2   plunky 		case 'v': /* verbose */
    131   1.5    pavel 			verbose = true;
    132   1.2   plunky 			break;
    133   1.2   plunky 
    134   1.2   plunky 		case 'h':
    135   1.2   plunky 		default:
    136   1.2   plunky 			usage();
    137   1.2   plunky 		}
    138   1.2   plunky 	}
    139   1.2   plunky 
    140   1.2   plunky 	argc -= optind;
    141   1.2   plunky 	argv += optind;
    142   1.2   plunky 
    143   1.2   plunky 	if (argc > 0
    144   1.5    pavel 	    || (attach == true && detach == true)
    145   1.2   plunky 	    || bdaddr_any(&laddr)
    146   1.2   plunky 	    || bdaddr_any(&raddr)
    147   1.2   plunky 	    || service == NULL)
    148   1.2   plunky 		usage();
    149   1.2   plunky 
    150   1.5    pavel 	if (attach == false && detach == false)
    151   1.5    pavel 		verbose = true;
    152   1.2   plunky 
    153   1.2   plunky 	dev = db_get(&laddr, &raddr, service);
    154   1.5    pavel 	if (dev == NULL || query == true) {
    155   1.5    pavel 		if (verbose == true)
    156   1.2   plunky 			printf("Performing SDP query for service '%s'..\n", service);
    157   1.2   plunky 
    158   1.2   plunky 		dev = cfg_query(&laddr, &raddr, service);
    159   1.5    pavel 		set = true;
    160   1.2   plunky 	}
    161   1.2   plunky 
    162   1.4   plunky 	if (mode != NULL) {
    163  1.11  thorpej 		if (!prop_dictionary_set_string_nocopy(dev, BTDEVmode, mode))
    164   1.4   plunky 			errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVmode);
    165   1.5    pavel 		set = true;
    166   1.4   plunky 	}
    167   1.4   plunky 
    168   1.5    pavel 	if (none == true) {
    169   1.4   plunky 		prop_dictionary_remove(dev, BTDEVmode);
    170   1.5    pavel 		set = true;
    171   1.4   plunky 	}
    172   1.4   plunky 
    173   1.5    pavel 	if (set == true && !db_set(dev, &laddr, &raddr, service))
    174   1.4   plunky 		errx(EXIT_FAILURE, "service store failed");
    175   1.4   plunky 
    176   1.2   plunky 	/* add binary local-bdaddr */
    177  1.11  thorpej 	if (!prop_dictionary_set_data(dev, BTDEVladdr, &laddr, sizeof(laddr)))
    178   1.2   plunky 		errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVladdr);
    179   1.1   plunky 
    180   1.2   plunky 	/* add binary remote-bdaddr */
    181  1.11  thorpej 	if (!prop_dictionary_set_data(dev, BTDEVraddr, &raddr, sizeof(raddr)))
    182   1.2   plunky 		errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVraddr);
    183   1.1   plunky 
    184   1.3   plunky 	/* add service name */
    185  1.11  thorpej 	if (!prop_dictionary_set_string(dev, BTDEVservice, service))
    186   1.3   plunky 		errx(EXIT_FAILURE, "proplib failure (%s)", BTDEVservice);
    187   1.3   plunky 
    188   1.5    pavel 	if (verbose == true)
    189   1.2   plunky 		cfg_print(dev);
    190   1.1   plunky 
    191   1.5    pavel 	if (attach == true)
    192   1.2   plunky 		bthub_pioctl(BTDEV_ATTACH, dev);
    193   1.1   plunky 
    194   1.5    pavel 	if (detach == true)
    195   1.2   plunky 		bthub_pioctl(BTDEV_DETACH, dev);
    196   1.1   plunky 
    197   1.2   plunky 	exit(EXIT_SUCCESS);
    198   1.1   plunky }
    199   1.1   plunky 
    200  1.10    joerg static void
    201   1.2   plunky usage(void)
    202   1.1   plunky {
    203   1.1   plunky 
    204   1.2   plunky 	fprintf(stderr,
    205   1.4   plunky 		"usage: %s [-A | -D] [-qv] [-m mode] -a address -d device -s service\n"
    206   1.2   plunky 		"Where:\n"
    207   1.2   plunky 		"\t-A           attach device\n"
    208   1.2   plunky 		"\t-a address   remote device address\n"
    209   1.2   plunky 		"\t-D           detach device\n"
    210   1.2   plunky 		"\t-d device    local device address\n"
    211   1.4   plunky 		"\t-m mode      link mode\n"
    212   1.2   plunky 		"\t-q           force SDP query\n"
    213   1.2   plunky 		"\t-s service   remote service\n"
    214   1.2   plunky 		"\t-v           verbose\n"
    215   1.2   plunky 		"", getprogname());
    216   1.1   plunky 
    217   1.2   plunky 	exit(EXIT_FAILURE);
    218   1.2   plunky }
    219   1.1   plunky 
    220  1.10    joerg static char *
    221   1.2   plunky uppercase(const char *arg)
    222   1.2   plunky {
    223   1.2   plunky 	char *str, *ptr;
    224   1.1   plunky 
    225   1.2   plunky 	str = strdup(arg);
    226   1.2   plunky 	if (str == NULL)
    227   1.2   plunky 		err(EXIT_FAILURE, "strdup");
    228   1.1   plunky 
    229   1.2   plunky 	for (ptr = str ; *ptr ; ptr++)
    230   1.2   plunky 		*ptr = (char)toupper((int)*ptr);
    231   1.1   plunky 
    232   1.2   plunky 	return str;
    233   1.1   plunky }
    234   1.1   plunky 
    235  1.10    joerg static int
    236   1.2   plunky bthub_pioctl(unsigned long cmd, prop_dictionary_t dict)
    237   1.1   plunky {
    238   1.1   plunky 	int fd;
    239   1.1   plunky 
    240   1.2   plunky 	fd = open(BTHUB_PATH, O_WRONLY, 0);
    241   1.1   plunky 	if (fd < 0)
    242   1.2   plunky 		err(EXIT_FAILURE, "%s", BTHUB_PATH);
    243   1.1   plunky 
    244   1.2   plunky 	if (prop_dictionary_send_ioctl(dict, fd, cmd))
    245   1.2   plunky 		err(EXIT_FAILURE, "%s", BTHUB_PATH);
    246   1.1   plunky 
    247   1.1   plunky 	close(fd);
    248   1.2   plunky 	return EXIT_SUCCESS;
    249   1.1   plunky }
    250