hyperion.ng
ip_connection.h
1 /*
2  * Copyright (C) 2012-2013 Matthias Bolte <matthias@tinkerforge.com>
3  * Copyright (C) 2011 Olaf Lüke <olaf@tinkerforge.com>
4  *
5  * Redistribution and use in source and binary forms of this file,
6  * with or without modification, are permitted.
7  */
8 
9 #ifndef IP_CONNECTION_H
10 #define IP_CONNECTION_H
11 
16 #ifndef __STDC_LIMIT_MACROS
17  #define __STDC_LIMIT_MACROS
18 #endif
19 #include <stdint.h>
20 #include <string.h>
21 #include <stdlib.h>
22 
23 #if !defined __cplusplus && defined __GNUC__
24  #include <stdbool.h>
25 #endif
26 
27 #ifdef _WIN32
28  #ifndef WIN32_LEAN_AND_MEAN
29  #define WIN32_LEAN_AND_MEAN
30  #endif
31  #include <windows.h>
32 #else
33  #include <pthread.h>
34  #include <semaphore.h>
35 #endif
36 
37 enum {
38  E_OK = 0,
39  E_TIMEOUT = -1,
40  E_NO_STREAM_SOCKET = -2,
41  E_HOSTNAME_INVALID = -3,
42  E_NO_CONNECT = -4,
43  E_NO_THREAD = -5,
44  E_NOT_ADDED = -6, // unused since v2.0
45  E_ALREADY_CONNECTED = -7,
46  E_NOT_CONNECTED = -8,
47  E_INVALID_PARAMETER = -9, // error response from device
48  E_NOT_SUPPORTED = -10, // error response from device
49  E_UNKNOWN_ERROR_CODE = -11 // error response from device
50 };
51 
52 #ifdef IPCON_EXPOSE_INTERNALS
53 
54 typedef struct _Socket Socket;
55 
56 typedef struct {
57 #ifdef _WIN32
58  CRITICAL_SECTION handle;
59 #else
60  pthread_mutex_t handle;
61 #endif
62 } Mutex;
63 
64 void mutex_create(Mutex *mutex);
65 
66 void mutex_destroy(Mutex *mutex);
67 
68 void mutex_lock(Mutex *mutex);
69 
70 void mutex_unlock(Mutex *mutex);
71 
72 typedef struct {
73 #ifdef _WIN32
74  HANDLE handle;
75 #else
76  pthread_cond_t condition;
77  pthread_mutex_t mutex;
78  bool flag;
79 #endif
80 } Event;
81 
82 typedef struct {
83 #ifdef _WIN32
84  HANDLE handle;
85 #else
86  sem_t object;
87  sem_t *pointer;
88 #endif
89 } Semaphore;
90 
91 typedef void (*ThreadFunction)(void *opaque);
92 
93 typedef struct {
94 #ifdef _WIN32
95  HANDLE handle;
96  DWORD id;
97 #else
98  pthread_t handle;
99 #endif
100  ThreadFunction function;
101  void *opaque;
102 } Thread;
103 
104 typedef struct {
105  Mutex mutex;
106  int used;
107  int allocated;
108  uint32_t *keys;
109  void **values;
110 } Table;
111 
112 typedef struct _QueueItem {
113  struct _QueueItem *next;
114  int kind;
115  void *data;
116  int length;
117 } QueueItem;
118 
119 typedef struct {
120  Mutex mutex;
121  Semaphore semaphore;
122  QueueItem *head;
123  QueueItem *tail;
124 } Queue;
125 
126 #if defined _MSC_VER || defined __BORLANDC__
127  #pragma pack(push)
128  #pragma pack(1)
129  #define ATTRIBUTE_PACKED
130 #elif defined __GNUC__
131  #ifdef _WIN32
132  // workaround struct packing bug in GCC 4.7 on Windows
133  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
134  #define ATTRIBUTE_PACKED __attribute__((gcc_struct, packed))
135  #else
136  #define ATTRIBUTE_PACKED __attribute__((packed))
137  #endif
138 #else
139  #error unknown compiler, do not know how to enable struct packing
140 #endif
141 
142 typedef struct {
143  uint32_t uid;
144  uint8_t length;
145  uint8_t function_id;
146  uint8_t sequence_number_and_options;
147  uint8_t error_code_and_future_use;
148 } ATTRIBUTE_PACKED PacketHeader;
149 
150 typedef struct {
151  PacketHeader header;
152  uint8_t payload[64];
153  uint8_t optional_data[8];
154 } ATTRIBUTE_PACKED Packet;
155 
156 #if defined _MSC_VER || defined __BORLANDC__
157  #pragma pack(pop)
158 #endif
159 #undef ATTRIBUTE_PACKED
160 
161 #endif // IPCON_EXPOSE_INTERNALS
162 
163 typedef struct _IPConnection IPConnection;
164 typedef struct _IPConnectionPrivate IPConnectionPrivate;
165 typedef struct _Device Device;
166 typedef struct _DevicePrivate DevicePrivate;
167 
168 #ifdef IPCON_EXPOSE_INTERNALS
169 
170 typedef struct _CallbackContext CallbackContext;
171 
172 #endif
173 
174 typedef void (*EnumerateCallbackFunction)(const char *uid,
175  const char *connected_uid,
176  char position,
177  uint8_t hardware_version[3],
178  uint8_t firmware_version[3],
179  uint16_t device_identifier,
180  uint8_t enumeration_type,
181  void *user_data);
182 typedef void (*ConnectedCallbackFunction)(uint8_t connect_reason,
183  void *user_data);
184 typedef void (*DisconnectedCallbackFunction)(uint8_t disconnect_reason,
185  void *user_data);
186 
187 #ifdef IPCON_EXPOSE_INTERNALS
188 
189 typedef void (*CallbackWrapperFunction)(DevicePrivate *device_p, Packet *packet);
190 
191 #endif
192 
196 struct _Device {
197  DevicePrivate *p;
198 };
199 
200 #ifdef IPCON_EXPOSE_INTERNALS
201 
202 #define DEVICE_NUM_FUNCTION_IDS 256
203 
207 struct _DevicePrivate {
208  uint32_t uid;
209 
210  IPConnectionPrivate *ipcon_p;
211 
212  uint8_t api_version[3];
213 
214  Mutex request_mutex;
215 
216  uint8_t expected_response_function_id; // protected by request_mutex
217  uint8_t expected_response_sequence_number; // protected by request_mutex
218  Mutex response_mutex;
219  Packet response_packet; // protected by response_mutex
220  Event response_event;
221  int response_expected[DEVICE_NUM_FUNCTION_IDS];
222 
223  void *registered_callbacks[DEVICE_NUM_FUNCTION_IDS];
224  void *registered_callback_user_data[DEVICE_NUM_FUNCTION_IDS];
225  CallbackWrapperFunction callback_wrappers[DEVICE_NUM_FUNCTION_IDS];
226 };
227 
231 enum {
232  DEVICE_RESPONSE_EXPECTED_INVALID_FUNCTION_ID = 0,
233  DEVICE_RESPONSE_EXPECTED_ALWAYS_TRUE, // getter
234  DEVICE_RESPONSE_EXPECTED_ALWAYS_FALSE, // callback
235  DEVICE_RESPONSE_EXPECTED_TRUE, // setter
236  DEVICE_RESPONSE_EXPECTED_FALSE // setter, default
237 };
238 
242 void device_create(Device *device, const char *uid,
243  IPConnectionPrivate *ipcon_p, uint8_t api_version_major,
244  uint8_t api_version_minor, uint8_t api_version_release);
245 
249 void device_destroy(Device *device);
250 
254 int device_get_response_expected(DevicePrivate *device_p, uint8_t function_id,
255  bool *ret_response_expected);
256 
260 int device_set_response_expected(DevicePrivate *device_p, uint8_t function_id,
261  bool response_expected);
262 
266 int device_set_response_expected_all(DevicePrivate *device_p, bool response_expected);
267 
271 void device_register_callback(DevicePrivate *device_p, uint8_t id, void *callback,
272  void *user_data);
273 
277 int device_get_api_version(DevicePrivate *device_p, uint8_t ret_api_version[3]);
278 
282 int device_send_request(DevicePrivate *device_p, Packet *request, Packet *response);
283 
284 #endif // IPCON_EXPOSE_INTERNALS
285 
291 enum {
292  IPCON_CALLBACK_ENUMERATE = 253,
293  IPCON_CALLBACK_CONNECTED = 0,
294  IPCON_CALLBACK_DISCONNECTED = 1
295 };
296 
302 enum {
303  IPCON_ENUMERATION_TYPE_AVAILABLE = 0,
304  IPCON_ENUMERATION_TYPE_CONNECTED = 1,
305  IPCON_ENUMERATION_TYPE_DISCONNECTED = 2
306 };
307 
313 enum {
314  IPCON_CONNECT_REASON_REQUEST = 0,
315  IPCON_CONNECT_REASON_AUTO_RECONNECT = 1
316 };
317 
323 enum {
324  IPCON_DISCONNECT_REASON_REQUEST = 0,
325  IPCON_DISCONNECT_REASON_ERROR = 1,
326  IPCON_DISCONNECT_REASON_SHUTDOWN = 2
327 };
328 
334 enum {
335  IPCON_CONNECTION_STATE_DISCONNECTED = 0,
336  IPCON_CONNECTION_STATE_CONNECTED = 1,
337  IPCON_CONNECTION_STATE_PENDING = 2 // auto-reconnect in progress
338 };
339 
344  IPConnectionPrivate *p;
345 };
346 
347 #ifdef IPCON_EXPOSE_INTERNALS
348 
349 #define IPCON_NUM_CALLBACK_IDS 256
350 
354 struct _IPConnectionPrivate {
355 #ifdef _WIN32
356  bool wsa_startup_done; // protected by socket_mutex
357 #endif
358 
359  char *host;
360  uint16_t port;
361 
362  uint32_t timeout; // in msec
363 
364  bool auto_reconnect;
365  bool auto_reconnect_allowed;
366  bool auto_reconnect_pending;
367 
368  Mutex sequence_number_mutex;
369  uint8_t next_sequence_number; // protected by sequence_number_mutex
370 
371  Table devices;
372 
373  void *registered_callbacks[IPCON_NUM_CALLBACK_IDS];
374  void *registered_callback_user_data[IPCON_NUM_CALLBACK_IDS];
375 
376  Mutex socket_mutex;
377  Socket *socket; // protected by socket_mutex
378  uint64_t socket_id; // protected by socket_mutex
379 
380  bool receive_flag;
381  Thread receive_thread; // protected by socket_mutex
382 
383  CallbackContext *callback;
384 
385  bool disconnect_probe_flag;
386  Thread disconnect_probe_thread; // protected by socket_mutex
387  Event disconnect_probe_event;
388 
389  Semaphore wait;
390 };
391 
392 #endif // IPCON_EXPOSE_INTERNALS
393 
400 void ipcon_create(IPConnection *ipcon);
401 
409 void ipcon_destroy(IPConnection *ipcon);
410 
424 int ipcon_connect(IPConnection *ipcon, const char *host, uint16_t port);
425 
432 int ipcon_disconnect(IPConnection *ipcon);
433 
446 
456 void ipcon_set_auto_reconnect(IPConnection *ipcon, bool auto_reconnect);
457 
464 
473 void ipcon_set_timeout(IPConnection *ipcon, uint32_t timeout);
474 
480 uint32_t ipcon_get_timeout(IPConnection *ipcon);
481 
488 int ipcon_enumerate(IPConnection *ipcon);
489 
502 void ipcon_wait(IPConnection *ipcon);
503 
512 void ipcon_unwait(IPConnection *ipcon);
513 
519 void ipcon_register_callback(IPConnection *ipcon, uint8_t id,
520  void *callback, void *user_data);
521 
522 #ifdef IPCON_EXPOSE_INTERNALS
523 
527 int packet_header_create(PacketHeader *header, uint8_t length,
528  uint8_t function_id, IPConnectionPrivate *ipcon_p,
529  DevicePrivate *device_p);
530 
534 uint8_t packet_header_get_sequence_number(PacketHeader *header);
535 
539 void packet_header_set_sequence_number(PacketHeader *header,
540  uint8_t sequence_number);
541 
545 uint8_t packet_header_get_response_expected(PacketHeader *header);
546 
550 void packet_header_set_response_expected(PacketHeader *header,
551  uint8_t response_expected);
552 
556 uint8_t packet_header_get_error_code(PacketHeader *header);
557 
561 int16_t leconvert_int16_to(int16_t native);
562 
566 uint16_t leconvert_uint16_to(uint16_t native);
567 
571 int32_t leconvert_int32_to(int32_t native);
572 
576 uint32_t leconvert_uint32_to(uint32_t native);
577 
581 int64_t leconvert_int64_to(int64_t native);
582 
586 uint64_t leconvert_uint64_to(uint64_t native);
587 
591 float leconvert_float_to(float native);
592 
596 int16_t leconvert_int16_from(int16_t little);
597 
601 uint16_t leconvert_uint16_from(uint16_t little);
602 
606 int32_t leconvert_int32_from(int32_t little);
607 
611 uint32_t leconvert_uint32_from(uint32_t little);
612 
616 int64_t leconvert_int64_from(int64_t little);
617 
621 uint64_t leconvert_uint64_from(uint64_t little);
622 
626 float leconvert_float_from(float little);
627 
628 #endif // IPCON_EXPOSE_INTERNALS
629 
630 #endif
Definition: ip_connection.c:169
Definition: ip_connection.h:343
Definition: flag.py:1
void ipcon_destroy(IPConnection *ipcon)
Destroys the IP Connection object.
Definition: ip_connection.c:1608
int ipcon_enumerate(IPConnection *ipcon)
Broadcasts an enumerate request.
Definition: ip_connection.c:1749
Definition: bricklet_led_strip.c:38
void ipcon_set_timeout(IPConnection *ipcon, uint32_t timeout)
Sets the timeout in milliseconds for getters and for setters for which the response expected flag is ...
Definition: ip_connection.c:1741
Definition: ip_connection.c:1010
Definition: ip_connection.h:196
void ipcon_create(IPConnection *ipcon)
Creates an IP Connection object that can be used to enumerate the available devices.
Definition: ip_connection.c:1564
void ipcon_unwait(IPConnection *ipcon)
Unwaits the thread previously stopped by ipcon_wait.
Definition: ip_connection.c:1768
int ipcon_disconnect(IPConnection *ipcon)
Disconnects the TCP/IP connection from the Brick Daemon or the WIFI/Ethernet Extension.
Definition: ip_connection.c:1667
bool ipcon_get_auto_reconnect(IPConnection *ipcon)
Returns true if auto-reconnect is enabled, false otherwise.
Definition: ip_connection.c:1737
uint32_t ipcon_get_timeout(IPConnection *ipcon)
Returns the timeout as set by ipcon_set_timeout.
Definition: ip_connection.c:1745
int ipcon_connect(IPConnection *ipcon, const char *host, uint16_t port)
Creates a TCP/IP connection to the given host and c\ port.
Definition: ip_connection.c:1628
int ipcon_get_connection_state(IPConnection *ipcon)
Can return the following states:
Definition: ip_connection.c:1714
void ipcon_register_callback(IPConnection *ipcon, uint8_t id, void *callback, void *user_data)
Registers a callback for a given ID.
Definition: ip_connection.c:1772
void ipcon_wait(IPConnection *ipcon)
Stops the current thread until ipcon_unwait is called.
Definition: ip_connection.c:1764
void ipcon_set_auto_reconnect(IPConnection *ipcon, bool auto_reconnect)
Enables or disables auto-reconnect.
Definition: ip_connection.c:1726