Pedro F. Giffuni 1de7b4b805 various: general adoption of SPDX licensing ID tags.
Mainly focus on files that use BSD 2-Clause license, however the tool I
was using misidentified many licenses so this was mostly a manual - error
prone - task.

The Software Package Data Exchange (SPDX) group provides a specification
to make it easier for automated tools to detect and summarize well known
opensource licenses. We are gradually adopting the specification, noting
that the tags are considered only advisory and do not, in any way,
superceed or replace the license texts.

No functional change intended.
2017-11-27 15:37:16 +00:00

506 lines
10 KiB
Plaintext

%{
/*
* parser.y
*/
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: parser.y,v 1.7 2006/09/07 21:06:53 max Exp $
* $FreeBSD$
*/
#include <sys/queue.h>
#define L2CAP_SOCKET_CHECKED
#include <bluetooth.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <usbhid.h>
#ifndef BTHIDCONTROL
#include <stdarg.h>
#include <syslog.h>
#define SYSLOG syslog
#define LOGCRIT LOG_CRIT
#define LOGERR LOG_ERR
#define LOGWARNING LOG_WARNING
#define EOL
#else
#define SYSLOG fprintf
#define LOGCRIT stderr
#define LOGERR stderr
#define LOGWARNING stderr
#define EOL "\n"
#endif /* ndef BTHIDCONTROL */
#include "bthid_config.h"
int yylex (void);
void yyerror (char const *);
static int32_t check_hid_device(hid_device_p hid_device);
static void free_hid_device (hid_device_p hid_device);
extern FILE *yyin;
extern int yylineno;
char const *config_file = BTHIDD_CONFFILE;
char const *hids_file = BTHIDD_HIDSFILE;
static char buffer[1024];
static int32_t hid_descriptor_size;
static hid_device_t *hid_device = NULL;
static LIST_HEAD(, hid_device) hid_devices;
%}
%union {
bdaddr_t bdaddr;
int32_t num;
}
%token <bdaddr> T_BDADDRSTRING
%token <num> T_HEXBYTE
%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
%%
config: line
| config line
;
line: T_DEVICE
{
hid_device = (hid_device_t *) calloc(1, sizeof(*hid_device));
if (hid_device == NULL) {
SYSLOG(LOGCRIT, "Could not allocate new " \
"config entry" EOL);
YYABORT;
}
hid_device->new_device = 1;
}
'{' options '}'
{
if (check_hid_device(hid_device))
LIST_INSERT_HEAD(&hid_devices,hid_device,next);
else
free_hid_device(hid_device);
hid_device = NULL;
}
;
options: option ';'
| options option ';'
;
option: bdaddr
| vendor_id
| product_id
| version
| control_psm
| interrupt_psm
| reconnect_initiate
| battery_power
| normally_connectable
| hid_descriptor
| parser_error
;
bdaddr: T_BDADDR T_BDADDRSTRING
{
memcpy(&hid_device->bdaddr, &$2, sizeof(hid_device->bdaddr));
}
;
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;
}
;
interrupt_psm: T_INTERRUPT_PSM T_HEXBYTE
{
hid_device->interrupt_psm = $2;
}
;
reconnect_initiate: T_RECONNECT_INITIATE T_TRUE
{
hid_device->reconnect_initiate = 1;
}
| T_RECONNECT_INITIATE T_FALSE
{
hid_device->reconnect_initiate = 0;
}
;
battery_power: T_BATTERY_POWER T_TRUE
{
hid_device->battery_power = 1;
}
| T_BATTERY_POWER T_FALSE
{
hid_device->battery_power = 0;
}
;
normally_connectable: T_NORMALLY_CONNECTABLE T_TRUE
{
hid_device->normally_connectable = 1;
}
| T_NORMALLY_CONNECTABLE T_FALSE
{
hid_device->normally_connectable = 0;
}
;
hid_descriptor: T_HID_DESCRIPTOR
{
hid_descriptor_size = 0;
}
'{' hid_descriptor_bytes '}'
{
if (hid_device->desc != NULL)
hid_dispose_report_desc(hid_device->desc);
hid_device->desc = hid_use_report_desc((unsigned char *) buffer, hid_descriptor_size);
if (hid_device->desc == NULL) {
SYSLOG(LOGCRIT, "Could not use HID descriptor" EOL);
YYABORT;
}
}
;
hid_descriptor_bytes: hid_descriptor_byte
| hid_descriptor_bytes hid_descriptor_byte
;
hid_descriptor_byte: T_HEXBYTE
{
if (hid_descriptor_size >= (int32_t) sizeof(buffer)) {
SYSLOG(LOGCRIT, "HID descriptor is too big" EOL);
YYABORT;
}
buffer[hid_descriptor_size ++] = $1;
}
;
parser_error: T_ERROR
{
YYABORT;
}
%%
/* Display parser error message */
void
yyerror(char const *message)
{
SYSLOG(LOGERR, "%s in line %d" EOL, message, yylineno);
}
/* Re-read config file */
int32_t
read_config_file(void)
{
int32_t e;
if (config_file == NULL) {
SYSLOG(LOGERR, "Unknown config file name!" EOL);
return (-1);
}
if ((yyin = fopen(config_file, "r")) == NULL) {
SYSLOG(LOGERR, "Could not open config file '%s'. %s (%d)" EOL,
config_file, strerror(errno), errno);
return (-1);
}
clean_config();
if (yyparse() < 0) {
SYSLOG(LOGERR, "Could not parse config file '%s'" EOL,
config_file);
e = -1;
} else
e = 0;
fclose(yyin);
yyin = NULL;
return (e);
}
/* Clean config */
void
clean_config(void)
{
while (!LIST_EMPTY(&hid_devices)) {
hid_device_p d = LIST_FIRST(&hid_devices);
LIST_REMOVE(d, next);
free_hid_device(d);
}
}
/* Lookup config entry */
hid_device_p
get_hid_device(bdaddr_p bdaddr)
{
hid_device_p d;
LIST_FOREACH(d, &hid_devices, next)
if (memcmp(&d->bdaddr, bdaddr, sizeof(bdaddr_t)) == 0)
break;
return (d);
}
/* Get next config entry */
hid_device_p
get_next_hid_device(hid_device_p d)
{
return ((d == NULL)? LIST_FIRST(&hid_devices) : LIST_NEXT(d, next));
}
/* Print config entry */
void
print_hid_device(hid_device_p d, FILE *f)
{
/* XXX FIXME hack! */
struct report_desc {
unsigned int size;
unsigned char data[1];
};
/* XXX FIXME hack! */
struct report_desc *desc = (struct report_desc *) d->desc;
uint32_t i;
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" \
" battery_power %s;\n" \
" 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",
d->normally_connectable? "true" : "false");
for (i = 0; i < desc->size; i ++) {
if ((i % 8) == 0)
fprintf(f, "\n ");
fprintf(f, "0x%2.2x ", desc->data[i]);
}
fprintf(f,
"\n" \
" };\n" \
"}\n");
}
/* Check config entry */
static int32_t
check_hid_device(hid_device_p d)
{
hid_data_t hd;
hid_item_t hi;
int32_t page;
if (get_hid_device(&d->bdaddr) != NULL) {
SYSLOG(LOGERR, "Ignoring duplicated entry for bdaddr %s" EOL,
bt_ntoa(&d->bdaddr, NULL));
return (0);
}
if (d->control_psm == 0) {
SYSLOG(LOGERR, "Ignoring entry with invalid control PSM" EOL);
return (0);
}
if (d->interrupt_psm == 0) {
SYSLOG(LOGERR, "Ignoring entry with invalid interrupt PSM" EOL);
return (0);
}
if (d->desc == NULL) {
SYSLOG(LOGERR, "Ignoring entry without HID descriptor" EOL);
return (0);
}
/* XXX somehow need to make sure descriptor is valid */
for (hd = hid_start_parse(d->desc, ~0, -1); hid_get_item(hd, &hi) > 0; ) {
switch (hi.kind) {
case hid_collection:
case hid_endcollection:
case hid_output:
case hid_feature:
break;
case hid_input:
/* Check if the device may send keystrokes */
page = HID_PAGE(hi.usage);
if (page == HUP_KEYBOARD)
d->keyboard = 1;
break;
}
}
hid_end_parse(hd);
return (1);
}
/* Free config entry */
static void
free_hid_device(hid_device_p d)
{
if (d->desc != NULL)
hid_dispose_report_desc(d->desc);
memset(d, 0, sizeof(*d));
free(d);
}
/* Re-read hids file */
int32_t
read_hids_file(void)
{
FILE *f;
hid_device_t *d;
char *line;
bdaddr_t bdaddr;
int32_t lineno;
if (hids_file == NULL) {
SYSLOG(LOGERR, "Unknown HIDs file name!" EOL);
return (-1);
}
if ((f = fopen(hids_file, "r")) == NULL) {
if (errno == ENOENT)
return (0);
SYSLOG(LOGERR, "Could not open HIDs file '%s'. %s (%d)" EOL,
hids_file, strerror(errno), errno);
return (-1);
}
for (lineno = 1; fgets(buffer, sizeof(buffer), f) != NULL; lineno ++) {
if ((line = strtok(buffer, "\r\n\t ")) == NULL)
continue; /* ignore empty lines */
if (!bt_aton(line, &bdaddr)) {
SYSLOG(LOGWARNING, "Ignoring unparseable BD_ADDR in " \
"%s:%d" EOL, hids_file, lineno);
continue;
}
if ((d = get_hid_device(&bdaddr)) != NULL)
d->new_device = 0;
}
fclose(f);
return (0);
}
/* Write hids file */
int32_t
write_hids_file(void)
{
char path[PATH_MAX];
FILE *f;
hid_device_t *d;
if (hids_file == NULL) {
SYSLOG(LOGERR, "Unknown HIDs file name!" EOL);
return (-1);
}
snprintf(path, sizeof(path), "%s.new", hids_file);
if ((f = fopen(path, "w")) == NULL) {
SYSLOG(LOGERR, "Could not open HIDs file '%s'. %s (%d)" EOL,
path, strerror(errno), errno);
return (-1);
}
LIST_FOREACH(d, &hid_devices, next)
if (!d->new_device)
fprintf(f, "%s\n", bt_ntoa(&d->bdaddr, NULL));
fclose(f);
if (rename(path, hids_file) < 0) {
SYSLOG(LOGERR, "Could not rename new HIDs file '%s' to '%s'. " \
"%s (%d)" EOL, path, hids_file, strerror(errno), errno);
unlink(path);
return (-1);
}
return (0);
}