parser.y (146357) | parser.y (162128) |
---|---|
1%{ 2/* 3 * parser.y | 1%{ 2/* 3 * parser.y |
4 * 5 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> | 4 */ 5 6/*- 7 * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com> |
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 * | 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 * |
29 * $Id: parser.y,v 1.4 2004/11/17 21:59:42 max Exp $ 30 * $FreeBSD: head/usr.sbin/bluetooth/bthidd/parser.y 146357 2005-05-18 23:03:44Z emax $ | 31 * $Id: parser.y,v 1.7 2006/09/07 21:06:53 max Exp $ 32 * $FreeBSD: head/usr.sbin/bluetooth/bthidd/parser.y 162128 2006-09-07 21:47:49Z emax $ |
31 */ 32 33#include <sys/queue.h> 34#include <bluetooth.h> | 33 */ 34 35#include <sys/queue.h> 36#include <bluetooth.h> |
37#include <dev/usb/usb.h> 38#include <dev/usb/usbhid.h> |
|
35#include <errno.h> 36#include <limits.h> 37#include <stdio.h> 38#include <string.h> 39#include <unistd.h> 40#include <usbhid.h> 41 42#ifndef BTHIDCONTROL --- 11 unchanged lines hidden (view full) --- 54#define LOGWARNING stderr 55#define EOL "\n" 56#endif /* ndef BTHIDCONTROL */ 57 58#include "bthid_config.h" 59 60 int yyparse (void); 61 int yylex (void); | 39#include <errno.h> 40#include <limits.h> 41#include <stdio.h> 42#include <string.h> 43#include <unistd.h> 44#include <usbhid.h> 45 46#ifndef BTHIDCONTROL --- 11 unchanged lines hidden (view full) --- 58#define LOGWARNING stderr 59#define EOL "\n" 60#endif /* ndef BTHIDCONTROL */ 61 62#include "bthid_config.h" 63 64 int yyparse (void); 65 int yylex (void); |
62static int check_hid_device(hid_device_p hid_device); | 66 void yyerror (char const *); 67static int32_t check_hid_device(hid_device_p hid_device); |
63static void free_hid_device (hid_device_p hid_device); 64 | 68static void free_hid_device (hid_device_p hid_device); 69 |
70extern FILE *yyin; |
|
65extern int yylineno; | 71extern int yylineno; |
66 char *config_file = BTHIDD_CONFFILE; 67 char *hids_file = BTHIDD_HIDSFILE; | 72 char const *config_file = BTHIDD_CONFFILE; 73 char const *hids_file = BTHIDD_HIDSFILE; |
68 69static char buffer[1024]; | 74 75static char buffer[1024]; |
70static int hid_descriptor_size; | 76static int32_t hid_descriptor_size; |
71static hid_device_t *hid_device = NULL; 72static LIST_HEAD(, hid_device) hid_devices; 73 74%} 75 76%union { 77 bdaddr_t bdaddr; | 77static hid_device_t *hid_device = NULL; 78static LIST_HEAD(, hid_device) hid_devices; 79 80%} 81 82%union { 83 bdaddr_t bdaddr; |
78 int num; | 84 int32_t num; |
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 --- 105 unchanged lines hidden (view full) --- 192 ; 193 194hid_descriptor_bytes: hid_descriptor_byte 195 | hid_descriptor_bytes hid_descriptor_byte 196 ; 197 198hid_descriptor_byte: T_HEXBYTE 199 { | 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 --- 105 unchanged lines hidden (view full) --- 198 ; 199 200hid_descriptor_bytes: hid_descriptor_byte 201 | hid_descriptor_bytes hid_descriptor_byte 202 ; 203 204hid_descriptor_byte: T_HEXBYTE 205 { |
200 if (hid_descriptor_size >= sizeof(buffer)) { | 206 if (hid_descriptor_size >= (int32_t) sizeof(buffer)) { |
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 */ | 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 */ |
224int | 230int32_t |
225read_config_file(void) 226{ | 231read_config_file(void) 232{ |
227 extern FILE *yyin; 228 int e; | 233 int32_t e; |
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)) { | 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)) { |
260 hid_device_p hid_device = LIST_FIRST(&hid_devices); | 265 hid_device_p d = LIST_FIRST(&hid_devices); |
261 | 266 |
262 LIST_REMOVE(hid_device, next); 263 free_hid_device(hid_device); | 267 LIST_REMOVE(d, next); 268 free_hid_device(d); |
264 } 265} 266 267/* Lookup config entry */ 268hid_device_p 269get_hid_device(bdaddr_p bdaddr) 270{ | 269 } 270} 271 272/* Lookup config entry */ 273hid_device_p 274get_hid_device(bdaddr_p bdaddr) 275{ |
271 hid_device_p hid_device; | 276 hid_device_p d; |
272 | 277 |
273 LIST_FOREACH(hid_device, &hid_devices, next) 274 if (memcmp(&hid_device->bdaddr, bdaddr, sizeof(bdaddr_t)) == 0) | 278 LIST_FOREACH(d, &hid_devices, next) 279 if (memcmp(&d->bdaddr, bdaddr, sizeof(bdaddr_t)) == 0) |
275 break; 276 | 280 break; 281 |
277 return (hid_device); | 282 return (d); |
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 | 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 |
289print_hid_device(hid_device_p hid_device, FILE *f) | 294print_hid_device(hid_device_p d, FILE *f) |
290{ 291 /* XXX FIXME hack! */ 292 struct report_desc { 293 unsigned int size; 294 unsigned char data[1]; 295 }; 296 /* XXX FIXME hack! */ 297 | 295{ 296 /* XXX FIXME hack! */ 297 struct report_desc { 298 unsigned int size; 299 unsigned char data[1]; 300 }; 301 /* XXX FIXME hack! */ 302 |
298 struct report_desc *desc = (struct report_desc *) hid_device->desc; 299 int i; | 303 struct report_desc *desc = (struct report_desc *) d->desc; 304 uint32_t i; |
300 301 fprintf(f, 302"device {\n" \ 303" bdaddr %s;\n" \ 304" control_psm 0x%x;\n" \ 305" interrupt_psm 0x%x;\n" \ 306" reconnect_initiate %s;\n" \ 307" battery_power %s;\n" \ 308" normally_connectable %s;\n" \ 309" hid_descriptor {", | 305 306 fprintf(f, 307"device {\n" \ 308" bdaddr %s;\n" \ 309" control_psm 0x%x;\n" \ 310" interrupt_psm 0x%x;\n" \ 311" reconnect_initiate %s;\n" \ 312" battery_power %s;\n" \ 313" normally_connectable %s;\n" \ 314" hid_descriptor {", |
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"); | 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"); |
315 316 for (i = 0; i < desc->size; i ++) { 317 if ((i % 8) == 0) 318 fprintf(f, "\n "); 319 320 fprintf(f, "0x%2.2x ", desc->data[i]); 321 } 322 323 fprintf(f, 324"\n" \ 325" };\n" \ 326"}\n"); 327} 328 329/* Check config entry */ | 320 321 for (i = 0; i < desc->size; i ++) { 322 if ((i % 8) == 0) 323 fprintf(f, "\n "); 324 325 fprintf(f, "0x%2.2x ", desc->data[i]); 326 } 327 328 fprintf(f, 329"\n" \ 330" };\n" \ 331"}\n"); 332} 333 334/* Check config entry */ |
330static int 331check_hid_device(hid_device_p hid_device) | 335static int32_t 336check_hid_device(hid_device_p d) |
332{ | 337{ |
333 if (get_hid_device(&hid_device->bdaddr) != NULL) { | 338 hid_data_t hd; 339 hid_item_t hi; 340 int32_t page; 341 342 if (get_hid_device(&d->bdaddr) != NULL) { |
334 SYSLOG(LOGERR, "Ignoring duplicated entry for bdaddr %s" EOL, | 343 SYSLOG(LOGERR, "Ignoring duplicated entry for bdaddr %s" EOL, |
335 bt_ntoa(&hid_device->bdaddr, NULL)); | 344 bt_ntoa(&d->bdaddr, NULL)); |
336 return (0); 337 } 338 | 345 return (0); 346 } 347 |
339 if (hid_device->control_psm == 0) { | 348 if (d->control_psm == 0) { |
340 SYSLOG(LOGERR, "Ignoring entry with invalid control PSM" EOL); 341 return (0); 342 } 343 | 349 SYSLOG(LOGERR, "Ignoring entry with invalid control PSM" EOL); 350 return (0); 351 } 352 |
344 if (hid_device->interrupt_psm == 0) { | 353 if (d->interrupt_psm == 0) { |
345 SYSLOG(LOGERR, "Ignoring entry with invalid interrupt PSM" EOL); 346 return (0); 347 } 348 | 354 SYSLOG(LOGERR, "Ignoring entry with invalid interrupt PSM" EOL); 355 return (0); 356 } 357 |
349 if (hid_device->desc == NULL) { | 358 if (d->desc == NULL) { |
350 SYSLOG(LOGERR, "Ignoring entry without HID descriptor" EOL); 351 return (0); 352 } 353 | 359 SYSLOG(LOGERR, "Ignoring entry without HID descriptor" EOL); 360 return (0); 361 } 362 |
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 || page == HUP_CONSUMER) 376 d->keyboard = 1; 377 break; 378 } 379 } 380 hid_end_parse(hd); 381 |
|
354 return (1); 355} 356 357/* Free config entry */ 358static void | 382 return (1); 383} 384 385/* Free config entry */ 386static void |
359free_hid_device(hid_device_p hid_device) | 387free_hid_device(hid_device_p d) |
360{ | 388{ |
361 if (hid_device->desc != NULL) 362 hid_dispose_report_desc(hid_device->desc); | 389 if (d->desc != NULL) 390 hid_dispose_report_desc(d->desc); |
363 | 391 |
364 memset(hid_device, 0, sizeof(*hid_device)); 365 free(hid_device); | 392 memset(d, 0, sizeof(*d)); 393 free(d); |
366} 367 368/* Re-read hids file */ | 394} 395 396/* Re-read hids file */ |
369int | 397int32_t |
370read_hids_file(void) 371{ | 398read_hids_file(void) 399{ |
372 FILE *f = NULL; 373 hid_device_t *hid_device = NULL; 374 char *line = NULL; | 400 FILE *f; 401 hid_device_t *d; 402 char *line; |
375 bdaddr_t bdaddr; | 403 bdaddr_t bdaddr; |
376 int lineno; | 404 int32_t lineno; |
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 | 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 |
402 if ((hid_device = get_hid_device(&bdaddr)) != NULL) 403 hid_device->new_device = 0; | 430 if ((d = get_hid_device(&bdaddr)) != NULL) 431 d->new_device = 0; |
404 } 405 406 fclose(f); 407 408 return (0); 409} 410 411/* Write hids file */ | 432 } 433 434 fclose(f); 435 436 return (0); 437} 438 439/* Write hids file */ |
412int | 440int32_t |
413write_hids_file(void) 414{ 415 char path[PATH_MAX]; | 441write_hids_file(void) 442{ 443 char path[PATH_MAX]; |
416 FILE *f = NULL; 417 hid_device_t *hid_device = NULL; | 444 FILE *f; 445 hid_device_t *d; |
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 | 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 |
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)); | 460 LIST_FOREACH(d, &hid_devices, next) 461 if (!d->new_device) 462 fprintf(f, "%s\n", bt_ntoa(&d->bdaddr, NULL)); |
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 | 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 |