1128080Semax/* 2128080Semax * hid.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: hid.c,v 1.3 2004/02/17 22:14:57 max Exp $ 29128080Semax * $FreeBSD: releng/10.3/usr.sbin/bluetooth/bthidcontrol/hid.c 163811 2006-10-31 00:26:58Z markus $ 30128080Semax */ 31128080Semax 32128080Semax#include <sys/queue.h> 33128080Semax#include <bluetooth.h> 34128080Semax#include <dev/usb/usb.h> 35128080Semax#include <dev/usb/usbhid.h> 36128080Semax#include <stdio.h> 37128080Semax#include <string.h> 38128080Semax#include <usbhid.h> 39128080Semax#include "bthid_config.h" 40128080Semax#include "bthidcontrol.h" 41128080Semax 42163811Smarkusextern uint32_t verbose; 43163811Smarkus 44128080Semaxstatic void hid_dump_descriptor (report_desc_t r); 45128080Semaxstatic void hid_dump_item (char const *label, struct hid_item *h); 46128080Semax 47128080Semaxstatic int 48128080Semaxhid_dump(bdaddr_t *bdaddr, int argc, char **argv) 49128080Semax{ 50128080Semax struct hid_device *hd = NULL; 51128080Semax int e = FAILED; 52128080Semax 53128080Semax if (read_config_file() == 0) { 54128080Semax if ((hd = get_hid_device(bdaddr)) != NULL) { 55128080Semax hid_dump_descriptor(hd->desc); 56128080Semax e = OK; 57128080Semax } 58128080Semax 59128080Semax clean_config(); 60128080Semax } 61128080Semax 62128080Semax return (e); 63128080Semax} 64128080Semax 65128080Semaxstatic int 66128080Semaxhid_forget(bdaddr_t *bdaddr, int argc, char **argv) 67128080Semax{ 68128080Semax struct hid_device *hd = NULL; 69128080Semax int e = FAILED; 70128080Semax 71128080Semax if (read_config_file() == 0) { 72128080Semax if (read_hids_file() == 0) { 73128080Semax if ((hd = get_hid_device(bdaddr)) != NULL) { 74128080Semax hd->new_device = 1; 75128080Semax if (write_hids_file() == 0) 76128080Semax e = OK; 77128080Semax } 78128080Semax } 79128080Semax 80128080Semax clean_config(); 81128080Semax } 82128080Semax 83128080Semax return (e); 84128080Semax} 85128080Semax 86128080Semaxstatic int 87128080Semaxhid_known(bdaddr_t *bdaddr, int argc, char **argv) 88128080Semax{ 89128080Semax struct hid_device *hd = NULL; 90128080Semax struct hostent *he = NULL; 91128080Semax int e = FAILED; 92128080Semax 93128080Semax if (read_config_file() == 0) { 94128080Semax if (read_hids_file() == 0) { 95128080Semax e = OK; 96128080Semax 97128080Semax for (hd = get_next_hid_device(hd); 98128080Semax hd != NULL; 99128080Semax hd = get_next_hid_device(hd)) { 100128080Semax if (hd->new_device) 101128080Semax continue; 102128080Semax 103128080Semax he = bt_gethostbyaddr((char *) &hd->bdaddr, 104128080Semax sizeof(hd->bdaddr), 105128080Semax AF_BLUETOOTH); 106128080Semax 107128080Semax fprintf(stdout, 108128080Semax"%s %s\n", bt_ntoa(&hd->bdaddr, NULL), 109128080Semax (he != NULL && he->h_name != NULL)? 110128080Semax he->h_name : ""); 111128080Semax } 112128080Semax } 113128080Semax 114128080Semax clean_config(); 115128080Semax } 116128080Semax 117128080Semax return (e); 118128080Semax} 119128080Semax 120128080Semaxstatic void 121128080Semaxhid_dump_descriptor(report_desc_t r) 122128080Semax{ 123128080Semax struct hid_data *d = NULL; 124128080Semax struct hid_item h; 125128080Semax 126128080Semax for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) { 127128080Semax switch (h.kind) { 128128080Semax case hid_collection: 129128080Semax fprintf(stdout, 130128080Semax"Collection page=%s usage=%s\n", hid_usage_page(HID_PAGE(h.usage)), 131128080Semax hid_usage_in_page(h.usage)); 132128080Semax break; 133128080Semax 134128080Semax case hid_endcollection: 135128080Semax fprintf(stdout, "End collection\n"); 136128080Semax break; 137128080Semax 138128080Semax case hid_input: 139128080Semax hid_dump_item("Input ", &h); 140128080Semax break; 141128080Semax 142128080Semax case hid_output: 143128080Semax hid_dump_item("Output ", &h); 144128080Semax break; 145128080Semax 146128080Semax case hid_feature: 147128080Semax hid_dump_item("Feature", &h); 148128080Semax break; 149128080Semax } 150128080Semax } 151128080Semax 152128080Semax hid_end_parse(d); 153128080Semax} 154128080Semax 155128080Semaxstatic void 156128080Semaxhid_dump_item(char const *label, struct hid_item *h) 157128080Semax{ 158163811Smarkus if ((h->flags & HIO_CONST) && !verbose) 159163811Smarkus return; 160163811Smarkus 161128080Semax fprintf(stdout, 162128080Semax"%s id=%u size=%u count=%u page=%s usage=%s%s%s%s%s%s%s%s%s%s", 163128080Semax label, (uint8_t) h->report_ID, h->report_size, h->report_count, 164128080Semax hid_usage_page(HID_PAGE(h->usage)), 165128080Semax hid_usage_in_page(h->usage), 166128080Semax h->flags & HIO_CONST ? " Const" : "", 167128080Semax h->flags & HIO_VARIABLE ? " Variable" : "", 168128080Semax h->flags & HIO_RELATIVE ? " Relative" : "", 169128080Semax h->flags & HIO_WRAP ? " Wrap" : "", 170128080Semax h->flags & HIO_NONLINEAR ? " NonLinear" : "", 171128080Semax h->flags & HIO_NOPREF ? " NoPref" : "", 172128080Semax h->flags & HIO_NULLSTATE ? " NullState" : "", 173128080Semax h->flags & HIO_VOLATILE ? " Volatile" : "", 174128080Semax h->flags & HIO_BUFBYTES ? " BufBytes" : ""); 175128080Semax 176128080Semax fprintf(stdout, 177128080Semax", logical range %d..%d", 178128080Semax h->logical_minimum, h->logical_maximum); 179128080Semax 180128080Semax if (h->physical_minimum != h->physical_maximum) 181128080Semax fprintf(stdout, 182128080Semax", physical range %d..%d", 183128080Semax h->physical_minimum, h->physical_maximum); 184128080Semax 185128080Semax if (h->unit) 186128080Semax fprintf(stdout, 187128080Semax", unit=0x%02x exp=%d", h->unit, h->unit_exponent); 188128080Semax 189128080Semax fprintf(stdout, "\n"); 190128080Semax} 191128080Semax 192128080Semaxstruct bthid_command hid_commands[] = { 193128080Semax{ 194128080Semax"Dump", 195128080Semax"Dump HID descriptor for the specified device in human readable form. The\n" \ 196128080Semax"device must have an entry in the Bluetooth HID daemon configuration file.\n", 197128080Semaxhid_dump 198128080Semax}, 199128080Semax{ 200128080Semax"Known", 201128080Semax"List all known to the Bluetooth HID daemon devices.\n", 202128080Semaxhid_known 203128080Semax}, 204128080Semax{ 205128080Semax"Forget", 206128080Semax"Forget (mark as new) specified HID device. This command is useful when it\n" \ 207128080Semax"is required to remove device from the known HIDs file. This should be done\n" \ 208128080Semax"when reset button was pressed on the device or the battery was changed. The\n"\ 209128080Semax"Bluetooth HID daemon should be restarted.\n", 210128080Semaxhid_forget 211128080Semax}, 212128080Semax{ NULL, NULL, NULL } 213128080Semax}; 214128080Semax 215