| /* |
| uSynergy client -- Interface for the embedded Synergy client library |
| version 1.0.0, July 7th, 2012 |
| |
| Copyright (C) 2012 Synergy Si Ltd. |
| Copyright (c) 2012 Alex Evans |
| |
| This software is provided 'as-is', without any express or implied |
| warranty. In no event will the authors be held liable for any damages |
| arising from the use of this software. |
| |
| Permission is granted to anyone to use this software for any purpose, |
| including commercial applications, and to alter it and redistribute it |
| freely, subject to the following restrictions: |
| |
| 1. The origin of this software must not be misrepresented; you must not |
| claim that you wrote the original software. If you use this software |
| in a product, an acknowledgment in the product documentation would be |
| appreciated but is not required. |
| |
| 2. Altered source versions must be plainly marked as such, and must not be |
| misrepresented as being the original software. |
| |
| 3. This notice may not be removed or altered from any source |
| distribution. |
| */ |
| #include <stdint.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| // Configuration |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| |
| |
| /** |
| @brief Determine endianness |
| **/ |
| #if defined(USYNERGY_LITTLE_ENDIAN) && defined(USYNERGY_BIG_ENDIAN) |
| /* Ambiguous: both endians specified */ |
| #error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN" |
| #elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN) |
| /* Attempt to auto detect */ |
| #if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN) |
| #define USYNERGY_LITTLE_ENDIAN |
| #elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN) |
| #define USYNERGY_BIG_ENDIAN |
| #else |
| #error "Can't detect endian-nes, please defined either USYNERGY_LITTLE_ENDIAN or USYNERGY_BIG_ENDIAN"; |
| #endif |
| #else |
| /* User-specified endian-nes, nothing to do for us */ |
| #endif |
| |
| |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| // Types and Constants |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| |
| |
| /** |
| @brief Boolean type |
| **/ |
| typedef int uSynergyBool; |
| #define USYNERGY_FALSE 0 /* False value */ |
| #define USYNERGY_TRUE 1 /* True value */ |
| |
| |
| /** |
| @brief User context type |
| |
| The uSynergyCookie type is an opaque type that is used by uSynergy to communicate to the client. It is passed along to |
| callback functions as context. |
| **/ |
| typedef struct { int ignored; } * uSynergyCookie; |
| |
| |
| |
| /** |
| @brief Clipboard types |
| **/ |
| enum uSynergyClipboardFormat |
| { |
| USYNERGY_CLIPBOARD_FORMAT_TEXT = 0, /* Text format, UTF-8, newline is LF */ |
| USYNERGY_CLIPBOARD_FORMAT_BITMAP = 1, /* Bitmap format, BMP 24/32bpp, BI_RGB */ |
| USYNERGY_CLIPBOARD_FORMAT_HTML = 2, /* HTML format, HTML fragment, UTF-8, newline is LF */ |
| }; |
| |
| |
| |
| /** |
| @brief Constants and limits |
| **/ |
| #define USYNERGY_NUM_JOYSTICKS 4 /* Maximum number of supported joysticks */ |
| |
| #define USYNERGY_PROTOCOL_MAJOR 1 /* Major protocol version */ |
| #define USYNERGY_PROTOCOL_MINOR 4 /* Minor protocol version */ |
| |
| #define USYNERGY_IDLE_TIMEOUT 2000 /* Timeout in milliseconds before reconnecting */ |
| |
| #define USYNERGY_TRACE_BUFFER_SIZE 1024 /* Maximum length of traced message */ |
| #define USYNERGY_REPLY_BUFFER_SIZE 1024 /* Maximum size of a reply packet */ |
| #define USYNERGY_RECEIVE_BUFFER_SIZE 4096 /* Maximum size of an incoming packet */ |
| |
| |
| |
| /** |
| @brief Keyboard constants |
| **/ |
| #define USYNERGY_MODIFIER_SHIFT 0x0001 /* Shift key modifier */ |
| #define USYNERGY_MODIFIER_CTRL 0x0002 /* Ctrl key modifier */ |
| #define USYNERGY_MODIFIER_ALT 0x0004 /* Alt key modifier */ |
| #define USYNERGY_MODIFIER_META 0x0008 /* Meta key modifier */ |
| #define USYNERGY_MODIFIER_WIN 0x0010 /* Windows key modifier */ |
| #define USYNERGY_MODIFIER_ALT_GR 0x0020 /* AltGr key modifier */ |
| #define USYNERGY_MODIFIER_LEVEL5LOCK 0x0040 /* Level5Lock key modifier */ |
| #define USYNERGY_MODIFIER_CAPSLOCK 0x1000 /* CapsLock key modifier */ |
| #define USYNERGY_MODIFIER_NUMLOCK 0x2000 /* NumLock key modifier */ |
| #define USYNERGY_MODIFIER_SCROLLOCK 0x4000 /* ScrollLock key modifier */ |
| |
| |
| |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| // Functions and Callbacks |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| |
| |
| /** |
| @brief Connect function |
| |
| This function is called when uSynergy needs to connect to the host. It doesn't imply a network implementation or |
| destination address, that must all be handled on the user side. The function should return USYNERGY_TRUE if a |
| connection was established or USYNERGY_FALSE if it could not connect. |
| |
| When network errors occur (e.g. uSynergySend or uSynergyReceive fail) then the connect call will be called again |
| so the implementation of the function must close any old connections and clean up resources before retrying. |
| |
| @param cookie Cookie supplied in the Synergy context |
| **/ |
| typedef uSynergyBool (*uSynergyConnectFunc)(uSynergyCookie cookie); |
| |
| |
| |
| /** |
| @brief Send function |
| |
| This function is called when uSynergy needs to send something over the default connection. It should return |
| USYNERGY_TRUE if sending succeeded and USYNERGY_FALSE otherwise. This function should block until the send |
| operation is completed. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param buffer Address of buffer to send |
| @param length Length of buffer to send |
| **/ |
| typedef uSynergyBool (*uSynergySendFunc)(uSynergyCookie cookie, const uint8_t *buffer, int length); |
| |
| |
| |
| /** |
| @brief Receive function |
| |
| This function is called when uSynergy needs to receive data from the default connection. It should return |
| USYNERGY_TRUE if receiving data succeeded and USYNERGY_FALSE otherwise. This function should block until data |
| has been received and wait for data to become available. If @a outLength is set to 0 upon completion it is |
| assumed that the connection is alive, but still in a connecting state and needs time to settle. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param buffer Address of buffer to receive data into |
| @param maxLength Maximum amount of bytes to write into the receive buffer |
| @param outLength Address of integer that receives the actual amount of bytes written into @a buffer |
| **/ |
| typedef uSynergyBool (*uSynergyReceiveFunc)(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength); |
| |
| |
| |
| /** |
| @brief Thread sleep function |
| |
| This function is called when uSynergy wants to suspend operation for a while before retrying an operation. It |
| is mostly used when a socket times out or disconnect occurs to prevent uSynergy from continuously hammering a |
| network connection in case the network is down. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param timeMs Time to sleep the current thread (in milliseconds) |
| **/ |
| typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs); |
| |
| |
| |
| /** |
| @brief Get time function |
| |
| This function is called when uSynergy needs to know the current time. This is used to determine when timeouts |
| have occured. The time base should be a cyclic millisecond time value. |
| |
| @returns Time value in milliseconds |
| **/ |
| typedef uint32_t (*uSynergyGetTimeFunc)(); |
| |
| |
| |
| /** |
| @brief Trace function |
| |
| This function is called when uSynergy wants to trace something. It is optional to show these messages, but they |
| are often useful when debugging. uSynergy only traces major events like connecting and disconnecting. Usually |
| only a single trace is shown when the connection is established and no more trace are called. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param text Text to be traced |
| **/ |
| typedef void (*uSynergyTraceFunc)(uSynergyCookie cookie, const char *text); |
| |
| |
| |
| /** |
| @brief Screen active callback |
| |
| This callback is called when Synergy makes the screen active or inactive. This |
| callback is usually sent when the mouse enters or leaves the screen. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param active Activation flag, 1 if the screen has become active, 0 if the screen has become inactive |
| **/ |
| typedef void (*uSynergyScreenActiveCallback)(uSynergyCookie cookie, uSynergyBool active); |
| |
| |
| |
| /** |
| @brief Mouse callback |
| |
| This callback is called when a mouse events happens. The mouse X and Y position, |
| wheel and button state is communicated in the message. It's up to the user to |
| interpret if this is a mouse up, down, double-click or other message. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param x Mouse X position |
| @param y Mouse Y position |
| @param wheelX Mouse wheel X position |
| @param wheelY Mouse wheel Y position |
| @param buttonLeft Left button pressed status, 0 for released, 1 for pressed |
| @param buttonMiddle Middle button pressed status, 0 for released, 1 for pressed |
| @param buttonRight Right button pressed status, 0 for released, 1 for pressed |
| **/ |
| typedef void (*uSynergyMouseCallback)(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle); |
| |
| |
| |
| /** |
| @brief Key event callback |
| |
| This callback is called when a key is pressed or released. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param key Key code of key that was pressed or released |
| @param modifiers Status of modifier keys (alt, shift, etc.) |
| @param down Down or up status, 1 is key is pressed down, 0 if key is released (up) |
| @param repeat Repeat flag, 1 if the key is down because the key is repeating, 0 if the key is initially pressed by the user |
| **/ |
| typedef void (*uSynergyKeyboardCallback)(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat); |
| |
| |
| |
| /** |
| @brief Joystick event callback |
| |
| This callback is called when a joystick stick or button changes. It is possible that multiple callbacks are |
| fired when different sticks or buttons change as these are individual messages in the packet stream. Each |
| callback will contain all the valid state for the different axes and buttons. The last callback received will |
| represent the most current joystick state. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param joyNum Joystick number, always in the range [0 ... USYNERGY_NUM_JOYSTICKS> |
| @param buttons Button pressed mask |
| @param leftStickX Left stick X position, in range [-127 ... 127] |
| @param leftStickY Left stick Y position, in range [-127 ... 127] |
| @param rightStickX Right stick X position, in range [-127 ... 127] |
| @param rightStickY Right stick Y position, in range [-127 ... 127] |
| **/ |
| typedef void (*uSynergyJoystickCallback)(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY); |
| |
| |
| |
| /** |
| @brief Clipboard event callback |
| |
| This callback is called when something is placed on the clipboard. Multiple callbacks may be fired for |
| multiple clipboard formats if they are supported. The data provided is read-only and may not be modified |
| by the application. |
| |
| @param cookie Cookie supplied in the Synergy context |
| @param format Clipboard format |
| @param data Memory area containing the clipboard raw data |
| @param size Size of clipboard data |
| **/ |
| typedef void (*uSynergyClipboardCallback)(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size); |
| |
| |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| // Context |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| |
| |
| /** |
| @brief uSynergy context |
| **/ |
| typedef struct |
| { |
| /* Mandatory configuration data, filled in by client */ |
| uSynergyConnectFunc m_connectFunc; /* Connect function */ |
| uSynergySendFunc m_sendFunc; /* Send data function */ |
| uSynergyReceiveFunc m_receiveFunc; /* Receive data function */ |
| uSynergySleepFunc m_sleepFunc; /* Thread sleep function */ |
| uSynergyGetTimeFunc m_getTimeFunc; /* Get current time function */ |
| const char* m_clientName; /* Name of Synergy Screen / Client */ |
| uint16_t m_clientWidth; /* Width of screen */ |
| uint16_t m_clientHeight; /* Height of screen */ |
| |
| /* Optional configuration data, filled in by client */ |
| uSynergyCookie m_cookie; /* Cookie pointer passed to callback functions (can be NULL) */ |
| uSynergyTraceFunc m_traceFunc; /* Function for tracing status (can be NULL) */ |
| uSynergyScreenActiveCallback m_screenActiveCallback; /* Callback for entering and leaving screen */ |
| uSynergyMouseCallback m_mouseCallback; /* Callback for mouse events */ |
| uSynergyKeyboardCallback m_keyboardCallback; /* Callback for keyboard events */ |
| uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */ |
| uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */ |
| |
| /* State data, used internall by client, initialized by uSynergyInit() */ |
| uSynergyBool m_connected; /* Is our socket connected? */ |
| uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */ |
| uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */ |
| uint32_t m_lastMessageTime; /* Time at which last message was received */ |
| uint32_t m_sequenceNumber; /* Packet sequence number */ |
| uint8_t m_receiveBuffer[USYNERGY_RECEIVE_BUFFER_SIZE]; /* Receive buffer */ |
| int m_receiveOfs; /* Receive buffer offset */ |
| uint8_t m_replyBuffer[USYNERGY_REPLY_BUFFER_SIZE]; /* Reply buffer */ |
| uint8_t* m_replyCur; /* Write offset into reply buffer */ |
| uint16_t m_mouseX; /* Mouse X position */ |
| uint16_t m_mouseY; /* Mouse Y position */ |
| int16_t m_mouseWheelX; /* Mouse wheel X position */ |
| int16_t m_mouseWheelY; /* Mouse wheel Y position */ |
| uSynergyBool m_mouseButtonLeft; /* Mouse left button */ |
| uSynergyBool m_mouseButtonRight; /* Mouse right button */ |
| uSynergyBool m_mouseButtonMiddle; /* Mouse middle button */ |
| int8_t m_joystickSticks[USYNERGY_NUM_JOYSTICKS][4]; /* Joystick stick position in 2 axes for 2 sticks */ |
| uint16_t m_joystickButtons[USYNERGY_NUM_JOYSTICKS]; /* Joystick button state */ |
| } uSynergyContext; |
| |
| |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| // Interface |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| |
| |
| /** |
| @brief Initialize uSynergy context |
| |
| This function initializes @a context for use. Call this function directly after |
| creating the context, before filling in any configuration data in it. Not calling |
| this function will cause undefined behavior. |
| |
| @param context Context to be initialized |
| **/ |
| extern void uSynergyInit(uSynergyContext *context); |
| |
| |
| |
| /** |
| @brief Update uSynergy |
| |
| This function updates uSynergy and does the bulk of the work. It does connection management, |
| receiving data, reconnecting after errors or timeouts and so on. It assumes that networking |
| operations are blocking and it can suspend the current thread if it needs to wait. It is |
| best practice to call uSynergyUpdate from a background thread so it is responsive. |
| |
| Because uSynergy relies mostly on blocking calls it will mostly stay in thread sleep state |
| waiting for system mutexes and won't eat much memory. |
| |
| uSynergyUpdate doesn't do any memory allocations or have any side effects beyond those of |
| the callbacks it calls. |
| |
| @param context Context to be updated |
| **/ |
| extern void uSynergyUpdate(uSynergyContext *context); |
| |
| |
| |
| /** |
| @brief Send clipboard data |
| |
| This function sets new clipboard data and sends it to the server. Use this function if |
| your client cuts or copies data onto the clipboard that it needs to share with the |
| server. |
| |
| Currently there is only support for plaintext, but HTML and image data could be |
| supported with some effort. |
| |
| @param context Context to send clipboard data to |
| @param text Text to set to the clipboard |
| **/ |
| extern void uSynergySendClipboard(uSynergyContext *context, const char *text); |
| |
| |
| |
| #ifdef __cplusplus |
| }; |
| #endif |