Author: wulf
Date: Sat Aug 12 21:20:51 2017
New Revision: 322439
URL: https://svnweb.freebsd.org/changeset/base/322439

Log:
  bthidd(8): Add support for vendor_id, product_id and version.
  
  Extend bthidd.conf format to store vendor and product IDs of remote
  Bluetooth HID devices to make possible implementation of device
  specific quirks inside bthidd(8).
  Add support for querying of this information from device's SDP records
  with bthidcontrol(8) "Query" command.
  
  Submitted by:         Dirk Engling <erdge...@erdgeist.org>
  Reviewed by:          emax
  Approved by:          bapt (mentor), gonzo (mentor)
  Differential Revision:        https://reviews.freebsd.org/D3702

Modified:
  head/usr.sbin/bluetooth/bthidcontrol/sdp.c
  head/usr.sbin/bluetooth/bthidd/bthid_config.h
  head/usr.sbin/bluetooth/bthidd/bthidd.conf.sample
  head/usr.sbin/bluetooth/bthidd/lexer.l
  head/usr.sbin/bluetooth/bthidd/parser.y

Modified: head/usr.sbin/bluetooth/bthidcontrol/sdp.c
==============================================================================
--- head/usr.sbin/bluetooth/bthidcontrol/sdp.c  Sat Aug 12 19:17:48 2017        
(r322438)
+++ head/usr.sbin/bluetooth/bthidcontrol/sdp.c  Sat Aug 12 21:20:51 2017        
(r322439)
@@ -47,7 +47,20 @@ static int32_t hid_sdp_parse_protocol_descriptor_list        
 static int32_t hid_sdp_parse_hid_descriptor            (sdp_attr_p a);
 static int32_t hid_sdp_parse_boolean                   (sdp_attr_p a);
 
+/*
+ * Hard coded attibute IDs taken from the
+ * DEVICE IDENTIFICATION PROFILE SPECIFICATION V13 p.12
+ */
+
+#define SDP_ATTR_DEVICE_ID_SERVICE_VENDORID  0x0201
+#define SDP_ATTR_DEVICE_ID_SERVICE_PRODUCTID 0x0202
+#define SDP_ATTR_DEVICE_ID_SERVICE_VERSION   0x0203
+#define SDP_ATTR_DEVICE_ID_RANGE SDP_ATTR_RANGE( \
+ SDP_ATTR_DEVICE_ID_SERVICE_VENDORID, SDP_ATTR_DEVICE_ID_SERVICE_VERSION )
+
 static uint16_t                service = 
SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE;
+static uint16_t                service_devid = 
SDP_SERVICE_CLASS_PNP_INFORMATION;
+static uint32_t        attrs_devid   = SDP_ATTR_DEVICE_ID_RANGE;
 
 static uint32_t                attrs[] = {
 SDP_ATTR_RANGE(        SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
@@ -85,27 +98,34 @@ static uint8_t              buffer[nvalues][512];
        return (((e) == 0)? 0 : -1);    \
 }
 
+static void
+hid_init_return_values() {
+       int i;
+       for (i = 0; i < nvalues; i ++) {
+               values[i].flags = SDP_ATTR_INVALID;
+               values[i].attr = 0;
+               values[i].vlen = sizeof(buffer[i]);
+               values[i].value = buffer[i];
+       }
+}
+
 static int32_t
 hid_sdp_query(bdaddr_t const *local, struct hid_device *hd, int32_t *error)
 {
        void    *ss = NULL;
-       uint8_t *hid_descriptor = NULL;
+       uint8_t *hid_descriptor = NULL, *v;
        int32_t  i, control_psm = -1, interrupt_psm = -1,
                 reconnect_initiate = -1,
                 normally_connectable = 0, battery_power = 0,
-                hid_descriptor_length = -1;
+                hid_descriptor_length = -1, type;
+       int16_t  vendor_id = 0, product_id = 0, version = 0;
 
        if (local == NULL)
                local = NG_HCI_BDADDR_ANY;
        if (hd == NULL)
                hid_sdp_query_exit(EINVAL);
 
-       for (i = 0; i < nvalues; i ++) {
-               values[i].flags = SDP_ATTR_INVALID;
-               values[i].attr = 0;
-               values[i].vlen = sizeof(buffer[i]);
-               values[i].value = buffer[i];
-       }
+       hid_init_return_values();
 
        if ((ss = sdp_open(local, &hd->bdaddr)) == NULL)
                hid_sdp_query_exit(ENOMEM);
@@ -114,9 +134,6 @@ hid_sdp_query(bdaddr_t const *local, struct hid_device
        if (sdp_search(ss, 1, &service, nattrs, attrs, nvalues, values) != 0)
                 hid_sdp_query_exit(sdp_error(ss));
 
-        sdp_close(ss);
-        ss = NULL;
-
        for (i = 0; i < nvalues; i ++) {
                if (values[i].flags != SDP_ATTR_OK)
                        continue;
@@ -151,11 +168,51 @@ hid_sdp_query(bdaddr_t const *local, struct hid_device
                }
        }
 
+       hid_init_return_values();
+
+       if (sdp_search(ss, 1, &service_devid, 1, &attrs_devid, nvalues, values) 
!= 0)
+                hid_sdp_query_exit(sdp_error(ss));
+
+        sdp_close(ss);
+        ss = NULL;
+
+       /* If search is successful, scan through return vals */
+       for (i = 0; i < 3; i ++ ) {
+               if (values[i].flags == SDP_ATTR_INVALID )
+                       continue;
+
+               /* Expecting tag + uint16_t on all 3 attributes */
+               if (values[i].vlen != 3)
+                       continue;
+
+               /* Make sure, we're reading a uint16_t */
+               v = values[i].value;
+               SDP_GET8(type, v);
+               if (type != SDP_DATA_UINT16 )
+                       continue;
+
+               switch (values[i].attr) {
+                       case SDP_ATTR_DEVICE_ID_SERVICE_VENDORID:
+                               SDP_GET16(vendor_id, v);
+                               break;
+                       case SDP_ATTR_DEVICE_ID_SERVICE_PRODUCTID:
+                               SDP_GET16(product_id, v);
+                               break;
+                       case SDP_ATTR_DEVICE_ID_SERVICE_VERSION:
+                               SDP_GET16(version, v);
+                               break;
+                       default:
+                               break;
+               }
+       }
+
        if (control_psm == -1 || interrupt_psm == -1 ||
            reconnect_initiate == -1 ||
            hid_descriptor == NULL || hid_descriptor_length == -1)
                hid_sdp_query_exit(ENOATTR);
-
+       hd->vendor_id = vendor_id;
+       hd->product_id = product_id;
+       hd->version = version;
        hd->control_psm = control_psm;
        hd->interrupt_psm = interrupt_psm;
        hd->reconnect_initiate = reconnect_initiate? 1 : 0;

Modified: head/usr.sbin/bluetooth/bthidd/bthid_config.h
==============================================================================
--- head/usr.sbin/bluetooth/bthidd/bthid_config.h       Sat Aug 12 19:17:48 
2017        (r322438)
+++ head/usr.sbin/bluetooth/bthidd/bthid_config.h       Sat Aug 12 21:20:51 
2017        (r322439)
@@ -42,6 +42,9 @@ struct hid_device
        bdaddr_t                bdaddr;         /* HID device BDADDR */
        uint16_t                control_psm;    /* control PSM */
        uint16_t                interrupt_psm;  /* interrupt PSM */
+       uint16_t                vendor_id;      /* primary vendor id */
+       uint16_t                product_id;
+       uint16_t                version;
        unsigned                new_device           : 1;
        unsigned                reconnect_initiate   : 1;
        unsigned                battery_power        : 1;

Modified: head/usr.sbin/bluetooth/bthidd/bthidd.conf.sample
==============================================================================
--- head/usr.sbin/bluetooth/bthidd/bthidd.conf.sample   Sat Aug 12 19:17:48 
2017        (r322438)
+++ head/usr.sbin/bluetooth/bthidd/bthidd.conf.sample   Sat Aug 12 21:20:51 
2017        (r322439)
@@ -2,6 +2,9 @@
 
 device {
        bdaddr                  00:50:f2:e5:68:84;
+       vendor_id               0x0000;
+       product_id              0x0000;
+       version                 0x0000;
        control_psm             0x11;
        interrupt_psm           0x13;
        reconnect_initiate      true;
@@ -24,6 +27,9 @@ device {
 
 device {
        bdaddr                  00:50:f2:e3:fb:e1;
+       vendor_id               0x0000;
+       product_id              0x0000;
+       version                 0x0000;
        control_psm             0x11;
        interrupt_psm           0x13;
        reconnect_initiate      true;

Modified: head/usr.sbin/bluetooth/bthidd/lexer.l
==============================================================================
--- head/usr.sbin/bluetooth/bthidd/lexer.l      Sat Aug 12 19:17:48 2017        
(r322438)
+++ head/usr.sbin/bluetooth/bthidd/lexer.l      Sat Aug 12 21:20:51 2017        
(r322439)
@@ -50,9 +50,13 @@ comment                              \#.*
 
 hexdigit                       [0-9a-fA-F]
 hexbyte                                {hexdigit}{hexdigit}?
+hexword                                
{hexdigit}{hexdigit}?{hexdigit}?{hexdigit}?
 
 device_word                    device
 bdaddr_word                    bdaddr
+vendor_id_word                 vendor_id
+product_id_word                        product_id
+version_word                   version
 control_psm_word               control_psm
 interrupt_psm_word             interrupt_psm
 reconnect_initiate_word                reconnect_initiate
@@ -64,6 +68,7 @@ false_word                    false
 
 bdaddrstring                   
{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}
 hexbytestring                  0x{hexbyte}
+hexwordstring                  0x{hexword}
 
 %%
 
@@ -78,6 +83,9 @@ hexbytestring                 0x{hexbyte}
 
 {device_word}                  return (T_DEVICE);
 {bdaddr_word}                  return (T_BDADDR);
+{vendor_id_word}               return (T_VENDOR_ID);
+{product_id_word}              return (T_PRODUCT_ID);
+{version_word}                 return (T_VERSION);
 {control_psm_word}             return (T_CONTROL_PSM);
 {interrupt_psm_word}           return (T_INTERRUPT_PSM);
 {reconnect_initiate_word}      return (T_RECONNECT_INITIATE);
@@ -98,6 +106,14 @@ hexbytestring                       0x{hexbyte}
                                yylval.num = strtoul(yytext, &ep, 16);
 
                                return (*ep == '\0'? T_HEXBYTE : T_ERROR);
+                               }
+
+{hexwordstring}                        {
+                               char    *ep;
+
+                               yylval.num = strtoul(yytext, &ep, 16);
+
+                               return (*ep == '\0'? T_HEXWORD : T_ERROR);
                                }
 
 .                              return (T_ERROR);

Modified: head/usr.sbin/bluetooth/bthidd/parser.y
==============================================================================
--- head/usr.sbin/bluetooth/bthidd/parser.y     Sat Aug 12 19:17:48 2017        
(r322438)
+++ head/usr.sbin/bluetooth/bthidd/parser.y     Sat Aug 12 21:20:51 2017        
(r322439)
@@ -87,8 +87,10 @@ static       LIST_HEAD(, hid_device)  hid_devices;
 
 %token <bdaddr> T_BDADDRSTRING
 %token <num>   T_HEXBYTE
-%token T_DEVICE T_BDADDR T_CONTROL_PSM T_INTERRUPT_PSM T_RECONNECT_INITIATE
-%token T_BATTERY_POWER T_NORMALLY_CONNECTABLE T_HID_DESCRIPTOR
+%token <num>   T_HEXWORD
+%token T_DEVICE T_BDADDR T_VENDOR_ID T_PRODUCT_ID T_VERSION T_CONTROL_PSM
+%token T_INTERRUPT_PSM T_RECONNECT_INITIATE T_BATTERY_POWER
+%token T_NORMALLY_CONNECTABLE T_HID_DESCRIPTOR
 %token T_TRUE T_FALSE T_ERROR
 
 %%
@@ -124,6 +126,9 @@ options:    option ';'
                ;
 
 option:                bdaddr
+               | vendor_id
+               | product_id
+               | version
                | control_psm
                | interrupt_psm
                | reconnect_initiate
@@ -139,6 +144,24 @@ bdaddr:            T_BDADDR T_BDADDRSTRING
                        }
                ;
 
+vendor_id:     T_VENDOR_ID T_HEXWORD
+                       {
+                       hid_device->vendor_id = $2;
+                       }
+               ;
+
+product_id:    T_PRODUCT_ID T_HEXWORD
+                       {
+                       hid_device->product_id = $2;
+                       }
+               ;
+
+version:       T_VERSION T_HEXWORD
+                       {
+                       hid_device->version = $2;
+                       }
+               ;
+
 control_psm:   T_CONTROL_PSM T_HEXBYTE
                        {
                        hid_device->control_psm = $2;
@@ -307,6 +330,9 @@ print_hid_device(hid_device_p d, FILE *f)
        fprintf(f,
 "device {\n"                                   \
 "      bdaddr                  %s;\n"          \
+"      vendor_id               0x%04x;\n"      \
+"      product_id              0x%04x;\n"      \
+"      version                 0x%04x;\n"      \
 "      control_psm             0x%x;\n"        \
 "      interrupt_psm           0x%x;\n"        \
 "      reconnect_initiate      %s;\n"          \
@@ -314,6 +340,7 @@ print_hid_device(hid_device_p d, FILE *f)
 "      normally_connectable    %s;\n"          \
 "      hid_descriptor          {",
                bt_ntoa(&d->bdaddr, NULL),
+               d->vendor_id, d->product_id, d->version,
                d->control_psm, d->interrupt_psm,
                 d->reconnect_initiate? "true" : "false",
                 d->battery_power? "true" : "false",
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to