Exemple #1
0
/** 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_PORT(port);

   core = port->priv->core;
   if (!core->connected_port)
   {
      UNLOCK_PORT(port);
      LOG_DEBUG("%s(%p) is not connected", port->name, port);
      return MMAL_ENOTCONN;
   }

   other_port = core->connected_port;

   if (port->is_enabled)
   {
      status = mmal_port_disable_locked(port);
      if (status != MMAL_SUCCESS)
      {
         LOG_ERROR("could not disable %s(%p) (%i)", port->name, port, status);
         goto finish;
      }

      if (port->priv->core->pool_for_connection)
         mmal_pool_destroy(port->priv->core->pool_for_connection);
      port->priv->core->pool_for_connection = NULL;
   }

   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 finish;
      }
   }

   core->connected_port = NULL;
   other_port->priv->core->connected_port = NULL;

finish:
   UNLOCK_PORT(port);
   return status;
}
Exemple #2
0
/** Allocate a payload buffer */
uint8_t *mmal_port_payload_alloc(MMAL_PORT_T *port, uint32_t payload_size)
{
   uint8_t *mem;

   if (!port || !port->priv)
      return NULL;

   LOG_TRACE("%s(%i:%i) port %p, size %i", port->component->name,
             (int)port->type, (int)port->index, port, (int)payload_size);

   if (!payload_size)
      return NULL;

   /* TODO: keep track of the allocs so we can free them when the component is destroyed */

   if (!port->priv->pf_payload_alloc)
   {
      /* Revert to using the heap */
      mem = vcos_malloc(payload_size, "mmal payload");
      goto end;
   }

   LOCK_PORT(port);
   mem = port->priv->pf_payload_alloc(port, payload_size);
   UNLOCK_PORT(port);

 end:
   /* Acquire the port if the allocation was successful.
    * This will ensure that the component is not destroyed until the payload has been freed. */
   if (mem)
      mmal_port_acquire(port);
   return mem;
}
Exemple #3
0
/** Free a payload buffer */
void mmal_port_payload_free(MMAL_PORT_T *port, uint8_t *payload)
{
   if (!port || !port->priv)
      return;

   LOG_TRACE("%s(%i:%i) port %p, payload %p", port->component->name,
             (int)port->type, (int)port->index, port, payload);

   if (!port->priv->pf_payload_alloc)
   {
      /* Revert to using the heap */
#ifdef _VIDEOCORE
      mem_release((MEM_HANDLE_T)payload);
#else
      vcos_free(payload);
#endif
      mmal_port_release(port);
      return;
   }

   LOCK_PORT(port);
   port->priv->pf_payload_free(port, payload);
   UNLOCK_PORT(port);
   mmal_port_release(port);
}
Exemple #4
0
/** Disable processing on a port */
MMAL_STATUS_T mmal_port_disable(MMAL_PORT_T *port)
{
   MMAL_POOL_T* pool = NULL;
   MMAL_STATUS_T status;

   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;

   LOCK_PORT(port);

   status = mmal_port_disable_locked(port);

   if (status == MMAL_SUCCESS)
      pool = port->priv->core->pool_for_connection;
   port->priv->core->pool_for_connection = NULL;

   UNLOCK_PORT(port);

   if (status == MMAL_SUCCESS && pool)
      mmal_pool_destroy(pool);

   return status;
}
Exemple #5
0
/* Get a port parameter */
MMAL_STATUS_T mmal_port_parameter_get(MMAL_PORT_T *port,
   MMAL_PARAMETER_HEADER_T *param)
{
   MMAL_STATUS_T status = MMAL_ENOSYS;

   if (!port || !port->priv)
      return MMAL_EINVAL;

   LOG_TRACE("%s(%i:%i) port %p, param %p (%x,%i)", port->component->name,
             (int)port->type, (int)port->index, port,
             param, param ? param->id : 0, param ? (int)param->size : 0);

   if (!param)
      return MMAL_EINVAL;

   LOCK_PORT(port);
   if (port->priv->pf_parameter_get)
      status = port->priv->pf_parameter_get(port, param);
   if (status == MMAL_ENOSYS)
   {
      /* is this a core parameter? */
      status = mmal_port_private_parameter_get(port, param);
   }

   UNLOCK_PORT(port);
   return status;
}
Exemple #6
0
static MMAL_STATUS_T mmal_port_disable_internal(MMAL_PORT_T *port)
{
   MMAL_PORT_PRIVATE_CORE_T* core = port->priv->core;
   MMAL_STATUS_T status = MMAL_SUCCESS;
   MMAL_BUFFER_HEADER_T *buffer;

   LOCK_PORT(port);

   if (!port->is_enabled)
      goto end;

   LOCK_SENDING(port);
   port->is_enabled = 0;
   UNLOCK_SENDING(port);

   mmal_component_action_lock(port->component);

   if (core->pool_for_connection)
      mmal_pool_callback_set(core->pool_for_connection, NULL, NULL);

   status = port->priv->pf_disable(port);

   mmal_component_action_unlock(port->component);

   if (status != MMAL_SUCCESS)
   {
      LOG_ERROR("port %p could not be disabled (%s)", port->name, mmal_status_to_string(status));
      LOCK_SENDING(port);
      port->is_enabled = 1;
      UNLOCK_SENDING(port);
      goto end;
   }

   /* Flush our internal queue */
   buffer = port->priv->core->queue_first;
   while (buffer)
   {
      MMAL_BUFFER_HEADER_T *next = buffer->next;
      mmal_port_buffer_header_callback(port, buffer);
      buffer = next;
   }
   port->priv->core->queue_first = 0;
   port->priv->core->queue_last = &port->priv->core->queue_first;

   /* Wait for all the buffers to have come back from the component */
   LOG_DEBUG("%s waiting for %i buffers left in transit", port->name, (int)IN_TRANSIT_COUNT(port));
   IN_TRANSIT_WAIT(port);
   LOG_DEBUG("%s has no buffers left in transit", port->name);

   port->priv->core->buffer_header_callback = NULL;

 end:
   UNLOCK_PORT(port);
   return status;
}
Exemple #7
0
void
bbos_delete_message(struct bbos_message* msg)
{
  bbos_port_id_t id;
  BBOS_ASSERT(msg != NULL);
  id = msg->receiver;
  LOCK_PORT(id);
  PRINT_DEBUG("[I] Thread %d deletes message 0x%x from %d\n",
              bbos_get_running_thread(), msg, id);
  mempool_free(bbos_ports[id].pool, msg);
  UNLOCK_PORT(id);
}
Exemple #8
0
struct bbos_message*
bbos_receive_message_from(bbos_port_id_t id)
{
  struct bbos_message* msg;
  if (PORT_IS_EMPTY(id)) {
    return NULL;
  }
  LOCK_PORT(id);
  msg = bbos_ports[id].inbox[bbos_ports[id].head];
  bbos_ports[id].head = (bbos_ports[id].head + 1) % (bbos_ports[id].capacity);
  PRINT_DEBUG("[I] Thread %d receives a message 0x%x with label %d from %d\n",
              id, msg, msg->label, msg->sender);
  UNLOCK_PORT(id);
  return msg;
}
Exemple #9
0
struct bbos_message*
bbos_request_message(bbos_port_id_t id)
{
  struct bbos_message* msg;
  ASSERT_PORT_ID(id);
  LOCK_PORT(id);
  PRINT_DEBUG("[I] Thread %d requests message from port %d\n",
              bbos_get_running_thread(), id);
  if ((msg = (struct bbos_message*)mempool_alloc(bbos_ports[id].pool)) == NULL) {
    PRINT_DEBUG("[I] Port %d doesn't have free messages\n", id);
    return NULL;
  }
  UNLOCK_PORT(id);
  msg->receiver = id;
  msg->sender = bbos_get_running_thread();
  msg->label = 0; /* BBOS_NOT_LABELED_MESSAGE ? */
  msg->payload = (void*)((void*)msg + sizeof(struct bbos_message));
  return msg;
}
Exemple #10
0
void
bbos_send_message(struct bbos_message* msg)
{
  bbos_port_id_t id;
  BBOS_ASSERT(msg != NULL);
  id = msg->receiver;
  ASSERT_PORT_ID(id); /* redundant? */
  LOCK_PORT(id);
  if (PORT_IS_FULL(id)) {
    /*
     * This should never happen unless the message receiver was manually
     * changed.
     */
    return;
  }
  PRINT_DEBUG("[I] Thread %d sends message 0x%x with label %d to %d\n",
              msg->sender, msg, msg->label, msg->receiver);
  bbos_ports[id].inbox[bbos_ports[id].tail] = msg;
  bbos_ports[id].tail = (bbos_ports[id].tail + 1) % (bbos_ports[id].capacity);
  UNLOCK_PORT(id);
}
Exemple #11
0
/** 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;

   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;

   LOCK_PORT(port);

   status = mmal_port_enable_locked(port, cb);

   UNLOCK_PORT(port);

   return status;
}
Exemple #12
0
static MMAL_STATUS_T mmal_port_enable_internal(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
{
   MMAL_PORT_PRIVATE_CORE_T* core = port->priv->core;
   MMAL_STATUS_T status = MMAL_SUCCESS;

   LOCK_PORT(port);

   if (port->is_enabled)
      goto end;

   /* Sanity check the buffer requirements */
   if (port->buffer_num < port->buffer_num_min)
   {
      LOG_ERROR("buffer_num too small (%i/%i)", (int)port->buffer_num, (int)port->buffer_num_min);
      status = MMAL_EINVAL;
      goto end;
   }
   if (port->buffer_size < port->buffer_size_min)
   {
      LOG_ERROR("buffer_size too small (%i/%i)", (int)port->buffer_size, (int)port->buffer_size_min);
      status = MMAL_EINVAL;
      goto end;
   }

   core->buffer_header_callback = cb;
   status = port->priv->pf_enable(port, cb);
   if (status != MMAL_SUCCESS)
      goto end;

   LOCK_SENDING(port);
   port->is_enabled = 1;
   UNLOCK_SENDING(port);

