uSynergy.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. uSynergy client -- Interface for the embedded Synergy client library
  3. version 1.0.0, July 7th, 2012
  4. Copyright (C) 2012 Synergy Si Ltd.
  5. Copyright (c) 2012 Alex Evans
  6. This software is provided 'as-is', without any express or implied
  7. warranty. In no event will the authors be held liable for any damages
  8. arising from the use of this software.
  9. Permission is granted to anyone to use this software for any purpose,
  10. including commercial applications, and to alter it and redistribute it
  11. freely, subject to the following restrictions:
  12. 1. The origin of this software must not be misrepresented; you must not
  13. claim that you wrote the original software. If you use this software
  14. in a product, an acknowledgment in the product documentation would be
  15. appreciated but is not required.
  16. 2. Altered source versions must be plainly marked as such, and must not be
  17. misrepresented as being the original software.
  18. 3. This notice may not be removed or altered from any source
  19. distribution.
  20. */
  21. #include <stdint.h>
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. //---------------------------------------------------------------------------------------------------------------------
  26. // Configuration
  27. //---------------------------------------------------------------------------------------------------------------------
  28. /**
  29. @brief Determine endianness
  30. **/
  31. #if defined(USYNERGY_LITTLE_ENDIAN) && defined(USYNERGY_BIG_ENDIAN)
  32. /* Ambiguous: both endians specified */
  33. #error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN"
  34. #elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN)
  35. /* Attempt to auto detect */
  36. #if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN)
  37. #define USYNERGY_LITTLE_ENDIAN
  38. #elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN)
  39. #define USYNERGY_BIG_ENDIAN
  40. #else
  41. #error "Can't detect endian-nes, please defined either USYNERGY_LITTLE_ENDIAN or USYNERGY_BIG_ENDIAN";
  42. #endif
  43. #else
  44. /* User-specified endian-nes, nothing to do for us */
  45. #endif
  46. //---------------------------------------------------------------------------------------------------------------------
  47. // Types and Constants
  48. //---------------------------------------------------------------------------------------------------------------------
  49. /**
  50. @brief Boolean type
  51. **/
  52. typedef int uSynergyBool;
  53. #define USYNERGY_FALSE 0 /* False value */
  54. #define USYNERGY_TRUE 1 /* True value */
  55. /**
  56. @brief User context type
  57. The uSynergyCookie type is an opaque type that is used by uSynergy to communicate to the client. It is passed along to
  58. callback functions as context.
  59. **/
  60. typedef struct { int ignored; } * uSynergyCookie;
  61. /**
  62. @brief Clipboard types
  63. **/
  64. enum uSynergyClipboardFormat
  65. {
  66. USYNERGY_CLIPBOARD_FORMAT_TEXT = 0, /* Text format, UTF-8, newline is LF */
  67. USYNERGY_CLIPBOARD_FORMAT_BITMAP = 1, /* Bitmap format, BMP 24/32bpp, BI_RGB */
  68. USYNERGY_CLIPBOARD_FORMAT_HTML = 2, /* HTML format, HTML fragment, UTF-8, newline is LF */
  69. };
  70. /**
  71. @brief Constants and limits
  72. **/
  73. #define USYNERGY_NUM_JOYSTICKS 4 /* Maximum number of supported joysticks */
  74. #define USYNERGY_PROTOCOL_MAJOR 1 /* Major protocol version */
  75. #define USYNERGY_PROTOCOL_MINOR 4 /* Minor protocol version */
  76. #define USYNERGY_IDLE_TIMEOUT 2000 /* Timeout in milliseconds before reconnecting */
  77. #define USYNERGY_TRACE_BUFFER_SIZE 1024 /* Maximum length of traced message */
  78. #define USYNERGY_REPLY_BUFFER_SIZE 1024 /* Maximum size of a reply packet */
  79. #define USYNERGY_RECEIVE_BUFFER_SIZE 4096 /* Maximum size of an incoming packet */
  80. /**
  81. @brief Keyboard constants
  82. **/
  83. #define USYNERGY_MODIFIER_SHIFT 0x0001 /* Shift key modifier */
  84. #define USYNERGY_MODIFIER_CTRL 0x0002 /* Ctrl key modifier */
  85. #define USYNERGY_MODIFIER_ALT 0x0004 /* Alt key modifier */
  86. #define USYNERGY_MODIFIER_META 0x0008 /* Meta key modifier */
  87. #define USYNERGY_MODIFIER_WIN 0x0010 /* Windows key modifier */
  88. #define USYNERGY_MODIFIER_ALT_GR 0x0020 /* AltGr key modifier */
  89. #define USYNERGY_MODIFIER_LEVEL5LOCK 0x0040 /* Level5Lock key modifier */
  90. #define USYNERGY_MODIFIER_CAPSLOCK 0x1000 /* CapsLock key modifier */
  91. #define USYNERGY_MODIFIER_NUMLOCK 0x2000 /* NumLock key modifier */
  92. #define USYNERGY_MODIFIER_SCROLLOCK 0x4000 /* ScrollLock key modifier */
  93. //---------------------------------------------------------------------------------------------------------------------
  94. // Functions and Callbacks
  95. //---------------------------------------------------------------------------------------------------------------------
  96. /**
  97. @brief Connect function
  98. This function is called when uSynergy needs to connect to the host. It doesn't imply a network implementation or
  99. destination address, that must all be handled on the user side. The function should return USYNERGY_TRUE if a
  100. connection was established or USYNERGY_FALSE if it could not connect.
  101. When network errors occur (e.g. uSynergySend or uSynergyReceive fail) then the connect call will be called again
  102. so the implementation of the function must close any old connections and clean up resources before retrying.
  103. @param cookie Cookie supplied in the Synergy context
  104. **/
  105. typedef uSynergyBool (*uSynergyConnectFunc)(uSynergyCookie cookie);
  106. /**
  107. @brief Send function
  108. This function is called when uSynergy needs to send something over the default connection. It should return
  109. USYNERGY_TRUE if sending succeeded and USYNERGY_FALSE otherwise. This function should block until the send
  110. operation is completed.
  111. @param cookie Cookie supplied in the Synergy context
  112. @param buffer Address of buffer to send
  113. @param length Length of buffer to send
  114. **/
  115. typedef uSynergyBool (*uSynergySendFunc)(uSynergyCookie cookie, const uint8_t *buffer, int length);
  116. /**
  117. @brief Receive function
  118. This function is called when uSynergy needs to receive data from the default connection. It should return
  119. USYNERGY_TRUE if receiving data succeeded and USYNERGY_FALSE otherwise. This function should block until data
  120. has been received and wait for data to become available. If @a outLength is set to 0 upon completion it is
  121. assumed that the connection is alive, but still in a connecting state and needs time to settle.
  122. @param cookie Cookie supplied in the Synergy context
  123. @param buffer Address of buffer to receive data into
  124. @param maxLength Maximum amount of bytes to write into the receive buffer
  125. @param outLength Address of integer that receives the actual amount of bytes written into @a buffer
  126. **/
  127. typedef uSynergyBool (*uSynergyReceiveFunc)(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength);
  128. /**
  129. @brief Thread sleep function
  130. This function is called when uSynergy wants to suspend operation for a while before retrying an operation. It
  131. is mostly used when a socket times out or disconnect occurs to prevent uSynergy from continuously hammering a
  132. network connection in case the network is down.
  133. @param cookie Cookie supplied in the Synergy context
  134. @param timeMs Time to sleep the current thread (in milliseconds)
  135. **/
  136. typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs);
  137. /**
  138. @brief Get time function
  139. This function is called when uSynergy needs to know the current time. This is used to determine when timeouts
  140. have occured. The time base should be a cyclic millisecond time value.
  141. @returns Time value in milliseconds
  142. **/
  143. typedef uint32_t (*uSynergyGetTimeFunc)();
  144. /**
  145. @brief Trace function
  146. This function is called when uSynergy wants to trace something. It is optional to show these messages, but they
  147. are often useful when debugging. uSynergy only traces major events like connecting and disconnecting. Usually
  148. only a single trace is shown when the connection is established and no more trace are called.
  149. @param cookie Cookie supplied in the Synergy context
  150. @param text Text to be traced
  151. **/
  152. typedef void (*uSynergyTraceFunc)(uSynergyCookie cookie, const char *text);
  153. /**
  154. @brief Screen active callback
  155. This callback is called when Synergy makes the screen active or inactive. This
  156. callback is usually sent when the mouse enters or leaves the screen.
  157. @param cookie Cookie supplied in the Synergy context
  158. @param active Activation flag, 1 if the screen has become active, 0 if the screen has become inactive
  159. **/
  160. typedef void (*uSynergyScreenActiveCallback)(uSynergyCookie cookie, uSynergyBool active);
  161. /**
  162. @brief Mouse callback
  163. This callback is called when a mouse events happens. The mouse X and Y position,
  164. wheel and button state is communicated in the message. It's up to the user to
  165. interpret if this is a mouse up, down, double-click or other message.
  166. @param cookie Cookie supplied in the Synergy context
  167. @param x Mouse X position
  168. @param y Mouse Y position
  169. @param wheelX Mouse wheel X position
  170. @param wheelY Mouse wheel Y position
  171. @param buttonLeft Left button pressed status, 0 for released, 1 for pressed
  172. @param buttonMiddle Middle button pressed status, 0 for released, 1 for pressed
  173. @param buttonRight Right button pressed status, 0 for released, 1 for pressed
  174. **/
  175. typedef void (*uSynergyMouseCallback)(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle);
  176. /**
  177. @brief Key event callback
  178. This callback is called when a key is pressed or released.
  179. @param cookie Cookie supplied in the Synergy context
  180. @param key Key code of key that was pressed or released
  181. @param modifiers Status of modifier keys (alt, shift, etc.)
  182. @param down Down or up status, 1 is key is pressed down, 0 if key is released (up)
  183. @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
  184. **/
  185. typedef void (*uSynergyKeyboardCallback)(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat);
  186. /**
  187. @brief Joystick event callback
  188. This callback is called when a joystick stick or button changes. It is possible that multiple callbacks are
  189. fired when different sticks or buttons change as these are individual messages in the packet stream. Each
  190. callback will contain all the valid state for the different axes and buttons. The last callback received will
  191. represent the most current joystick state.
  192. @param cookie Cookie supplied in the Synergy context
  193. @param joyNum Joystick number, always in the range [0 ... USYNERGY_NUM_JOYSTICKS>
  194. @param buttons Button pressed mask
  195. @param leftStickX Left stick X position, in range [-127 ... 127]
  196. @param leftStickY Left stick Y position, in range [-127 ... 127]
  197. @param rightStickX Right stick X position, in range [-127 ... 127]
  198. @param rightStickY Right stick Y position, in range [-127 ... 127]
  199. **/
  200. typedef void (*uSynergyJoystickCallback)(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY);
  201. /**
  202. @brief Clipboard event callback
  203. This callback is called when something is placed on the clipboard. Multiple callbacks may be fired for
  204. multiple clipboard formats if they are supported. The data provided is read-only and may not be modified
  205. by the application.
  206. @param cookie Cookie supplied in the Synergy context
  207. @param format Clipboard format
  208. @param data Memory area containing the clipboard raw data
  209. @param size Size of clipboard data
  210. **/
  211. typedef void (*uSynergyClipboardCallback)(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size);
  212. //---------------------------------------------------------------------------------------------------------------------
  213. // Context
  214. //---------------------------------------------------------------------------------------------------------------------
  215. /**
  216. @brief uSynergy context
  217. **/
  218. typedef struct
  219. {
  220. /* Mandatory configuration data, filled in by client */
  221. uSynergyConnectFunc m_connectFunc; /* Connect function */
  222. uSynergySendFunc m_sendFunc; /* Send data function */
  223. uSynergyReceiveFunc m_receiveFunc; /* Receive data function */
  224. uSynergySleepFunc m_sleepFunc; /* Thread sleep function */
  225. uSynergyGetTimeFunc m_getTimeFunc; /* Get current time function */
  226. const char* m_clientName; /* Name of Synergy Screen / Client */
  227. uint16_t m_clientWidth; /* Width of screen */
  228. uint16_t m_clientHeight; /* Height of screen */
  229. /* Optional configuration data, filled in by client */
  230. uSynergyCookie m_cookie; /* Cookie pointer passed to callback functions (can be NULL) */
  231. uSynergyTraceFunc m_traceFunc; /* Function for tracing status (can be NULL) */
  232. uSynergyScreenActiveCallback m_screenActiveCallback; /* Callback for entering and leaving screen */
  233. uSynergyMouseCallback m_mouseCallback; /* Callback for mouse events */
  234. uSynergyKeyboardCallback m_keyboardCallback; /* Callback for keyboard events */
  235. uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */
  236. uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */
  237. /* State data, used internall by client, initialized by uSynergyInit() */
  238. uSynergyBool m_connected; /* Is our socket connected? */
  239. uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */
  240. uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */
  241. uint32_t m_lastMessageTime; /* Time at which last message was received */
  242. uint32_t m_sequenceNumber; /* Packet sequence number */
  243. uint8_t m_receiveBuffer[USYNERGY_RECEIVE_BUFFER_SIZE]; /* Receive buffer */
  244. int m_receiveOfs; /* Receive buffer offset */
  245. uint8_t m_replyBuffer[USYNERGY_REPLY_BUFFER_SIZE]; /* Reply buffer */
  246. uint8_t* m_replyCur; /* Write offset into reply buffer */
  247. uint16_t m_mouseX; /* Mouse X position */
  248. uint16_t m_mouseY; /* Mouse Y position */
  249. int16_t m_mouseWheelX; /* Mouse wheel X position */
  250. int16_t m_mouseWheelY; /* Mouse wheel Y position */
  251. uSynergyBool m_mouseButtonLeft; /* Mouse left button */
  252. uSynergyBool m_mouseButtonRight; /* Mouse right button */
  253. uSynergyBool m_mouseButtonMiddle; /* Mouse middle button */
  254. int8_t m_joystickSticks[USYNERGY_NUM_JOYSTICKS][4]; /* Joystick stick position in 2 axes for 2 sticks */
  255. uint16_t m_joystickButtons[USYNERGY_NUM_JOYSTICKS]; /* Joystick button state */
  256. } uSynergyContext;
  257. //---------------------------------------------------------------------------------------------------------------------
  258. // Interface
  259. //---------------------------------------------------------------------------------------------------------------------
  260. /**
  261. @brief Initialize uSynergy context
  262. This function initializes @a context for use. Call this function directly after
  263. creating the context, before filling in any configuration data in it. Not calling
  264. this function will cause undefined behavior.
  265. @param context Context to be initialized
  266. **/
  267. extern void uSynergyInit(uSynergyContext *context);
  268. /**
  269. @brief Update uSynergy
  270. This function updates uSynergy and does the bulk of the work. It does connection management,
  271. receiving data, reconnecting after errors or timeouts and so on. It assumes that networking
  272. operations are blocking and it can suspend the current thread if it needs to wait. It is
  273. best practice to call uSynergyUpdate from a background thread so it is responsive.
  274. Because uSynergy relies mostly on blocking calls it will mostly stay in thread sleep state
  275. waiting for system mutexes and won't eat much memory.
  276. uSynergyUpdate doesn't do any memory allocations or have any side effects beyond those of
  277. the callbacks it calls.
  278. @param context Context to be updated
  279. **/
  280. extern void uSynergyUpdate(uSynergyContext *context);
  281. /**
  282. @brief Send clipboard data
  283. This function sets new clipboard data and sends it to the server. Use this function if
  284. your client cuts or copies data onto the clipboard that it needs to share with the
  285. server.
  286. Currently there is only support for plaintext, but HTML and image data could be
  287. supported with some effort.
  288. @param context Context to send clipboard data to
  289. @param text Text to set to the clipboard
  290. **/
  291. extern void uSynergySendClipboard(uSynergyContext *context, const char *text);
  292. #ifdef __cplusplus
  293. };
  294. #endif