1 /** 2 3 @brief Eeze Device Library 4 5 @page eeze_main Eeze 6 7 @date 2010 (created) 8 9 @section eeze_toc Table of Contents 10 11 @li @ref eeze_main_intro 12 @li @ref eeze_main_compiling 13 @li @ref eeze_main_next_steps 14 15 @section eeze_main_intro Introduction 16 17 Eeze is a library for manipulating devices through udev with a 18 simple and fast api. It interfaces directly with libudev, avoiding 19 such middleman daemons as udisks/upower or hal, to immediately 20 gather device information the instant it becomes known to the 21 system. This can be used to determine such things as: 22 23 @li If a cdrom has a disk inserted 24 @li The temperature of a cpu core 25 @li The remaining power left in a battery 26 @li The current power consumption of various parts 27 @li Monitor in realtime the status of peripheral devices 28 29 Each of the above examples can be performed by using only a single eeze 30 function, as one of the primary focuses of the library is to reduce the 31 complexity of managing devices. 32 33 @section eeze_main_compiling How to compile 34 35 Eeze is a library your application links to. The procedure for this is very 36 simple. You simply have to compile your application with the appropriate 37 compiler flags that the @p pkg-config script outputs. For example: 38 39 Compiling C or C++ files into object files: 40 41 @verbatim 42 gcc -c -o main.o main.c `pkg-config --cflags eeze` 43 @endverbatim 44 45 Linking object files into a binary executable: 46 47 @verbatim 48 gcc -o my_application main.o `pkg-config --libs eeze` 49 @endverbatim 50 51 See @ref pkgconfig 52 53 @section eeze_main_next_steps Next Steps 54 55 After you understood what Eeze is and installed it in your system 56 you should proceed understanding the programming interface. We'd 57 recommend you to take a while to learn @ref Eina and @ref Ecore as 58 they convenient and Eeze provides integration with it. 59 60 Recommended reading: 61 62 @li @link Eeze.h Eeze functions @endlink 63 @li @ref Eeze_Udev UDEV functions 64 @li @ref Eeze_Watch Functions that watch for events 65 @li @ref Eeze_Syspath Functions that accept a device /sys/ path 66 @li @ref Eeze_Find Functions which find types of devices 67 @li @ref Eeze_Disk Disk functions 68 @li @ref Eeze_Net Net functions 69 @li @ref Eeze_Sensor Sensor functions 70 71 */ 72 #ifndef EEZE_UDEV_H 73 #define EEZE_UDEV_H 74 75 #include <Eina.h> 76 #include <Efl_Config.h> 77 78 #ifdef EAPI 79 # undef EAPI 80 #endif 81 82 #ifdef __GNUC__ 83 # if __GNUC__ >= 4 84 # define EAPI __attribute__ ((visibility("default"))) 85 # else 86 # define EAPI 87 # endif 88 #else 89 # define EAPI 90 #endif 91 92 /** 93 * @file Eeze.h 94 * @brief Easy device manipulation. 95 * 96 * Eeze is a library for manipulating devices through udev with a simple and fast 97 * api. It interfaces directly with libudev, avoiding such middleman daemons as 98 * udisks/upower or hal, to immediately gather device information the instant it 99 * becomes known to the system. This can be used to determine such things as: 100 * @li If a cdrom has a disk inserted 101 * @li The temperature of a cpu core 102 * @li The remaining power left in a battery 103 * @li The current power consumption of various parts 104 * @li Monitor in realtime the status of peripheral devices 105 * Each of the above examples can be performed by using only a single eeze 106 * function, as one of the primary focuses of the library is to reduce the 107 * complexity of managing devices. 108 * 109 * 110 * For udev functions, see @ref udev. 111 */ 112 113 /** 114 * @defgroup Eeze_Main main 115 * @ingroup Eeze 116 * 117 * These are general eeze functions which include init and shutdown. 118 */ 119 120 /** 121 * @defgroup Eeze_Udev udev 122 * @ingroup Eeze_Main 123 * 124 * These are functions which interact directly with udev. 125 */ 126 127 /** 128 * @addtogroup Eeze_Udev 129 * 130 * These are the device subsystems of udev: 131 * @li ac97 132 * @li acpi 133 * @li backlight 134 * @li bdi 135 * @li block 136 * @li bsg 137 * @li dmi 138 * @li drm 139 * @li graphics 140 * @li hid 141 * @li hwmon 142 * @li i2c 143 * @li input 144 * @li leds 145 * @li mem 146 * @li misc 147 * @li net 148 * @li pci 149 * @li pci_bus 150 * @li pci_express 151 * @li platform 152 * @li pnp 153 * @li rtc 154 * @li scsi 155 * @li scsi_device 156 * @li scsi_disk 157 * @li scsi_generic 158 * @li scsi_host 159 * @li serio 160 * @li sound 161 * @li thermal 162 * @li tty 163 * @li usb 164 * @li usb_device 165 * @li vc 166 * @li vtconsole 167 * 168 * These are the devtypes of udev. 169 * @li atapi 170 * @li audio 171 * @li block 172 * @li cd 173 * @li char 174 * @li disk 175 * @li drm_minor 176 * @li floppy 177 * @li generic 178 * @li hid 179 * @li hub 180 * @li media 181 * @li optical 182 * @li printer 183 * @li rbc 184 * @li scsi 185 * @li storage 186 * @li tape 187 * @li video 188 */ 189 #ifdef __cplusplus 190 extern "C" { 191 #endif 192 193 /** 194 * @addtogroup Eeze_Udev 195 * @typedef Eeze_Udev_Event 196 * @enum Eeze_Udev_Event 197 * @brief Flags for watch events 198 * 199 * These events are used to specify the events to watch in a 200 * #Eeze_Udev_Watch. They can be ORed together. 201 *@{ 202 */ 203 typedef enum 204 { 205 /** - No event specified */ 206 EEZE_UDEV_EVENT_NONE = 0xf0, 207 /** - Device added */ 208 EEZE_UDEV_EVENT_ADD = (1 << 1), 209 /** - Device removed */ 210 EEZE_UDEV_EVENT_REMOVE = (1 << 2), 211 /** - Device changed */ 212 EEZE_UDEV_EVENT_CHANGE = (1 << 3), 213 /** - Device has come online */ 214 EEZE_UDEV_EVENT_ONLINE = (1 << 4), 215 /** - Device has gone offline */ 216 EEZE_UDEV_EVENT_OFFLINE = (1 << 5) 217 } Eeze_Udev_Event; 218 /** @} */ 219 220 /** 221 * @addtogroup Eeze_Udev udev 222 * @typedef Eeze_Udev_Type Eeze_Udev_Type 223 * @enum Eeze_Udev_Type 224 * @brief Convenience types to simplify udev access. 225 * 226 * These types allow easy access to certain udev device types. They 227 * may only be used in specified functions. 228 * 229 * @{ 230 */ 231 /*FIXME: these probably need to be bitmasks with categories*/ 232 typedef enum 233 { 234 /** - No type */ 235 EEZE_UDEV_TYPE_NONE, 236 /** - Keyboard device */ 237 EEZE_UDEV_TYPE_KEYBOARD, 238 /** - Mouse device */ 239 EEZE_UDEV_TYPE_MOUSE, 240 /** - Touchpad device */ 241 EEZE_UDEV_TYPE_TOUCHPAD, 242 /** - Mountable drive */ 243 EEZE_UDEV_TYPE_DRIVE_MOUNTABLE, 244 /** - Internal drive */ 245 EEZE_UDEV_TYPE_DRIVE_INTERNAL, 246 /** - Removable drive */ 247 EEZE_UDEV_TYPE_DRIVE_REMOVABLE, 248 /** - cd drive */ 249 EEZE_UDEV_TYPE_DRIVE_CDROM, 250 /** - AC adapter */ 251 EEZE_UDEV_TYPE_POWER_AC, 252 /** - Battery */ 253 EEZE_UDEV_TYPE_POWER_BAT, 254 /** - Temperature sensor */ 255 EEZE_UDEV_TYPE_IS_IT_HOT_OR_IS_IT_COLD_SENSOR, 256 /** - Network devices */ 257 EEZE_UDEV_TYPE_NET, 258 /** - WebCam */ 259 EEZE_UDEV_TYPE_V4L, 260 /** - Bluetooth */ 261 EEZE_UDEV_TYPE_BLUETOOTH, 262 /** - Joystick 263 * @since 1.7 264 */ 265 EEZE_UDEV_TYPE_JOYSTICK, 266 /** - Drm 267 * @since 1.12 268 */ 269 EEZE_UDEV_TYPE_DRM, 270 /** - Backlight 271 * @since 1.12 272 */ 273 EEZE_UDEV_TYPE_BACKLIGHT, 274 /** - Leds 275 * @since 1.12 276 */ 277 EEZE_UDEV_TYPE_LEDS, 278 /** - Graphics 279 * @since 1.18 280 */ 281 EEZE_UDEV_TYPE_GRAPHICS, 282 /** - GPIOS (includes gpioN and gpiochipN) 283 * @since 1.19 284 */ 285 EEZE_UDEV_TYPE_GPIO 286 } Eeze_Udev_Type; 287 /**@}*/ 288 289 struct Eeze_Udev_Watch; 290 291 /** 292 * @addtogroup Eeze_Watch 293 * @typedef Eeze_Udev_Watch Eeze_Udev_Watch 294 * @brief Opaque structure to hold data for a udev watch 295 */ 296 typedef struct Eeze_Udev_Watch Eeze_Udev_Watch; 297 298 #define EEZE_VERSION_MAJOR EFL_VERSION_MAJOR 299 #define EEZE_VERSION_MINOR EFL_VERSION_MINOR 300 /** 301 * @typedef Eeeze_Version 302 * Represents the current version of Eeze 303 */ 304 typedef struct _Eeze_Version 305 { 306 int major; /** < major (binary or source incompatible changes) */ 307 int minor; /** < minor (new features, bugfixes, major improvements version) */ 308 int micro; /** < micro (bugfix, internal improvements, no new features version) */ 309 int revision; /** < git revision (0 if a proper release or the git revision number Eeze is built from) */ 310 } Eeze_Version; 311 312 EAPI extern Eeze_Version *eeze_version; 313 314 /** 315 * @addtogroup Eeze_Watch 316 * @typedef Eeze_Udev_Watch_Cb Eeze_Udev_Watch_Cb 317 * @brief Callback type for use with #Eeze_Udev_Watch 318 */ 319 typedef void(*Eeze_Udev_Watch_Cb)(const char *, Eeze_Udev_Event, void *, Eeze_Udev_Watch *); 320 321 322 /** 323 * Initialize the eeze library. 324 * @return The number of times the function has been called, or -1 on failure. 325 * 326 * This function should be called prior to using any eeze functions, and MUST 327 * be called prior to using any udev functions to avoid a segv. 328 * 329 * @ingroup Eeze_Main 330 */ 331 EAPI int eeze_init(void); 332 333 /** 334 * Shut down the eeze library. 335 * @return The number of times the eeze_init has been called, or -1 when 336 * all occurrences of eeze have been shut down. 337 * 338 * This function should be called when no further eeze functions will be called. 339 * 340 * @ingroup Eeze_Main 341 */ 342 EAPI int eeze_shutdown(void); 343 344 /** 345 * @return the main udev context used by the library 346 * This allows for external reuse of the udev context, reducing direct dependency 347 * on libudev. 348 * @warning DO NOT CLOSE THIS CONTEXT. 349 * @since 1.10 350 */ 351 EAPI void *eeze_udev_get(void); 352 353 354 /** 355 * @addtogroup Eeze_Find Find 356 * 357 * These are functions which find/supplement lists of devices. 358 * 359 * @ingroup Eeze_Udev 360 * 361 * @{ 362 */ 363 364 /** 365 * Returns a stringshared list of all syspaths that are (or should be) the same 366 * device as the device pointed at by @p syspath. 367 * 368 * @param syspath The syspath of the device to find matches for 369 * @return All devices which are the same as the one passed 370 */ 371 EAPI Eina_List *eeze_udev_find_similar_from_syspath(const char *syspath); 372 373 /** 374 * Updates a list of all syspaths that are (or should be) the same 375 * device. 376 * 377 * @param list The list of devices to update 378 * @return The updated list 379 * 380 * This function will update @p list to include all devices matching 381 * devices with syspaths currently stored in @p list. All strings are 382 * stringshared. 383 * 384 * @note This is an expensive call, do not use it unless you must. 385 */ 386 EAPI Eina_List *eeze_udev_find_unlisted_similar(Eina_List *list); 387 388 /** 389 * Find a list of devices by a sysattr (and, optionally, a value of that sysattr). 390 * 391 * @param sysattr The attribute to find 392 * @param value Optional: the value that the attribute should have 393 * 394 * @return A stringshared list of the devices found with the attribute 395 * 396 * @ingroup Eeze_Find 397 */ 398 EAPI Eina_List *eeze_udev_find_by_sysattr(const char *sysattr, const char *value); 399 400 /** 401 * Find devices using an #Eeze_Udev_Type and/or a name. 402 * 403 * @param type An #Eeze_Udev_Type or 0 404 * @param name A filter for the device name or @c NULL 405 * @return A stringshared Eina_List of matched devices or @c NULL on failure 406 * 407 * Return a list of syspaths (/sys/$syspath) for matching udev devices. 408 */ 409 EAPI Eina_List *eeze_udev_find_by_type(Eeze_Udev_Type type, const char *name); 410 411 /** 412 * A more advanced find, allows finds using udev properties. 413 * 414 * @param subsystem The udev subsystem to filter by, or @c NULL 415 * @param type "ID_INPUT_KEY", "ID_INPUT_MOUSE", "ID_INPUT_TOUCHPAD", @c NULL, etc 416 * @param name A filter for the device name, or @c NULL 417 * @return A stringshared Eina_List* of matched devices or @c NULL on failure 418 * 419 * Return a list of syspaths (/sys/$syspath) for matching udev devices. 420 * Requires at least one filter. 421 */ 422 EAPI Eina_List *eeze_udev_find_by_filter(const char *subsystem, const char *type, const char *name); 423 424 /** 425 * A more advanced find, allows finds using udev subsystem and sysname 426 * 427 * @param subsystem The udev subsystem to filter by, or @c NULL 428 * @param sysname A filter for the device name, or @c NULL 429 * @return A stringshared Eina_List* of matched devices or @c NULL on failure 430 * 431 * @return A stringshared list of the devices found 432 * 433 * @since 1.13 434 435 EAPI */ 436 EAPI Eina_List *eeze_udev_find_by_subsystem_sysname(const char *subsystem, const char *sysname); 437 438 /** 439 * @} 440 */ 441 442 /** 443 * @addtogroup Eeze_Syspath Syspath 444 * 445 * These are functions which interact with the syspath (/sys/$PATH) of 446 * a device. 447 * 448 * @ingroup Eeze_Udev 449 * 450 * @{ 451 */ 452 453 /** 454 * Get the syspath of a device from the /dev/ path. 455 * 456 * @param devpath The /dev/ path of the device 457 * @return A stringshared char* which corresponds to the /sys/ path of the device or @c NULL on failure 458 * 459 * Takes "/dev/path" and returns the corresponding /sys/ path (without the "/sys/") 460 */ 461 EAPI const char *eeze_udev_devpath_get_syspath(const char *devpath); 462 463 /** 464 * Find the root device of a device from its syspath. 465 * 466 * @param syspath The syspath of a device, with or without "/sys/" 467 * @return The syspath of the parent device 468 * 469 * Return a stringshared syspath (/sys/$syspath) for the parent device. 470 */ 471 EAPI const char *eeze_udev_syspath_get_parent(const char *syspath); 472 473 /** 474 * Find the parent device of a device from its syspath with a filter applied. 475 * 476 * @param syspath The syspath of a device, with or without "/sys/" 477 * @param subsystem The desired subsystem of the parent device 478 * @param devtype The desired device type of the parent device 479 * @return The syspath of the parent device 480 * 481 * Return a stringshared syspath (/sys/$syspath) for the parent device if one exists which matches the filter. 482 * @since 1.10 483 */ 484 EAPI Eina_Stringshare *eeze_udev_syspath_get_parent_filtered(const char *syspath, const char *subsystem, const char *devtype); 485 486 /** 487 * Returns a list of all parent device syspaths for @p syspath. 488 * 489 * @param syspath The device to find parents of 490 * @return A stringshared list of the parent devices of @p syspath 491 */ 492 EAPI Eina_List *eeze_udev_syspath_get_parents(const char *syspath); 493 494 /** 495 * Get the /dev/ path from the /sys/ path. 496 * 497 * @param syspath The /sys/ path with or without the /sys/ 498 * @return A stringshared char* with the /dev/ path or @c NULL on failure 499 * 500 * Takes /sys/$PATH and turns it into the corresponding "/dev/x/y". 501 */ 502 EAPI const char *eeze_udev_syspath_get_devpath(const char *syspath); 503 504 /** 505 * Get the /dev/ name from the /sys/ path. 506 * 507 * @param syspath The /sys/ path with or without the /sys/ 508 * @return A stringshared char* of the device name without the /dev/ path, or @c NULL on failure 509 * 510 * Takes /sys/$PATH and turns it into the corresponding /dev/x/"y". 511 */ 512 EAPI const char *eeze_udev_syspath_get_devname(const char *syspath); 513 514 /** 515 * Get the subsystem of a device from the /sys/ path. 516 * 517 * @param syspath The /sys/ path with or without the /sys/ 518 * @return A stringshared char* with the subsystem of the device or @c NULL on failure 519 * 520 * Takes /sys/$PATH and returns the corresponding device subsystem, 521 * such as "input" for keyboards/mice. 522 */ 523 EAPI const char *eeze_udev_syspath_get_subsystem(const char *syspath); 524 525 /** 526 * Check the property value of a device from the /sys/ path against a provided value. 527 * 528 * @param syspath The /sys/ path with or without the /sys/ 529 * @param property The property to check; full list of these is a FIXME 530 * @param value The value to check the property against 531 * @return @c EINA_TRUE if the property matches the supplied value 532 * @since 1.10 533 */ 534 EAPI Eina_Bool eeze_udev_syspath_check_property(const char *syspath, const char *property, const char *value); 535 536 /** 537 * Get the property value of a device from the /sys/ path. 538 * 539 * @param syspath The /sys/ path with or without the /sys/ 540 * @param property The property to get; full list of these is a FIXME 541 * @return A stringshared char* with the property or @c NULL on failure 542 */ 543 EAPI const char *eeze_udev_syspath_get_property(const char *syspath, const char *property); 544 545 /** 546 * Get the sysattr value of a device from the /sys/ path. 547 * 548 * @param syspath The /sys/ path with or without the /sys/ 549 * @param sysattr The sysattr to get; full list of these is a FIXME 550 * @return A stringshared char* with the sysattr or @c NULL on failure 551 */ 552 EAPI const char *eeze_udev_syspath_get_sysattr(const char *syspath, const char *sysattr); 553 554 /** 555 * Check the sysattr value of a device from the /sys/ path against a provided value. 556 * 557 * @param syspath The /sys/ path with or without the /sys/ 558 * @param sysattr The sysattr to check; full list of these is a FIXME 559 * @param value The value to check the property against 560 * @return @c EINA_TRUE if the sysattr matches the supplied value 561 * @since 1.10 562 */ 563 EAPI Eina_Bool eeze_udev_syspath_check_sysattr(const char *syspath, const char *sysattr, const char *value); 564 565 /** 566 * Set the sysattr value of a device from the /sys/ path. 567 * 568 * @param syspath The /sys/ path with or without the /sys/ 569 * @param sysattr The sysattr to set; 570 * @param value The value of sysattr to be set 571 * @return @c EINA_TRUE if the sysattr value is set 572 * @since 1.12 573 */ 574 EAPI Eina_Bool eeze_udev_syspath_set_sysattr(const char *syspath, const char *sysattr, double value); 575 576 /** 577 * Get the sysattr list of a device from the /sys/ path. 578 * 579 * @param syspath The /sys/ path with or without the /sys/ 580 * @return Eina_list containing list of sysattr for a device or @c NULL on failure 581 * @since 1.12 582 */ 583 EAPI Eina_List *eeze_udev_syspath_get_sysattr_list(const char *syspath); 584 585 /** 586 * Checks whether the device is a mouse. 587 * 588 * @param syspath The /sys/ path with or without the /sys/ 589 * @return If true, the device is a mouse 590 */ 591 EAPI Eina_Bool eeze_udev_syspath_is_mouse(const char *syspath); 592 593 /** 594 * Checks whether the device is a keyboard. 595 * 596 * @param syspath The /sys/ path with or without the /sys/ 597 * @return If true, the device is a keyboard 598 */ 599 EAPI Eina_Bool eeze_udev_syspath_is_kbd(const char *syspath); 600 601 /** 602 * Checks whether the device is a touchpad. 603 * 604 * @param syspath The /sys/ path with or without the /sys/ 605 * @return If true, the device is a touchpad 606 */ 607 EAPI Eina_Bool eeze_udev_syspath_is_touchpad(const char *syspath); 608 609 /** 610 * Checks whether the device is a joystick. 611 * 612 * @param syspath The /sys/ path with or without the /sys/ 613 * @return If true, the device is a joystick 614 * @since 1.7 615 */ 616 EAPI Eina_Bool eeze_udev_syspath_is_joystick(const char *syspath); 617 618 /** 619 * Get the sysnum value of a device from the /sys/ path. 620 * 621 * @param syspath The /sys/ path with or without the /sys/ 622 * @return A integer with the sysnum or -1 on failure 623 * 624 * @since 1.12 625 */ 626 EAPI int eeze_udev_syspath_get_sysnum(const char *syspath); 627 628 /** 629 * @} 630 */ 631 632 /** 633 * @addtogroup Eeze_Walks Walks 634 * 635 * These are functions which walk up the device chain. 636 * 637 * @ingroup Eeze_Udev 638 * 639 * @{ 640 */ 641 642 /** 643 * Walks up the device chain starting at @p syspath, 644 * checking each device for @p sysattr with (optional) @p value. 645 * 646 * @param syspath The /sys/ path of the device to start at, with or without the /sys/ 647 * @param sysattr The attribute to find 648 * @param value OPTIONAL: The value that @p sysattr should have, or @c NULL 649 * 650 * @return If the sysattr (with value) is found, returns TRUE. Else, false. 651 */ 652 EAPI Eina_Bool eeze_udev_walk_check_sysattr(const char *syspath, const char *sysattr, const char *value); 653 654 /** 655 * Walks up the device chain starting at @p syspath, 656 * checking each device for @p sysattr, and returns the value if found. 657 * 658 * @param syspath The /sys/ path of the device to start at, with or without the /sys/ 659 * @param sysattr The attribute to find 660 * 661 * @return The stringshared value of @p sysattr if found, or @c NULL 662 */ 663 EAPI const char *eeze_udev_walk_get_sysattr(const char *syspath, const char *sysattr); 664 /** 665 * @} 666 */ 667 668 /** 669 * @addtogroup Eeze_Watch Watch 670 * 671 * @brief These are functions which monitor udev for events. 672 * 673 * Eeze watches are simple: you specify a type of device to watch (or all devices), some events (or all) to watch for, a callback, 674 * and some data, and then udev watches those device types for events of the type you specified. Your callback is called with a 675 * syspath of the triggering device and the event that happened to the device, along with the data you associated with the watch and 676 * the watch object itself in case you want to stop the watch easily in a callback. 677 * 678 * @ingroup Eeze_Udev 679 * 680 * @{ 681 */ 682 683 /** 684 * Add a watch for a device type 685 * 686 * @param type The #Eeze_Udev_Type to watch 687 * @param event The events to watch; an OR list of #Eeze_Udev_Event (ie (#EEZE_UDEV_EVENT_ADD | #EEZE_UDEV_EVENT_REMOVE)), or 0 for all events 688 * @param cb The function to call when the watch receives data of type #Eeze_Udev_Watch_Cb 689 * @param user_data Data to pass to the callback function 690 * 691 * @return A watch struct for the watch type specified, or @c NULL on failure 692 * 693 * Eeze watches will monitor udev for changes of type(s) @p event to devices of type @p type. When these changes occur, the stringshared 694 * syspath of the device will be sent to function @p func, along with the bitmask of the event type which can be detected through 695 * binary &. 696 */ 697 EAPI Eeze_Udev_Watch *eeze_udev_watch_add(Eeze_Udev_Type type, int event, Eeze_Udev_Watch_Cb cb, void *user_data); 698 699 /** 700 * Deletes a watch. 701 * 702 * @param watch An Eeze_Udev_Watch object 703 * @return The data originally associated with the watch, or @c NULL 704 * 705 * Deletes a watch, closing file descriptors and freeing related udev memory. 706 */ 707 EAPI void *eeze_udev_watch_del(Eeze_Udev_Watch *watch); 708 /** 709 * @} 710 */ 711 712 #ifdef __cplusplus 713 } 714 #endif 715 716 #undef EAPI 717 #define EAPI 718 719 #endif 720