end:
   UNLOCK_PORT(port);
   return status;
}
Exemple #13
0
/* Set a parameter on a port. */
MMAL_STATUS_T mmal_port_parameter_set(MMAL_PORT_T *port,
   const MMAL_PARAMETER_HEADER_T *param)
{
   MMAL_STATUS_T status = MMAL_ENOSYS;

   if (!port)
   {
      LOG_ERROR("no port");
      return MMAL_EINVAL;
   }
   if (!param)
   {
      LOG_ERROR("param not supplied");
      return MMAL_EINVAL;
   }
   if (!port->priv)
   {
      LOG_ERROR("port not configured");
      return MMAL_EINVAL;
   }

   LOG_TRACE("%s(%i:%i) port %p, param %p (%x,%i)", port->component->name,
             (int)port->type, (int)port->index, port,
             param, param ? param->id : 0, param ? (int)param->size : 0);

   LOCK_PORT(port);
   if (port->priv->pf_parameter_set)
      status = port->priv->pf_parameter_set(port, param);
   if (status == MMAL_ENOSYS)
   {
      /* is this a core parameter? */
      status = mmal_port_private_parameter_set(port, param);
   }
   UNLOCK_PORT(port);
   return status;
}
Exemple #14
0
static MMAL_STATUS_T mmal_port_enable_locked_connected(MMAL_PORT_T* output, MMAL_PORT_T* input)
{
   MMAL_PORT_PRIVATE_CORE_T* output_core = output->priv->core;
   MMAL_STATUS_T status = MMAL_SUCCESS;

   output_core->buffer_header_callback = mmal_port_connected_output_cb;

   /* Output port already locked, lock input port */
   LOCK_PORT(input);

   /* Disable connected port if its buffer config needs to change */
   if (input->is_enabled &&
         (input->buffer_size != output->buffer_size ||
          input->buffer_num != output->buffer_num))
   {
      status = mmal_port_disable_locked(input);
      if (status != MMAL_SUCCESS)
         goto finish;
   }

   /* Ensure the connected port has the same buffer configuration */
   input->buffer_size = output->buffer_size;
   input->buffer_num = output->buffer_num;

   /* Enable other end of the connection, if not already enabled */
   if (!input->is_enabled)
   {
      status = mmal_port_enable_locked(input, NULL);
      if (status != MMAL_SUCCESS)
         goto finish;
   }

   if (output_core->allocate_pool)
   {
      MMAL_POOL_T* pool = NULL;
      /* Decide which port will be used to allocate the pool */
      MMAL_PORT_T* pool_port = (output->capabilities & MMAL_PORT_CAPABILITY_ALLOCATION) ? output : input;
      MMAL_PORT_PRIVATE_CORE_T* pool_core = pool_port->priv->core;
      uint32_t buffer_size = pool_port->buffer_size;

      /* No need to allocate payload memory for pass-through ports */
      if (output->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH)
         buffer_size = 0;

      UNLOCK_PORT(input);
      if (pool_port == output)
         UNLOCK_PORT(output);

      /* Port pool creation must be done without the lock held */
      pool = mmal_port_pool_create(pool_port, pool_port->buffer_num, buffer_size);

      if (pool_port == output)
         LOCK_PORT(output);
      LOCK_PORT(input);

      if (!pool)
      {
         status = MMAL_ENOMEM;
         goto finish;
      }

      pool_core->pool_for_connection = pool;
      mmal_pool_callback_set(pool_core->pool_for_connection, mmal_port_connected_pool_cb, output);

      /* Put the buffers into the output port */
      status = mmal_port_populate_from_pool(output, pool_port->priv->core->pool_for_connection);
   }

finish:
   /* At this point, both locks must be held */

   if (status != MMAL_SUCCESS && input->is_enabled)
      mmal_port_disable_locked(input);

   UNLOCK_PORT(input);

   if (status != MMAL_SUCCESS)
      mmal_port_disable_locked(output);

   return status;
}
Exemple #15
0
/** Set format of a port */
MMAL_STATUS_T mmal_port_format_commit(MMAL_PORT_T *port)
{
   MMAL_STATUS_T status;
   char encoding_string[16];

   if (!port || !port->priv)
   {
      LOG_ERROR("invalid port (%p/%p)", port, port ? port->priv : NULL);
      return MMAL_EINVAL;
   }

   if (port->format != port->priv->core->format_ptr_copy)
   {
      LOG_ERROR("%s: port format has been overwritten, resetting %p to %p",
            port->name, port->format, port->priv->core->format_ptr_copy);
      port->format = port->priv->core->format_ptr_copy;
      return MMAL_EFAULT;
   }

   if (port->format->encoding == 0)
      snprintf(encoding_string, sizeof(encoding_string), "<NO-FORMAT>");
   else
      snprintf(encoding_string, sizeof(encoding_string), "%4.4s", (char*)&port->format->encoding);

   LOG_TRACE("%s(%i:%i) port %p format %i:%s",
             port->component->name, (int)port->type, (int)port->index, port,
             (int)port->format->type, encoding_string);

   if (!port->priv->pf_set_format)
   {
      LOG_ERROR("%s: no component implementation", port->name);
      return MMAL_ENOSYS;
   }

   LOCK_PORT(port);
   status = port->priv->pf_set_format(port);
   mmal_port_name_update(port);

   /* Make sure the buffer size / num are sensible */
   if (port->buffer_size < port->buffer_size_min)
      port->buffer_size = port->buffer_size_min;
   if (port->buffer_num < port->buffer_num_min)
      port->buffer_num = port->buffer_num_min;
   /* The output port settings might have changed */
   if (port->type == MMAL_PORT_TYPE_INPUT)
   {
      MMAL_PORT_T **ports = port->component->output;
      unsigned int i;

      for (i = 0; i < port->component->output_num; i++)
      {
         if (ports[i]->buffer_size < ports[i]->buffer_size_min)
            ports[i]->buffer_size = ports[i]->buffer_size_min;
         if (ports[i]->buffer_num < ports[i]->buffer_num_min)
            ports[i]->buffer_num = ports[i]->buffer_num_min;
      }
   }

   UNLOCK_PORT(port);
   return status;
}
Exemple #16
0
/** 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* input_port = NULL;
   MMAL_PORT_T* output_port = NULL;

   if (!port || !port->priv || !other_port || !other_port->priv)
   {
      LOG_ERROR("invalid port");
      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;
   }

   mmal_port_set_input_or_output(port, &input_port, &output_port);
   mmal_port_set_input_or_output(other_port, &input_port, &output_port);

   if (!input_port || !output_port)
   {
      LOG_ERROR("invalid port types used: %i, %i", port->type, other_port->type);
      return MMAL_EINVAL;
   }

   /* Always lock output then input to avoid deadlock */
   LOCK_PORT(output_port);
   LOCK_PORT(input_port);

   core = port->priv->core;
   other_core = other_port->priv->core;

   if (core->connected_port || other_core->connected_port)
   {
      MMAL_PORT_T* problem_port = core->connected_port ? port : other_port;
      MMAL_PORT_T* connected_port = problem_port->priv->core->connected_port;

      LOG_ERROR("port %p is already connected to port %p", problem_port, connected_port);
      status = MMAL_EISCONN;
      goto finish;
   }

   if (port->is_enabled || other_port->is_enabled)
   {
      LOG_ERROR("neither port is allowed to be enabled already: %i, %i",
                (int)port->is_enabled, (int)other_port->is_enabled);
      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;
   output_port->priv->core->allocate_pool = 0;

   /* Check to see if the port will manage the connection on its own. If not then the core
    * will manage it. */
   if (output_port->priv->pf_connect(port, other_port) == MMAL_SUCCESS)
      goto finish;

   core->core_owns_connection = 1;
   other_core->core_owns_connection = 1;
   output_port->priv->core->allocate_pool = 1;

finish:
   UNLOCK_PORT(input_port);
   UNLOCK_PORT(output_port);
   return status;
}
Exemple #17
0
static MMAL_STATUS_T mmal_port_enable_locked(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb)
{
   MMAL_PORT_PRIVATE_CORE_T* core = port->priv->core;
   MMAL_PORT_T* connected_port = core->connected_port;
   MMAL_STATUS_T status;

   if (port->is_enabled)
   {
      LOG_DEBUG("already enabled");
      return MMAL_EINVAL;
   }

   /* Ensure that the buffer numbers and sizes used are the maxima between connected ports. */
   if (connected_port && port->type == MMAL_PORT_TYPE_OUTPUT)
   {
      LOCK_PORT(connected_port);

      if (connected_port->buffer_num > port->buffer_num)
         port->buffer_num = connected_port->buffer_num;
      if (connected_port->buffer_size > port->buffer_size)
         port->buffer_size = connected_port->buffer_size;

      UNLOCK_PORT(connected_port);
   }

   /* Sanity check the buffer requirements */
   if (port->buffer_num < port->buffer_num_min)
   {
      LOG_ERROR("buffer_num too small (%i/%i)", (int)port->buffer_num, (int)port->buffer_num_min);
      return MMAL_EINVAL;
   }
   if (port->buffer_size < port->buffer_size_min)
   {
      LOG_ERROR("buffer_size too small (%i/%i)", (int)port->buffer_size, (int)port->buffer_size_min);
      return MMAL_EINVAL;
   }

   if (!connected_port == !cb)
   {
      /* Callback must be NULL if connected port is not NULL */
      LOG_ERROR("connected port %p, callback %p not allowed", connected_port, cb);
      return MMAL_EINVAL;
   }

   core->buffer_header_callback = cb;
   status = port->priv->pf_enable(port, cb);
   if (status != MMAL_SUCCESS)
      return status;

   LOCK_SENDING(port);
   port->is_enabled = 1;
   UNLOCK_SENDING(port);

   //FIXME: move before is_enabled is set ?
   if (connected_port)
   {
      if (port->type == MMAL_PORT_TYPE_INPUT)
         core->buffer_header_callback = mmal_port_connected_input_cb;
      else
         status = mmal_port_enable_locked_connected(port, connected_port);
   }

   return status;
}