1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, 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
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON 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
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "mmal.h"
29 #include "core/mmal_component_private.h"
30 #include "core/mmal_port_private.h"
31 #include "core/mmal_core_private.h"
32 #include "mmal_logging.h"
33
34 /* Minimum number of buffers that will be available on the control port */
35 #define MMAL_CONTROL_PORT_BUFFERS_MIN 4
36
37 /** Definition of the core private context. */
38 typedef struct
39 {
40 MMAL_COMPONENT_PRIVATE_T private;
41
42 /** Action registered by component and run when buffers are received by any of the ports */
43 void (*pf_action)(MMAL_COMPONENT_T *component);
44
45 /** Action thread */
46 VCOS_THREAD_T action_thread;
47 VCOS_SEMAPHORE_T action_sema;
48 VCOS_MUTEX_T action_mutex;
49 MMAL_BOOL_T action_quit;
50
51 VCOS_MUTEX_T lock; /**< Used to lock access to the component */
52 MMAL_BOOL_T destruction_pending;
53
54 } MMAL_COMPONENT_CORE_PRIVATE_T;
55
56 /*****************************************************************************/
57 static void mmal_core_init(void);
58 static void mmal_core_deinit(void);
59
60 static MMAL_STATUS_T mmal_component_supplier_create(const char *name, MMAL_COMPONENT_T *component);
61 static void mmal_component_init_control_port(MMAL_PORT_T *port);
62
63 static MMAL_STATUS_T mmal_component_destroy_internal(MMAL_COMPONENT_T *component);
64 static MMAL_STATUS_T mmal_component_release_internal(MMAL_COMPONENT_T *component);
65
66 /*****************************************************************************/
67 static VCOS_MUTEX_T mmal_core_lock;
68 /** Used to generate a unique id for each MMAL component in this context. */
69 static unsigned int mmal_core_instance_count;
70 static unsigned int mmal_core_refcount;
71 /*****************************************************************************/
72
73 /** Create an instance of a component */
mmal_component_create_core(const char * name,MMAL_STATUS_T (* constructor)(const char * name,MMAL_COMPONENT_T *),struct MMAL_COMPONENT_MODULE_T * constructor_private,MMAL_COMPONENT_T ** component)74 static MMAL_STATUS_T mmal_component_create_core(const char *name,
75 MMAL_STATUS_T (*constructor)(const char *name, MMAL_COMPONENT_T *),
76 struct MMAL_COMPONENT_MODULE_T *constructor_private,
77 MMAL_COMPONENT_T **component)
78 {
79 MMAL_COMPONENT_CORE_PRIVATE_T *private;
80 MMAL_STATUS_T status = MMAL_ENOMEM;
81 unsigned int size = sizeof(MMAL_COMPONENT_T) + sizeof(MMAL_COMPONENT_CORE_PRIVATE_T);
82 unsigned int i, name_length = strlen(name) + 1;
83 unsigned int port_index;
84 char *component_name;
85
86 if(!component)
87 return MMAL_EINVAL;
88
89 mmal_core_init();
90
91 *component = vcos_calloc(1, size + name_length, "mmal component");
92 if(!*component)
93 return MMAL_ENOMEM;
94
95 private = (MMAL_COMPONENT_CORE_PRIVATE_T *)&(*component)[1];
96 (*component)->priv = (MMAL_COMPONENT_PRIVATE_T *)private;
97 (*component)->name = component_name= (char *)&((MMAL_COMPONENT_CORE_PRIVATE_T *)(*component)->priv)[1];
98 memcpy(component_name, name, name_length);
99 (*component)->priv->refcount = 1;
100 (*component)->priv->priority = VCOS_THREAD_PRI_NORMAL;
101
102 if(vcos_mutex_create(&private->lock, "mmal component lock") != VCOS_SUCCESS)
103 {
104 vcos_free(*component);
105 return MMAL_ENOMEM;
106 }
107
108 vcos_mutex_lock(&mmal_core_lock);
109 (*component)->id=mmal_core_instance_count++;
110 vcos_mutex_unlock(&mmal_core_lock);
111
112 /* Create the control port */
113 (*component)->control = mmal_port_alloc(*component, MMAL_PORT_TYPE_CONTROL, 0);
114 if(!(*component)->control)
115 goto error;
116 mmal_component_init_control_port((*component)->control);
117
118 /* Create the actual component */
119 (*component)->priv->module = constructor_private;
120 if (!constructor)
121 constructor = mmal_component_supplier_create;
122 status = constructor(name, *component);
123 if (status != MMAL_SUCCESS)
124 {
125 if (status == MMAL_ENOSYS)
126 LOG_ERROR("could not find component '%s'", name);
127 else
128 LOG_ERROR("could not create component '%s' (%i)", name, status);
129 goto error;
130 }
131
132 /* Make sure we have enough space for at least a MMAL_EVENT_FORMAT_CHANGED */
133 if ((*component)->control->buffer_size_min <
134 sizeof(MMAL_ES_FORMAT_T) + sizeof(MMAL_ES_SPECIFIC_FORMAT_T) + sizeof(MMAL_EVENT_FORMAT_CHANGED_T))
135 (*component)->control->buffer_size_min = sizeof(MMAL_ES_FORMAT_T) +
136 sizeof(MMAL_ES_SPECIFIC_FORMAT_T) + sizeof(MMAL_EVENT_FORMAT_CHANGED_T);
137 /* Make sure we have enough events */
138 if ((*component)->control->buffer_num_min < MMAL_CONTROL_PORT_BUFFERS_MIN)
139 (*component)->control->buffer_num_min = MMAL_CONTROL_PORT_BUFFERS_MIN;
140
141 /* Create the event pool */
142 (*component)->priv->event_pool = mmal_pool_create((*component)->control->buffer_num_min,
143 (*component)->control->buffer_size_min);
144 if (!(*component)->priv->event_pool)
145 {
146 status = MMAL_ENOMEM;
147 LOG_ERROR("could not create event pool (%d, %d)", (*component)->control->buffer_num_min,
148 (*component)->control->buffer_size_min);
149 goto error;
150 }
151
152 /* Build the list of all the ports */
153 (*component)->port_num = (*component)->input_num + (*component)->output_num + (*component)->clock_num + 1;
154 (*component)->port = vcos_malloc((*component)->port_num * sizeof(MMAL_PORT_T *), "mmal ports");
155 if (!(*component)->port)
156 {
157 status = MMAL_ENOMEM;
158 LOG_ERROR("could not create list of ports");
159 goto error;
160 }
161 port_index = 0;
162 (*component)->port[port_index++] = (*component)->control;
163 for (i = 0; i < (*component)->input_num; i++)
164 (*component)->port[port_index++] = (*component)->input[i];
165 for (i = 0; i < (*component)->output_num; i++)
166 (*component)->port[port_index++] = (*component)->output[i];
167 for (i = 0; i < (*component)->clock_num; i++)
168 (*component)->port[port_index++] = (*component)->clock[i];
169 for (i = 0; i < (*component)->port_num; i++)
170 (*component)->port[i]->index_all = i;
171
172 LOG_INFO("created '%s' %d %p", name, (*component)->id, *component);
173
174 /* Make sure the port types, indexes and buffer sizes are set correctly */
175 (*component)->control->type = MMAL_PORT_TYPE_CONTROL;
176 (*component)->control->index = 0;
177 for (i = 0; i < (*component)->input_num; i++)
178 {
179 MMAL_PORT_T *port = (*component)->input[i];
180 port->type = MMAL_PORT_TYPE_INPUT;
181 port->index = i;
182 }
183 for (i = 0; i < (*component)->output_num; i++)
184 {
185 MMAL_PORT_T *port = (*component)->output[i];
186 port->type = MMAL_PORT_TYPE_OUTPUT;
187 port->index = i;
188 }
189 for (i = 0; i < (*component)->clock_num; i++)
190 {
191 MMAL_PORT_T *port = (*component)->clock[i];
192 port->type = MMAL_PORT_TYPE_CLOCK;
193 port->index = i;
194 }
195 for (i = 0; i < (*component)->port_num; i++)
196 {
197 MMAL_PORT_T *port = (*component)->port[i];
198 if (port->buffer_size < port->buffer_size_min)
199 port->buffer_size = port->buffer_size_min;
200 if (port->buffer_num < port->buffer_num_min)
201 port->buffer_num = port->buffer_num_min;
202 }
203
204 return MMAL_SUCCESS;
205
206 error:
207 mmal_component_destroy_internal(*component);
208 *component = 0;
209 return status;
210 }
211
212 /** Create an instance of a component */
mmal_component_create(const char * name,MMAL_COMPONENT_T ** component)213 MMAL_STATUS_T mmal_component_create(const char *name,
214 MMAL_COMPONENT_T **component)
215 {
216 LOG_TRACE("%s", name);
217 return mmal_component_create_core(name, 0, 0, component);
218 }
219
220 /** Create an instance of a component */
mmal_component_create_with_constructor(const char * name,MMAL_STATUS_T (* constructor)(const char * name,MMAL_COMPONENT_T *),struct MMAL_COMPONENT_MODULE_T * constructor_private,MMAL_COMPONENT_T ** component)221 MMAL_STATUS_T mmal_component_create_with_constructor(const char *name,
222 MMAL_STATUS_T (*constructor)(const char *name, MMAL_COMPONENT_T *),
223 struct MMAL_COMPONENT_MODULE_T *constructor_private,
224 MMAL_COMPONENT_T **component)
225 {
226 LOG_TRACE("%s", name);
227 return mmal_component_create_core(name, constructor, constructor_private, component);
228 }
229
230 /** Destroy a previously created component */
mmal_component_destroy_internal(MMAL_COMPONENT_T * component)231 static MMAL_STATUS_T mmal_component_destroy_internal(MMAL_COMPONENT_T *component)
232 {
233 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
234 MMAL_STATUS_T status;
235
236 LOG_TRACE("%s %d", component->name, component->id);
237
238 mmal_component_action_deregister(component);
239
240 /* Should pf_destroy be allowed to fail ?
241 * If so, what do we do if it fails ?
242 */
243 if (component->priv->pf_destroy)
244 {
245 status = component->priv->pf_destroy(component);
246 if(!vcos_verify(status == MMAL_SUCCESS))
247 return status;
248 }
249
250 if (component->priv->event_pool)
251 mmal_pool_destroy(component->priv->event_pool);
252
253 if (component->control)
254 mmal_port_free(component->control);
255
256 if (component->port)
257 vcos_free(component->port);
258
259 vcos_mutex_delete(&private->lock);
260 vcos_free(component);
261 mmal_core_deinit();
262 return MMAL_SUCCESS;
263 }
264
265 /** Release a reference to a component */
mmal_component_release_internal(MMAL_COMPONENT_T * component)266 static MMAL_STATUS_T mmal_component_release_internal(MMAL_COMPONENT_T *component)
267 {
268 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
269 unsigned int i;
270
271 if (!vcos_verify(component->priv->refcount > 0))
272 return MMAL_EINVAL;
273
274 vcos_mutex_lock(&private->lock);
275 if (--component->priv->refcount)
276 {
277 vcos_mutex_unlock(&private->lock);
278 return MMAL_SUCCESS;
279 }
280 private->destruction_pending = 1;
281 vcos_mutex_unlock(&private->lock);
282
283 LOG_TRACE("%s %d preparing for destruction", component->name, component->id);
284
285 /* Make sure the ports are all disabled */
286 for(i = 0; i < component->input_num; i++)
287 if(component->input[i]->is_enabled)
288 mmal_port_disable(component->input[i]);
289 for(i = 0; i < component->output_num; i++)
290 if(component->output[i]->is_enabled)
291 mmal_port_disable(component->output[i]);
292 for(i = 0; i < component->clock_num; i++)
293 if(component->clock[i]->is_enabled)
294 mmal_port_disable(component->clock[i]);
295 if(component->control->is_enabled)
296 mmal_port_disable(component->control);
297
298 /* Make sure all the ports are disconnected. This is necessary to prevent
299 * connected ports from referencing destroyed components */
300 for(i = 0; i < component->input_num; i++)
301 mmal_port_disconnect(component->input[i]);
302 for(i = 0; i < component->output_num; i++)
303 mmal_port_disconnect(component->output[i]);
304 for(i = 0; i < component->clock_num; i++)
305 mmal_port_disconnect(component->clock[i]);
306
307 /* If there is any reference pending on the ports we will delay the actual destruction */
308 vcos_mutex_lock(&private->lock);
309 if (component->priv->refcount_ports)
310 {
311 private->destruction_pending = 0;
312 vcos_mutex_unlock(&private->lock);
313 LOG_TRACE("%s %d delaying destruction", component->name, component->id);
314 return MMAL_SUCCESS;
315 }
316 vcos_mutex_unlock(&private->lock);
317
318 return mmal_component_destroy_internal(component);
319 }
320
321 /** Destroy a component */
mmal_component_destroy(MMAL_COMPONENT_T * component)322 MMAL_STATUS_T mmal_component_destroy(MMAL_COMPONENT_T *component)
323 {
324 if(!component)
325 return MMAL_EINVAL;
326
327 LOG_TRACE("%s %d", component->name, component->id);
328
329 return mmal_component_release_internal(component);
330 }
331
332 /** Acquire a reference to a component */
mmal_component_acquire(MMAL_COMPONENT_T * component)333 void mmal_component_acquire(MMAL_COMPONENT_T *component)
334 {
335 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
336
337 LOG_TRACE("component %s(%d), refcount %i", component->name, component->id,
338 component->priv->refcount);
339
340 vcos_mutex_lock(&private->lock);
341 component->priv->refcount++;
342 vcos_mutex_unlock(&private->lock);
343 }
344
345 /** Release a reference to a component */
mmal_component_release(MMAL_COMPONENT_T * component)346 MMAL_STATUS_T mmal_component_release(MMAL_COMPONENT_T *component)
347 {
348 if(!component)
349 return MMAL_EINVAL;
350
351 LOG_TRACE("component %s(%d), refcount %i", component->name, component->id,
352 component->priv->refcount);
353
354 return mmal_component_release_internal(component);
355 }
356
357 /** Enable processing on a component */
mmal_component_enable(MMAL_COMPONENT_T * component)358 MMAL_STATUS_T mmal_component_enable(MMAL_COMPONENT_T *component)
359 {
360 MMAL_COMPONENT_CORE_PRIVATE_T *private;
361 MMAL_STATUS_T status;
362 unsigned int i;
363
364 if(!component)
365 return MMAL_EINVAL;
366
367 private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
368
369 LOG_TRACE("%s %d", component->name, component->id);
370
371 vcos_mutex_lock(&private->lock);
372
373 /* Check we have anything to do */
374 if (component->is_enabled)
375 {
376 vcos_mutex_unlock(&private->lock);
377 return MMAL_SUCCESS;
378 }
379
380 status = component->priv->pf_enable(component);
381
382 /* Resume all input / output ports */
383 for (i = 0; status == MMAL_SUCCESS && i < component->input_num; i++)
384 status = mmal_port_pause(component->input[i], MMAL_FALSE);
385 for (i = 0; status == MMAL_SUCCESS && i < component->output_num; i++)
386 status = mmal_port_pause(component->output[i], MMAL_FALSE);
387
388 if (status == MMAL_SUCCESS)
389 component->is_enabled = 1;
390
391 vcos_mutex_unlock(&private->lock);
392
393 return status;
394 }
395
396 /** Disable processing on a component */
mmal_component_disable(MMAL_COMPONENT_T * component)397 MMAL_STATUS_T mmal_component_disable(MMAL_COMPONENT_T *component)
398 {
399 MMAL_COMPONENT_CORE_PRIVATE_T *private;
400 MMAL_STATUS_T status;
401 unsigned int i;
402
403 if (!component)
404 return MMAL_EINVAL;
405
406 private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
407
408 LOG_TRACE("%s %d", component->name, component->id);
409
410 vcos_mutex_lock(&private->lock);
411
412 /* Check we have anything to do */
413 if (!component->is_enabled)
414 {
415 vcos_mutex_unlock(&private->lock);
416 return MMAL_SUCCESS;
417 }
418
419 status = component->priv->pf_disable(component);
420
421 /* Pause all input / output ports */
422 for (i = 0; status == MMAL_SUCCESS && i < component->input_num; i++)
423 status = mmal_port_pause(component->input[i], MMAL_TRUE);
424 for (i = 0; status == MMAL_SUCCESS && i < component->output_num; i++)
425 status = mmal_port_pause(component->output[i], MMAL_TRUE);
426
427 if (status == MMAL_SUCCESS)
428 component->is_enabled = 0;
429
430 vcos_mutex_unlock(&private->lock);
431
432 return status;
433 }
434
mmal_component_enable_control_port(MMAL_PORT_T * port,MMAL_PORT_BH_CB_T cb)435 static MMAL_STATUS_T mmal_component_enable_control_port(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
436 {
437 (void)port;
438 (void)cb;
439 return MMAL_SUCCESS;
440 }
441
mmal_component_disable_control_port(MMAL_PORT_T * port)442 static MMAL_STATUS_T mmal_component_disable_control_port(MMAL_PORT_T *port)
443 {
444 (void)port;
445 return MMAL_SUCCESS;
446 }
447
mmal_component_parameter_set(MMAL_PORT_T * control_port,const MMAL_PARAMETER_HEADER_T * param)448 MMAL_STATUS_T mmal_component_parameter_set(MMAL_PORT_T *control_port,
449 const MMAL_PARAMETER_HEADER_T *param)
450 {
451 (void)control_port;
452 (void)param;
453 /* No generic component control parameters */
454 LOG_ERROR("parameter id 0x%08x not supported", param->id);
455 return MMAL_ENOSYS;
456 }
457
mmal_component_parameter_get(MMAL_PORT_T * control_port,MMAL_PARAMETER_HEADER_T * param)458 MMAL_STATUS_T mmal_component_parameter_get(MMAL_PORT_T *control_port,
459 MMAL_PARAMETER_HEADER_T *param)
460 {
461 (void)control_port;
462 (void)param;
463 /* No generic component control parameters */
464 LOG_ERROR("parameter id 0x%08x not supported", param->id);
465 return MMAL_ENOSYS;
466 }
467
mmal_component_init_control_port(MMAL_PORT_T * port)468 static void mmal_component_init_control_port(MMAL_PORT_T *port)
469 {
470 port->format->type = MMAL_ES_TYPE_CONTROL;
471 port->buffer_num_min = MMAL_CONTROL_PORT_BUFFERS_MIN;
472 port->buffer_num = port->buffer_num_min;
473 port->buffer_size_min = sizeof(MMAL_ES_FORMAT_T) + sizeof(MMAL_ES_SPECIFIC_FORMAT_T);
474 port->buffer_size = port->buffer_size_min;
475
476 /* Default to generic handling */
477 port->priv->pf_enable = mmal_component_enable_control_port;
478 port->priv->pf_disable = mmal_component_disable_control_port;
479 port->priv->pf_parameter_set = mmal_component_parameter_set;
480 port->priv->pf_parameter_get = mmal_component_parameter_get;
481 /* No pf_set_format - format of control port cannot be changed */
482 /* No pf_send - buffers cannot be sent to control port */
483 }
484
485 /** Acquire a reference on a port */
mmal_port_acquire(MMAL_PORT_T * port)486 void mmal_port_acquire(MMAL_PORT_T *port)
487 {
488 MMAL_COMPONENT_T *component = port->component;
489 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
490
491 LOG_TRACE("port %s(%p), refcount %i", port->name, port,
492 component->priv->refcount_ports);
493
494 vcos_mutex_lock(&private->lock);
495 component->priv->refcount_ports++;
496 vcos_mutex_unlock(&private->lock);
497 }
498
499 /** Release a reference on a port */
mmal_port_release(MMAL_PORT_T * port)500 MMAL_STATUS_T mmal_port_release(MMAL_PORT_T *port)
501 {
502 MMAL_COMPONENT_T *component = port->component;
503 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
504
505 LOG_TRACE("port %s(%p), refcount %i", port->name, port,
506 component->priv->refcount_ports);
507
508 /* Sanity check the refcount */
509 if (!vcos_verify(component->priv->refcount_ports > 0))
510 return MMAL_EINVAL;
511
512 vcos_mutex_lock(&private->lock);
513 if (--component->priv->refcount_ports ||
514 component->priv->refcount || private->destruction_pending)
515 {
516 vcos_mutex_unlock(&private->lock);
517 return MMAL_SUCCESS;
518 }
519 vcos_mutex_unlock(&private->lock);
520
521 return mmal_component_destroy_internal(component);
522 }
523
524 /*****************************************************************************
525 * Actions support
526 *****************************************************************************/
527
528 /** Registers an action with the core */
mmal_component_action_thread_func(void * arg)529 static void *mmal_component_action_thread_func(void *arg)
530 {
531 MMAL_COMPONENT_T *component = (MMAL_COMPONENT_T *)arg;
532 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
533 VCOS_STATUS_T status;
534
535 while (1)
536 {
537 status = vcos_semaphore_wait(&private->action_sema);
538
539 if (status == VCOS_EAGAIN)
540 continue;
541 if (private->action_quit)
542 break;
543 if (!vcos_verify(status == VCOS_SUCCESS))
544 break;
545
546 vcos_mutex_lock(&private->action_mutex);
547 private->pf_action(component);
548 vcos_mutex_unlock(&private->action_mutex);
549 }
550 return 0;
551 }
552
553 /** Registers an action with the core */
mmal_component_action_register(MMAL_COMPONENT_T * component,void (* pf_action)(MMAL_COMPONENT_T *))554 MMAL_STATUS_T mmal_component_action_register(MMAL_COMPONENT_T *component,
555 void (*pf_action)(MMAL_COMPONENT_T *) )
556 {
557 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
558 VCOS_THREAD_ATTR_T attrs;
559 VCOS_STATUS_T status;
560
561 if (private->pf_action)
562 return MMAL_EINVAL;
563
564 status = vcos_semaphore_create(&private->action_sema, component->name, 0);
565 if (status != VCOS_SUCCESS)
566 return MMAL_ENOMEM;
567
568 status = vcos_mutex_create(&private->action_mutex, component->name);
569 if (status != VCOS_SUCCESS)
570 {
571 vcos_semaphore_delete(&private->action_sema);
572 return MMAL_ENOMEM;
573 }
574
575 vcos_thread_attr_init(&attrs);
576 vcos_thread_attr_setpriority(&attrs,
577 private->private.priority);
578 status = vcos_thread_create(&private->action_thread, component->name, &attrs,
579 mmal_component_action_thread_func, component);
580 if (status != VCOS_SUCCESS)
581 {
582 vcos_mutex_delete(&private->action_mutex);
583 vcos_semaphore_delete(&private->action_sema);
584 return MMAL_ENOMEM;
585 }
586
587 private->pf_action = pf_action;
588 return MMAL_SUCCESS;
589 }
590
591 /** De-registers the current action with the core */
mmal_component_action_deregister(MMAL_COMPONENT_T * component)592 MMAL_STATUS_T mmal_component_action_deregister(MMAL_COMPONENT_T *component)
593 {
594 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
595
596 if (!private->pf_action)
597 return MMAL_EINVAL;
598
599 private->action_quit = 1;
600 vcos_semaphore_post(&private->action_sema);
601 vcos_thread_join(&private->action_thread, NULL);
602 vcos_semaphore_delete(&private->action_sema);
603 vcos_mutex_delete(&private->action_mutex);
604 private->pf_action = NULL;
605 private->action_quit = 0;
606 return MMAL_SUCCESS;
607 }
608
609 /** Triggers a registered action */
mmal_component_action_trigger(MMAL_COMPONENT_T * component)610 MMAL_STATUS_T mmal_component_action_trigger(MMAL_COMPONENT_T *component)
611 {
612 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
613
614 if (!private->pf_action)
615 return MMAL_EINVAL;
616
617 vcos_semaphore_post(&private->action_sema);
618 return MMAL_SUCCESS;
619 }
620
621 /** Lock an action to prevent it from running */
mmal_component_action_lock(MMAL_COMPONENT_T * component)622 MMAL_STATUS_T mmal_component_action_lock(MMAL_COMPONENT_T *component)
623 {
624 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
625
626 if (!private->pf_action)
627 return MMAL_EINVAL;
628
629 vcos_mutex_lock(&private->action_mutex);
630 return MMAL_SUCCESS;
631 }
632
633 /** Unlock an action to allow it to run again */
mmal_component_action_unlock(MMAL_COMPONENT_T * component)634 MMAL_STATUS_T mmal_component_action_unlock(MMAL_COMPONENT_T *component)
635 {
636 MMAL_COMPONENT_CORE_PRIVATE_T *private = (MMAL_COMPONENT_CORE_PRIVATE_T *)component->priv;
637
638 if (!private->pf_action)
639 return MMAL_EINVAL;
640
641 vcos_mutex_unlock(&private->action_mutex);
642 return MMAL_SUCCESS;
643 }
644
645 /*****************************************************************************
646 * Initialisation / Deinitialisation of the MMAL core
647 *****************************************************************************/
mmal_core_init_once(void)648 static void mmal_core_init_once(void)
649 {
650 vcos_mutex_create(&mmal_core_lock, VCOS_FUNCTION);
651 }
652
mmal_core_init(void)653 static void mmal_core_init(void)
654 {
655 static VCOS_ONCE_T once = VCOS_ONCE_INIT;
656 vcos_init();
657 vcos_once(&once, mmal_core_init_once);
658
659 vcos_mutex_lock(&mmal_core_lock);
660 if (mmal_core_refcount++)
661 {
662 vcos_mutex_unlock(&mmal_core_lock);
663 return;
664 }
665
666 mmal_logging_init();
667 vcos_mutex_unlock(&mmal_core_lock);
668 }
669
mmal_core_deinit(void)670 static void mmal_core_deinit(void)
671 {
672 vcos_mutex_lock(&mmal_core_lock);
673 if (!mmal_core_refcount || --mmal_core_refcount)
674 {
675 vcos_mutex_unlock(&mmal_core_lock);
676 return;
677 }
678
679 mmal_logging_deinit();
680 vcos_mutex_unlock(&mmal_core_lock);
681 vcos_deinit();
682 }
683
684 /*****************************************************************************
685 * Supplier support
686 *****************************************************************************/
687
688 /** a component supplier gets passed a string and returns a
689 * component (if it can) based on that string.
690 */
691
692 #define SUPPLIER_PREFIX_LEN 32
693 typedef struct MMAL_COMPONENT_SUPPLIER_T
694 {
695 struct MMAL_COMPONENT_SUPPLIER_T *next;
696 MMAL_COMPONENT_SUPPLIER_FUNCTION_T create;
697 char prefix[SUPPLIER_PREFIX_LEN];
698 } MMAL_COMPONENT_SUPPLIER_T;
699
700 /** List of component suppliers.
701 *
702 * Does not need to be thread-safe if we assume that suppliers
703 * can never be removed.
704 */
705 static MMAL_COMPONENT_SUPPLIER_T *suppliers;
706
707 /** Create an instance of a component */
mmal_component_supplier_create(const char * name,MMAL_COMPONENT_T * component)708 static MMAL_STATUS_T mmal_component_supplier_create(const char *name, MMAL_COMPONENT_T *component)
709 {
710 MMAL_COMPONENT_SUPPLIER_T *supplier = suppliers;
711 MMAL_STATUS_T status = MMAL_ENOSYS;
712 const char *dot = strchr(name, '.');
713 size_t dot_size = dot ? dot - name : (int)strlen(name);
714
715 /* walk list of suppliers to see if any can create this component */
716 while (supplier)
717 {
718 if (strlen(supplier->prefix) == dot_size && !memcmp(supplier->prefix, name, dot_size))
719 {
720 status = supplier->create(name, component);
721 if (status == MMAL_SUCCESS)
722 break;
723 }
724 supplier = supplier->next;
725 }
726 return status;
727 }
728
mmal_component_supplier_register(const char * prefix,MMAL_COMPONENT_SUPPLIER_FUNCTION_T create_fn)729 void mmal_component_supplier_register(const char *prefix,
730 MMAL_COMPONENT_SUPPLIER_FUNCTION_T create_fn)
731 {
732 MMAL_COMPONENT_SUPPLIER_T *supplier = vcos_calloc(1,sizeof(*supplier),NULL);
733
734 LOG_TRACE("prefix %s fn %p", (prefix ? prefix : "NULL"), create_fn);
735
736 if (vcos_verify(supplier))
737 {
738 supplier->create = create_fn;
739 strncpy(supplier->prefix, prefix, SUPPLIER_PREFIX_LEN);
740 supplier->prefix[SUPPLIER_PREFIX_LEN-1] = '\0';
741
742 supplier->next = suppliers;
743 suppliers = supplier;
744 }
745 else
746 {
747 LOG_ERROR("no memory for supplier registry entry");
748 }
749 }
750
751 MMAL_DESTRUCTOR(mmal_component_supplier_destructor);
mmal_component_supplier_destructor(void)752 void mmal_component_supplier_destructor(void)
753 {
754 MMAL_COMPONENT_SUPPLIER_T *supplier = suppliers;
755
756 /* walk list of suppliers and free associated memory */
757 while (supplier)
758 {
759 MMAL_COMPONENT_SUPPLIER_T *current = supplier;
760 supplier = supplier->next;
761 vcos_free(current);
762 }
763 }
764