MMAL_BOOL_T mmal_port_is_connected(MMAL_PORT_T *port) { MMAL_PORT_PRIVATE_CORE_T *core; MMAL_PORT_T *connected_port; if (!port || !port->priv || !port->priv->core) return MMAL_FALSE; core = port->priv->core; LOCK_CONNECTION(port); connected_port = core->connected_port; UNLOCK_CONNECTION(port); return !!connected_port; }
/** Connect an output port to an input port. */ MMAL_STATUS_T mmal_port_connect(MMAL_PORT_T *port, MMAL_PORT_T *other_port) { MMAL_PORT_PRIVATE_CORE_T* core; MMAL_PORT_PRIVATE_CORE_T* other_core; MMAL_STATUS_T status = MMAL_SUCCESS; MMAL_PORT_T* output_port = NULL; if (!port || !port->priv || !other_port || !other_port->priv) { LOG_ERROR("invalid port"); return MMAL_EINVAL; } if ((port->type == MMAL_PORT_TYPE_CLOCK) && (port->type != other_port->type)) { LOG_ERROR("invalid port connection"); return MMAL_EINVAL; } LOG_TRACE("connecting %s(%p) to %s(%p)", port->name, port, other_port->name, other_port); if (!port->priv->pf_connect || !other_port->priv->pf_connect) { LOG_ERROR("at least one pf_connect is NULL"); return MMAL_ENOSYS; } core = port->priv->core; other_core = other_port->priv->core; LOCK_CONNECTION(port); if (core->connected_port) { LOG_ERROR("port %p is already connected", port); UNLOCK_CONNECTION(port); return MMAL_EISCONN; } if (port->is_enabled) { LOG_ERROR("port %p should not be enabled", port); UNLOCK_CONNECTION(port); return MMAL_EINVAL; } LOCK_CONNECTION(other_port); if (other_core->connected_port) { LOG_ERROR("port %p is already connected", other_port); status = MMAL_EISCONN; goto finish; } if (other_port->is_enabled) { LOG_ERROR("port %p should not be enabled", other_port); status = MMAL_EINVAL; goto finish; } core->connected_port = other_port; other_core->connected_port = port; core->core_owns_connection = 0; other_core->core_owns_connection = 0; /* Check to see if the port will manage the connection on its own. If not then the core * will manage it. */ output_port = port->type == MMAL_PORT_TYPE_OUTPUT ? port : other_port; if (output_port->priv->pf_connect(port, other_port) == MMAL_SUCCESS) goto finish; core->core_owns_connection = 1; other_core->core_owns_connection = 1; finish: UNLOCK_CONNECTION(other_port); UNLOCK_CONNECTION(port); return status; }
/** Disable processing on a port */ MMAL_STATUS_T mmal_port_disable(MMAL_PORT_T *port) { MMAL_STATUS_T status; MMAL_PORT_T *connected_port; MMAL_PORT_PRIVATE_CORE_T *core; if (!port || !port->priv) return MMAL_EINVAL; LOG_TRACE("%s(%i:%i) port %p", port->component->name, (int)port->type, (int)port->index, port); if (!port->priv->pf_disable) return MMAL_ENOSYS; core = port->priv->core; LOCK_CONNECTION(port); connected_port = core->connected_port; /* Sanity checking */ if (!port->is_enabled) { UNLOCK_CONNECTION(port); LOG_ERROR("port %s(%p) is not enabled", port->name, port); return MMAL_EINVAL; } if (connected_port) LOCK_CONNECTION(connected_port); /* Disable the output port of a connection first */ if (connected_port && connected_port->type != MMAL_PORT_TYPE_INPUT) { status = mmal_port_disable_internal(connected_port); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to disable connected port (%s)%p (%s)", connected_port->name, connected_port, mmal_status_to_string(status)); goto end; } } status = mmal_port_disable_internal(port); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to disable port (%s)%p", port->name, port); goto end; } /* Disable the input port of a connection last */ if (connected_port && connected_port->type == MMAL_PORT_TYPE_INPUT) { status = mmal_port_disable_internal(connected_port); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to disable connected port (%s)%p (%s)", connected_port->name, connected_port, mmal_status_to_string(status)); goto end; } } if (connected_port) { status = mmal_port_connection_disable(port, connected_port); if (status != MMAL_SUCCESS) LOG_ERROR("failed to disable connection (%s)%p (%s)", port->name, port, mmal_status_to_string(status)); } end: if (connected_port) UNLOCK_CONNECTION(connected_port); UNLOCK_CONNECTION(port); return status; }
/** Enable processing on a port */ MMAL_STATUS_T mmal_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb) { MMAL_STATUS_T status; MMAL_PORT_T *connected_port; MMAL_PORT_PRIVATE_CORE_T *core; if (!port || !port->priv) return MMAL_EINVAL; LOG_TRACE("%s port %p, cb %p, buffers (%i/%i/%i,%i/%i/%i)", port->name, port, cb, (int)port->buffer_num, (int)port->buffer_num_recommended, (int)port->buffer_num_min, (int)port->buffer_size, (int)port->buffer_size_recommended, (int)port->buffer_size_min); if (!port->priv->pf_enable) return MMAL_ENOSYS; core = port->priv->core; LOCK_CONNECTION(port); connected_port = core->connected_port; /* Sanity checking */ if (port->is_enabled) { UNLOCK_CONNECTION(port); LOG_ERROR("%s(%p) already enabled", port->name, port); return MMAL_EINVAL; } if (connected_port && cb) /* Callback must be NULL for connected ports */ { UNLOCK_CONNECTION(port); LOG_ERROR("callback (%p) not allowed for connected port (%s)%p", cb, port->name, connected_port); return MMAL_EINVAL; } /* Start by preparing the port connection so that everything is ready for when * both ports are enabled */ if (connected_port) { LOCK_CONNECTION(connected_port); status = mmal_port_connection_enable(port, connected_port); if (status != MMAL_SUCCESS) { UNLOCK_CONNECTION(connected_port); UNLOCK_CONNECTION(port); return status; } cb = connected_port->type == MMAL_PORT_TYPE_INPUT ? mmal_port_connected_output_cb : mmal_port_connected_input_cb; } /* Enable the input port of a connection first */ if (connected_port && connected_port->type == MMAL_PORT_TYPE_INPUT) { status = mmal_port_enable_internal(connected_port, mmal_port_connected_input_cb); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to enable connected port (%s)%p (%s)", connected_port->name, connected_port, mmal_status_to_string(status)); goto error; } } status = mmal_port_enable_internal(port, cb); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to enable port %s(%p) (%s)", port->name, port, mmal_status_to_string(status)); goto error; } /* Enable the output port of a connection last */ if (connected_port && connected_port->type != MMAL_PORT_TYPE_INPUT) { status = mmal_port_enable_internal(connected_port, mmal_port_connected_output_cb); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to enable connected port (%s)%p (%s)", connected_port->name, connected_port, mmal_status_to_string(status)); goto error; } } /* Kick off the connection */ if (connected_port && core->core_owns_connection) { status = mmal_port_connection_start(port, connected_port); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to start connection (%s)%p (%s)", port->name, port, mmal_status_to_string(status)); goto error; } } if (connected_port) UNLOCK_CONNECTION(connected_port); UNLOCK_CONNECTION(port); return MMAL_SUCCESS; error: if (connected_port && connected_port->is_enabled) mmal_port_disable_internal(connected_port); if (port->is_enabled) mmal_port_disable_internal(port); if (connected_port) mmal_port_connection_disable(port, connected_port); if (connected_port) UNLOCK_CONNECTION(connected_port); UNLOCK_CONNECTION(port); return status; }
/** Disconnect a connected port. */ MMAL_STATUS_T mmal_port_disconnect(MMAL_PORT_T *port) { MMAL_PORT_PRIVATE_CORE_T* core; MMAL_PORT_T* other_port; MMAL_STATUS_T status = MMAL_SUCCESS; if (!port || !port->priv) { LOG_ERROR("invalid port"); return MMAL_EINVAL; } LOG_TRACE("%s(%p)", port->name, port); LOCK_CONNECTION(port); core = port->priv->core; other_port = core->connected_port; if (!other_port) { UNLOCK_CONNECTION(port); LOG_DEBUG("%s(%p) is not connected", port->name, port); return MMAL_ENOTCONN; } LOCK_CONNECTION(other_port); /* Make sure the connection is disabled first */ if (port->is_enabled) { MMAL_PORT_T *output = port->type == MMAL_PORT_TYPE_OUTPUT ? port : other_port; MMAL_PORT_T *input = other_port->type == MMAL_PORT_TYPE_INPUT ? other_port : port; status = mmal_port_disable_internal(output); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to disable port (%s)%p", port->name, port); goto end; } status = mmal_port_disable_internal(input); if (status != MMAL_SUCCESS) { LOG_ERROR("failed to disable port (%s)%p", port->name, port); goto end; } status = mmal_port_connection_disable(port, other_port); } if (!core->core_owns_connection) { status = port->priv->pf_connect(port, NULL); if (status != MMAL_SUCCESS) { LOG_ERROR("disconnection of %s(%p) failed (%i)", port->name, port, status); goto end; } } core->connected_port = NULL; other_port->priv->core->connected_port = NULL; end: UNLOCK_CONNECTION(other_port); UNLOCK_CONNECTION(port); return status; }