int vc_ilcs_execute_function_usr(vcilcs_func_out_t* arg) { vcilcs_func_out_t omxdesc; uint8_t cmd[VC_ILCS_MAX_CMD_LENGTH]; uint8_t resp[VC_ILCS_MAX_CMD_LENGTH]; void *data2 = NULL; int len2 = 0; IL_BUFFER_BULK_T fixup; // if(copy_from_user( &omxdesc, (void *)arg, sizeof(omxdesc)) != 0) { VC_DEBUG( Trace, "error, arg=0x%08X\n", (int)arg); return -EFAULT; } assert(omxdesc.len <= VC_ILCS_MAX_CMD_LENGTH); assert(omxdesc.resplen <= VC_ILCS_MAX_RESP_LENGTH); if(copy_from_user(cmd, omxdesc.data, omxdesc.len) != 0) { VC_DEBUG( Trace, "copy_from_user error, arg=0x%08X\n", (int)arg); return -EFAULT; } // memset(resp, 0, omxdesc.resplen); if(IL_EMPTY_THIS_BUFFER == omxdesc.func) { omx_buffer_fixup((IL_PASS_BUFFER_EXECUTE_T*)cmd,&data2,&len2,&fixup); } // vc_ilcs_execute_function((IL_FUNCTION_T)omxdesc.func, cmd, omxdesc.len, data2, len2, resp, omxdesc.resplen); // if(copy_to_user((void *)omxdesc.resp, resp, omxdesc.resplen) != 0) { VC_DEBUG( Trace, "vc03: error, copy_to_user failed\n" ); return -EFAULT; } return 0; }
// send a buffer to VideoCore either by writing the buffer data in a control // message or by sending an aligned bulk transfer with fixup information in the // control message. OMX_ERRORTYPE vc_ilcs_pass_buffer(IL_FUNCTION_T func, void *reference, OMX_BUFFERHEADERTYPE *pBuffer) { IL_PASS_BUFFER_EXECUTE_T exe; IL_BUFFER_BULK_T fixup; IL_RESPONSE_HEADER_T resp; void *data2 = NULL; int len2 = 0; if ((func == IL_EMPTY_THIS_BUFFER && pBuffer->pInputPortPrivate == NULL) || (func == IL_FILL_THIS_BUFFER && pBuffer->pOutputPortPrivate == NULL)) { // return this to pass conformance // the actual error is using a buffer that hasn't be registered with usebuffer/allocatebuffer return OMX_ErrorIncorrectStateOperation; } exe.reference = reference; memcpy(&exe.bufferHeader, pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); if(pBuffer->nFilledLen) { if(pBuffer->nFilledLen + sizeof(IL_PASS_BUFFER_EXECUTE_T) <= VC_ILCS_MAX_INLINE) { exe.method = IL_BUFFER_INLINE; data2 = pBuffer->pBuffer + pBuffer->nOffset; len2 = pBuffer->nFilledLen; } else { const uint8_t *start = pBuffer->pBuffer + pBuffer->nOffset; const uint8_t *end = start + pBuffer->nFilledLen; const uint8_t *round_start = (const OMX_U8*)VCHI_BULK_ROUND_UP(start); const uint8_t *round_end = (const OMX_U8*)VCHI_BULK_ROUND_DOWN(end); int bulk_len = round_end-round_start; int32_t result; exe.method = IL_BUFFER_BULK; result = vchi_bulk_queue_transmit( vc_ilcsg.vchi_handle, round_start, round_end-round_start, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); // when IL_EMPTY_THIS_BUFFER executes on videocore, there is a // corresponding vchi_bulk_queue_receive, which blocks until // complete (at which point, the above vchi_bulk_queue_transmit // must by definition have completed) vc_assert(result == 0); if((fixup.headerlen = round_start - start) > 0) memcpy(fixup.header, start, fixup.headerlen); if((fixup.trailerlen = end - round_end) > 0) memcpy(fixup.trailer, round_end, fixup.trailerlen); data2 = &fixup; len2 = sizeof(IL_BUFFER_BULK_T); } } else { exe.method = IL_BUFFER_NONE; } vc_ilcs_execute_function(func, &exe, sizeof(IL_PASS_BUFFER_EXECUTE_T), data2, len2, &resp, sizeof(resp)); return resp.err; }
OMX_ERRORTYPE vc_ilcs_pass_buffer(IL_FUNCTION_T func, void *reference, OMX_BUFFERHEADERTYPE *pBuffer) { IL_PASS_BUFFER_EXECUTE_T exe; IL_BUFFER_BULK_T fixup; IL_RESPONSE_HEADER_T resp; void *data2 = NULL; int len2 = 0; void *bulk = NULL; int bulk_len = 0; if ((func == IL_EMPTY_THIS_BUFFER && pBuffer->pInputPortPrivate == NULL) || (func == IL_FILL_THIS_BUFFER && pBuffer->pOutputPortPrivate == NULL)) { // return this to pass conformance // the actual error is using a buffer that hasn't be registered with usebuffer/allocatebuffer return OMX_ErrorIncorrectStateOperation; } exe.reference = reference; memcpy(&exe.bufferHeader, pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); exe.bufferLen = pBuffer->nFilledLen; if(pBuffer->nFlags & OMX_BUFFERFLAG_EXTRADATA) { OMX_U8 *ptr = pBuffer->pBuffer + pBuffer->nOffset + pBuffer->nFilledLen + 3; OMX_OTHER_EXTRADATATYPE *extra = (OMX_OTHER_EXTRADATATYPE *) (((uint32_t) ptr) & ~3); while(extra->eType != OMX_ExtraDataNone) extra = (OMX_OTHER_EXTRADATATYPE *) (((uint8_t *) extra) + extra->nSize); exe.bufferLen = (((uint8_t *) extra) + extra->nSize) - (pBuffer->pBuffer + pBuffer->nOffset); } if(exe.bufferLen) { if(exe.bufferLen + sizeof(IL_PASS_BUFFER_EXECUTE_T) <= VC_ILCS_MAX_INLINE) { exe.method = IL_BUFFER_INLINE; data2 = pBuffer->pBuffer + pBuffer->nOffset; len2 = exe.bufferLen; } else { const uint8_t *start = pBuffer->pBuffer + pBuffer->nOffset; const uint8_t *end = start + exe.bufferLen; const uint8_t *round_start = (const OMX_U8*)VCHI_BULK_ROUND_UP(start); const uint8_t *round_end = (const OMX_U8*)VCHI_BULK_ROUND_DOWN(end); exe.method = IL_BUFFER_BULK; bulk = (void *) round_start; bulk_len = round_end - round_start; if((fixup.headerlen = round_start - start) > 0) memcpy(fixup.header, start, fixup.headerlen); if((fixup.trailerlen = end - round_end) > 0) memcpy(fixup.trailer, round_end, fixup.trailerlen); data2 = &fixup; len2 = sizeof(IL_BUFFER_BULK_T); } } else { exe.method = IL_BUFFER_NONE; } if(vc_ilcs_execute_function(func, &exe, sizeof(IL_PASS_BUFFER_EXECUTE_T), data2, len2, bulk, bulk_len, &resp) < 0) return OMX_ErrorHardware; return resp.err; }