/** Send a message and do not wait for a reply. * * @note * This function should only be called from within a mmal component, so * vchiq_use/release_service calls aren't required (dealt with at higher level). * * @param client client to send message for * @param msg_header message header to send * @param size length of message, including header * @param msgid message id */ MMAL_STATUS_T mmal_vc_send_message(MMAL_CLIENT_T *client, mmal_worker_msg_header *msg_header, size_t size, uint8_t *data, size_t data_size, uint32_t msgid) { VCHIQ_STATUS_T vst; VCHIQ_ELEMENT_T elems[] = {{msg_header, size}}; MMAL_BOOL_T using_bulk_transfer = (data_size != 0); LOG_TRACE("len %d", data_size); vcos_assert(size >= sizeof(mmal_worker_msg_header)); if (!client->inited) { vcos_assert(0); return MMAL_EINVAL; } if (using_bulk_transfer) vcos_mutex_lock(&client->bulk_lock); msg_header->msgid = msgid; msg_header->magic = MMAL_MAGIC; vst = vchiq_queue_message(client->service, elems, 1); if (vst != VCHIQ_SUCCESS) { if (using_bulk_transfer) vcos_mutex_unlock(&client->bulk_lock); LOG_ERROR("failed"); goto error; } if (using_bulk_transfer) { LOG_TRACE("bulk transmit: %p, %i", data, data_size); data_size = (data_size + 3) & ~3; vst = vchiq_queue_bulk_transmit(client->service, data, data_size, msg_header); vcos_mutex_unlock(&client->bulk_lock); if (!vcos_verify(vst == VCHIQ_SUCCESS)) { LOG_ERROR("failed bulk transmit"); /* This really should not happen and if it does, things will go wrong as * we've already queued the vchiq message above. */ vcos_assert(0); goto error; } } return MMAL_SUCCESS; error: return MMAL_EIO; }
static void send_bulk(CLIENT_THREAD_STATE_T *thread, const void *in, uint32_t len) { if (len <= CTRL_THRESHOLD) { VCHIQ_ELEMENT_T element; element.data = in; element.size = len; VCHIQ_STATUS_T vchiq_status = vchiq_queue_message(get_handle(thread), &element, 1); assert(vchiq_status == VCHIQ_SUCCESS); } else { VCHIQ_STATUS_T vchiq_status = vchiq_queue_bulk_transmit(get_handle(thread), in, rpc_pad_bulk(len), NULL); assert(vchiq_status == VCHIQ_SUCCESS); VCOS_STATUS_T vcos_status = vcos_event_wait(&bulk_event); assert(vcos_status == VCOS_SUCCESS); } }
/** Send a message and wait for a reply. * * @param client client to send message for * @param msg_header message vchiq_header to send * @param size length of message, including header * @param msgid message id * @param dest destination for reply * @param destlen size of destination, updated with actual length * @param send_dummy_bulk whether to send a dummy bulk transfer */ MMAL_STATUS_T mmal_vc_sendwait_message(struct MMAL_CLIENT_T *client, mmal_worker_msg_header *msg_header, size_t size, uint32_t msgid, void *dest, size_t *destlen, MMAL_BOOL_T send_dummy_bulk) { MMAL_STATUS_T ret; MMAL_WAITER_T *waiter; VCHIQ_STATUS_T vst; VCHIQ_ELEMENT_T elems[] = {{msg_header, size}}; vcos_assert(size >= sizeof(mmal_worker_msg_header)); vcos_assert(dest); if (!client->inited) { vcos_assert(0); return MMAL_EINVAL; } if (send_dummy_bulk) vcos_mutex_lock(&client->bulk_lock); waiter = get_waiter(client); msg_header->msgid = msgid; msg_header->u.waiter = waiter; msg_header->magic = MMAL_MAGIC; waiter->dest = dest; waiter->destlen = *destlen; LOG_TRACE("wait %p, reply to %p", waiter, dest); mmal_vc_use_internal(client); vst = vchiq_queue_message(client->service, elems, 1); if (vst != VCHIQ_SUCCESS) { ret = MMAL_EIO; if (send_dummy_bulk) vcos_mutex_unlock(&client->bulk_lock); goto fail_msg; } if (send_dummy_bulk) { uint32_t data_size = 8; /* The data is just some dummy bytes so it's fine for it to be static */ static uint8_t data[8]; vst = vchiq_queue_bulk_transmit(client->service, data, data_size, msg_header); vcos_mutex_unlock(&client->bulk_lock); if (!vcos_verify(vst == VCHIQ_SUCCESS)) { LOG_ERROR("failed bulk transmit"); /* This really should not happen and if it does, things will go wrong as * we've already queued the vchiq message above. */ vcos_assert(0); ret = MMAL_EIO; goto fail_msg; } } /* now wait for the reply... * * FIXME: we could do with a timeout here. Need to be careful to cancel * the semaphore on a timeout. */ vcos_semaphore_wait(&waiter->sem); mmal_vc_release_internal(client); LOG_TRACE("got reply (len %i/%i)", (int)*destlen, (int)waiter->destlen); *destlen = waiter->destlen; release_waiter(client, waiter); return MMAL_SUCCESS; fail_msg: mmal_vc_release_internal(client); release_waiter(client, waiter); return ret; }