/alps/ipecamera

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/ipecamera

« back to all changes in this revision

Viewing changes to event.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-04-27 00:28:57 UTC
  • Revision ID: csa@suren.me-20150427002857-82fk6r3e8rfgy4wr
First stand-alone ipecamera implementation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define _POSIX_C_SOURCE 199309L
2
 
#include <stdio.h>
3
 
#include <string.h>
4
 
#include <strings.h>
5
 
#include <stdlib.h>
6
 
#include <stdint.h>
7
 
#include <stdarg.h>
8
 
#include <fcntl.h>
9
 
#include <unistd.h>
10
 
#include <sys/ioctl.h>
11
 
#include <sys/mman.h>
12
 
#include <arpa/inet.h>
13
 
#include <errno.h>
14
 
#include <assert.h>
15
 
#include <time.h>
16
 
 
17
 
#include "pci.h"
18
 
 
19
 
#include "tools.h"
20
 
#include "error.h"
21
 
 
22
 
#ifndef __timespec_defined
23
 
struct timespec {
24
 
    time_t tv_sec;
25
 
    long tv_nsec;
26
 
};
27
 
#endif /* __timespec_defined */
28
 
 
29
 
 
30
 
pcilib_event_t pcilib_find_event(pcilib_t *ctx, const char *event) {
31
 
    int i;
32
 
 
33
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
34
 
    pcilib_event_description_t *events = model_info->events;
35
 
 
36
 
    for (i = 0; events[i].name; i++) {
37
 
        if (!strcasecmp(events[i].name, event)) return events[i].evid;
38
 
    }
39
 
 
40
 
    return (pcilib_event_t)-1;
41
 
}
42
 
 
43
 
pcilib_event_data_type_t pcilib_find_event_data_type(pcilib_t *ctx, pcilib_event_t event, const char *data_type) {
44
 
    int i;
45
 
    
46
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
47
 
    pcilib_event_data_type_description_t *data_types = model_info->data_types;
48
 
    
49
 
    for (i = 0; data_types[i].name; i++) {
50
 
        if ((data_types[i].evid&event)&&(!strcasecmp(data_types[i].name, data_type))) return data_types[i].data_type;
51
 
    }
52
 
 
53
 
    return (pcilib_event_data_type_t)-1;
54
 
}
55
 
 
56
 
int pcilib_init_event_engine(pcilib_t *ctx) {
57
 
    pcilib_event_api_description_t *api;
58
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
59
 
 
60
 
    api = model_info->event_api;
61
 
 
62
 
//    api = pcilib_model[model].event_api;
63
 
    if ((api)&&(api->init)) {
64
 
        ctx->event_ctx = api->init(ctx);
65
 
        if (ctx->event_ctx) {
66
 
            ctx->event_ctx->pcilib = ctx;
67
 
        }
68
 
    }
69
 
    
70
 
    return 0;
71
 
}
72
 
 
73
 
int pcilib_reset(pcilib_t *ctx) {
74
 
    pcilib_event_api_description_t *api;
75
 
    
76
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
77
 
 
78
 
    api = model_info->event_api;
79
 
    if (!api) {
80
 
        pcilib_error("Event API is not supported by the selected model");
81
 
        return PCILIB_ERROR_NOTSUPPORTED;
82
 
    }
83
 
    
84
 
    if (api->reset) 
85
 
        return api->reset(ctx->event_ctx);
86
 
        
87
 
    return 0;
88
 
}
89
 
 
90
 
int pcilib_configure_rawdata_callback(pcilib_t *ctx, pcilib_event_rawdata_callback_t callback, void *user) {
91
 
    pcilib_event_api_description_t *api;
92
 
    
93
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
94
 
 
95
 
    api = model_info->event_api;
96
 
    if (!api) {
97
 
        pcilib_error("Event API is not supported by the selected model");
98
 
        return PCILIB_ERROR_NOTSUPPORTED;
99
 
    }
100
 
 
101
 
    ctx->event_ctx->params.rawdata.callback = callback;
102
 
    ctx->event_ctx->params.rawdata.user = user;
103
 
    
104
 
    return 0;    
105
 
}
106
 
 
107
 
int pcilib_configure_autostop(pcilib_t *ctx, size_t max_events, pcilib_timeout_t duration) {
108
 
    pcilib_event_api_description_t *api;
109
 
    
110
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
111
 
 
112
 
    api = model_info->event_api;
113
 
    if (!api) {
114
 
        pcilib_error("Event API is not supported by the selected model");
115
 
        return PCILIB_ERROR_NOTSUPPORTED;
116
 
    }
117
 
 
118
 
    ctx->event_ctx->params.autostop.max_events = max_events;
119
 
    ctx->event_ctx->params.autostop.duration = duration;
120
 
    
121
 
    return 0;    
122
 
}
123
 
 
124
 
