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