Revert "mmal: Support 64 bit clients"

This reverts commit c2cd8020ed571c2db13d2ba99695c654136fb440.
This commit is contained in:
popcornmix
2020-01-09 16:00:03 +00:00
parent 4a57ea4107
commit e31da99739
4 changed files with 74 additions and 461 deletions

View File

@@ -85,10 +85,8 @@ typedef struct MMAL_COMPONENT_MODULE_T
MMAL_BOOL_T event_ctx_initialised;
MMAL_VC_CLIENT_BUFFER_CONTEXT_T event_ctx; /**< Used as the ctx for event buffers */
uint32_t event_ctx_handle; /**< Used as the ctx for event buffers */
} MMAL_COMPONENT_MODULE_T;
/*****************************************************************************
* Local function prototypes
*****************************************************************************/
@@ -150,8 +148,7 @@ static MMAL_STATUS_T mmal_vc_port_requirements_set(MMAL_PORT_T *port)
msg.component_handle = module->component_handle;
msg.action = MMAL_WORKER_PORT_ACTION_SET_REQUIREMENTS;
msg.port_handle = module->port_handle;
msg.param.enable.port.buffer_num = port->buffer_num;
msg.param.enable.port.buffer_size = port->buffer_size;
msg.param.enable.port = *port;
status = mmal_vc_sendwait_message(mmal_vc_get_client(), &msg.header, sizeof(msg),
MMAL_WORKER_PORT_ACTION, &reply, &replylen, MMAL_FALSE);
@@ -227,7 +224,7 @@ static MMAL_STATUS_T mmal_vc_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb
for (i = 0; i < pool->headers_num; i++)
{
drv = mmal_buffer_header_driver_data(pool->header[i]);
drv->client_context = port->component->priv->module->event_ctx_handle;
drv->client_context = &port->component->priv->module->event_ctx;
drv->magic = MMAL_MAGIC;
}
@@ -258,8 +255,7 @@ static MMAL_STATUS_T mmal_vc_port_enable(MMAL_PORT_T *port, MMAL_PORT_BH_CB_T cb
msg.component_handle = module->component_handle;
msg.action = MMAL_WORKER_PORT_ACTION_ENABLE;
msg.port_handle = module->port_handle;
msg.param.enable.port.buffer_num = port->buffer_num;
msg.param.enable.port.buffer_size = port->buffer_size;
msg.param.enable.port = *port;
status = mmal_vc_sendwait_message(mmal_vc_get_client(), &msg.header, sizeof(msg),
MMAL_WORKER_PORT_ACTION, &reply, &replylen, MMAL_FALSE);
@@ -372,7 +368,7 @@ static MMAL_STATUS_T mmal_vc_port_flush_sync(MMAL_PORT_T *port)
client_context.magic = MMAL_MAGIC;
client_context.port = port;
msg->drvbuf.client_context = mmal_vc_allocate_client_context(&client_context);
msg->drvbuf.client_context = &client_context;
msg->drvbuf.component_handle = module->component_handle;
msg->drvbuf.port_handle = module->port_handle;
msg->drvbuf.magic = MMAL_MAGIC;
@@ -388,7 +384,6 @@ static MMAL_STATUS_T mmal_vc_port_flush_sync(MMAL_PORT_T *port)
if (status != MMAL_SUCCESS)
LOG_ERROR("failed to disable port - reason %d", status);
mmal_vc_release_client_context(&client_context);
return status;
}
@@ -507,7 +502,7 @@ static void mmal_vc_do_callback(MMAL_COMPONENT_T *component)
/* Events generated by this component are handled differently */
if (mmal_buffer_header_driver_data(buffer)->client_context ==
component->priv->module->event_ctx_handle)
&component->priv->module->event_ctx)
{
mmal_port_event_send(port, buffer);
return;
@@ -533,16 +528,14 @@ static void mmal_vc_port_send_callback(mmal_worker_buffer_from_host *msg)
{
MMAL_BUFFER_HEADER_T *buffer;
MMAL_PORT_T *port;
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = msg->drvbuf.client_context;
vcos_assert(client_context);
vcos_assert(client_context->magic == MMAL_MAGIC);
buffer = client_context->buffer;
port = client_context->port;
vcos_blockpool_free(client_context);
mmal_vc_release_client_context(client_context);
vcos_blockpool_free(msg->drvbuf.client_context);
vcos_assert(port->priv->module->magic == MMAL_MAGIC);
mmal_vc_msg_to_buffer_header(buffer, msg);
@@ -621,7 +614,7 @@ static MMAL_STATUS_T mmal_vc_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *
client_context->callback_event = NULL;
client_context->port = port;
msg->drvbuf.client_context = mmal_vc_allocate_client_context(client_context);
msg->drvbuf.client_context = client_context;
msg->drvbuf.component_handle = module->component_handle;
msg->drvbuf.port_handle = module->port_handle;
msg->drvbuf.magic = MMAL_MAGIC;
@@ -648,14 +641,12 @@ static MMAL_STATUS_T mmal_vc_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *
if (!VCOS_BLOCKPOOL_IS_VALID_HANDLE_FORMAT(msg->drvbuf.component_handle, 256))
{
LOG_ERROR("bad component handle 0x%x", msg->drvbuf.component_handle);
mmal_vc_release_client_context(client_context);
return MMAL_EINVAL;
}
if (msg->drvbuf.port_handle > 255)
{
LOG_ERROR("bad port handle 0x%x", msg->drvbuf.port_handle);
mmal_vc_release_client_context(client_context);
return MMAL_EINVAL;
}
@@ -702,8 +693,7 @@ static MMAL_STATUS_T mmal_vc_port_send(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *
if (status != MMAL_SUCCESS)
{
LOG_INFO("failed %d", status);
vcos_blockpool_free(client_context);
mmal_vc_release_client_context(client_context);
vcos_blockpool_free(msg->drvbuf.client_context);
buffer->data = mmal_vc_shm_lock(buffer->data, port->priv->module->zero_copy_workaround);
}
@@ -805,7 +795,6 @@ static MMAL_STATUS_T mmal_vc_component_destroy(MMAL_COMPONENT_T *component)
mmal_ports_free(component->clock, component->clock_num);
mmal_queue_destroy(component->priv->module->callback_queue);
mmal_vc_release_client_context(&component->priv->module->event_ctx);
vcos_free(component->priv->module);
component->priv->module = NULL;
@@ -813,7 +802,6 @@ static MMAL_STATUS_T mmal_vc_component_destroy(MMAL_COMPONENT_T *component)
fail:
// no longer require videocore
mmal_vc_release();
mmal_vc_release_client_component(component);
mmal_vc_shm_exit();
mmal_vc_deinit();
return status;
@@ -940,17 +928,6 @@ MMAL_STATUS_T mmal_vc_get_core_stats(MMAL_CORE_STATISTICS_T *stats,
return status;
}
static void mmal_vc_copy_es_format_to_vc(MMAL_ES_FORMAT_T *src, MMAL_VC_ES_FORMAT_T *dest)
{
// IPC MMAL_VC_ES_FORMAT_T is not necessarily the same as MMAL_ES_FORMAT_T,
// so copy fields individually.
dest->type = src->type;
dest->encoding = src->encoding;
dest->encoding_variant = src->encoding_variant;
dest->bitrate = src->bitrate;
dest->flags = src->flags;
dest->extradata_size = src->extradata_size;
}
/** Get port context data. */
static MMAL_STATUS_T mmal_vc_port_info_get(MMAL_PORT_T *port)
@@ -992,9 +969,9 @@ static MMAL_STATUS_T mmal_vc_port_info_get(MMAL_PORT_T *port)
port->buffer_alignment_min = reply.port.buffer_alignment_min;
port->is_enabled = reply.port.is_enabled;
port->capabilities = reply.port.capabilities;
mmal_vc_copy_es_format_from_vc(&reply.format, port->format);
reply.format.extradata = port->format->extradata;
reply.format.es = port->format->es;
*port->format = reply.format;
*port->format->es = reply.es;
if(port->format->extradata_size)
{
@@ -1024,22 +1001,15 @@ static MMAL_STATUS_T mmal_vc_port_info_set(MMAL_PORT_T *port)
msg.component_handle = module->component_handle;
msg.port_type = port->type;
msg.index = port->index;
//Only copy the values that are used into the MMAL_PORT_T of the IPC.
msg.port.buffer_num = port->buffer_num;
msg.port.buffer_size = port->buffer_size;
msg.port.is_enabled = port->is_enabled;
mmal_vc_copy_es_format_to_vc(port->format, &msg.format);
msg.port = *port;
msg.format = *port->format;
msg.es = *port->format->es;
if(msg.format.extradata_size > MMAL_FORMAT_EXTRADATA_MAX_SIZE)
{
vcos_assert(0);
msg.format.extradata_size = MMAL_FORMAT_EXTRADATA_MAX_SIZE;
}
memcpy(msg.extradata, port->format->extradata, msg.format.extradata_size);
memcpy(msg.extradata, msg.format.extradata, msg.format.extradata_size);
LOG_TRACE("set port info (%i:%i)", port->type, port->index);
@@ -1067,9 +1037,9 @@ static MMAL_STATUS_T mmal_vc_port_info_set(MMAL_PORT_T *port)
port->buffer_alignment_min = reply.port.buffer_alignment_min;
port->is_enabled = reply.port.is_enabled;
port->capabilities = reply.port.capabilities;
mmal_vc_copy_es_format_from_vc(&reply.format, port->format);
reply.format.extradata = port->format->extradata;
reply.format.es = port->format->es;
*port->format = reply.format;
*port->format->es = reply.es;
if(port->format->extradata_size)
{
@@ -1358,6 +1328,7 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
return MMAL_EINVAL;
}
msg.client_component = component;
/* coverity[secure_coding] Length tested above */
strcpy(msg.name, basename);
#ifdef __linux__
@@ -1380,8 +1351,6 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
return status;
}
msg.client_component = mmal_vc_allocate_client_component(component);
// claim VC for entire duration of component.
status = mmal_vc_use();
@@ -1402,7 +1371,6 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
LOG_ERROR("failed to create component '%s' (%i:%s)", name, status,
mmal_status_to_string(status));
mmal_vc_release();
mmal_vc_release_client_component(component);
mmal_vc_shm_exit();
mmal_vc_deinit();
return status;
@@ -1423,7 +1391,6 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
MMAL_WORKER_COMPONENT_DESTROY, &reply, &replylen, MMAL_FALSE);
vcos_assert(destroy_status == MMAL_SUCCESS);
mmal_vc_release();
mmal_vc_release_client_component(component);
mmal_vc_shm_exit();
mmal_vc_deinit();
return status;
@@ -1529,7 +1496,6 @@ static MMAL_STATUS_T mmal_vc_component_create(const char *name, MMAL_COMPONENT_T
module->event_ctx_initialised = MMAL_FALSE;
module->event_ctx.magic = MMAL_MAGIC;
module->event_ctx.callback_event = mmal_vc_port_send_event_callback;
module->event_ctx_handle = mmal_vc_allocate_client_context(&module->event_ctx);
/* populate component structure */
component->priv->pf_enable = mmal_vc_component_enable;

View File

@@ -53,7 +53,6 @@ static VCOS_LOG_CAT_T mmal_ipc_log_category;
*/
typedef struct MMAL_WAITER_T
{
int index;
VCOS_SEMAPHORE_T sem;
unsigned inuse;
void *dest; /**< Where to write reply */
@@ -83,151 +82,6 @@ struct MMAL_CLIENT_T
MMAL_BOOL_T inited;
};
/*****************************************************************************
* Lookup table functions for client_component handles.
* Required as the IPC is strictly 32bit, therefore 64bit userland can not
* pass in the required pointers.
*****************************************************************************/
#define MAX_COMPONENT_HANDLES 128
typedef struct
{
unsigned int inuse:1;
unsigned int index:31;
MMAL_COMPONENT_T *component;
} MMAL_CLIENT_COMPONENT_T;
typedef struct
{
MMAL_CLIENT_COMPONENT_T components[MAX_COMPONENT_HANDLES];
VCOS_MUTEX_T lock;
} MMAL_CLIENT_COMPONENT_POOL_T;
static MMAL_CLIENT_COMPONENT_POOL_T client_component_pool;
uint32_t mmal_vc_allocate_client_component(MMAL_COMPONENT_T *component)
{
int i;
vcos_mutex_lock(&client_component_pool.lock);
for (i=0; i<MAX_COMPONENT_HANDLES; i++)
{
if (client_component_pool.components[i].inuse == 0)
break;
}
if (vcos_verify(i != MAX_COMPONENT_HANDLES))
{
client_component_pool.components[i].index = i;
client_component_pool.components[i].component = component;
client_component_pool.components[i].inuse = 1;
}
vcos_mutex_unlock(&client_component_pool.lock);
return i;
}
static MMAL_COMPONENT_T *lookup_client_component(int index)
{
if (vcos_verify(index < MAX_COMPONENT_HANDLES))
{
vcos_assert(client_component_pool.components[index].inuse);
return client_component_pool.components[index].component;
}
return NULL;
}
void mmal_vc_release_client_component(MMAL_COMPONENT_T *component)
{
int i;
vcos_mutex_lock(&client_component_pool.lock);
for (i=0; i<MAX_COMPONENT_HANDLES; i++)
{
if (client_component_pool.components[i].component == component)
{
client_component_pool.components[i].component = NULL;
client_component_pool.components[i].inuse = 0;
}
}
vcos_mutex_unlock(&client_component_pool.lock);
}
#define MAX_CLIENT_CONTEXTS 512
typedef struct
{
unsigned int inuse:1;
unsigned int index:31;
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *ctx;
} MMAL_CLIENT_CONTEXT_T;
typedef struct
{
MMAL_CLIENT_CONTEXT_T contexts[MAX_CLIENT_CONTEXTS];
VCOS_MUTEX_T lock;
} MMAL_CLIENT_CONTEXT_POOL_T;
static MMAL_CLIENT_CONTEXT_POOL_T client_context_pool;
#define CLIENT_CONTEXT_MAGIC 0xFEDC0000
#define CLIENT_CONTEXT_MAGIC_MASK(a) (a & 0xFFFF)
#define CLIENT_CONTEXT_MAGIC_CHECK(a) (a & 0xFFFF0000)
uint32_t mmal_vc_allocate_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context)
{
int i;
vcos_mutex_lock(&client_context_pool.lock);
for (i=0; i<MAX_CLIENT_CONTEXTS; i++)
{
if (client_context_pool.contexts[i].inuse == 0)
break;
}
if (vcos_verify(i != MAX_CLIENT_CONTEXTS))
{
client_context_pool.contexts[i].index = i;
client_context_pool.contexts[i].ctx = context;
client_context_pool.contexts[i].inuse = 1;
}
vcos_mutex_unlock(&client_context_pool.lock);
return i | CLIENT_CONTEXT_MAGIC;
}
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *mmal_vc_lookup_client_context(int index)
{
if (vcos_verify((CLIENT_CONTEXT_MAGIC_CHECK(index) == CLIENT_CONTEXT_MAGIC) &&
(CLIENT_CONTEXT_MAGIC_MASK(index) < MAX_CLIENT_CONTEXTS)))
{
vcos_assert(client_context_pool.contexts[CLIENT_CONTEXT_MAGIC_MASK(index)].inuse);
return client_context_pool.contexts[CLIENT_CONTEXT_MAGIC_MASK(index)].ctx;
}
return NULL;
}
void mmal_vc_release_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context)
{
int i;
vcos_mutex_lock(&client_context_pool.lock);
for (i=0; i<MAX_CLIENT_CONTEXTS; i++)
{
if (client_context_pool.contexts[i].ctx == context)
{
client_context_pool.contexts[i].ctx = NULL;
client_context_pool.contexts[i].inuse = 0;
break;
}
}
if (i >= MAX_CLIENT_CONTEXTS)
LOG_ERROR("Failed to release context %p - not found", context);
vcos_mutex_unlock(&client_context_pool.lock);
}
/* One client per process/VC connection. Multiple threads may
* be using a single client.
*/
@@ -236,8 +90,6 @@ static MMAL_CLIENT_T client;
static void init_once(void)
{
vcos_mutex_create(&client.lock, VCOS_FUNCTION);
vcos_mutex_create(&client_component_pool.lock, VCOS_FUNCTION);
vcos_mutex_create(&client_context_pool.lock, VCOS_FUNCTION);
}
/** Create a pool of wait-structures.
@@ -255,7 +107,6 @@ static MMAL_STATUS_T create_waitpool(MMAL_WAITPOOL_T *waitpool)
for (i=0; i<MAX_WAITERS; i++)
{
waitpool->waiters[i].inuse = 0;
waitpool->waiters[i].index = i;
status = vcos_semaphore_create(&waitpool->waiters[i].sem,
"mmal waiter", 0);
if (status != VCOS_SUCCESS)
@@ -310,19 +161,6 @@ static MMAL_WAITER_T *get_waiter(MMAL_CLIENT_T *client)
return waiter;
}
/** Look up a waiter reference based on the static client
*/
static MMAL_WAITER_T *lookup_waiter(uint32_t index)
{
//NB this uses the static client variable, whilst most others use the client
//variable passed in. I don't believe there is a way to have multiple clients
//in one process, so this should be safe.
if (vcos_verify(index < MAX_WAITERS))
return &client.waitpool.waiters[index];
return NULL;
}
/** Return a waiter to the pool.
*/
static void release_waiter(MMAL_CLIENT_T *client, MMAL_WAITER_T *waiter)
@@ -360,15 +198,13 @@ static void mmal_vc_handle_event_msg(VCHIQ_HEADER_T *vchiq_header,
void *context)
{
mmal_worker_event_to_host *msg = (mmal_worker_event_to_host *)vchiq_header->data;
MMAL_COMPONENT_T *component = lookup_client_component(msg->client_component);
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context;
MMAL_COMPONENT_T *component = msg->client_component;
MMAL_BUFFER_HEADER_T *buffer;
MMAL_STATUS_T status;
MMAL_PORT_T *port;
LOG_DEBUG("event to host, cmd 0x%08x len %d to component %u/%p port (%d,%d)",
msg->cmd, msg->length, msg->client_component, component, msg->port_type,
msg->port_num);
LOG_DEBUG("event to host, cmd 0x%08x len %d to component %p port (%d,%d)",
msg->cmd, msg->length, msg->client_component, msg->port_type, msg->port_num);
(void)context;
port = mmal_vc_port_by_number(component, msg->port_type, msg->port_num);
@@ -393,12 +229,11 @@ static void mmal_vc_handle_event_msg(VCHIQ_HEADER_T *vchiq_header,
}
buffer->length = msg->length;
client_context = mmal_vc_lookup_client_context(mmal_buffer_header_driver_data(buffer)->client_context);
/* Sanity check that the event buffers have the proper vc client context */
if (!vcos_verify(mmal_buffer_header_driver_data(buffer)->magic == MMAL_MAGIC &&
client_context &&
client_context->magic == MMAL_MAGIC &&
client_context->callback_event))
mmal_buffer_header_driver_data(buffer)->client_context &&
mmal_buffer_header_driver_data(buffer)->client_context->magic == MMAL_MAGIC &&
mmal_buffer_header_driver_data(buffer)->client_context->callback_event))
{
LOG_ERROR("event buffers not configured properly by component");
goto error;
@@ -423,53 +258,9 @@ static void mmal_vc_handle_event_msg(VCHIQ_HEADER_T *vchiq_header,
else
{
if (msg->length)
{
if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED && buffer->length >= msg->length)
{
//64bit userspace.
//No need to fix the pointers in the msg as mmal_event_format_changed_get
//will do that for us, but the start positions of each section does need
//to be adjusted.
mmal_worker_event_format_changed *fmt_changed_vc =
(mmal_worker_event_format_changed*)msg->data;
MMAL_EVENT_FORMAT_CHANGED_T *fmt_changed_host =
(MMAL_EVENT_FORMAT_CHANGED_T*)buffer->data;
MMAL_ES_FORMAT_T *fmt_host;
MMAL_VC_ES_FORMAT_T *fmt_vc;
MMAL_ES_SPECIFIC_FORMAT_T *es_host, *es_vc;
const uint32_t size_host = sizeof(MMAL_EVENT_FORMAT_CHANGED_T) +
sizeof(MMAL_ES_FORMAT_T) +
sizeof(MMAL_ES_SPECIFIC_FORMAT_T);
const uint32_t size_vc = sizeof(mmal_worker_event_format_changed) +
sizeof(MMAL_VC_ES_FORMAT_T) +
sizeof(MMAL_ES_SPECIFIC_FORMAT_T);
memcpy(buffer->data, msg->data, msg->length);
//Copy the base event (ignore the format pointer from the end)
memcpy(fmt_changed_host, fmt_changed_vc, sizeof(mmal_worker_event_format_changed));
fmt_changed_host->format = NULL;
//Copy the es format
fmt_vc = (MMAL_VC_ES_FORMAT_T *)&fmt_changed_vc[1];
fmt_host = (MMAL_ES_FORMAT_T *)&fmt_changed_host[1];
mmal_vc_copy_es_format_from_vc(fmt_vc, fmt_host);
//Copy the ES_SPECIFIC_FORMAT_T (structures are identical)
es_host = (MMAL_ES_SPECIFIC_FORMAT_T *)&fmt_host[1];
es_vc = (MMAL_ES_SPECIFIC_FORMAT_T *)&fmt_vc[1];
memcpy(es_host, es_vc, sizeof(MMAL_ES_SPECIFIC_FORMAT_T));
//Copy the extradata (if present)
fmt_host->extradata_size = msg->length - size_vc;
memcpy((uint8_t *)&es_host[1], (uint8_t*)&es_vc[1], fmt_host->extradata_size);
buffer->length = size_host + fmt_host->extradata_size;
}
else
{
memcpy(buffer->data, msg->data, msg->length);
}
}
client_context->callback_event(port, buffer);
mmal_buffer_header_driver_data(buffer)->client_context->callback_event(port, buffer);
LOG_DEBUG("done callback back to client");
vchiq_release_message(service, vchiq_header);
}
@@ -533,36 +324,29 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
if (msg->msgid == MMAL_WORKER_BUFFER_TO_HOST)
{
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context;
LOG_TRACE("buffer to host");
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)vchiq_header->data;
client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
LOG_TRACE("len %d context %p", msg->buffer_header.length, client_context);
vcos_assert(client_context);
vcos_assert(client_context->magic == MMAL_MAGIC);
LOG_TRACE("len %d context %p", msg->buffer_header.length, msg->drvbuf.client_context);
vcos_assert(msg->drvbuf.client_context);
vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
/* If the buffer is referencing another, need to replicate it here
* in order to use the reference buffer's payload and ensure the
* reference is not released prematurely */
if (msg->has_reference)
{
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *ref_context =
mmal_vc_lookup_client_context(msg->drvbuf_ref.client_context);
vcos_assert(ref_context);
mmal_buffer_header_replicate(client_context->buffer, ref_context->buffer);
}
mmal_buffer_header_replicate(msg->drvbuf.client_context->buffer,
msg->drvbuf_ref.client_context->buffer);
/* Sanity check the size of the transfer so we don't overrun our buffer */
if (!vcos_verify(msg->buffer_header.offset + msg->buffer_header.length <=
client_context->buffer->alloc_size))
msg->drvbuf.client_context->buffer->alloc_size))
{
LOG_TRACE("buffer too small (%i, %i)",
msg->buffer_header.offset + msg->buffer_header.length,
client_context->buffer->alloc_size);
msg->drvbuf.client_context->buffer->alloc_size);
msg->buffer_header.length = 0;
msg->buffer_header.flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
client_context->callback(msg);
msg->drvbuf.client_context->callback(msg);
vchiq_release_message(service, vchiq_header);
break;
}
@@ -573,7 +357,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
{
/* a buffer full of data for us to process */
VCHIQ_STATUS_T vst = VCHIQ_SUCCESS;
LOG_TRACE("queue bulk rx: %p, %d", client_context->buffer->data +
LOG_TRACE("queue bulk rx: %p, %d", msg->drvbuf.client_context->buffer->data +
msg->buffer_header.offset, msg->buffer_header.length);
int len = msg->buffer_header.length;
len = (len+3) & (~3);
@@ -586,7 +370,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
{
/* buffer transferred using vchiq bulk xfer */
vst = vchiq_queue_bulk_receive(service,
client_context->buffer->data + msg->buffer_header.offset,
msg->drvbuf.client_context->buffer->data + msg->buffer_header.offset,
len, vchiq_header);
if (vst != VCHIQ_SUCCESS)
@@ -594,20 +378,20 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
LOG_TRACE("queue bulk rx len %d failed to start", msg->buffer_header.length);
msg->buffer_header.length = 0;
msg->buffer_header.flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
client_context->callback(msg);
msg->drvbuf.client_context->callback(msg);
vchiq_release_message(service, vchiq_header);
}
}
else if (msg->payload_in_message <= MMAL_VC_SHORT_DATA)
{
/* we have already received the buffer data in the message! */
MMAL_BUFFER_HEADER_T *dst = client_context->buffer;
MMAL_BUFFER_HEADER_T *dst = msg->drvbuf.client_context->buffer;
LOG_TRACE("short data: dst = %p, dst->data = %p, len %d short len %d", dst, dst? dst->data : 0, msg->buffer_header.length, msg->payload_in_message);
memcpy(dst->data, msg->short_data, msg->payload_in_message);
dst->offset = 0;
dst->length = msg->payload_in_message;
vchiq_release_message(service, vchiq_header);
client_context->callback(msg);
msg->drvbuf.client_context->callback(msg);
}
else
{
@@ -625,9 +409,9 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
* be picked up in the callback to complete the sequence.
*/
LOG_TRACE("doing cb (%p) context %p",
client_context, client_context ?
client_context->callback : 0);
client_context->callback(msg);
msg->drvbuf.client_context, msg->drvbuf.client_context ?
msg->drvbuf.client_context->callback : 0);
msg->drvbuf.client_context->callback(msg);
LOG_TRACE("done callback back to client");
vchiq_release_message(service, vchiq_header);
}
@@ -638,7 +422,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
}
else
{
MMAL_WAITER_T *waiter = lookup_waiter(msg->u.waiter);
MMAL_WAITER_T *waiter = msg->u.waiter;
LOG_TRACE("waking up waiter at %p", waiter);
vcos_assert(waiter->inuse);
int len = vcos_min(waiter->destlen, vchiq_header->size);
@@ -659,7 +443,7 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
#ifdef VCOS_LOGGING_ENABLED
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)context;
#endif
LOG_TRACE("bulk tx done: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
LOG_TRACE("bulk tx done: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
}
break;
case VCHIQ_BULK_RECEIVE_DONE:
@@ -669,21 +453,18 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
if (msg_hdr->msgid == MMAL_WORKER_BUFFER_TO_HOST)
{
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)msg_hdr;
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
vcos_assert(client_context && client_context->magic == MMAL_MAGIC);
client_context->callback(msg);
LOG_TRACE("bulk rx done: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
msg->drvbuf.client_context->callback(msg);
LOG_TRACE("bulk rx done: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
}
else
{
mmal_worker_event_to_host *msg = (mmal_worker_event_to_host *)msg_hdr;
MMAL_COMPONENT_T *component = lookup_client_component(msg->client_component);
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context =
mmal_vc_lookup_client_context(mmal_buffer_header_driver_data(msg->delayed_buffer)->client_context);
MMAL_PORT_T *port = mmal_vc_port_by_number(component, msg->port_type, msg->port_num);
MMAL_PORT_T *port = mmal_vc_port_by_number(msg->client_component, msg->port_type, msg->port_num);
vcos_assert(client_context && port);
client_context->callback_event(port, msg->delayed_buffer);
vcos_assert(port);
mmal_buffer_header_driver_data(msg->delayed_buffer)->
client_context->callback_event(port, msg->delayed_buffer);
LOG_DEBUG("event bulk rx done, length %d", msg->length);
}
vchiq_release_message(service, header);
@@ -696,25 +477,21 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
if (msg_hdr->msgid == MMAL_WORKER_BUFFER_TO_HOST)
{
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)msg_hdr;
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context = mmal_vc_lookup_client_context(msg->drvbuf.client_context);
LOG_TRACE("bulk rx aborted: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
vcos_assert(client_context && client_context->magic == MMAL_MAGIC);
LOG_TRACE("bulk rx aborted: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
msg->buffer_header.flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
client_context->callback(msg);
msg->drvbuf.client_context->callback(msg);
}
else
{
mmal_worker_event_to_host *msg = (mmal_worker_event_to_host *)msg_hdr;
MMAL_COMPONENT_T *component = lookup_client_component(msg->client_component);
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context =
mmal_vc_lookup_client_context(mmal_buffer_header_driver_data(msg->delayed_buffer)->client_context);
MMAL_PORT_T *port = mmal_vc_port_by_number(component, msg->port_type, msg->port_num);
MMAL_PORT_T *port = mmal_vc_port_by_number(msg->client_component, msg->port_type, msg->port_num);
vcos_assert(port);
LOG_DEBUG("event bulk rx aborted");
msg->delayed_buffer->flags |= MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED;
client_context->callback_event(port, msg->delayed_buffer);
mmal_buffer_header_driver_data(msg->delayed_buffer)->
client_context->callback_event(port, msg->delayed_buffer);
}
vchiq_release_message(service, header);
}
@@ -722,12 +499,9 @@ static VCHIQ_STATUS_T mmal_vc_vchiq_callback(VCHIQ_REASON_T reason,
case VCHIQ_BULK_TRANSMIT_ABORTED:
{
mmal_worker_buffer_from_host *msg = (mmal_worker_buffer_from_host *)context;
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context =
mmal_vc_lookup_client_context(msg->drvbuf.client_context);
LOG_INFO("bulk tx aborted: %08x, %d", msg->buffer_header.data, msg->buffer_header.length);
vcos_assert(client_context->magic == MMAL_MAGIC);
LOG_INFO("bulk tx aborted: %p, %d", msg->buffer_header.data, msg->buffer_header.length);
vcos_assert(msg->drvbuf.client_context->magic == MMAL_MAGIC);
/* Nothing to do as the VC side will release the buffer and notify us of the error */
client_context = NULL; // Avoid warnings in release builds
}
break;
default:
@@ -774,7 +548,7 @@ MMAL_STATUS_T mmal_vc_sendwait_message(struct MMAL_CLIENT_T *client,
waiter = get_waiter(client);
msg_header->msgid = msgid;
msg_header->u.waiter = waiter->index;
msg_header->u.waiter = waiter;
msg_header->magic = MMAL_MAGIC;
waiter->dest = dest;

View File

@@ -76,11 +76,5 @@ MMAL_STATUS_T mmal_vc_send_message(MMAL_CLIENT_T *client,
uint8_t *data, size_t data_size,
uint32_t msgid);
uint32_t mmal_vc_allocate_client_component(MMAL_COMPONENT_T *component);
void mmal_vc_release_client_component(MMAL_COMPONENT_T *component);
uint32_t mmal_vc_allocate_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context);
MMAL_VC_CLIENT_BUFFER_CONTEXT_T *mmal_vc_lookup_client_context(int index);
void mmal_vc_release_client_context(MMAL_VC_CLIENT_BUFFER_CONTEXT_T *context);
#endif

View File

@@ -112,10 +112,10 @@ typedef struct
{
uint32_t magic;
uint32_t msgid;
uint32_t control_service; /** Handle to the control service (unused) */
struct MMAL_CONTROL_SERVICE_T *control_service; /** Handle to the control service */
union {
uint32_t waiter; /** User-land wait structure, passed back */
struct MMAL_WAITER_T *waiter; /** User-land wait structure, passed back */
} u;
MMAL_STATUS_T status; /** Result code, passed back */
@@ -152,7 +152,7 @@ typedef struct
typedef struct
{
mmal_worker_msg_header header;
uint32_t client_component; /** Client component */
void *client_component; /** Client component */
char name[128];
uint32_t pid; /**< For debug */
} mmal_worker_component_create;
@@ -206,71 +206,6 @@ typedef struct
} mmal_worker_port_info_get;
vcos_static_assert(sizeof(mmal_worker_port_info_get) <= MMAL_WORKER_MAX_MSG_LEN);
typedef struct
{
MMAL_ES_TYPE_T type; /**< Type of the elementary stream */
MMAL_FOURCC_T encoding; /**< FourCC specifying the encoding of the elementary stream.
* See the \ref MmalEncodings "pre-defined encodings" for some
* examples.
*/
MMAL_FOURCC_T encoding_variant;/**< FourCC specifying the specific encoding variant of
* the elementary stream. See the \ref MmalEncodingVariants
* "pre-defined encoding variants" for some examples.
*/
uint32_t es; /**< Type specific information for the elementary stream */
uint32_t bitrate; /**< Bitrate in bits per second */
uint32_t flags; /**< Flags describing properties of the elementary stream.
* See \ref elementarystreamflags "Elementary stream flags".
*/
uint32_t extradata_size; /**< Size of the codec specific data */
uint32_t extradata; /**< Codec specific data */
} MMAL_VC_ES_FORMAT_T;
typedef struct
{
uint32_t priv; /**< Private member used by the framework */
uint32_t name; /**< Port name. Used for debugging purposes (Read Only) */
MMAL_PORT_TYPE_T type; /**< Type of the port (Read Only) */
uint16_t index; /**< Index of the port in its type list (Read Only) */
uint16_t index_all; /**< Index of the port in the list of all ports (Read Only) */
uint32_t is_enabled; /**< Indicates whether the port is enabled or not (Read Only) */
uint32_t format; /**< Format of the elementary stream */
uint32_t buffer_num_min; /**< Minimum number of buffers the port requires (Read Only).
This is set by the component. */
uint32_t buffer_size_min; /**< Minimum size of buffers the port requires (Read Only).
This is set by the component. */
uint32_t buffer_alignment_min; /**< Minimum alignment requirement for the buffers (Read Only).
A value of zero means no special alignment requirements.
This is set by the component. */
uint32_t buffer_num_recommended; /**< Number of buffers the port recommends for optimal performance (Read Only).
A value of zero means no special recommendation.
This is set by the component. */
uint32_t buffer_size_recommended; /**< Size of buffers the port recommends for optimal performance (Read Only).
A value of zero means no special recommendation.
This is set by the component. */
uint32_t buffer_num; /**< Actual number of buffers the port will use.
This is set by the client. */
uint32_t buffer_size; /**< Actual maximum size of the buffers that will be sent
to the port. This is set by the client. */
uint32_t component; /**< Component this port belongs to (Read Only) */
uint32_t userdata; /**< Field reserved for use by the client */
uint32_t capabilities; /**< Flags describing the capabilities of a port (Read Only).
* Bitwise combination of \ref portcapabilities "Port capabilities"
* values.
*/
} MMAL_VC_PORT_T;
/** Component port info. Used to set port info.
*/
typedef struct
@@ -279,8 +214,8 @@ typedef struct
uint32_t component_handle; /**< Which component */
MMAL_PORT_TYPE_T port_type; /**< Type of port */
uint32_t index; /**< Which port of given type to get */
MMAL_VC_PORT_T port;
MMAL_VC_ES_FORMAT_T format;
MMAL_PORT_T port;
MMAL_ES_FORMAT_T format;
MMAL_ES_SPECIFIC_FORMAT_T es;
uint8_t extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
} mmal_worker_port_info_set;
@@ -296,8 +231,8 @@ typedef struct
uint32_t index; /**< Which port of given type to get */
int32_t found; /**< Did we find anything? */
uint32_t port_handle; /**< Handle to use for this port */
MMAL_VC_PORT_T port;
MMAL_VC_ES_FORMAT_T format;
MMAL_PORT_T port;
MMAL_ES_FORMAT_T format;
MMAL_ES_SPECIFIC_FORMAT_T es;
uint8_t extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
} mmal_worker_port_info;
@@ -350,7 +285,7 @@ typedef struct
/** Action parameter */
union {
struct {
MMAL_VC_PORT_T port;
MMAL_PORT_T port;
} enable;
struct {
uint32_t component_handle;
@@ -422,41 +357,9 @@ struct MMAL_DRIVER_BUFFER_T
uint32_t port_handle; /**< Index into array of ports for this component */
/** Client side uses this to get back to its context structure. */
uint32_t client_context;
struct MMAL_VC_CLIENT_BUFFER_CONTEXT_T *client_context;
};
typedef struct MMAL_VC_BUFFER_HEADER_T
{
uint32_t next; /**< Used to link several buffer headers together */
uint32_t priv; /**< Data private to the framework */
uint32_t cmd; /**< Defines what the buffer header contains. This is a FourCC
with 0 as a special value meaning stream data */
uint32_t data; /**< Pointer to the start of the payload buffer (should not be
changed by component) */
uint32_t alloc_size; /**< Allocated size in bytes of payload buffer */
uint32_t length; /**< Number of bytes currently used in the payload buffer (starting
from offset) */
uint32_t offset; /**< Offset in bytes to the start of valid data in the payload buffer */
uint32_t flags; /**< Flags describing properties of a buffer header (see
\ref bufferheaderflags "Buffer header flags") */
int64_t pts; /**< Presentation timestamp in microseconds. \ref MMAL_TIME_UNKNOWN
is used when the pts is unknown. */
int64_t dts; /**< Decode timestamp in microseconds (dts = pts, except in the case
of video streams with B frames). \ref MMAL_TIME_UNKNOWN
is used when the dts is unknown. */
/** Type specific data that's associated with a payload buffer */
uint32_t type;
uint32_t user_data; /**< Field reserved for use by the client */
} MMAL_VC_BUFFER_HEADER_T;
/** Receive a buffer from the host.
*
* @sa mmal_port_send_buffer()
@@ -479,7 +382,7 @@ typedef struct mmal_worker_buffer_from_host
struct MMAL_DRIVER_BUFFER_T drvbuf_ref;
/** the buffer header itself */
MMAL_VC_BUFFER_HEADER_T buffer_header;
MMAL_BUFFER_HEADER_T buffer_header;
MMAL_BUFFER_HEADER_TYPE_SPECIFIC_T buffer_header_type_specific;
MMAL_BOOL_T is_zero_copy;
@@ -508,29 +411,17 @@ typedef struct mmal_worker_event_to_host
{
mmal_worker_msg_header header;
uint32_t client_component;
struct MMAL_COMPONENT_T *client_component;
uint32_t port_type;
uint32_t port_num;
uint32_t cmd;
uint32_t length;
uint8_t data[MMAL_WORKER_EVENT_SPACE];
MMAL_BUFFER_HEADER_T *delayed_buffer; /* Only used to remember buffer for bulk rx */ // FIXME
MMAL_BUFFER_HEADER_T *delayed_buffer; /* Only used to remember buffer for bulk rx */
} mmal_worker_event_to_host;
vcos_static_assert(sizeof(mmal_worker_event_to_host) <= MMAL_WORKER_MAX_MSG_LEN);
typedef struct mmal_worker_event_format_changed
{
uint32_t buffer_size_min; /**< Minimum size of buffers the port requires */
uint32_t buffer_num_min; /**< Minimum number of buffers the port requires */
uint32_t buffer_size_recommended; /**< Size of buffers the port recommends for optimal performance.
A value of zero means no special recommendation. */
uint32_t buffer_num_recommended; /**< Number of buffers the port recommends for optimal
performance. A value of zero means no special recommendation. */
uint32_t format; /**< New elementary stream format */
} mmal_worker_event_format_changed;
typedef struct
{
mmal_worker_msg_header header;
@@ -624,7 +515,7 @@ static inline void mmal_vc_buffer_header_to_msg(mmal_worker_buffer_from_host *ms
msg->buffer_header.pts = header->pts;
msg->buffer_header.dts = header->dts;
msg->buffer_header.alloc_size = header->alloc_size;
msg->buffer_header.data = (uintptr_t)header->data;
msg->buffer_header.data = header->data;
msg->buffer_header_type_specific = *header->type;
}
@@ -640,17 +531,5 @@ static inline void mmal_vc_msg_to_buffer_header(MMAL_BUFFER_HEADER_T *header,
*header->type = msg->buffer_header_type_specific;
}
static inline void mmal_vc_copy_es_format_from_vc(MMAL_VC_ES_FORMAT_T *src, MMAL_ES_FORMAT_T *dest)
{
// IPC MMAL_VC_ES_FORMAT_T is not necessarily the same as MMAL_ES_FORMAT_T,
// so copy fields individually.
dest->type = src->type;
dest->encoding = src->encoding;
dest->encoding_variant = src->encoding_variant;
dest->bitrate = src->bitrate;
dest->flags = src->flags;
dest->extradata_size = src->extradata_size;
}
#endif