int pcilib_configure_autotrigger(pcilib_t *ctx, pcilib_timeout_t interval, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
125
 
        /* To support hardware without autotriggering, we need to provide in event.c a code 
126
 
        to generate multiple triggers in a thread (available in cli). The function should 
127
 
        be re-enabled afterwards: just set parameters and let implementation decide if it 
128
 
        can make triggering in hardware or will use our emulation */
129
 
        
130
 
    return PCILIB_ERROR_NOTSUPPORTED;
131
 
}
132
 
 
133
 
int pcilib_configure_preprocessing_threads(pcilib_t *ctx, size_t max_threads) {
134
 
    pcilib_event_api_description_t *api;
135
 
    
136
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
137
 
 
138
 
    api = model_info->event_api;
139
 
    if (!api) {
140
 
        pcilib_error("Event API is not supported by the selected model");
141
 
        return PCILIB_ERROR_NOTSUPPORTED;
142
 
    }
143
 
 
144
 
    ctx->event_ctx->params.parallel.max_threads = max_threads;
145
 
 
146
 
    return 0;
147
 
}
148
 
 
149
 
int pcilib_start(pcilib_t *ctx, pcilib_event_t event_mask, pcilib_event_flags_t flags) {
150
 
    pcilib_event_api_description_t *api;
151
 
    
152
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
153
 
 
154
 
    api = model_info->event_api;
155
 
    if (!api) {
156
 
        pcilib_error("Event API is not supported by the selected model");
157
 
        return PCILIB_ERROR_NOTSUPPORTED;
158
 
    }
159
 
 
160
 
    if (api->start) 
161
 
        return api->start(ctx->event_ctx, event_mask, flags);
162
 
 
163
 
    return 0;
164
 
}
165
 
 
166
 
int pcilib_stop(pcilib_t *ctx, pcilib_event_flags_t flags) {
167
 
    pcilib_event_api_description_t *api;
168
 
    
169
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
170
 
 
171
 
    api = model_info->event_api;
172
 
    if (!api) {
173
 
        pcilib_error("Event API is not supported by the selected model");
174
 
        return PCILIB_ERROR_NOTSUPPORTED;
175
 
    }
176
 
 
177
 
    if (api->stop) 
178
 
        return api->stop(ctx->event_ctx, flags);
179
 
 
180
 
    return 0;
181
 
}
182
 
 
183
 
int pcilib_stream(pcilib_t *ctx, pcilib_event_callback_t callback, void *user) {
184
 
    pcilib_event_api_description_t *api;
185
 
    
186
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
187
 
 
188
 
    api = model_info->event_api;
189
 
    if (!api) {
190
 
        pcilib_error("Event API is not supported by the selected model");
191
 
        return PCILIB_ERROR_NOTSUPPORTED;
192
 
    }
193
 
 
194
 
    if (api->stream)
195
 
        return api->stream(ctx->event_ctx, callback, user);
196
 
 
197
 
    if (api->next_event) {
198
 
        pcilib_error("Streaming using next_event API is not implemented yet");
199
 
    }
200
 
 
201
 
    pcilib_error("Event enumeration is not suppored by API");
202
 
    return PCILIB_ERROR_NOTSUPPORTED;
203
 
}
204
 
/*
205
 
typedef struct {
206
 
    pcilib_event_id_t event_id;
207
 
    pcilib_event_info_t *info;
208
 
} pcilib_return_event_callback_context_t;
209
 
 
210
 
static int pcilib_return_event_callback(pcilib_event_id_t event_id, pcilib_event_info_t *info, void *user) {
211
 
    pcilib_return_event_callback_context_t *ctx = (pcilib_return_event_callback_context_t*)user;
212
 
    ctx->event_id = event_id;
213
 
    ctx->info = info;
214
 
}
215
 
*/
216
 
 
217
 
