parser.y (06912ebab3a2e8ca9643e79fabb50de1d445f4b4) | parser.y (6490c2ffabe2a6e5df2545d164f1c257e0d471de) |
---|---|
1%{ 2/* 3 * parser.y | 1%{ 2/* 3 * parser.y |
4 */ 5 6/*- 7 * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com> | 4 * 5 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> |
8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * | 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
31 * $Id: parser.y,v 1.7 2006/09/07 21:06:53 max Exp $ | 29 * $Id: parser.y,v 1.3 2004/02/13 21:46:21 max Exp $ |
32 * $FreeBSD$ 33 */ 34 35#include <sys/queue.h> 36#include <bluetooth.h> | 30 * $FreeBSD$ 31 */ 32 33#include <sys/queue.h> 34#include <bluetooth.h> |
37#include <dev/usb/usb.h> 38#include <dev/usb/usbhid.h> | |
39#include <errno.h> | 35#include <errno.h> |
36#include <libusbhid.h> |
|
40#include <limits.h> 41#include <stdio.h> 42#include <string.h> 43#include <unistd.h> | 37#include <limits.h> 38#include <stdio.h> 39#include <string.h> 40#include <unistd.h> |
44#include <usbhid.h> | |
45 46#ifndef BTHIDCONTROL 47#include <stdarg.h> 48#include <syslog.h> 49#define SYSLOG syslog 50#define LOGCRIT LOG_CRIT 51#define LOGERR LOG_ERR 52#define LOGWARNING LOG_WARNING 53#define EOL 54#else 55#define SYSLOG fprintf 56#define LOGCRIT stderr 57#define LOGERR stderr 58#define LOGWARNING stderr | 41 42#ifndef BTHIDCONTROL 43#include <stdarg.h> 44#include <syslog.h> 45#define SYSLOG syslog 46#define LOGCRIT LOG_CRIT 47#define LOGERR LOG_ERR 48#define LOGWARNING LOG_WARNING 49#define EOL 50#else 51#define SYSLOG fprintf 52#define LOGCRIT stderr 53#define LOGERR stderr 54#define LOGWARNING stderr |
59#define EOL "\n" | 55#define EOL "\n" |
60#endif /* ndef BTHIDCONTROL */ 61 62#include "bthid_config.h" 63 64 int yyparse (void); 65 int yylex (void); | 56#endif /* ndef BTHIDCONTROL */ 57 58#include "bthid_config.h" 59 60 int yyparse (void); 61 int yylex (void); |
66 void yyerror (char const *); 67static int32_t check_hid_device(hid_device_p hid_device); | 62static int check_hid_device(hid_device_p hid_device); |
68static void free_hid_device (hid_device_p hid_device); 69 | 63static void free_hid_device (hid_device_p hid_device); 64 |
70extern FILE *yyin; | |
71extern int yylineno; | 65extern int yylineno; |
72 char const *config_file = BTHIDD_CONFFILE; 73 char const *hids_file = BTHIDD_HIDSFILE; | 66 char *config_file = BTHIDD_CONFFILE; 67 char *hids_file = BTHIDD_HIDSFILE; |
74 75static char buffer[1024]; | 68 69static char buffer[1024]; |
76static int32_t hid_descriptor_size; | 70static int hid_descriptor_size; |
77static hid_device_t *hid_device = NULL; 78static LIST_HEAD(, hid_device) hid_devices; 79 80%} 81 82%union { 83 bdaddr_t bdaddr; | 71static hid_device_t *hid_device = NULL; 72static LIST_HEAD(, hid_device) hid_devices; 73 74%} 75 76%union { 77 bdaddr_t bdaddr; |
84 int32_t num; | 78 int num; |
85} 86 87%token <bdaddr> T_BDADDRSTRING 88%token <num> T_HEXBYTE 89%token T_DEVICE T_BDADDR T_CONTROL_PSM T_INTERRUPT_PSM T_RECONNECT_INITIATE 90%token T_BATTERY_POWER T_NORMALLY_CONNECTABLE T_HID_DESCRIPTOR 91%token T_TRUE T_FALSE T_ERROR 92 --- 91 unchanged lines hidden (view full) --- 184 { 185 hid_descriptor_size = 0; 186 } 187 '{' hid_descriptor_bytes '}' 188 { 189 if (hid_device->desc != NULL) 190 hid_dispose_report_desc(hid_device->desc); 191 | 79} 80 81%token <bdaddr> T_BDADDRSTRING 82%token <num> T_HEXBYTE 83%token T_DEVICE T_BDADDR T_CONTROL_PSM T_INTERRUPT_PSM T_RECONNECT_INITIATE 84%token T_BATTERY_POWER T_NORMALLY_CONNECTABLE T_HID_DESCRIPTOR 85%token T_TRUE T_FALSE T_ERROR 86 --- 91 unchanged lines hidden (view full) --- 178 { 179 hid_descriptor_size = 0; 180 } 181 '{' hid_descriptor_bytes '}' 182 { 183 if (hid_device->desc != NULL) 184 hid_dispose_report_desc(hid_device->desc); 185 |
192 hid_device->desc = hid_use_report_desc((unsigned char *) buffer, hid_descriptor_size); | 186 hid_device->desc = hid_use_report_desc(buffer, hid_descriptor_size); |
193 if (hid_device->desc == NULL) { 194 SYSLOG(LOGCRIT, "Could not use HID descriptor" EOL); 195 YYABORT; 196 } 197 } 198 ; 199 200hid_descriptor_bytes: hid_descriptor_byte 201 | hid_descriptor_bytes hid_descriptor_byte 202 ; 203 204hid_descriptor_byte: T_HEXBYTE 205 { | 187 if (hid_device->desc == NULL) { 188 SYSLOG(LOGCRIT, "Could not use HID descriptor" EOL); 189 YYABORT; 190 } 191 } 192 ; 193 194hid_descriptor_bytes: hid_descriptor_byte 195 | hid_descriptor_bytes hid_descriptor_byte 196 ; 197 198hid_descriptor_byte: T_HEXBYTE 199 { |
206 if (hid_descriptor_size >= (int32_t) sizeof(buffer)) { | 200 if (hid_descriptor_size >= sizeof(buffer)) { |
207 SYSLOG(LOGCRIT, "HID descriptor is too big" EOL); 208 YYABORT; 209 } 210 211 buffer[hid_descriptor_size ++] = $1; 212 } 213 ; 214 --- 7 unchanged lines hidden (view full) --- 222/* Display parser error message */ 223void 224yyerror(char const *message) 225{ 226 SYSLOG(LOGERR, "%s in line %d" EOL, message, yylineno); 227} 228 229/* Re-read config file */ | 201 SYSLOG(LOGCRIT, "HID descriptor is too big" EOL); 202 YYABORT; 203 } 204 205 buffer[hid_descriptor_size ++] = $1; 206 } 207 ; 208 --- 7 unchanged lines hidden (view full) --- 216/* Display parser error message */ 217void 218yyerror(char const *message) 219{ 220 SYSLOG(LOGERR, "%s in line %d" EOL, message, yylineno); 221} 222 223/* Re-read config file */ |
230int32_t | 224int |
231read_config_file(void) 232{ | 225read_config_file(void) 226{ |
233 int32_t e; | 227 extern FILE *yyin; 228 int e; |
234 235 if (config_file == NULL) { 236 SYSLOG(LOGERR, "Unknown config file name!" EOL); 237 return (-1); 238 } 239 240 if ((yyin = fopen(config_file, "r")) == NULL) { 241 SYSLOG(LOGERR, "Could not open config file '%s'. %s (%d)" EOL, --- 15 unchanged lines hidden (view full) --- 257 return (e); 258} 259 260/* Clean config */ 261void 262clean_config(void) 263{ 264 while (!LIST_EMPTY(&hid_devices)) { | 229 230 if (config_file == NULL) { 231 SYSLOG(LOGERR, "Unknown config file name!" EOL); 232 return (-1); 233 } 234 235 if ((yyin = fopen(config_file, "r")) == NULL) { 236 SYSLOG(LOGERR, "Could not open config file '%s'. %s (%d)" EOL, --- 15 unchanged lines hidden (view full) --- 252 return (e); 253} 254 255/* Clean config */ 256void 257clean_config(void) 258{ 259 while (!LIST_EMPTY(&hid_devices)) { |
265 hid_device_p d = LIST_FIRST(&hid_devices); | 260 hid_device_p hid_device = LIST_FIRST(&hid_devices); |
266 | 261 |
267 LIST_REMOVE(d, next); 268 free_hid_device(d); | 262 LIST_REMOVE(hid_device, next); 263 free_hid_device(hid_device); |
269 } 270} 271 272/* Lookup config entry */ 273hid_device_p 274get_hid_device(bdaddr_p bdaddr) 275{ | 264 } 265} 266 267/* Lookup config entry */ 268hid_device_p 269get_hid_device(bdaddr_p bdaddr) 270{ |
276 hid_device_p d; | 271 hid_device_p hid_device; |
277 | 272 |
278 LIST_FOREACH(d, &hid_devices, next) 279 if (memcmp(&d->bdaddr, bdaddr, sizeof(bdaddr_t)) == 0) | 273 LIST_FOREACH(hid_device, &hid_devices, next) 274 if (memcmp(&hid_device->bdaddr, bdaddr, sizeof(bdaddr_t)) == 0) |
280 break; 281 | 275 break; 276 |
282 return (d); | 277 return (hid_device); |
283} 284 285/* Get next config entry */ 286hid_device_p 287get_next_hid_device(hid_device_p d) 288{ 289 return ((d == NULL)? LIST_FIRST(&hid_devices) : LIST_NEXT(d, next)); 290} 291 292/* Print config entry */ 293void | 278} 279 280/* Get next config entry */ 281hid_device_p 282get_next_hid_device(hid_device_p d) 283{ 284 return ((d == NULL)? LIST_FIRST(&hid_devices) : LIST_NEXT(d, next)); 285} 286 287/* Print config entry */ 288void |
294print_hid_device(hid_device_p d, FILE *f) | 289print_hid_device(hid_device_p hid_device, FILE *f) |
295{ 296 /* XXX FIXME hack! */ 297 struct report_desc { 298 unsigned int size; 299 unsigned char data[1]; 300 }; 301 /* XXX FIXME hack! */ 302 | 290{ 291 /* XXX FIXME hack! */ 292 struct report_desc { 293 unsigned int size; 294 unsigned char data[1]; 295 }; 296 /* XXX FIXME hack! */ 297 |
303 struct report_desc *desc = (struct report_desc *) d->desc; 304 uint32_t i; | 298 struct report_desc *desc = (struct report_desc *) hid_device->desc; 299 int i; |
305 306 fprintf(f, 307"device {\n" \ 308" bdaddr %s;\n" \ 309" control_psm 0x%x;\n" \ | 300 301 fprintf(f, 302"device {\n" \ 303" bdaddr %s;\n" \ 304" control_psm 0x%x;\n" \ |
310" interrupt_psm 0x%x;\n" \ | 305" interrupt_psm 0x%d;\n" \ |
311" reconnect_initiate %s;\n" \ 312" battery_power %s;\n" \ 313" normally_connectable %s;\n" \ 314" hid_descriptor {", | 306" reconnect_initiate %s;\n" \ 307" battery_power %s;\n" \ 308" normally_connectable %s;\n" \ 309" hid_descriptor {", |
315 bt_ntoa(&d->bdaddr, NULL), 316 d->control_psm, d->interrupt_psm, 317 d->reconnect_initiate? "true" : "false", 318 d->battery_power? "true" : "false", 319 d->normally_connectable? "true" : "false"); | 310 bt_ntoa(&hid_device->bdaddr, NULL), 311 hid_device->control_psm, hid_device->interrupt_psm, 312 hid_device->reconnect_initiate? "true" : "false", 313 hid_device->battery_power? "true" : "false", 314 hid_device->normally_connectable? "true" : "false"); |
320 321 for (i = 0; i < desc->size; i ++) { 322 if ((i % 8) == 0) | 315 316 for (i = 0; i < desc->size; i ++) { 317 if ((i % 8) == 0) |
323 fprintf(f, "\n "); | 318 fprintf(stdout, "\n "); |
324 325 fprintf(f, "0x%2.2x ", desc->data[i]); 326 } 327 | 319 320 fprintf(f, "0x%2.2x ", desc->data[i]); 321 } 322 |
328 fprintf(f, | 323 fprintf(stdout, |
329"\n" \ 330" };\n" \ 331"}\n"); 332} 333 334/* Check config entry */ | 324"\n" \ 325" };\n" \ 326"}\n"); 327} 328 329/* Check config entry */ |
335static int32_t 336check_hid_device(hid_device_p d) | 330static int 331check_hid_device(hid_device_p hid_device) |
337{ | 332{ |
338 hid_data_t hd; 339 hid_item_t hi; 340 int32_t page; 341 342 if (get_hid_device(&d->bdaddr) != NULL) { | 333 if (get_hid_device(&hid_device->bdaddr) != NULL) { |
343 SYSLOG(LOGERR, "Ignoring duplicated entry for bdaddr %s" EOL, | 334 SYSLOG(LOGERR, "Ignoring duplicated entry for bdaddr %s" EOL, |
344 bt_ntoa(&d->bdaddr, NULL)); | 335 bt_ntoa(&hid_device->bdaddr, NULL)); |
345 return (0); 346 } 347 | 336 return (0); 337 } 338 |
348 if (d->control_psm == 0) { | 339 if (hid_device->control_psm == 0) { |
349 SYSLOG(LOGERR, "Ignoring entry with invalid control PSM" EOL); 350 return (0); 351 } 352 | 340 SYSLOG(LOGERR, "Ignoring entry with invalid control PSM" EOL); 341 return (0); 342 } 343 |
353 if (d->interrupt_psm == 0) { | 344 if (hid_device->interrupt_psm == 0) { |
354 SYSLOG(LOGERR, "Ignoring entry with invalid interrupt PSM" EOL); 355 return (0); 356 } 357 | 345 SYSLOG(LOGERR, "Ignoring entry with invalid interrupt PSM" EOL); 346 return (0); 347 } 348 |
358 if (d->desc == NULL) { | 349 if (hid_device->desc == NULL) { |
359 SYSLOG(LOGERR, "Ignoring entry without HID descriptor" EOL); 360 return (0); 361 } 362 | 350 SYSLOG(LOGERR, "Ignoring entry without HID descriptor" EOL); 351 return (0); 352 } 353 |
363 /* XXX somehow need to make sure descriptor is valid */ 364 for (hd = hid_start_parse(d->desc, ~0, -1); hid_get_item(hd, &hi) > 0; ) { 365 switch (hi.kind) { 366 case hid_collection: 367 case hid_endcollection: 368 case hid_output: 369 case hid_feature: 370 break; 371 372 case hid_input: 373 /* Check if the device may send keystrokes */ 374 page = HID_PAGE(hi.usage); 375 if (page == HUP_KEYBOARD) 376 d->keyboard = 1; 377 break; 378 } 379 } 380 hid_end_parse(hd); 381 | |
382 return (1); 383} 384 385/* Free config entry */ 386static void | 354 return (1); 355} 356 357/* Free config entry */ 358static void |
387free_hid_device(hid_device_p d) | 359free_hid_device(hid_device_p hid_device) |
388{ | 360{ |
389 if (d->desc != NULL) 390 hid_dispose_report_desc(d->desc); | 361 if (hid_device->desc != NULL) 362 hid_dispose_report_desc(hid_device->desc); |
391 | 363 |
392 memset(d, 0, sizeof(*d)); 393 free(d); | 364 memset(hid_device, 0, sizeof(*hid_device)); 365 free(hid_device); |
394} 395 396/* Re-read hids file */ | 366} 367 368/* Re-read hids file */ |
397int32_t | 369int |
398read_hids_file(void) 399{ | 370read_hids_file(void) 371{ |
400 FILE *f; 401 hid_device_t *d; 402 char *line; | 372 FILE *f = NULL; 373 hid_device_t *hid_device = NULL; 374 char *line = NULL; |
403 bdaddr_t bdaddr; | 375 bdaddr_t bdaddr; |
404 int32_t lineno; | 376 int lineno; |
405 406 if (hids_file == NULL) { 407 SYSLOG(LOGERR, "Unknown HIDs file name!" EOL); 408 return (-1); 409 } 410 411 if ((f = fopen(hids_file, "r")) == NULL) { 412 if (errno == ENOENT) --- 9 unchanged lines hidden (view full) --- 422 continue; /* ignore empty lines */ 423 424 if (!bt_aton(line, &bdaddr)) { 425 SYSLOG(LOGWARNING, "Ignoring unparseable BD_ADDR in " \ 426 "%s:%d" EOL, hids_file, lineno); 427 continue; 428 } 429 | 377 378 if (hids_file == NULL) { 379 SYSLOG(LOGERR, "Unknown HIDs file name!" EOL); 380 return (-1); 381 } 382 383 if ((f = fopen(hids_file, "r")) == NULL) { 384 if (errno == ENOENT) --- 9 unchanged lines hidden (view full) --- 394 continue; /* ignore empty lines */ 395 396 if (!bt_aton(line, &bdaddr)) { 397 SYSLOG(LOGWARNING, "Ignoring unparseable BD_ADDR in " \ 398 "%s:%d" EOL, hids_file, lineno); 399 continue; 400 } 401 |
430 if ((d = get_hid_device(&bdaddr)) != NULL) 431 d->new_device = 0; | 402 if ((hid_device = get_hid_device(&bdaddr)) != NULL) 403 hid_device->new_device = 0; |
432 } 433 434 fclose(f); 435 436 return (0); 437} 438 439/* Write hids file */ | 404 } 405 406 fclose(f); 407 408 return (0); 409} 410 411/* Write hids file */ |
440int32_t | 412int |
441write_hids_file(void) 442{ 443 char path[PATH_MAX]; | 413write_hids_file(void) 414{ 415 char path[PATH_MAX]; |
444 FILE *f; 445 hid_device_t *d; | 416 FILE *f = NULL; 417 hid_device_t *hid_device = NULL; |
446 447 if (hids_file == NULL) { 448 SYSLOG(LOGERR, "Unknown HIDs file name!" EOL); 449 return (-1); 450 } 451 452 snprintf(path, sizeof(path), "%s.new", hids_file); 453 454 if ((f = fopen(path, "w")) == NULL) { 455 SYSLOG(LOGERR, "Could not open HIDs file '%s'. %s (%d)" EOL, 456 path, strerror(errno), errno); 457 return (-1); 458 } 459 | 418 419 if (hids_file == NULL) { 420 SYSLOG(LOGERR, "Unknown HIDs file name!" EOL); 421 return (-1); 422 } 423 424 snprintf(path, sizeof(path), "%s.new", hids_file); 425 426 if ((f = fopen(path, "w")) == NULL) { 427 SYSLOG(LOGERR, "Could not open HIDs file '%s'. %s (%d)" EOL, 428 path, strerror(errno), errno); 429 return (-1); 430 } 431 |
460 LIST_FOREACH(d, &hid_devices, next) 461 if (!d->new_device) 462 fprintf(f, "%s\n", bt_ntoa(&d->bdaddr, NULL)); | 432 LIST_FOREACH(hid_device, &hid_devices, next) 433 if (!hid_device->new_device) 434 fprintf(f, "%s\n", bt_ntoa(&hid_device->bdaddr, NULL)); |
463 464 fclose(f); 465 466 if (rename(path, hids_file) < 0) { 467 SYSLOG(LOGERR, "Could not rename new HIDs file '%s' to '%s'. " \ 468 "%s (%d)" EOL, path, hids_file, strerror(errno), errno); 469 unlink(path); 470 return (-1); 471 } 472 473 return (0); 474} 475 | 435 436 fclose(f); 437 438 if (rename(path, hids_file) < 0) { 439 SYSLOG(LOGERR, "Could not rename new HIDs file '%s' to '%s'. " \ 440 "%s (%d)" EOL, path, hids_file, strerror(errno), errno); 441 unlink(path); 442 return (-1); 443 } 444 445 return (0); 446} 447 |