1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#include "interface/khronos/wf/wfc_server_api.h"
29#include "interface/khronos/wf/wfc_client_ipc.h"
30#include "interface/khronos/wf/wfc_ipc.h"
31#include "interface/vcos/vcos.h"
32#include "interface/khronos/include/WF/wfc.h"
33#include "interface/khronos/wf/wfc_int.h"
34#include "interface/khronos/include/EGL/eglext.h"
35
36#define VCOS_LOG_CATEGORY (&wfc_client_server_api_log_category)
37
38//#define WFC_FULL_LOGGING
39#ifdef WFC_FULL_LOGGING
40#define WFC_CLIENT_SERVER_API_LOGLEVEL VCOS_LOG_TRACE
41#else
42#define WFC_CLIENT_SERVER_API_LOGLEVEL VCOS_LOG_WARN
43#endif
44
45static VCOS_LOG_CAT_T wfc_client_server_api_log_category;
46
47/** Implement "void foo(WFCContext context)" */
48static VCOS_STATUS_T wfc_client_server_api_send_context(WFC_IPC_MSG_TYPE msg_type, WFCContext context)
49{
50 WFC_IPC_MSG_CONTEXT_T msg;
51
52 msg.header.type = msg_type;
53 msg.context = context;
54
55 return wfc_client_ipc_send(&msg.header, sizeof(msg));
56}
57
58/** Implement "void foo(WFCNativeStreamType stream)" */
59static VCOS_STATUS_T wfc_client_server_api_send_stream(WFC_IPC_MSG_TYPE msg_type, WFCNativeStreamType stream)
60{
61 WFC_IPC_MSG_STREAM_T msg;
62
63 msg.header.type = msg_type;
64 msg.stream = stream;
65
66 return wfc_client_ipc_send(&msg.header, sizeof(msg));
67}
68
69/** Implement "foo(WFCNativeStreamType stream)" where a result is returned.
70 * This may either be as a return value, or via a pointer parameter.
71 */
72static VCOS_STATUS_T wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_TYPE msg_type, WFCNativeStreamType stream,
73 void *result, size_t *result_len)
74{
75 WFC_IPC_MSG_STREAM_T msg;
76
77 msg.header.type = msg_type;
78 msg.stream = stream;
79
80 return wfc_client_ipc_sendwait(&msg.header, sizeof(msg), result, result_len);
81}
82
83/* ========================================================================= */
84
85VCOS_STATUS_T wfc_server_connect(void)
86{
87 VCOS_STATUS_T status;
88
89 vcos_log_set_level(VCOS_LOG_CATEGORY, WFC_CLIENT_SERVER_API_LOGLEVEL);
90 vcos_log_register("wfccsapi", VCOS_LOG_CATEGORY);
91
92 status = wfc_client_ipc_init();
93
94 vcos_log_trace("%s: result %d", VCOS_FUNCTION, status);
95
96 if (status != VCOS_SUCCESS)
97 {
98 vcos_log_unregister(VCOS_LOG_CATEGORY);
99 }
100
101 return status;
102}
103
104/* ------------------------------------------------------------------------- */
105
106void wfc_server_disconnect(void)
107{
108 vcos_log_trace("%s: called", VCOS_FUNCTION);
109
110 if (wfc_client_ipc_deinit())
111 {
112 vcos_log_unregister(VCOS_LOG_CATEGORY);
113 }
114}
115
116/* ------------------------------------------------------------------------- */
117
118void wfc_server_use_keep_alive(void)
119{
120 wfc_client_ipc_use_keep_alive();
121}
122
123/* ------------------------------------------------------------------------- */
124
125void wfc_server_release_keep_alive(void)
126{
127 wfc_client_ipc_release_keep_alive();
128}
129
130/* ------------------------------------------------------------------------- */
131
132uint32_t wfc_server_create_context(WFCContext context, uint32_t context_type,
133 uint32_t screen_or_stream_num, uint32_t pid_lo, uint32_t pid_hi)
134{
135 WFC_IPC_MSG_CREATE_CONTEXT_T msg;
136 VCOS_STATUS_T status;
137 uint32_t result = -1;
138 size_t result_len = sizeof(result);
139
140 vcos_log_trace("%s: context 0x%x type 0x%x num 0x%x pid 0x%x%08x", VCOS_FUNCTION,
141 context, context_type, screen_or_stream_num, pid_hi, pid_lo);
142
143 msg.header.type = WFC_IPC_MSG_CREATE_CONTEXT;
144 msg.context = context;
145 msg.context_type = context_type;
146 msg.screen_or_stream_num = screen_or_stream_num;
147 msg.pid_lo = pid_lo;
148 msg.pid_hi = pid_hi;
149
150 status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len);
151
152 vcos_log_trace("%s: status 0x%x, result 0x%x", VCOS_FUNCTION, status, result);
153
154 if (status != VCOS_SUCCESS)
155 result = -1;
156
157 return result;
158}
159
160/* ------------------------------------------------------------------------- */
161
162void wfc_server_destroy_context(WFCContext context)
163{
164 VCOS_STATUS_T status;
165
166 vcos_log_trace("%s: context 0x%x", VCOS_FUNCTION, context);
167
168 status = wfc_client_server_api_send_context(WFC_IPC_MSG_DESTROY_CONTEXT, context);
169
170 vcos_assert(status == VCOS_SUCCESS);
171}
172
173/* ------------------------------------------------------------------------- */
174
175uint32_t wfc_server_commit_scene(WFCContext context, const WFC_SCENE_T *scene,
176 uint32_t flags, WFC_CALLBACK_T scene_taken_cb, void *scene_taken_data)
177{
178 WFC_IPC_MSG_COMMIT_SCENE_T msg;
179 VCOS_STATUS_T status = VCOS_SUCCESS;
180 uint32_t result = VCOS_ENOSYS;
181 size_t result_len = sizeof(result);
182 uint32_t i;
183
184 vcos_log_trace("%s: context 0x%x commit %u elements %u flags 0x%x",
185 VCOS_FUNCTION, context, scene->commit_count, scene->element_count, flags);
186 for (i = 0; i < scene->element_count; i++)
187 {
188 vcos_log_trace("%s: element[%u] stream 0x%x", VCOS_FUNCTION, i, scene->elements[i].source_stream);
189 }
190
191 msg.header.type = WFC_IPC_MSG_COMMIT_SCENE;
192 msg.context = context;
193 msg.flags = flags;
194 msg.scene_taken_cb.ptr = scene_taken_cb;
195 msg.scene_taken_data.ptr = scene_taken_data;
196 memcpy(&msg.scene, scene, sizeof(*scene));
197
198 if (flags & WFC_SERVER_COMMIT_WAIT)
199 {
200 /* Caller will wait for callback, call cannot fail */
201 vcos_assert(scene_taken_cb != NULL);
202 vcos_assert(scene_taken_data != NULL);
203 }
204 else
205 {
206 /* Caller will not wait for callback, so need to at least wait for result. */
207 vcos_assert(scene_taken_cb == NULL);
208 vcos_assert(scene_taken_data == NULL);
209 }
210
211 status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len);
212
213 /* Override the result if the status was an error */
214 if (status != VCOS_SUCCESS)
215 result = status;
216
217 return result;
218}
219
220/* ------------------------------------------------------------------------- */
221
222void wfc_server_activate(WFCContext context)
223{
224 VCOS_STATUS_T status;
225
226 vcos_log_trace("%s: context 0x%x", VCOS_FUNCTION, context);
227
228 status = wfc_client_server_api_send_context(WFC_IPC_MSG_ACTIVATE, context);
229
230 vcos_assert(status == VCOS_SUCCESS);
231}
232
233/* ------------------------------------------------------------------------- */
234
235void wfc_server_deactivate(WFCContext context)
236{
237 VCOS_STATUS_T status;
238
239 vcos_log_trace("%s: context 0x%x", VCOS_FUNCTION, context);
240
241 status = wfc_client_server_api_send_context(WFC_IPC_MSG_DEACTIVATE, context);
242
243 vcos_assert(status == VCOS_SUCCESS);
244}
245
246/* ------------------------------------------------------------------------- */
247
248void wfc_server_set_deferral_stream(WFCContext context, WFCNativeStreamType stream)
249{
250 WFC_IPC_MSG_SET_DEFERRAL_STREAM_T msg;
251 VCOS_STATUS_T status;
252
253 vcos_log_trace("%s: context 0x%x stream 0x%x", VCOS_FUNCTION, context, stream);
254
255 msg.header.type = WFC_IPC_MSG_SET_DEFERRAL_STREAM;
256 msg.context = context;
257 msg.stream = stream;
258
259 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
260
261 vcos_assert(status == VCOS_SUCCESS);
262}
263
264/* ------------------------------------------------------------------------- */
265
266WFCNativeStreamType wfc_server_stream_create(WFCNativeStreamType stream, uint32_t flags, uint32_t pid_lo, uint32_t pid_hi)
267{
268 WFC_IPC_MSG_SS_CREATE_INFO_T msg;
269 VCOS_STATUS_T status;
270 WFCNativeStreamType result = WFC_INVALID_HANDLE;
271 size_t result_len = sizeof(result);
272
273 vcos_log_trace("%s: stream 0x%x flags 0x%x pid 0x%x%08x", VCOS_FUNCTION, stream, flags, pid_hi, pid_lo);
274
275 msg.header.type = WFC_IPC_MSG_SS_CREATE_INFO;
276 msg.stream = stream;
277 memset(&msg.info, 0, sizeof(msg.info));
278 msg.info.size = sizeof(msg.info);
279 msg.info.flags = flags;
280 msg.pid_lo = pid_lo;
281 msg.pid_hi = pid_hi;
282
283 status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len);
284
285 vcos_log_trace("%s: status 0x%x, result 0x%x", VCOS_FUNCTION, status, result);
286
287 if (status != VCOS_SUCCESS)
288 result = WFC_INVALID_HANDLE;
289
290 return result;
291}
292
293/* ------------------------------------------------------------------------- */
294
295WFCNativeStreamType wfc_server_stream_create_info(WFCNativeStreamType stream, const WFC_STREAM_INFO_T *info, uint32_t pid_lo, uint32_t pid_hi)
296{
297 WFC_IPC_MSG_SS_CREATE_INFO_T msg;
298 uint32_t copy_size;
299 VCOS_STATUS_T status;
300 WFCNativeStreamType result = WFC_INVALID_HANDLE;
301 size_t result_len = sizeof(result);
302
303 if (!info)
304 {
305 vcos_log_error("%s: NULL info pointer passed", VCOS_FUNCTION);
306 return WFC_INVALID_HANDLE;
307 }
308
309 if (info->size < sizeof(uint32_t))
310 {
311 vcos_log_error("%s: invalid info pointer passed (size:%u)", VCOS_FUNCTION, info->size);
312 return WFC_INVALID_HANDLE;
313 }
314
315 vcos_log_trace("%s: stream 0x%x flags 0x%x pid 0x%x%08x", VCOS_FUNCTION, stream, info->flags, pid_hi, pid_lo);
316
317 msg.header.type = WFC_IPC_MSG_SS_CREATE_INFO;
318 msg.stream = stream;
319 copy_size = vcos_min(info->size, sizeof(msg.info));
320 memcpy(&msg.info, info, copy_size);
321 msg.info.size = copy_size;
322 msg.pid_lo = pid_lo;
323 msg.pid_hi = pid_hi;
324
325 status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len);
326
327 vcos_log_trace("%s: status 0x%x, result 0x%x", VCOS_FUNCTION, status, result);
328
329 if (status != VCOS_SUCCESS)
330 result = WFC_INVALID_HANDLE;
331
332 return result;
333}
334
335/* ------------------------------------------------------------------------- */
336
337void wfc_server_stream_destroy(WFCNativeStreamType stream, uint32_t pid_lo, uint32_t pid_hi)
338{
339 WFC_IPC_MSG_SS_DESTROY_T msg;
340 VCOS_STATUS_T status;
341
342 vcos_log_trace("%s: stream 0x%x", VCOS_FUNCTION, stream);
343
344 msg.header.type = WFC_IPC_MSG_SS_DESTROY;
345 msg.stream = stream;
346 msg.pid_lo = pid_lo;
347 msg.pid_hi = pid_hi;
348
349 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
350
351 vcos_assert(status == VCOS_SUCCESS);
352}
353
354/* ------------------------------------------------------------------------- */
355
356void wfc_server_stream_on_rects_change(WFCNativeStreamType stream, WFC_CALLBACK_T rects_change_cb, void *rects_change_data)
357{
358 WFC_IPC_MSG_SS_ON_RECTS_CHANGE_T msg;
359 VCOS_STATUS_T status;
360
361 vcos_log_trace("%s: stream 0x%x cb %p data %p", VCOS_FUNCTION, stream, rects_change_cb, rects_change_data);
362
363 msg.header.type = WFC_IPC_MSG_SS_ON_RECTS_CHANGE;
364 msg.stream = stream;
365 msg.rects_change_cb.ptr = rects_change_cb;
366 msg.rects_change_data.ptr = rects_change_data;
367
368 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
369
370 if (!vcos_verify(status == VCOS_SUCCESS))
371 {
372 (*rects_change_cb)(rects_change_data);
373 }
374}
375
376/* ------------------------------------------------------------------------- */
377
378uint32_t wfc_server_stream_get_rects(WFCNativeStreamType stream, int32_t rects[WFC_SERVER_STREAM_RECTS_SIZE])
379{
380 uint32_t result;
381 VCOS_STATUS_T status;
382 WFC_IPC_MSG_SS_GET_RECTS_T reply;
383 size_t rects_len = sizeof(reply) - sizeof(WFC_IPC_MSG_HEADER_T);
384
385 vcos_log_trace("%s: stream 0x%x", VCOS_FUNCTION, stream);
386 memset(&reply, 0, sizeof(reply));
387 status = wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_SS_GET_RECTS, stream, &reply.result, &rects_len);
388
389 if (status == VCOS_SUCCESS)
390 {
391 result = reply.result;
392
393 if (result == VCOS_SUCCESS)
394 {
395 memcpy(rects, reply.rects, WFC_SERVER_STREAM_RECTS_SIZE * sizeof(*rects));
396 vcos_log_trace("%s: rects (%d,%d,%d,%d) (%d,%d,%d,%d)", VCOS_FUNCTION,
397 rects[0], rects[1], rects[2], rects[3], rects[4], rects[5], rects[6], rects[7]);
398 }
399 else
400 {
401 vcos_log_error("%s: result %d", VCOS_FUNCTION, result);
402 }
403 }
404 else
405 {
406 vcos_log_error("%s: send msg status %d", VCOS_FUNCTION, status);
407 result = status;
408 }
409
410 return result;
411}
412
413/* ------------------------------------------------------------------------- */
414
415bool wfc_server_stream_is_in_use(WFCNativeStreamType stream)
416{
417 VCOS_STATUS_T status;
418 uint32_t result = 0;
419 size_t result_len = sizeof(result);
420
421 vcos_log_trace("%s: stream 0x%x", VCOS_FUNCTION, stream);
422
423 status = wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_SS_IS_IN_USE, stream, &result, &result_len);
424
425 vcos_log_trace("%s: status 0x%x, result %u", VCOS_FUNCTION, status, result);
426
427 if (status != VCOS_SUCCESS)
428 result = 0;
429
430 return result != 0;
431}
432
433/* ------------------------------------------------------------------------- */
434
435bool wfc_server_stream_allocate_images(WFCNativeStreamType stream, uint32_t width, uint32_t height, uint32_t nbufs)
436{
437 WFC_IPC_MSG_SS_ALLOCATE_IMAGES_T msg;
438 VCOS_STATUS_T status;
439 uint32_t result = 0;
440 size_t result_len = sizeof(result);
441
442 vcos_log_trace("%s: stream 0x%x width %u height %u nbufs %u", VCOS_FUNCTION, stream, width, height, nbufs);
443
444 msg.header.type = WFC_IPC_MSG_SS_ALLOCATE_IMAGES;
445 msg.stream = stream;
446 msg.width = width;
447 msg.height = height;
448 msg.nbufs = nbufs;
449
450 status = wfc_client_ipc_sendwait(&msg.header, sizeof(msg), &result, &result_len);
451
452 vcos_log_trace("%s: status 0x%x result %u", VCOS_FUNCTION, status, result);
453
454 if (status != VCOS_SUCCESS)
455 result = 0;
456
457 return result;
458}
459
460/* ------------------------------------------------------------------------- */
461
462void wfc_server_stream_signal_eglimage_data(WFCNativeStreamType stream,
463 uint32_t ustorage, uint32_t width, uint32_t height, uint32_t stride,
464 uint32_t offset, uint32_t format, uint32_t flags, bool flip)
465{
466 WFC_IPC_MSG_SS_SIGNAL_EGLIMAGE_DATA_T msg;
467 VCOS_STATUS_T status;
468
469 memset(&msg, 0, sizeof msg);
470 msg.header.type = WFC_IPC_MSG_SS_SIGNAL_EGLIMAGE_DATA;
471 msg.stream = stream;
472 msg.ustorage = ustorage;
473 msg.width = width;
474 msg.height = height;
475 msg.stride = stride;
476 msg.offset = offset;
477 msg.format = format;
478 msg.flags = flags;
479 msg.flip = flip;
480
481 vcos_log_trace("%s: stream 0x%x image storage 0x%x",
482 VCOS_FUNCTION, stream, ustorage);
483
484 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
485
486 vcos_assert(status == VCOS_SUCCESS);
487}
488
489/* ------------------------------------------------------------------------- */
490
491void wfc_server_stream_signal_mm_image_data(WFCNativeStreamType stream, uint32_t image_handle)
492{
493 WFC_IPC_MSG_SS_SIGNAL_MM_IMAGE_DATA_T msg;
494 VCOS_STATUS_T status;
495
496 vcos_log_trace("%s: stream 0x%x image 0x%x", VCOS_FUNCTION, stream, image_handle);
497
498 msg.header.type = WFC_IPC_MSG_SS_SIGNAL_MM_IMAGE_DATA;
499 msg.stream = stream;
500 msg.image_handle = image_handle;
501
502 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
503
504 vcos_assert(status == VCOS_SUCCESS);
505}
506
507/* ------------------------------------------------------------------------- */
508
509void wfc_server_stream_signal_raw_pixels(WFCNativeStreamType stream,
510 uint32_t handle, uint32_t format, uint32_t width, uint32_t height,
511 uint32_t pitch, uint32_t vpitch)
512{
513 WFC_IPC_MSG_SS_SIGNAL_RAW_PIXELS_T msg;
514 VCOS_STATUS_T status;
515
516 vcos_log_trace("%s: stream 0x%x image 0x%x format 0x%x width %u height %u"
517 " pitch %u vpitch %u",
518 VCOS_FUNCTION, stream, handle, format, width, height, pitch, vpitch);
519
520 msg.header.type = WFC_IPC_MSG_SS_SIGNAL_RAW_PIXELS;
521 msg.stream = stream;
522 msg.handle = handle;
523 msg.format = format;
524 msg.width = width;
525 msg.height = height;
526 msg.pitch = pitch;
527 msg.vpitch = vpitch;
528
529 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
530 vcos_assert(status == VCOS_SUCCESS);
531}
532
533/* ------------------------------------------------------------------------- */
534void wfc_server_stream_signal_image(WFCNativeStreamType stream,
535 const WFC_STREAM_IMAGE_T *image)
536{
537 WFC_IPC_MSG_SS_SIGNAL_IMAGE_T msg;
538 VCOS_STATUS_T status;
539
540 vcos_log_trace("%s: stream 0x%x type 0x%x handle 0x%x "
541 " format 0x%x protection 0x%x width %u height %u "
542 " pitch %u vpitch %u",
543 VCOS_FUNCTION, stream, image->type, image->handle,
544 image->format, image->protection, image->width, image->height,
545 image->pitch, image->vpitch);
546
547 msg.header.type = WFC_IPC_MSG_SS_SIGNAL_IMAGE;
548 msg.stream = stream;
549 if vcos_verify(image->length <= sizeof(msg.image))
550 {
551 msg.image = *image;
552 }
553 else
554 {
555 /* Client is newer than VC ? */
556 memcpy(&msg.image, image, sizeof(msg.image));
557 msg.image.length = sizeof(msg.image);
558 }
559
560 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
561
562 vcos_assert(status == VCOS_SUCCESS);
563}
564
565/* ------------------------------------------------------------------------- */
566
567void wfc_server_stream_register(WFCNativeStreamType stream, uint32_t pid_lo, uint32_t pid_hi)
568{
569 WFC_IPC_MSG_SS_REGISTER_T msg;
570 VCOS_STATUS_T status;
571
572 vcos_log_trace("%s: stream 0x%x pid 0x%x%08x", VCOS_FUNCTION, stream, pid_hi, pid_lo);
573
574 msg.header.type = WFC_IPC_MSG_SS_REGISTER;
575 msg.stream = stream;
576 msg.pid_lo = pid_lo;
577 msg.pid_hi = pid_hi;
578
579 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
580
581 vcos_assert(status == VCOS_SUCCESS);
582}
583
584/* ------------------------------------------------------------------------- */
585
586void wfc_server_stream_unregister(WFCNativeStreamType stream, uint32_t pid_lo, uint32_t pid_hi)
587{
588 WFC_IPC_MSG_SS_UNREGISTER_T msg;
589 VCOS_STATUS_T status;
590
591 vcos_log_trace("%s: stream 0x%x pid 0x%x%08x", VCOS_FUNCTION, stream, pid_hi, pid_lo);
592
593 msg.header.type = WFC_IPC_MSG_SS_UNREGISTER;
594 msg.stream = stream;
595 msg.pid_lo = pid_lo;
596 msg.pid_hi = pid_hi;
597
598 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
599
600 vcos_assert(status == VCOS_SUCCESS);
601}
602
603/* ------------------------------------------------------------------------- */
604
605uint32_t wfc_server_stream_get_info(WFCNativeStreamType stream, WFC_STREAM_INFO_T *info)
606{
607 uint32_t result;
608 VCOS_STATUS_T status;
609 WFC_IPC_MSG_SS_GET_INFO_T reply;
610 size_t info_len = sizeof(reply) - sizeof(WFC_IPC_MSG_HEADER_T);
611
612 if (!info)
613 {
614 vcos_log_error("%s: NULL info pointer passed", VCOS_FUNCTION);
615 return WFC_INVALID_HANDLE;
616 }
617
618 if (info->size < sizeof(uint32_t))
619 {
620 vcos_log_error("%s: invalid info pointer passed (size:%u)", VCOS_FUNCTION, info->size);
621 return WFC_INVALID_HANDLE;
622 }
623
624 vcos_log_trace("%s: stream 0x%x", VCOS_FUNCTION, stream);
625 memset(&reply, 0, sizeof(reply));
626 status = wfc_client_server_api_sendwait_stream(WFC_IPC_MSG_SS_GET_INFO, stream, &reply.result, &info_len);
627
628 if (status == VCOS_SUCCESS)
629 {
630 result = reply.result;
631
632 if (result == VCOS_SUCCESS)
633 {
634 uint32_t copy_size = vcos_min(info->size, reply.info.size);
635 memcpy(info, &reply.info, copy_size);
636 info->size = copy_size;
637 vcos_log_trace("%s: copied %u bytes", VCOS_FUNCTION, copy_size);
638 }
639 else
640 {
641 vcos_log_error("%s: result %d", VCOS_FUNCTION, result);
642 }
643 }
644 else
645 {
646 vcos_log_error("%s: send msg status %d", VCOS_FUNCTION, status);
647 result = status;
648 }
649
650 return result;
651}
652
653/* ------------------------------------------------------------------------- */
654
655void wfc_server_stream_on_image_available(WFCNativeStreamType stream, WFC_CALLBACK_T image_available_cb, void *image_available_data)
656{
657 WFC_IPC_MSG_SS_ON_IMAGE_AVAILABLE_T msg;
658 VCOS_STATUS_T status;
659
660 vcos_log_trace("%s: stream 0x%x cb %p data %p", VCOS_FUNCTION, stream, image_available_cb, image_available_data);
661
662 msg.header.type = WFC_IPC_MSG_SS_ON_IMAGE_AVAILABLE;
663 msg.stream = stream;
664 msg.image_available_cb.ptr = image_available_cb;
665 msg.image_available_data.ptr = image_available_data;
666
667 status = wfc_client_ipc_send(&msg.header, sizeof(msg));
668
669 if (!vcos_verify(status == VCOS_SUCCESS))
670 {
671 (*image_available_cb)(image_available_data);
672 }
673}
674