int pcilib_get_next_event(pcilib_t *ctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info) {
218
 
    pcilib_event_api_description_t *api;
219
 
//    pcilib_return_event_callback_context_t user;
220
 
    
221
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
222
 
 
223
 
    api = model_info->event_api;
224
 
    if (!api) {
225
 
        pcilib_error("Event API is not supported by the selected model");
226
 
        return PCILIB_ERROR_NOTSUPPORTED;
227
 
    }
228
 
 
229
 
    if (api->next_event) 
230
 
        return api->next_event(ctx->event_ctx, timeout, evid, info_size, info);
231
 
 
232
 
/*      
233
 
    if (api->stream) {
234
 
        err = api->stream(ctx->event_ctx, 1, timeout, pcilib_return_event_callback, &user);
235
 
        if (err) return err;
236
 
        
237
 
        if (evid) *evid = user->event_id;
238
 
        if (info) *info = user->info;
239
 
 
240
 
        return 0;
241
 
    }
242
 
*/
243
 
 
244
 
    pcilib_error("Event enumeration is not suppored by API");
245
 
    return PCILIB_ERROR_NOTSUPPORTED;
246
 
}
247
 
 
248
 
int pcilib_trigger(pcilib_t *ctx, pcilib_event_t event, size_t trigger_size, void *trigger_data) {
249
 
    pcilib_event_api_description_t *api;
250
 
    
251
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
252
 
 
253
 
    api = model_info->event_api;
254
 
    if (!api) {
255
 
        pcilib_error("Event API is not supported by the selected model");
256
 
        return PCILIB_ERROR_NOTSUPPORTED;
257
 
    }
258
 
 
259
 
    if (api->trigger) 
260
 
        return api->trigger(ctx->event_ctx, event, trigger_size, trigger_data);
261
 
 
262
 
    pcilib_error("Self triggering is not supported by the selected model");
263
 
    return PCILIB_ERROR_NOTSUPPORTED;
264
 
}
265
 
 
266
 
 
267
 
void *pcilib_get_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size) {
268
 
    int err;
269
 
    void *res = NULL;
270
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
271
 
 
272
 
    pcilib_event_api_description_t *api = model_info->event_api;
273
 
    if (!api) {
274
 
        if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED;
275
 
        pcilib_error("Event API is not supported by the selected model");
276
 
        return NULL;
277
 
    }
278
 
 
279
 
    if (api->get_data) {
280
 
        err = api->get_data(ctx->event_ctx, event_id, data_type, arg_size, arg, size, &res);
281
 
        if (err) {
282
 
            if (size) *size = (size_t)err;
283
 
            return NULL;
284
 
        }
285
 
        return res;
286
 
    }
287
 
    
288
 
    if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED;
289
 
    return NULL;
290
 
}
291
 
 
292
 
int pcilib_copy_data_with_argument(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t size, void *buf, size_t *retsize) {
293
 
    int err;
294
 
    void *res = buf;
295
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
296
 
 
297
 
    pcilib_event_api_description_t *api = model_info->event_api;
298
 
    if (!api) {
299
 
        pcilib_error("Event API is not supported by the selected model");
300
 
        return PCILIB_ERROR_NOTSUPPORTED;
301
 
    }
302
 
 
303
 
    if (api->get_data) {
304
 
        err = api->get_data(ctx->event_ctx, event_id, data_type, arg_size, arg, &size, &res);
305
 
        if (err) return err;
306
 
        
307
 
        if (buf != res) memcpy(buf, res, size);
308
 
        
309
 
        if (retsize) *retsize = size;
310
 
        return 0;
311
 
    }   
312
 
 
313
 
    return PCILIB_ERROR_NOTSUPPORTED;
314
 
}
315
 
 
316
 
 
317
 
void *pcilib_get_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t *size) {
318
 
    int err;
319
 
    void *res = NULL;
320
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
321
 
 
322
 
    pcilib_event_api_description_t *api = model_info->event_api;
323
 
    if (!api) {
324
 
        pcilib_error("Event API is not supported by the selected model");
325
 
        if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED;
326
 
        return NULL;
327
 
    }
328
 
 
329
 
    if (api->get_data) {
330
 
        err = api->get_data(ctx->event_ctx, event_id, data_type, 0, NULL, size, &res);
331
 
        if (err) {
332
 
            if (size) *size = (size_t)err;
333
 
            return NULL;
334
 
        }
335
 
        return res;
336
 
    }
337
 
 
338
 
    if (size) *size = (size_t)PCILIB_ERROR_NOTSUPPORTED;
339
 
    return NULL;
340
 
}
341
 
 
342
 
