1128080Semax/* 2128080Semax * bthidcontrol.c 3128080Semax * 4128080Semax * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5128080Semax * All rights reserved. 6128080Semax * 7128080Semax * Redistribution and use in source and binary forms, with or without 8128080Semax * modification, are permitted provided that the following conditions 9128080Semax * are met: 10128080Semax * 1. Redistributions of source code must retain the above copyright 11128080Semax * notice, this list of conditions and the following disclaimer. 12128080Semax * 2. Redistributions in binary form must reproduce the above copyright 13128080Semax * notice, this list of conditions and the following disclaimer in the 14128080Semax * documentation and/or other materials provided with the distribution. 15128080Semax * 16128080Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17128080Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18128080Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19128080Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20128080Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21128080Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22128080Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23128080Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24128080Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25128080Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26128080Semax * SUCH DAMAGE. 27128080Semax * 28128080Semax * $Id: bthidcontrol.c,v 1.2 2004/02/13 21:44:41 max Exp $ 29128080Semax * $FreeBSD$ 30128080Semax */ 31128080Semax 32128080Semax#include <sys/queue.h> 33128080Semax#include <assert.h> 34128080Semax#include <bluetooth.h> 35128080Semax#include <err.h> 36128080Semax#include <errno.h> 37128080Semax#include <stdio.h> 38128080Semax#include <stdlib.h> 39128080Semax#include <string.h> 40128080Semax#include <unistd.h> 41128080Semax#include <usbhid.h> 42128080Semax#include "bthid_config.h" 43128080Semax#include "bthidcontrol.h" 44128080Semax 45128080Semaxstatic int do_bthid_command(bdaddr_p bdaddr, int argc, char **argv); 46128080Semaxstatic struct bthid_command * find_bthid_command(char const *command, struct bthid_command *category); 47128080Semaxstatic void print_bthid_command(struct bthid_command *category); 48128080Semaxstatic void usage(void); 49128080Semax 50128080Semaxint32_t hid_sdp_query(bdaddr_t const *local, bdaddr_t const *remote, int32_t *error); 51128080Semax 52163811Smarkusuint32_t verbose = 0; 53163811Smarkus 54128080Semax/* 55128080Semax * bthidcontrol 56128080Semax */ 57128080Semax 58128080Semaxint 59128080Semaxmain(int argc, char *argv[]) 60128080Semax{ 61128080Semax bdaddr_t bdaddr; 62128080Semax int opt; 63128080Semax 64128080Semax hid_init(NULL); 65128080Semax memcpy(&bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr)); 66128080Semax 67163811Smarkus while ((opt = getopt(argc, argv, "a:c:H:hv")) != -1) { 68128080Semax switch (opt) { 69128080Semax case 'a': /* bdaddr */ 70128080Semax if (!bt_aton(optarg, &bdaddr)) { 71128080Semax struct hostent *he = NULL; 72128080Semax 73128080Semax if ((he = bt_gethostbyname(optarg)) == NULL) 74128080Semax errx(1, "%s: %s", optarg, hstrerror(h_errno)); 75128080Semax 76128080Semax memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); 77128080Semax } 78128080Semax break; 79128080Semax 80128080Semax case 'c': /* config file */ 81128080Semax config_file = optarg; 82128080Semax break; 83128080Semax 84128080Semax case 'H': /* HIDs file */ 85128080Semax hids_file = optarg; 86128080Semax break; 87128080Semax 88163811Smarkus case 'v': /* verbose */ 89163811Smarkus verbose++; 90163811Smarkus break; 91163811Smarkus 92128080Semax case 'h': 93128080Semax default: 94128080Semax usage(); 95128080Semax /* NOT REACHED */ 96128080Semax } 97128080Semax } 98128080Semax 99128080Semax argc -= optind; 100128080Semax argv += optind; 101128080Semax 102128080Semax if (*argv == NULL) 103128080Semax usage(); 104128080Semax 105128080Semax return (do_bthid_command(&bdaddr, argc, argv)); 106128080Semax} /* main */ 107128080Semax 108128080Semax/* Execute commands */ 109128080Semaxstatic int 110128080Semaxdo_bthid_command(bdaddr_p bdaddr, int argc, char **argv) 111128080Semax{ 112128080Semax char *cmd = argv[0]; 113128080Semax struct bthid_command *c = NULL; 114128080Semax int e, help; 115128080Semax 116128080Semax help = 0; 117128080Semax if (strcasecmp(cmd, "help") == 0) { 118128080Semax argc --; 119128080Semax argv ++; 120128080Semax 121128080Semax if (argc <= 0) { 122128080Semax fprintf(stdout, "Supported commands:\n"); 123128080Semax print_bthid_command(sdp_commands); 124128080Semax print_bthid_command(hid_commands); 125128080Semax fprintf(stdout, "\nFor more information use " \ 126128080Semax "'help command'\n"); 127128080Semax 128128080Semax return (OK); 129128080Semax } 130128080Semax 131128080Semax help = 1; 132128080Semax cmd = argv[0]; 133128080Semax } 134128080Semax 135128080Semax c = find_bthid_command(cmd, sdp_commands); 136128080Semax if (c == NULL) 137128080Semax c = find_bthid_command(cmd, hid_commands); 138128080Semax 139128080Semax if (c == NULL) { 140128080Semax fprintf(stdout, "Unknown command: \"%s\"\n", cmd); 141128080Semax return (ERROR); 142128080Semax } 143128080Semax 144128080Semax if (!help) 145128080Semax e = (c->handler)(bdaddr, -- argc, ++ argv); 146128080Semax else 147128080Semax e = USAGE; 148128080Semax 149128080Semax switch (e) { 150128080Semax case OK: 151128080Semax case FAILED: 152128080Semax break; 153128080Semax 154128080Semax case ERROR: 155128080Semax fprintf(stdout, "Could not execute command \"%s\". %s\n", 156128080Semax cmd, strerror(errno)); 157128080Semax break; 158128080Semax 159128080Semax case USAGE: 160128080Semax fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); 161128080Semax break; 162128080Semax 163128080Semax default: assert(0); break; 164128080Semax } 165128080Semax 166128080Semax return (e); 167128080Semax} /* do_bthid_command */ 168128080Semax 169128080Semax/* Try to find command in specified category */ 170128080Semaxstatic struct bthid_command * 171128080Semaxfind_bthid_command(char const *command, struct bthid_command *category) 172128080Semax{ 173128080Semax struct bthid_command *c = NULL; 174128080Semax 175128080Semax for (c = category; c->command != NULL; c++) { 176128080Semax char *c_end = strchr(c->command, ' '); 177128080Semax 178128080Semax if (c_end != NULL) { 179128080Semax int len = c_end - c->command; 180128080Semax 181128080Semax if (strncasecmp(command, c->command, len) == 0) 182128080Semax return (c); 183128080Semax } else if (strcasecmp(command, c->command) == 0) 184128080Semax return (c); 185128080Semax } 186128080Semax 187128080Semax return (NULL); 188128080Semax} /* find_bthid_command */ 189128080Semax 190128080Semax/* Print commands in specified category */ 191128080Semaxstatic void 192128080Semaxprint_bthid_command(struct bthid_command *category) 193128080Semax{ 194128080Semax struct bthid_command *c = NULL; 195128080Semax 196128080Semax for (c = category; c->command != NULL; c++) 197128080Semax fprintf(stdout, "\t%s\n", c->command); 198128080Semax} /* print_bthid_command */ 199128080Semax 200128080Semax/* Usage */ 201128080Semaxstatic void 202128080Semaxusage(void) 203128080Semax{ 204128080Semax fprintf(stderr, 205128080Semax"Usage: bthidcontrol options command\n" \ 206128080Semax"Where options are:\n" 207128080Semax" -a bdaddr specify bdaddr\n" \ 208128080Semax" -c file specify path to the bthidd config file\n" \ 209128080Semax" -H file specify path to the bthidd HIDs file\n" \ 210128080Semax" -h display usage and quit\n" \ 211163811Smarkus" -v be verbose\n" \ 212128080Semax" command one of the supported commands\n"); 213128080Semax exit(255); 214128080Semax} /* usage */ 215128080Semax 216