/*********************************************************** * Name: vc_dispmanx_resource_read_data * * Arguments: * DISPMANX_RESOURCE_HANDLE_T res * int src_pitch * void * src_address * const VC_RECT_T * rect * * Description: Copy the bitmap data to VideoCore memory * * Returns: 0 or failure * ***********************************************************/ VCHPRE_ int VCHPOST_ vc_dispmanx_resource_read_data( DISPMANX_RESOURCE_HANDLE_T handle, const VC_RECT_T* p_rect, void * dst_address, uint32_t dst_pitch ) { uint8_t* host_start; int32_t bulk_len; int32_t success = 0; if ( p_rect == 0 || dst_address == 0 || dst_pitch == 0 ) { return -1; } host_start = (uint8_t *)dst_address + (dst_pitch * p_rect->y); bulk_len = (int32_t)dst_pitch * (p_rect->height-p_rect->y); // Now send the bulk transfer across // command parameters: resource handle, destination y, bulk length uint32_t param[] = { VC_HTOV32(handle), VC_HTOV32(p_rect->y), VC_HTOV32(bulk_len) }; success = dispmanx_send_command( EDispmanBulkRead | DISPMANX_NO_REPLY_MASK, param, sizeof(param)); if (success == 0) { lock_obtain(); success = vchi_bulk_queue_receive( dispmanx_client.client_handle[0], host_start, bulk_len, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, 0 ); lock_release(); } return (int) success; }
/*********************************************************** * Name: cecservice_wait_for_bulk_receive * * Arguments: response buffer, buffer length * * Description: blocked until bulk receive * * Returns error code of vchi * ***********************************************************/ static int32_t cecservice_wait_for_bulk_receive(void *buffer, uint32_t max_length) { vcos_assert(((uint32_t) buffer & 0xf) == 0); //should be 16 byte aligned return vchi_bulk_queue_receive( cecservice_client.client_handle[0], buffer, max_length, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL ); }
/****************************************************************************** NAME vchostreq_writemem SYNOPSIS VC_RESP_CODE_T vchostreq_writemem( void* host_addr, void *vc_addr, int len, int channel ) FUNCTION Writes a block of data from Videocore into the host memory area specified by host_addr Obsolete now RETURNS Success : 0 - all the data was copied Fail : 1 - error in input parameters or operation ******************************************************************************/ int vchostreq_writemem( void* host_addr, void *vc_addr, int len, int channel /* not used */ ) { uint32_t param[] = {(uint32_t) host_addr, len, (uint32_t) vc_addr}; int success = hostreq_send_command(VC_HOSTREQ_WRITEMEM, param, sizeof(param)); assert(success == 0); assert(0); // should not be calling this function success = vchi_bulk_queue_receive(hostreq_client.client_handle[0], host_addr, len, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL); assert(success == 0); return (success == 0) ? 0 : 1; }
// if handle==MEM_HANDLE_INVALID: data is a pointer, size is length // if handle!=MEM_HANDLE_INVALID: data is int, offset from handle base, size is length void vchiq_queue_bulk_receive(VCHIQ_STATE_T *state, int fourcc, VCHI_MEM_HANDLE_T handle, void *data, int size, void *userdata) { VCHIQ_WRAPPER_T *st = wrapper_list; while(st != NULL && (st->state != state || st->fourcc != fourcc)) st = st->next; vcos_demand(st != NULL); if(handle == MEM_HANDLE_INVALID) vchi_bulk_queue_receive(st->vchi_handle, data, size, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL); else vchi_bulk_queue_receive_reloc(st->vchi_handle, handle, (uint32_t) data, size, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL); st->callback(VCHIQ_BULK_RECEIVE_DONE, NULL, st->userdata, NULL); }
int32_t vc_vchi_fb_read(VC_VCHI_FB_HANDLE_T handle, uint32_t res_handle, void *buf, int32_t size) { int32_t ret, success = 0; FB_INSTANCE_T *instance = handle; uint32_t msg_len; VC_FB_MSG_HDR_T *msg_hdr; VC_FB_READ_T *fb_read; VC_FB_RESULT_T result; if (handle == NULL) { LOG_ERR("%s: invalid handle", __func__); ret = -1; goto out; } if (buf == NULL) { LOG_ERR("%s: invalid buffer pointer", __func__); ret = -1; goto out; } if (size <= 0) { LOG_ERR("%s: invalid buffer size %d", __func__, size); ret = -1; goto out; } mutex_lock(&instance->vchi_mutex); vchi_service_use(instance->vchi_handle[0]); LOG_INFO("%s: enter", __func__); msg_len = sizeof(*msg_hdr) + sizeof(*fb_read); memset(instance->msg_buf, 0, msg_len); msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf; msg_hdr->type = VC_FB_MSG_TYPE_READ; fb_read = (VC_FB_READ_T *) msg_hdr->body; fb_read->res_handle = res_handle; fb_read->size = size; /* Send the message to the videocore */ success = vchi_msg_queue(instance->vchi_handle[0], instance->msg_buf, msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (success != 0) { LOG_ERR("%s: failed to queue message (success=%d)", __func__, success); ret = -1; goto unlock; } LOG_INFO("%s: done sending msg", __func__); /* We are expecting a reply from the videocore */ down(&instance->msg_avail); success = vchi_msg_dequeue(instance->vchi_handle[0], &result, sizeof(result), &msg_len, VCHI_FLAGS_NONE); LOG_INFO("%s: got reply message %x", __func__, result.success); if (success != 0) { LOG_ERR("%s: failed to dequeue message (success=%d)", __func__, success); ret = -1; goto unlock; } else if (msg_len != sizeof(result)) { LOG_ERR("%s: incorrect message length %u (expected=%u)", __func__, msg_len, sizeof(result)); ret = -1; goto unlock; } LOG_INFO("%s: all good do bulk_receive %x", __func__, result.success); success = vchi_bulk_queue_receive(instance->vchi_handle[0], buf, size, VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, 0); if (success != 0) LOG_ERR("%s: vchi_bulk_queue_receive failed", __func__); unlock: vchi_service_release(instance->vchi_handle[0]); mutex_unlock(&instance->vchi_mutex); ret = success; LOG_INFO("%s: exit", __func__); out: return ret; }
// receive a buffer from VideoCore either from the message bytes // or by a bulk transfer receieve OMX_BUFFERHEADERTYPE *vc_ilcs_receive_buffer(void *call, int clen, OMX_COMPONENTTYPE **pComp) { IL_PASS_BUFFER_EXECUTE_T *exe = call; OMX_BUFFERHEADERTYPE *pHeader = exe->bufferHeader.pInputPortPrivate; OMX_U8 *pBuffer = pHeader->pBuffer; OMX_PTR *pAppPrivate = pHeader->pAppPrivate; OMX_PTR *pPlatformPrivate = pHeader->pPlatformPrivate; OMX_PTR *pInputPortPrivate = pHeader->pInputPortPrivate; OMX_PTR *pOutputPortPrivate = pHeader->pOutputPortPrivate; vc_assert(pHeader); memcpy(pHeader, &exe->bufferHeader, sizeof(OMX_BUFFERHEADERTYPE)); *pComp = exe->reference; pHeader->pBuffer = pBuffer; pHeader->pAppPrivate = pAppPrivate; pHeader->pPlatformPrivate = pPlatformPrivate; pHeader->pInputPortPrivate = pInputPortPrivate; pHeader->pOutputPortPrivate = pOutputPortPrivate; if(exe->method == IL_BUFFER_BULK) { vc_assert(VCHI_BULK_ALIGNED(pHeader->pBuffer)); IL_BUFFER_BULK_T *fixup = (IL_BUFFER_BULK_T *) (exe+1); // bulk transfer from videocore to host uint8_t *start = pHeader->pBuffer + pHeader->nOffset; uint8_t *end = start + pHeader->nFilledLen; int32_t bulk_len = pHeader->nFilledLen - fixup->headerlen - fixup->trailerlen; int32_t result; vc_assert(clen == sizeof(IL_PASS_BUFFER_EXECUTE_T) + sizeof(IL_BUFFER_BULK_T)); result = vchi_bulk_queue_receive( vc_ilcsg.vchi_handle, start + fixup->headerlen, bulk_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED | VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL ); vc_assert(result == 0); if (fixup->headerlen) memcpy(start, fixup->header, fixup->headerlen); if (fixup->trailerlen) memcpy(end-fixup->trailerlen, fixup->trailer, fixup->trailerlen); } else if(exe->method == IL_BUFFER_INLINE) { IL_BUFFER_INLINE_T *buffer = (IL_BUFFER_INLINE_T *) (exe+1); vc_assert(clen == sizeof(IL_PASS_BUFFER_EXECUTE_T) + pHeader->nFilledLen); memcpy(pBuffer+pHeader->nOffset, buffer->buffer, pHeader->nFilledLen); } else if(exe->method == IL_BUFFER_NONE) { vc_assert(clen == sizeof(IL_PASS_BUFFER_EXECUTE_T)); } else if(exe->method == IL_BUFFER_MAX) { vc_assert(0); } return pHeader; }
//Request handler static void hostreq_request_handler(int inum, HOSTREQ_SERVICE_T *state){ assert(state->response_length); uint32_t *data = (uint32_t*)state->response_buffer; uint32_t command = *data; int32_t success = 0; data ++; state->response_length -= sizeof(uint32_t); switch(command) { case VC_HOSTREQ_TIME: { //VC asks for time //HOST specific implementation //We just return zero for time for now time_t dummytime = vchi_hostreq_time(); int success = hostreq_send_command(VC_HOSTREQ_TIME, &dummytime, sizeof(dummytime)); assert(success == 0); break; } case VC_HOSTREQ_NOTIFY: { //Host notify assert(state->response_length == 2*sizeof(uint32_t)); VC_HRNOTIFY_T reason = (VC_HRNOTIFY_T) *data; data ++; uint32_t param = *data; if(hostreq_client.notify_callbacks[reason]) { (*hostreq_client.notify_callbacks[reason])(reason, param); } break; } case VC_HOSTREQ_READMEM: { //params are hostaddr, len, vc addr uint32_t *param = data; assert(param[0]); success = vchi_bulk_queue_transmit(hostreq_client.client_handle[0], (void *)param[0], param[1], VCHI_FLAGS_NONE, NULL); assert(success == 0); break; } case VC_HOSTREQ_WRITEMEM: { //params are hostaddr, len, vc addr uint32_t *param = data; assert(param[0]); success = vchi_bulk_queue_receive(hostreq_client.client_handle[0], (void *)param[0], param[1], VCHI_FLAGS_NONE, NULL); assert(success == 0); break; } default: assert(!"unhandled request"); } }