int pcilib_copy_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t size, void *buf, size_t *ret_size) {
343
 
    int err;
344
 
    void *res = buf;
345
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
346
 
 
347
 
    pcilib_event_api_description_t *api = model_info->event_api;
348
 
    if (!api) {
349
 
        pcilib_error("Event API is not supported by the selected model");
350
 
        return PCILIB_ERROR_NOTSUPPORTED;
351
 
    }
352
 
 
353
 
    if (api->get_data) {
354
 
        err = api->get_data(ctx->event_ctx, event_id, data_type, 0, NULL, &size, &res);
355
 
        if (err) return err;
356
 
        
357
 
        if (buf != res) memcpy(buf, res, size);
358
 
 
359
 
        if (ret_size) *ret_size = size;
360
 
        return 0;
361
 
    }
362
 
 
363
 
    return PCILIB_ERROR_NOTSUPPORTED;
364
 
}
365
 
 
366
 
int pcilib_return_data(pcilib_t *ctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) {
367
 
    pcilib_model_description_t *model_info = pcilib_get_model_description(ctx);
368
 
    
369
 
    pcilib_event_api_description_t *api = model_info->event_api;
370
 
    if (!api) {
371
 
        pcilib_error("Event API is not supported by the selected model");
372
 
        return PCILIB_ERROR_NOTSUPPORTED;
373
 
    }
374
 
 
375
 
    if (api->return_data) 
376
 
        return api->return_data(ctx->event_ctx, event_id, data_type, data);
377
 
 
378
 
    return 0;
379
 
}
380
 
 
381
 
 
382
 
typedef struct {
383
 
    pcilib_t *ctx;
384
 
    
385
 
    size_t *size;
386
 
    void **data;
387
 
} pcilib_grab_callback_user_data_t;
388
 
 
389
 
 
390
 
static int pcilib_grab_callback(pcilib_event_t event, pcilib_event_id_t event_id, void *vuser) {
391
 
    int err;
392
 
    void *data;
393
 
    size_t size;
394
 
    int allocated = 0;
395
 
 
396
 
    pcilib_grab_callback_user_data_t *user = (pcilib_grab_callback_user_data_t*)vuser;
397
 
 
398
 
    data = pcilib_get_data(user->ctx, event_id, PCILIB_EVENT_DATA, &size);
399
 
    if (!data) {
400
 
        pcilib_error("Error getting event data");
401
 
        return -(int)size;
402
 
    }
403
 
    
404
 
    if (*(user->data)) {
405
 
        if ((user->size)&&(*(user->size) < size)) {
406
 
            pcilib_error("The supplied buffer does not have enough space to hold the event data. Buffer size is %z, but %z is required", user->size, size);
407
 
            return -PCILIB_ERROR_MEMORY;
408
 
        }
409
 
 
410
 
        *(user->size) = size;
411
 
    } else {
412
 
        *(user->data) = malloc(size);
413
 
        if (!*(user->data)) {
414
 
            pcilib_error("Memory allocation (%i bytes) for event data is failed");
415
 
            return -PCILIB_ERROR_MEMORY;
416
 
        }
417
 
        if (*(user->size)) *(user->size) = size;
418
 
        allocated = 1;
419
 
    }
420
 
    
421
 
    memcpy(*(user->data), data, size);
422
 
    
423
 
    err = pcilib_return_data(user->ctx, event_id, PCILIB_EVENT_DATA, data);
424
 
    if (err) {
425
 
        if (allocated) {
426
 
            free(*(user->data));
427
 
            *(user->data) = NULL;
428
 
        }
429
 
        pcilib_error("The event data had been overwritten before it was returned, data corruption may occur");
430
 
        return -err;
431
 
    }
432
 
    
433
 
    return PCILIB_STREAMING_CONTINUE;
434
 
}
435
 
 
436
 
int pcilib_grab(pcilib_t *ctx, pcilib_event_t event_mask, size_t *size, void **data, pcilib_timeout_t timeout) {
437
 
    int err;
438
 
    pcilib_event_id_t eid;
439
 
    
440
 
    pcilib_grab_callback_user_data_t user = {ctx, size, data};
441
 
    
442
 
    err = pcilib_start(ctx, event_mask, PCILIB_EVENT_FLAGS_DEFAULT);
443
 
    if (!err) err = pcilib_trigger(ctx, event_mask, 0, NULL);
444
 
    if (!err) {
445
 
        err = pcilib_get_next_event(ctx, timeout, &eid, 0, NULL);
446
 
        if (!err) pcilib_grab_callback(event_mask, eid, &user);
447
 
    }
448
 
    pcilib_stop(ctx, PCILIB_EVENT_FLAGS_DEFAULT);
449
 
    return err;
450
 
}