00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef IP_CONNECTION_H
00011 #define IP_CONNECTION_H
00012
00017 #ifndef __STDC_LIMIT_MACROS
00018 #define __STDC_LIMIT_MACROS
00019 #endif
00020 #include <stdint.h>
00021 #include <string.h>
00022 #include <stdlib.h>
00023
00024 #if !defined __cplusplus && defined __GNUC__
00025 #include <stdbool.h>
00026 #endif
00027
00028 #ifdef _WIN32
00029 #ifndef WIN32_LEAN_AND_MEAN
00030 #define WIN32_LEAN_AND_MEAN
00031 #endif
00032 #include <windows.h>
00033 #else
00034 #include <pthread.h>
00035 #include <semaphore.h>
00036 #endif
00037
00038 #ifdef __cplusplus
00039 extern "C" {
00040 #endif
00041
00042 enum {
00043 E_OK = 0,
00044 E_TIMEOUT = -1,
00045 E_NO_STREAM_SOCKET = -2,
00046 E_HOSTNAME_INVALID = -3,
00047 E_NO_CONNECT = -4,
00048 E_NO_THREAD = -5,
00049 E_NOT_ADDED = -6,
00050 E_ALREADY_CONNECTED = -7,
00051 E_NOT_CONNECTED = -8,
00052 E_INVALID_PARAMETER = -9,
00053 E_NOT_SUPPORTED = -10,
00054 E_UNKNOWN_ERROR_CODE = -11
00055 };
00056
00057 #ifdef IPCON_EXPOSE_INTERNALS
00058
00059 typedef struct _Socket Socket;
00060
00061 typedef struct {
00062 #ifdef _WIN32
00063 CRITICAL_SECTION handle;
00064 #else
00065 pthread_mutex_t handle;
00066 #endif
00067 } Mutex;
00068
00069 void mutex_create(Mutex *mutex);
00070
00071 void mutex_destroy(Mutex *mutex);
00072
00073 void mutex_lock(Mutex *mutex);
00074
00075 void mutex_unlock(Mutex *mutex);
00076
00077 typedef struct {
00078 #ifdef _WIN32
00079 HANDLE handle;
00080 #else
00081 pthread_cond_t condition;
00082 pthread_mutex_t mutex;
00083 bool flag;
00084 #endif
00085 } Event;
00086
00087 typedef struct {
00088 #ifdef _WIN32
00089 HANDLE handle;
00090 #else
00091 sem_t object;
00092 sem_t *pointer;
00093 #endif
00094 } Semaphore;
00095
00096 typedef void (*ThreadFunction)(void *opaque);
00097
00098 typedef struct {
00099 #ifdef _WIN32
00100 HANDLE handle;
00101 DWORD id;
00102 #else
00103 pthread_t handle;
00104 #endif
00105 ThreadFunction function;
00106 void *opaque;
00107 } Thread;
00108
00109 typedef struct {
00110 Mutex mutex;
00111 int used;
00112 int allocated;
00113 uint32_t *keys;
00114 void **values;
00115 } Table;
00116
00117 typedef struct _QueueItem {
00118 struct _QueueItem *next;
00119 int kind;
00120 void *data;
00121 } QueueItem;
00122
00123 typedef struct {
00124 Mutex mutex;
00125 Semaphore semaphore;
00126 QueueItem *head;
00127 QueueItem *tail;
00128 } Queue;
00129
00130 #if defined _MSC_VER || defined __BORLANDC__
00131 #pragma pack(push)
00132 #pragma pack(1)
00133 #define ATTRIBUTE_PACKED
00134 #elif defined __GNUC__
00135 #ifdef _WIN32
00136
00137
00138 #define ATTRIBUTE_PACKED __attribute__((gcc_struct, packed))
00139 #else
00140 #define ATTRIBUTE_PACKED __attribute__((packed))
00141 #endif
00142 #else
00143 #error unknown compiler, do not know how to enable struct packing
00144 #endif
00145
00146 typedef struct {
00147 uint32_t uid;
00148 uint8_t length;
00149 uint8_t function_id;
00150 uint8_t sequence_number_and_options;
00151 uint8_t error_code_and_future_use;
00152 } ATTRIBUTE_PACKED PacketHeader;
00153
00154 typedef struct {
00155 PacketHeader header;
00156 uint8_t payload[64];
00157 uint8_t optional_data[8];
00158 } ATTRIBUTE_PACKED Packet;
00159
00160 #if defined _MSC_VER || defined __BORLANDC__
00161 #pragma pack(pop)
00162 #endif
00163 #undef ATTRIBUTE_PACKED
00164
00165 #endif // IPCON_EXPOSE_INTERNALS
00166
00167 typedef struct _IPConnection IPConnection;
00168 typedef struct _IPConnectionPrivate IPConnectionPrivate;
00169 typedef struct _Device Device;
00170 typedef struct _DevicePrivate DevicePrivate;
00171
00172 #ifdef IPCON_EXPOSE_INTERNALS
00173
00174 typedef struct _CallbackContext CallbackContext;
00175
00176 #endif
00177
00178 typedef void (*EnumerateCallbackFunction)(const char *uid,
00179 const char *connected_uid,
00180 char position,
00181 uint8_t hardware_version[3],
00182 uint8_t firmware_version[3],
00183 uint16_t device_identifier,
00184 uint8_t enumeration_type,
00185 void *user_data);
00186 typedef void (*ConnectedCallbackFunction)(uint8_t connect_reason,
00187 void *user_data);
00188 typedef void (*DisconnectedCallbackFunction)(uint8_t disconnect_reason,
00189 void *user_data);
00190
00191 #ifdef IPCON_EXPOSE_INTERNALS
00192
00193 typedef void (*CallbackWrapperFunction)(DevicePrivate *device_p, Packet *packet);
00194
00195 #endif
00196
00200 struct _Device {
00201 DevicePrivate *p;
00202 };
00203
00204 #ifdef IPCON_EXPOSE_INTERNALS
00205
00206 #define DEVICE_NUM_FUNCTION_IDS 256
00207
00211 struct _DevicePrivate {
00212 int ref_count;
00213
00214 uint32_t uid;
00215
00216 IPConnectionPrivate *ipcon_p;
00217
00218 uint8_t api_version[3];
00219
00220 Mutex request_mutex;
00221
00222 uint8_t expected_response_function_id;
00223 uint8_t expected_response_sequence_number;
00224 Mutex response_mutex;
00225 Packet response_packet;
00226 Event response_event;
00227 int response_expected[DEVICE_NUM_FUNCTION_IDS];
00228
00229 void *registered_callbacks[DEVICE_NUM_FUNCTION_IDS];
00230 void *registered_callback_user_data[DEVICE_NUM_FUNCTION_IDS];
00231 CallbackWrapperFunction callback_wrappers[DEVICE_NUM_FUNCTION_IDS];
00232 };
00233
00237 enum {
00238 DEVICE_RESPONSE_EXPECTED_INVALID_FUNCTION_ID = 0,
00239 DEVICE_RESPONSE_EXPECTED_ALWAYS_TRUE,
00240 DEVICE_RESPONSE_EXPECTED_ALWAYS_FALSE,
00241 DEVICE_RESPONSE_EXPECTED_TRUE,
00242 DEVICE_RESPONSE_EXPECTED_FALSE
00243 };
00244
00248 void device_create(Device *device, const char *uid,
00249 IPConnectionPrivate *ipcon_p, uint8_t api_version_major,
00250 uint8_t api_version_minor, uint8_t api_version_release);
00251
00255 void device_release(DevicePrivate *device_p);
00256
00260 int device_get_response_expected(DevicePrivate *device_p, uint8_t function_id,
00261 bool *ret_response_expected);
00262
00266 int device_set_response_expected(DevicePrivate *device_p, uint8_t function_id,
00267 bool response_expected);
00268
00272 int device_set_response_expected_all(DevicePrivate *device_p, bool response_expected);
00273
00277 void device_register_callback(DevicePrivate *device_p, uint8_t id, void *callback,
00278 void *user_data);
00279
00283 int device_get_api_version(DevicePrivate *device_p, uint8_t ret_api_version[3]);
00284
00288 int device_send_request(DevicePrivate *device_p, Packet *request, Packet *response);
00289
00290 #endif // IPCON_EXPOSE_INTERNALS
00291
00297 enum {
00298 IPCON_CALLBACK_ENUMERATE = 253,
00299 IPCON_CALLBACK_CONNECTED = 0,
00300 IPCON_CALLBACK_DISCONNECTED = 1
00301 };
00302
00308 enum {
00309 IPCON_ENUMERATION_TYPE_AVAILABLE = 0,
00310 IPCON_ENUMERATION_TYPE_CONNECTED = 1,
00311 IPCON_ENUMERATION_TYPE_DISCONNECTED = 2
00312 };
00313
00319 enum {
00320 IPCON_CONNECT_REASON_REQUEST = 0,
00321 IPCON_CONNECT_REASON_AUTO_RECONNECT = 1
00322 };
00323
00329 enum {
00330 IPCON_DISCONNECT_REASON_REQUEST = 0,
00331 IPCON_DISCONNECT_REASON_ERROR = 1,
00332 IPCON_DISCONNECT_REASON_SHUTDOWN = 2
00333 };
00334
00340 enum {
00341 IPCON_CONNECTION_STATE_DISCONNECTED = 0,
00342 IPCON_CONNECTION_STATE_CONNECTED = 1,
00343 IPCON_CONNECTION_STATE_PENDING = 2
00344 };
00345
00349 struct _IPConnection {
00350 IPConnectionPrivate *p;
00351 };
00352
00353 #ifdef IPCON_EXPOSE_INTERNALS
00354
00355 #define IPCON_NUM_CALLBACK_IDS 256
00356 #define IPCON_MAX_SECRET_LENGTH 64
00357
00361 typedef Device BrickDaemon;
00362
00366 struct _IPConnectionPrivate {
00367 #ifdef _WIN32
00368 bool wsa_startup_done;
00369 #endif
00370
00371 char *host;
00372 uint16_t port;
00373
00374 uint32_t timeout;
00375
00376 bool auto_reconnect;
00377 bool auto_reconnect_allowed;
00378 bool auto_reconnect_pending;
00379
00380 Mutex sequence_number_mutex;
00381 uint8_t next_sequence_number;
00382
00383 Mutex authentication_mutex;
00384 uint32_t next_authentication_nonce;
00385
00386 Mutex devices_ref_mutex;
00387 Table devices;
00388
00389 void *registered_callbacks[IPCON_NUM_CALLBACK_IDS];
00390 void *registered_callback_user_data[IPCON_NUM_CALLBACK_IDS];
00391
00392 Mutex socket_mutex;
00393 Socket *socket;
00394 uint64_t socket_id;
00395
00396 bool receive_flag;
00397 Thread receive_thread;
00398
00399 CallbackContext *callback;
00400
00401 bool disconnect_probe_flag;
00402 Thread disconnect_probe_thread;
00403 Event disconnect_probe_event;
00404
00405 Semaphore wait;
00406
00407 BrickDaemon brickd;
00408 };
00409
00410 #endif // IPCON_EXPOSE_INTERNALS
00411
00418 void ipcon_create(IPConnection *ipcon);
00419
00427 void ipcon_destroy(IPConnection *ipcon);
00428
00442 int ipcon_connect(IPConnection *ipcon, const char *host, uint16_t port);
00443
00450 int ipcon_disconnect(IPConnection *ipcon);
00451
00465 int ipcon_authenticate(IPConnection *ipcon, const char secret[64]);
00466
00478 int ipcon_get_connection_state(IPConnection *ipcon);
00479
00489 void ipcon_set_auto_reconnect(IPConnection *ipcon, bool auto_reconnect);
00490
00496 bool ipcon_get_auto_reconnect(IPConnection *ipcon);
00497
00506 void ipcon_set_timeout(IPConnection *ipcon, uint32_t timeout);
00507
00513 uint32_t ipcon_get_timeout(IPConnection *ipcon);
00514
00521 int ipcon_enumerate(IPConnection *ipcon);
00522
00535 void ipcon_wait(IPConnection *ipcon);
00536
00545 void ipcon_unwait(IPConnection *ipcon);
00546
00552 void ipcon_register_callback(IPConnection *ipcon, uint8_t id,
00553 void *callback, void *user_data);
00554
00555 #ifdef IPCON_EXPOSE_INTERNALS
00556
00560 int packet_header_create(PacketHeader *header, uint8_t length,
00561 uint8_t function_id, IPConnectionPrivate *ipcon_p,
00562 DevicePrivate *device_p);
00563
00567 uint8_t packet_header_get_sequence_number(PacketHeader *header);
00568
00572 void packet_header_set_sequence_number(PacketHeader *header,
00573 uint8_t sequence_number);
00574
00578 uint8_t packet_header_get_response_expected(PacketHeader *header);
00579
00583 void packet_header_set_response_expected(PacketHeader *header,
00584 uint8_t response_expected);
00585
00589 uint8_t packet_header_get_error_code(PacketHeader *header);
00590
00594 int16_t leconvert_int16_to(int16_t native);
00595
00599 uint16_t leconvert_uint16_to(uint16_t native);
00600
00604 int32_t leconvert_int32_to(int32_t native);
00605
00609 uint32_t leconvert_uint32_to(uint32_t native);
00610
00614 int64_t leconvert_int64_to(int64_t native);
00615
00619 uint64_t leconvert_uint64_to(uint64_t native);
00620
00624 float leconvert_float_to(float native);
00625
00629 int16_t leconvert_int16_from(int16_t little);
00630
00634 uint16_t leconvert_uint16_from(uint16_t little);
00635
00639 int32_t leconvert_int32_from(int32_t little);
00640
00644 uint32_t leconvert_uint32_from(uint32_t little);
00645
00649 int64_t leconvert_int64_from(int64_t little);
00650
00654 uint64_t leconvert_uint64_from(uint64_t little);
00655
00659 float leconvert_float_from(float little);
00660
00661 #endif // IPCON_EXPOSE_INTERNALS
00662
00663 #ifdef __cplusplus
00664 }
00665 #endif
00666
00667 #endif