diff options
Diffstat (limited to 'xorg-server/include')
-rw-r--r-- | xorg-server/include/dix.h | 4 | ||||
-rw-r--r-- | xorg-server/include/eventstr.h | 488 | ||||
-rw-r--r-- | xorg-server/include/input.h | 50 | ||||
-rw-r--r-- | xorg-server/include/inputstr.h | 10 | ||||
-rw-r--r-- | xorg-server/include/inpututils.h | 2 | ||||
-rw-r--r-- | xorg-server/include/misc.h | 18 |
6 files changed, 303 insertions, 269 deletions
diff --git a/xorg-server/include/dix.h b/xorg-server/include/dix.h index de78b7e24..daac63a2e 100644 --- a/xorg-server/include/dix.h +++ b/xorg-server/include/dix.h @@ -375,7 +375,7 @@ extern void ReleaseActiveGrabs( extern GrabPtr CheckPassiveGrabsOnWindow(
WindowPtr /* pWin */,
DeviceIntPtr /* device */,
- DeviceEvent * /* event */,
+ InternalEvent * /* event */,
BOOL /* checkCore */,
BOOL /* activate */);
@@ -415,7 +415,7 @@ extern void DeliverFocusedEvent( InternalEvent* /* event */,
WindowPtr /* window */);
-extern void DeliverGrabbedEvent(
+extern int DeliverGrabbedEvent(
InternalEvent* /* event */,
DeviceIntPtr /* thisDev */,
Bool /* deactivateGrab */);
diff --git a/xorg-server/include/eventstr.h b/xorg-server/include/eventstr.h index 673207ce3..83f96d168 100644 --- a/xorg-server/include/eventstr.h +++ b/xorg-server/include/eventstr.h @@ -1,246 +1,242 @@ -/* - * Copyright © 2009 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef EVENTSTR_H -#define EVENTSTR_H - -#include <events.h> -/** - * @file events.h - * This file describes the event structures used internally by the X - * server during event generation and event processing. - * - * When are internal events used? - * Events from input devices are stored as internal events in the EQ and - * processed as internal events until late in the processing cycle. Only then - * do they switch to their respective wire events. - */ - -/** - * Event types. Used exclusively internal to the server, not visible on the - * protocol. - * - * Note: Keep KeyPress to Motion aligned with the core events. - * Keep ET_Raw* in the same order as KeyPress - Motion - */ -enum EventType { - ET_KeyPress = 2, - ET_KeyRelease, - ET_ButtonPress, - ET_ButtonRelease, - ET_Motion, - ET_Enter, - ET_Leave, - ET_FocusIn, - ET_FocusOut, - ET_ProximityIn, - ET_ProximityOut, - ET_DeviceChanged, - ET_Hierarchy, - ET_DGAEvent, - ET_RawKeyPress, - ET_RawKeyRelease, - ET_RawButtonPress, - ET_RawButtonRelease, - ET_RawMotion, - ET_XQuartz, - ET_Internal = 0xFF /* First byte */ -}; - -#define CHECKEVENT(ev) if (ev && ((InternalEvent*)(ev))->any.header != 0xFF) \ - FatalError("Wrong event type %d.\n", \ - ((InternalEvent*)(ev))->any.header); - -/** - * Used for ALL input device events internal in the server until - * copied into the matching protocol event. - * - * Note: We only use the device id because the DeviceIntPtr may become invalid while - * the event is in the EQ. - */ -struct _DeviceEvent -{ - unsigned char header; /**< Always ET_Internal */ - enum EventType type; /**< One of EventType */ - int length; /**< Length in bytes */ - Time time; /**< Time in ms */ - int deviceid; /**< Device to post this event for */ - int sourceid; /**< The physical source device */ - union { - uint32_t button; /**< Button number */ - uint32_t key; /**< Key code */ - } detail; - int16_t root_x; /**< Pos relative to root window in integral data */ - float root_x_frac; /**< Pos relative to root window in frac part */ - int16_t root_y; /**< Pos relative to root window in integral part */ - float root_y_frac; /**< Pos relative to root window in frac part */ - uint8_t buttons[(MAX_BUTTONS + 7)/8]; /**< Button mask */ - struct { - uint8_t mask[(MAX_VALUATORS + 7)/8]; /**< Valuator mask */ - uint8_t mode[(MAX_VALUATORS + 7)/8]; /**< Valuator mode (Abs or Rel)*/ - int32_t data[MAX_VALUATORS]; /**< Valuator data */ - int32_t data_frac[MAX_VALUATORS]; /**< Fractional part for data */ - } valuators; - struct { - uint32_t base; /**< XKB base modifiers */ - uint32_t latched; /**< XKB latched modifiers */ - uint32_t locked; /**< XKB locked modifiers */ - uint32_t effective;/**< XKB effective modifiers */ - } mods; - struct { - uint8_t base; /**< XKB base group */ - uint8_t latched; /**< XKB latched group */ - uint8_t locked; /**< XKB locked group */ - uint8_t effective;/**< XKB effective group */ - } group; - Window root; /**< Root window of the event */ - int corestate; /**< Core key/button state BEFORE the event */ - int key_repeat; /**< Internally-generated key repeat event */ -}; - - -/* Flags used in DeviceChangedEvent to signal if the slave has changed */ -#define DEVCHANGE_SLAVE_SWITCH 0x2 -/* Flags used in DeviceChangedEvent to signal whether the event was a - * pointer event or a keyboard event */ -#define DEVCHANGE_POINTER_EVENT 0x4 -#define DEVCHANGE_KEYBOARD_EVENT 0x8 -/* device capabilities changed */ -#define DEVCHANGE_DEVICE_CHANGE 0x10 - -/** - * Sent whenever a device's capabilities have changed. - */ -struct _DeviceChangedEvent -{ - unsigned char header; /**< Always ET_Internal */ - enum EventType type; /**< ET_DeviceChanged */ - int length; /**< Length in bytes */ - Time time; /**< Time in ms */ - int deviceid; /**< Device whose capabilities have changed */ - int flags; /**< Mask of ::HAS_NEW_SLAVE, - ::POINTER_EVENT, ::KEYBOARD_EVENT */ - int masterid; /**< MD when event was generated */ - int sourceid; /**< The device that caused the change */ - - struct { - int num_buttons; /**< Number of buttons */ - Atom names[MAX_BUTTONS];/**< Button names */ - } buttons; - - int num_valuators; /**< Number of axes */ - struct { - uint32_t min; /**< Minimum value */ - uint32_t max; /**< Maximum value */ - /* FIXME: frac parts of min/max */ - uint32_t resolution; /**< Resolution counts/m */ - uint8_t mode; /**< Relative or Absolute */ - Atom name; /**< Axis name */ - } valuators[MAX_VALUATORS]; - - struct { - int min_keycode; - int max_keycode; - } keys; -}; - -#if XFreeXDGA -/** - * DGAEvent, used by DGA to intercept and emulate input events. - */ -struct _DGAEvent -{ - unsigned char header; /**< Always ET_Internal */ - enum EventType type; /**< ET_DGAEvent */ - int length; /**< Length in bytes */ - Time time; /**< Time in ms */ - int subtype; /**< KeyPress, KeyRelease, ButtonPress, - ButtonRelease, MotionNotify */ - int detail; /**< Button number or key code */ - int dx; /**< Relative x coordinate */ - int dy; /**< Relative y coordinate */ - int screen; /**< Screen number this event applies to */ - uint16_t state; /**< Core modifier/button state */ -}; -#endif - -/** - * Raw event, contains the data as posted by the device. - */ -struct _RawDeviceEvent -{ - unsigned char header; /**< Always ET_Internal */ - enum EventType type; /**< ET_Raw */ - int length; /**< Length in bytes */ - Time time; /**< Time in ms */ - int deviceid; /**< Device to post this event for */ - int sourceid; /**< The physical source device */ - union { - uint32_t button; /**< Button number */ - uint32_t key; /**< Key code */ - } detail; - struct { - uint8_t mask[(MAX_VALUATORS + 7)/8]; /**< Valuator mask */ - int32_t data[MAX_VALUATORS]; /**< Valuator data */ - int32_t data_frac[MAX_VALUATORS]; /**< Fractional part for data */ - int32_t data_raw[MAX_VALUATORS]; /**< Valuator data as posted */ - int32_t data_raw_frac[MAX_VALUATORS];/**< Fractional part for data_raw */ - } valuators; -}; - -#ifdef XQUARTZ -#define XQUARTZ_EVENT_MAXARGS 5 -struct _XQuartzEvent { - unsigned char header; /**< Always ET_Internal */ - enum EventType type; /**< Always ET_XQuartz */ - int length; /**< Length in bytes */ - Time time; /**< Time in ms. */ - int subtype; /**< Subtype defined by XQuartz DDX */ - uint32_t data[XQUARTZ_EVENT_MAXARGS]; /**< Up to 5 32bit values passed to handler */ -}; -#endif - -/** - * Event type used inside the X server for input event - * processing. - */ -union _InternalEvent { - struct { - unsigned char header; /**< Always ET_Internal */ - enum EventType type; /**< One of ET_* */ - int length; /**< Length in bytes */ - Time time; /**< Time in ms. */ - } any; - DeviceEvent device_event; - DeviceChangedEvent changed_event; -#if XFreeXDGA - DGAEvent dga_event; -#endif - RawDeviceEvent raw_event; -#ifdef XQUARTZ - XQuartzEvent xquartz_event; -#endif -}; - -#endif +/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef EVENTSTR_H
+#define EVENTSTR_H
+
+#include <events.h>
+/**
+ * @file events.h
+ * This file describes the event structures used internally by the X
+ * server during event generation and event processing.
+ *
+ * When are internal events used?
+ * Events from input devices are stored as internal events in the EQ and
+ * processed as internal events until late in the processing cycle. Only then
+ * do they switch to their respective wire events.
+ */
+
+/**
+ * Event types. Used exclusively internal to the server, not visible on the
+ * protocol.
+ *
+ * Note: Keep KeyPress to Motion aligned with the core events.
+ * Keep ET_Raw* in the same order as KeyPress - Motion
+ */
+enum EventType {
+ ET_KeyPress = 2,
+ ET_KeyRelease,
+ ET_ButtonPress,
+ ET_ButtonRelease,
+ ET_Motion,
+ ET_Enter,
+ ET_Leave,
+ ET_FocusIn,
+ ET_FocusOut,
+ ET_ProximityIn,
+ ET_ProximityOut,
+ ET_DeviceChanged,
+ ET_Hierarchy,
+ ET_DGAEvent,
+ ET_RawKeyPress,
+ ET_RawKeyRelease,
+ ET_RawButtonPress,
+ ET_RawButtonRelease,
+ ET_RawMotion,
+ ET_XQuartz,
+ ET_Internal = 0xFF /* First byte */
+};
+
+/**
+ * Used for ALL input device events internal in the server until
+ * copied into the matching protocol event.
+ *
+ * Note: We only use the device id because the DeviceIntPtr may become invalid while
+ * the event is in the EQ.
+ */
+struct _DeviceEvent
+{
+ unsigned char header; /**< Always ET_Internal */
+ enum EventType type; /**< One of EventType */
+ int length; /**< Length in bytes */
+ Time time; /**< Time in ms */
+ int deviceid; /**< Device to post this event for */
+ int sourceid; /**< The physical source device */
+ union {
+ uint32_t button; /**< Button number */
+ uint32_t key; /**< Key code */
+ } detail;
+ int16_t root_x; /**< Pos relative to root window in integral data */
+ float root_x_frac; /**< Pos relative to root window in frac part */
+ int16_t root_y; /**< Pos relative to root window in integral part */
+ float root_y_frac; /**< Pos relative to root window in frac part */
+ uint8_t buttons[(MAX_BUTTONS + 7)/8]; /**< Button mask */
+ struct {
+ uint8_t mask[(MAX_VALUATORS + 7)/8]; /**< Valuator mask */
+ uint8_t mode[(MAX_VALUATORS + 7)/8]; /**< Valuator mode (Abs or Rel)*/
+ int32_t data[MAX_VALUATORS]; /**< Valuator data */
+ int32_t data_frac[MAX_VALUATORS]; /**< Fractional part for data */
+ } valuators;
+ struct {
+ uint32_t base; /**< XKB base modifiers */
+ uint32_t latched; /**< XKB latched modifiers */
+ uint32_t locked; /**< XKB locked modifiers */
+ uint32_t effective;/**< XKB effective modifiers */
+ } mods;
+ struct {
+ uint8_t base; /**< XKB base group */
+ uint8_t latched; /**< XKB latched group */
+ uint8_t locked; /**< XKB locked group */
+ uint8_t effective;/**< XKB effective group */
+ } group;
+ Window root; /**< Root window of the event */
+ int corestate; /**< Core key/button state BEFORE the event */
+ int key_repeat; /**< Internally-generated key repeat event */
+};
+
+
+/* Flags used in DeviceChangedEvent to signal if the slave has changed */
+#define DEVCHANGE_SLAVE_SWITCH 0x2
+/* Flags used in DeviceChangedEvent to signal whether the event was a
+ * pointer event or a keyboard event */
+#define DEVCHANGE_POINTER_EVENT 0x4
+#define DEVCHANGE_KEYBOARD_EVENT 0x8
+/* device capabilities changed */
+#define DEVCHANGE_DEVICE_CHANGE 0x10
+
+/**
+ * Sent whenever a device's capabilities have changed.
+ */
+struct _DeviceChangedEvent
+{
+ unsigned char header; /**< Always ET_Internal */
+ enum EventType type; /**< ET_DeviceChanged */
+ int length; /**< Length in bytes */
+ Time time; /**< Time in ms */
+ int deviceid; /**< Device whose capabilities have changed */
+ int flags; /**< Mask of ::HAS_NEW_SLAVE,
+ ::POINTER_EVENT, ::KEYBOARD_EVENT */
+ int masterid; /**< MD when event was generated */
+ int sourceid; /**< The device that caused the change */
+
+ struct {
+ int num_buttons; /**< Number of buttons */
+ Atom names[MAX_BUTTONS];/**< Button names */
+ } buttons;
+
+ int num_valuators; /**< Number of axes */
+ struct {
+ uint32_t min; /**< Minimum value */
+ uint32_t max; /**< Maximum value */
+ /* FIXME: frac parts of min/max */
+ uint32_t resolution; /**< Resolution counts/m */
+ uint8_t mode; /**< Relative or Absolute */
+ Atom name; /**< Axis name */
+ } valuators[MAX_VALUATORS];
+
+ struct {
+ int min_keycode;
+ int max_keycode;
+ } keys;
+};
+
+#if XFreeXDGA
+/**
+ * DGAEvent, used by DGA to intercept and emulate input events.
+ */
+struct _DGAEvent
+{
+ unsigned char header; /**< Always ET_Internal */
+ enum EventType type; /**< ET_DGAEvent */
+ int length; /**< Length in bytes */
+ Time time; /**< Time in ms */
+ int subtype; /**< KeyPress, KeyRelease, ButtonPress,
+ ButtonRelease, MotionNotify */
+ int detail; /**< Button number or key code */
+ int dx; /**< Relative x coordinate */
+ int dy; /**< Relative y coordinate */
+ int screen; /**< Screen number this event applies to */
+ uint16_t state; /**< Core modifier/button state */
+};
+#endif
+
+/**
+ * Raw event, contains the data as posted by the device.
+ */
+struct _RawDeviceEvent
+{
+ unsigned char header; /**< Always ET_Internal */
+ enum EventType type; /**< ET_Raw */
+ int length; /**< Length in bytes */
+ Time time; /**< Time in ms */
+ int deviceid; /**< Device to post this event for */
+ int sourceid; /**< The physical source device */
+ union {
+ uint32_t button; /**< Button number */
+ uint32_t key; /**< Key code */
+ } detail;
+ struct {
+ uint8_t mask[(MAX_VALUATORS + 7)/8]; /**< Valuator mask */
+ int32_t data[MAX_VALUATORS]; /**< Valuator data */
+ int32_t data_frac[MAX_VALUATORS]; /**< Fractional part for data */
+ int32_t data_raw[MAX_VALUATORS]; /**< Valuator data as posted */
+ int32_t data_raw_frac[MAX_VALUATORS];/**< Fractional part for data_raw */
+ } valuators;
+};
+
+#ifdef XQUARTZ
+#define XQUARTZ_EVENT_MAXARGS 5
+struct _XQuartzEvent {
+ unsigned char header; /**< Always ET_Internal */
+ enum EventType type; /**< Always ET_XQuartz */
+ int length; /**< Length in bytes */
+ Time time; /**< Time in ms. */
+ int subtype; /**< Subtype defined by XQuartz DDX */
+ uint32_t data[XQUARTZ_EVENT_MAXARGS]; /**< Up to 5 32bit values passed to handler */
+};
+#endif
+
+/**
+ * Event type used inside the X server for input event
+ * processing.
+ */
+union _InternalEvent {
+ struct {
+ unsigned char header; /**< Always ET_Internal */
+ enum EventType type; /**< One of ET_* */
+ int length; /**< Length in bytes */
+ Time time; /**< Time in ms. */
+ } any;
+ DeviceEvent device_event;
+ DeviceChangedEvent changed_event;
+#if XFreeXDGA
+ DGAEvent dga_event;
+#endif
+ RawDeviceEvent raw_event;
+#ifdef XQUARTZ
+ XQuartzEvent xquartz_event;
+#endif
+};
+
+#endif
diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h index 2aa5dbb74..13f4ba98e 100644 --- a/xorg-server/include/input.h +++ b/xorg-server/include/input.h @@ -109,19 +109,8 @@ typedef union _GrabMask GrabMask; typedef struct _ValuatorMask ValuatorMask;
-typedef struct _EventList {
- xEvent* event;
- int evlen; /* length of allocated memory for event in bytes. This is not
- the actual length of the event. The event's actual length is
- 32 for standard events or 32 +
- ((xGenericEvent*)event)->length * 4 for GenericEvents.
- For events in the EQ, the length is
- ((InternalEvent*)event)->u.any.length */
-} EventList, *EventListPtr;
-
/* The DIX stores incoming input events in this list */
-extern EventListPtr InputEventList;
-extern int InputEventListLen;
+extern InternalEvent* InputEventList;
typedef int (*DeviceProc)(
DeviceIntPtr /*device*/,
@@ -439,22 +428,28 @@ extern _X_EXPORT void CloseInput(void); extern _X_EXPORT int GetMaximumEventsNum(void);
-extern _X_EXPORT int GetEventList(EventListPtr* list);
-extern _X_EXPORT EventListPtr InitEventList(int num_events);
-extern _X_EXPORT void FreeEventList(EventListPtr list, int num_events);
+extern _X_EXPORT InternalEvent *InitEventList(int num_events);
+extern _X_EXPORT void FreeEventList(InternalEvent *list, int num_events);
-extern void CreateClassesChangedEvent(EventListPtr event,
+extern void CreateClassesChangedEvent(InternalEvent *event,
DeviceIntPtr master,
DeviceIntPtr slave,
int type);
-extern EventListPtr UpdateFromMaster(
- EventListPtr events,
+extern InternalEvent * UpdateFromMaster(
+ InternalEvent *events,
DeviceIntPtr pDev,
int type,
int *num_events);
extern _X_EXPORT int GetPointerEvents(
- EventListPtr events,
+ InternalEvent *events,
+ DeviceIntPtr pDev,
+ int type,
+ int buttons,
+ int flags,
+ const ValuatorMask *mask);
+
+extern _X_EXPORT void QueuePointerEvents(
DeviceIntPtr pDev,
int type,
int buttons,
@@ -462,14 +457,25 @@ extern _X_EXPORT int GetPointerEvents( const ValuatorMask *mask);
extern _X_EXPORT int GetKeyboardEvents(
- EventListPtr events,
+ InternalEvent *events,
+ DeviceIntPtr pDev,
+ int type,
+ int key_code,
+ const ValuatorMask *mask);
+
+extern _X_EXPORT void QueueKeyboardEvents(
DeviceIntPtr pDev,
int type,
int key_code,
const ValuatorMask *mask);
extern int GetProximityEvents(
- EventListPtr events,
+ InternalEvent *events,
+ DeviceIntPtr pDev,
+ int type,
+ const ValuatorMask *mask);
+
+extern void QueueProximityEvents(
DeviceIntPtr pDev,
int type,
const ValuatorMask *mask);
@@ -495,6 +501,8 @@ extern _X_EXPORT int GetMotionHistory( ScreenPtr pScreen,
BOOL core);
+extern void ReleaseButtonsAndKeys(DeviceIntPtr dev);
+
extern int AttachDevice(ClientPtr client,
DeviceIntPtr slave,
DeviceIntPtr master);
diff --git a/xorg-server/include/inputstr.h b/xorg-server/include/inputstr.h index 80e8ad8c7..ecbc6e09e 100644 --- a/xorg-server/include/inputstr.h +++ b/xorg-server/include/inputstr.h @@ -591,4 +591,14 @@ typedef struct _EventSyncInfo { extern EventSyncInfoRec syncEvents;
+/**
+ * Given a sprite, returns the window at the bottom of the trace (i.e. the
+ * furthest window from the root).
+ */
+static inline WindowPtr DeepestSpriteWin(SpritePtr sprite)
+{
+ assert(sprite->spriteTraceGood > 0);
+ return sprite->spriteTrace[sprite->spriteTraceGood - 1];
+}
+
#endif /* INPUTSTRUCT_H */
diff --git a/xorg-server/include/inpututils.h b/xorg-server/include/inpututils.h index af07afeb0..0e8488af5 100644 --- a/xorg-server/include/inpututils.h +++ b/xorg-server/include/inpututils.h @@ -37,4 +37,6 @@ struct _ValuatorMask { int valuators[MAX_VALUATORS]; /* valuator data */
};
+extern void verify_internal_event(const InternalEvent *ev);
+
#endif
diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h index 02790d38e..ba3776079 100644 --- a/xorg-server/include/misc.h +++ b/xorg-server/include/misc.h @@ -228,6 +228,24 @@ pad_to_int32(const int bytes) { extern char**
xstrtokenize(const char *str, const char* separators);
+/**
+ * Compare the two version numbers comprising of major.minor.
+ *
+ * @return A value less than 0 if a is less than b, 0 if a is equal to b,
+ * or a value greater than 0
+ */
+static inline int
+version_compare(uint16_t a_major, uint16_t a_minor,
+ uint16_t b_major, uint16_t b_minor)
+{
+ int a, b;
+
+ a = a_major << 16 | a_minor;
+ b = b_major << 16 | b_minor;
+
+ return (a - b);
+}
+
/* some macros to help swap requests, replies, and events */
#define LengthRestB(stuff) \
|