Пример #1
0
/***********************************************************
 * Name: vc_dispmanx_resource_write_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_write_data( DISPMANX_RESOURCE_HANDLE_T handle, VC_IMAGE_TYPE_T src_type /* not used */,
                                                      int src_pitch, void * src_address, const VC_RECT_T * rect ) {
	(void)src_type;

   //Note that x coordinate of the rect is NOT used
   //Address of data in host
   uint8_t *host_start = (uint8_t *)src_address + src_pitch * rect->y;
   int32_t bulk_len = src_pitch * rect->height, success = 0;

   //Now send the bulk transfer across
   //command parameters: resource handle, destination y, bulk length
   uint32_t param[] = {VC_HTOV32(handle), VC_HTOV32(rect->y), VC_HTOV32(bulk_len)};
   success = dispmanx_send_command(  EDispmanBulkWrite | DISPMANX_NO_REPLY_MASK, param, sizeof(param));
   if(success == 0)
   {
      lock_obtain();
      success = vchi_bulk_queue_transmit( dispmanx_client.client_handle[0],
                                          host_start,
                                          bulk_len,
                                          VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
                                          NULL );
      lock_release();
   }
   return (int) success;
}
Пример #2
0
/******************************************************************************
NAME
   vchostreq_readmem

SYNOPSIS
   VC_RESP_CODE_T vchostreq_readmem( void* host_addr, void *vc_addr, int len )

FUNCTION
   Allows Videocore to read a block of memory from a
   memory area on the host specified by host_addr
   Obsolete now

RETURNS
   Success  : 0 - all the data was copied
   Fail     : 1 - error in input parameters or operation
******************************************************************************/
int vchostreq_readmem( void* host_addr, void *vc_addr, int len ) {
   uint32_t param[] = {(uint32_t) host_addr, len, (uint32_t) vc_addr};
   int success = hostreq_send_command(VC_HOSTREQ_READMEM, param, sizeof(param));
   assert(success == 0);
   assert(0); // should not be calling this function
   success =  vchi_bulk_queue_transmit(hostreq_client.client_handle[0],
                                       host_addr,
                                       len,
                                       VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
                                       NULL);
   assert(success == 0);
   return (success == 0) ? 0 : 1;
}
Пример #3
0
// 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_transmit(VCHIQ_STATE_T *state, int fourcc, VCHI_MEM_HANDLE_T handle, const 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_transmit(st->vchi_handle, data, size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
   else
      vchi_bulk_queue_transmit_reloc(st->vchi_handle, handle, (uint32_t) data, size, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
}
Пример #4
0
/***********************************************************
 * Name: vc_dispmanx_resource_set_palette
 *
 * Arguments:
 *       DISPMANX_RESOURCE_HANDLE_T res
 *       void * src_address
 *       int offset
 *       int size
 *
 * Description: Set the resource palette (for VC_IMAGE_4BPP and VC_IMAGE_8BPP)
 *              offset should be 0
 *              size is 16*2 for 4BPP and 256*2 for 8BPP
 * Returns: 0 or failure
 *
 ***********************************************************/
