Пример #1
0
/* ----------------------------------------------------------------------
 * received response to an ILCS command
 * -------------------------------------------------------------------- */
static void
vc_ilcs_command( uint32_t cmd, uint32_t xid, unsigned char *msg, int len )
{
   // execute this function call
   unsigned char resp[VC_ILCS_MAX_CMD_LENGTH];
   int rlen = -1;

   if ( cmd >= IL_FUNCTION_MAX_NUM ) {
      assert(0);
      return;
   }

   VCIL_FN_T *fn = &vcilcs_fns[ cmd ];
   if ( !fn ) {
      assert(0);
      return;
   }

   //logging_message( LOGGING_VMCS_VERBOSE, "ilcs_poll_fifo: executing xid:%x", xid );

   // at this point we are executing in ILCS task context (videocore side).
   // FIXME: can this cause ilcs_execute_function() calls from within bowels of openmaxil?
   (*fn)( msg, len, resp, &rlen );

   // make sure rlen has been initialised by the function
   assert( rlen != -1 );

   // if rlen is zero, then we don't send a response
   if ( rlen )
      vc_ilcs_transmit( IL_RESPONSE, xid, resp, rlen, NULL, 0 );
}
Пример #2
0
/* ----------------------------------------------------------------------
 * received response to an ILCS command
 * -------------------------------------------------------------------- */
static void
vc_ilcs_command( uint32_t cmd, uint32_t xid, unsigned char *msg, int len )
{
   // execute this function call
   unsigned char resp[VC_ILCS_MAX_CMD_LENGTH];
   int rlen = -1;
   VCIL_FN_T *fn;

   if ( cmd >= IL_FUNCTION_MAX_NUM ) {
      vc_assert(0);
      return;
   }

   fn = &vcilcs_fns[ cmd ];
   if ( !fn ) {
      vc_assert(0);
      return;
   }

   // at this point we are executing in ILCS task context (host side).
   // NOTE: this cause vc_ilcs_execute_function() calls from within bowels of openmaxil?
   (*fn)( msg, len, resp, &rlen );

   // make sure rlen has been initialised by the function
   vc_assert( rlen != -1 );

   // if rlen is zero, then we don't send a response
   if ( rlen )
      vc_ilcs_transmit( IL_RESPONSE, xid, resp, rlen, NULL, 0 );
}
Пример #3
0
static void vc_ilcs_command_usr( uint32_t cmd, uint32_t xid, unsigned char *msg, int msglen )
{
  int rlen;
  uint8_t resp[VC_ILCS_MAX_CMD_LENGTH];
  
  vcilcs_inb_put(cmd, xid, msg, msglen, resp, &rlen); // no responce is expected iommediately, it'll be sent asynch.
  if ( rlen )
    vc_ilcs_transmit( IL_RESPONSE, xid, resp, rlen,NULL,0 );
}
Пример #4
0
int vc_ilcsinb_sendresp(vc_ilcsinb_t* msgptr)
{
  vc_ilcs_transmit(IL_RESPONSE, msgptr->xid, msgptr->resp, msgptr->resplen,NULL,0);
  return 0;
}
Пример #5
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 response, written to 'resp' pointer
 * -------------------------------------------------------------------- */
void
vc_ilcs_execute_function( IL_FUNCTION_T func, void *data, int len, void *data2, int len2, void *resp, int resplen )
{
   VC_ILCS_WAIT_T *wait;
   int num;

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

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

   for (;;) {
      num = 0;

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

      if ( num < VC_ILCS_MAX_WAITING )
         break;

      assert( num < VC_ILCS_MAX_WAITING );
      // 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
      os_semaphore_obtain( &vc_ilcsg.wait_sem );
   }
   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 );

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

   if ( !os_thread_current(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
         if ( vc_ilcs_process_message() == 0 ) {
            // there were no more messages in the fifo; need to wait
            os_semaphore_obtain( &vc_ilcsg.rxmsg_sem );
            continue;
         }

         // 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;
}
Пример #6
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;
}