VCHPRE_ int VCHPOST_ vc_dispmanx_resource_set_palette( DISPMANX_RESOURCE_HANDLE_T handle, 
                                                      void * src_address, int offset, int size) {
   //Note that x coordinate of the rect is NOT used
   //Address of data in host
   uint8_t *host_start = src_address;
   int32_t bulk_len = size, success = 0;

   //Now send the bulk transfer across
   //command parameters: resource size
   uint32_t param[] = {VC_HTOV32(handle), VC_HTOV32(offset), VC_HTOV32(bulk_len) };
   success = dispmanx_send_command(  EDispmanSetPalette | DISPMANX_NO_REPLY_MASK, param, sizeof(param));
   if(success == 0)
   {
      lock_obtain();
      success = vchi_bulk_queue_transmit( dispmanx_client.client_handle[0],
                                          host_start,
                                          bulk_len,
                                          VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
                                          NULL );
      lock_release();
   }
   return (int) success;
}
Пример #5
0
int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream,
			       uint32_t count, void *src)
{
	VC_AUDIO_MSG_T m;
	AUDIO_INSTANCE_T *instance = alsa_stream->instance;
	int32_t success;
	int ret;

	LOG_DBG(" .. IN\n");

	LOG_INFO(" Writing %d bytes from %p\n", count, src);

	if(mutex_lock_interruptible(&instance->vchi_mutex))
	{
		LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections);
		return -EINTR;
	}
	vchi_service_use(instance->vchi_handle[0]);

	if ( instance->peer_version==0 && vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0 ) {
		LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version);
	}
	m.type = VC_AUDIO_MSG_TYPE_WRITE;
	m.u.write.count = count;
	// old version uses bulk, new version uses control
	m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0:4000;
	m.u.write.callback = alsa_stream->fifo_irq_handler;
	m.u.write.cookie = alsa_stream;
	m.u.write.silence = src == NULL;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 &m, sizeof m,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);

	if (success != 0) {
		LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	if (!m.u.write.silence) {
		if (m.u.write.max_packet == 0) {
			/* Send the message to the videocore */
			success = vchi_bulk_queue_transmit(instance->vchi_handle[0],
							   src, count,
							   0 *
							   VCHI_FLAGS_BLOCK_UNTIL_QUEUED
							   +
							   1 *
							   VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
							   NULL);
		} else {
			while (count > 0) {
				int bytes = min((int)m.u.write.max_packet, (int)count);
				success = vchi_msg_queue(instance->vchi_handle[0],
							 src, bytes,
							 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
				src = (char *)src + bytes;
				count -= bytes;
			}
		}
		if (success != 0) {
			LOG_ERR
			    ("%s: failed on vchi_bulk_queue_transmit (status=%d)\n",
			     __func__, success);

			ret = -1;
			goto unlock;
		}
	}
	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);
	LOG_DBG(" .. OUT\n");
	return ret;
}
Пример #6
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;
}
Пример #7
0
static void omx_buffer_fixup(IL_PASS_BUFFER_EXECUTE_T* data, void**data2, int*len2,IL_BUFFER_BULK_T *fixup)
{
  OMX_BUFFERHEADERTYPE* headptr;
  void* uaddr;
  vc_malloc_t desc;

   OMX_BUFFERHEADERTYPE *pBuffer;
   IL_RESPONSE_HEADER_T *resp;
   
   *data2 = NULL;
   *len2 = 0;
   
  if(NULL==data || NULL == data->bufferHeader.pBuffer)
	{
	  OMX_DEBUG("error: invalid / corrupt memory\n");
	  return;
	}
  
  headptr = &data->bufferHeader;
  uaddr = (void*)headptr->pBuffer;
  uaddr -= sizeof(desc);
  memcpy(&desc, uaddr, sizeof(desc));

  //
  if(desc.key != VC_MAGIC || NULL == desc.kaddr || NULL == desc.addr)
	{
	  OMX_DEBUG("error: invalid / corrupt memory\n");
	  return;
	}

  headptr->pPlatformPrivate =  headptr->pBuffer;
  headptr->pBuffer = desc.kaddr + sizeof(desc);
#if 0
  vchi_bulk_queue_transmit(vc_ilcs_vchi_handle(),
			   headptr->pBuffer + headptr->nOffset,
			   headptr->nFilledLen,
			   VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
			   NULL );
#else
  pBuffer = headptr;
   if(pBuffer->nFilledLen)
   {
      if(pBuffer->nFilledLen + sizeof(IL_PASS_BUFFER_EXECUTE_T) <= VC_ILCS_MAX_INLINE)
      {
         data->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;

         data->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
   {
      data->method = IL_BUFFER_NONE;
   }
#endif


}
Пример #8
0
/* ----------------------------------------------------------------------
 * send a string to the host side IL component service.  if resp is NULL
 * then there is no response to this call, so we should not wait for one.
 *
 * returns 0 on successful call made, -1 on failure to send call.
 * on success, the response is written to 'resp' pointer
 * -------------------------------------------------------------------- */
int vc_ilcs_execute_function( IL_FUNCTION_T func, void *data, int len, void *data2, int len2, void *bulk, int bulk_len, void *resp )
{
   VC_ILCS_WAIT_T *wait;
   int i, num;

   // the host MUST receive a response
   vc_assert( resp );

   // need to atomically find free ->wait entry
   os_semaphore_obtain( &vc_ilcsg.wait_sem );

   // we try a number of times then give up with an error message
   // rather than just deadlocking
   for (i=0; i<VC_ILCS_WAIT_TIMEOUT; i++) {
      num = 0;

      while( num < VC_ILCS_MAX_WAITING && vc_ilcsg.wait[num].resp )
         num++;

      if ( num < VC_ILCS_MAX_WAITING || i == VC_ILCS_WAIT_TIMEOUT-1)
         break;

      // might be a fatal error if another thread is relying
      // on this call completing before it can complete
      // we'll pause until we can carry on and hope that's sufficient.
      os_semaphore_release( &vc_ilcsg.wait_sem );
      os_sleep( 10 ); // 10 msec

      // if we're the vcilcs thread, then the waiters might need
      // us to handle their response, so try and clear those now
      if(os_thread_is_running(&vc_ilcsg.thread))
         while(vc_ilcs_process_message(0));

      os_logging_message( "%s: wait for sem", __FUNCTION__);
      os_semaphore_obtain( &vc_ilcsg.wait_sem );
   }

   if(num == VC_ILCS_MAX_WAITING)
   {
      // failed to send message.
      vc_assert(0);
      os_semaphore_release( &vc_ilcsg.wait_sem );
      return -1;
   }

   wait = &vc_ilcsg.wait[num];

   wait->resp = resp;
   wait->xid = vc_ilcsg.next_xid++;
   os_semaphore_create( &wait->sem, OS_SEMAPHORE_TYPE_SUSPEND );
   os_semaphore_obtain( &wait->sem );

   // at this point, ->wait is exclusively ours ()
   os_semaphore_release( &vc_ilcsg.wait_sem );

   if(bulk)
      os_semaphore_obtain( &vc_ilcsg.send_sem);

   // write the command header.
   vc_ilcs_transmit( func, wait->xid, data, len, data2, len2 );

   if(bulk)
   {
      int result;
      result = vchi_bulk_queue_transmit( vc_ilcsg.vchi_handle,                // call to VCHI
                                         bulk, bulk_len,
                                         VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
                                         NULL );
      vc_assert(result == 0);
      os_semaphore_release( &vc_ilcsg.send_sem);
   }

   if ( !os_thread_is_running(&vc_ilcsg.thread) ) {

      os_semaphore_obtain( &wait->sem );

   } else {

      // we're the vcilcs task, so wait for, and handle, incoming
      // messages while we're not completed
      for (;;) {
         // wait->sem will not be released until we process the response message
         vc_ilcs_process_message(1);

         // did the last message release wait->sem ?
         if ( !os_semaphore_obtained(&wait->sem) )
            break;
      }
   }

   // safe to do the following - the assignment of NULL is effectively atomic
   os_semaphore_destroy( &wait->sem );
   wait->resp = NULL;
   return 0;
}
Пример #9
0
//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");
   }
}