void Start(CThreadProc pThreadProc, T* pInstance, const char* pThreadName = "")
		{
			m_pThreadProc = pThreadProc;
			m_pInstance = pInstance;
			CHECK_VCOS(vcos_thread_create(&m_Thread, pThreadName, NULL, static_cast<VCOS_THREAD_ENTRY_FN_T>(&CThreadT::ThreadProc), this), "failed to create thread");
			CHECK_VCOS(vcos_event_wait(&m_InitializedEvent), "failed to wait for the thread to start");
		}
Example #2
0
/***********************************************************
 * Name: dispmanx_notify_handle
 *
 * Arguments: not used
 *
 * Description: this purely notifies the update callback
 *
 * Returns: does not return
 *
 ***********************************************************/
static void *dispmanx_notify_func( void *arg ) {
    int32_t success;
    VCOS_STATUS_T status;

    (void)arg;

    while (1) {
        DISPMANX_UPDATE_HANDLE_T handle;
        status = vcos_event_wait(&dispmanx_notify_available_event);
        if (status != VCOS_SUCCESS || !dispmanx_client.initialised)
            break;
        success = vchi_msg_dequeue( dispmanx_client.notify_handle[0], dispmanx_client.notify_buffer, sizeof(dispmanx_client.notify_buffer), &dispmanx_client.notify_length, VCHI_FLAGS_NONE );
        if (success != 0)
            continue;

        handle = (DISPMANX_UPDATE_HANDLE_T)dispmanx_client.notify_buffer[0];
        if (handle) {
            // This is the response to an update submit
            // Decrement the use count - the corresponding "use" is in vc_dispmanx_update_submit.
            vchi_service_release(dispmanx_client.notify_handle[0]);
            if (dispmanx_client.update_callback ) {
                vcos_assert( dispmanx_client.pending_update_handle == handle);
                dispmanx_client.update_callback(handle, dispmanx_client.update_callback_param);
            }
        } else {
            // This is a vsync notification
            if (dispmanx_client.vsync_callback ) {
                dispmanx_client.vsync_callback(handle, dispmanx_client.vsync_callback_param);
            }
        }
    }
    return 0;
}
/***********************************************************
 * Name: os_cond_wait
 *
 * Arguments:  OS_COND_T *cond,
 *             OS_SEMAPHORE_T *semaphore
 *
 * Description: Routine to wait for a condition variable
 *              to be signalled. Semaphore is released
 *              while waiting. The same semaphore must
 *              always be used.
 *
 * Returns: int32_t - success == 0
 *
 ***********************************************************/
int32_t os_cond_wait( OS_COND_T *cond, OS_SEMAPHORE_T *semaphore )
{
   int32_t success = -1;
    
   if (cond && semaphore)
   {
      COND_WAITER_T w;
      COND_WAITER_T *p, **prev;
       
      // Check the API is being followed
      os_assert((*cond)->semaphore == semaphore && os_semaphore_obtained(semaphore));
      
      // Fill in a new waiter structure allocated on our stack
      w.next = NULL;
      vcos_demand(vcos_event_create(&w.latch, NULL) == VCOS_SUCCESS);
      
      // Add it to the end of the condvar's wait queue (we wake first come, first served)
      prev = &(*cond)->waiters;
      p = (*cond)->waiters;
      while (p)
         prev = &p->next, p = p->next;
      *prev = &w;

      // Ready to go to sleep now
      success = os_semaphore_release(semaphore);
      os_assert(success == 0);

      vcos_event_wait(&w.latch);

      success = os_semaphore_obtain(semaphore);
      os_assert(success == 0);
   }
   
   return success;
}
Example #4
0
VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
{
   while (queue->write == queue->read)
      vcos_event_wait(&queue->push);

   return queue->storage[queue->read & (queue->size - 1)];
}
Example #5
0
static int __inline remote_event_wait(REMOTE_EVENT_T *event)
{
#ifdef VCHIQ_LOCAL
   return (vcos_event_wait(&event->event) == VCOS_SUCCESS);
#else
   return local_event_wait(&event->local);
#endif
}
static void *khrn_worker_main(void * param)
{
   UNUSED(param);

   do {
      vcos_event_wait(&event);
      while (more_msgs(khrn_worker_msg.done_it, khrn_worker_msg.post) && do_it()) ;
   } while (!exit_thread);
   return NULL;
}
Example #7
0
void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
{
   while (queue->write == queue->read + queue->size)
      vcos_event_wait(&queue->pop);

   queue->storage[queue->write & (queue->size - 1)] = header;

   queue->write++;

   vcos_event_signal(&queue->push);
}
	void CComponent::ChangeState(OMX_STATETYPE State)
	{
		OMX_STATETYPE CurrentState;
		CHECK_OMX(OMX_GetState(m_hComponent, &CurrentState), "failed to query the current state of the component");
		if (CurrentState == State)
		{
			return;
		}
		CHECK_OMX(OMX_SendCommand(m_hComponent, OMX_CommandStateSet, State, NULL), "component state transtition failed");
		CHECK_VCOS(vcos_event_wait(&m_StateChangedEvent), "failed to wait for component state transition");
	}
Example #9
0
/******************************************************************************
NAME
   vc_gencmd_read_response

SYNOPSIS
   int vc_gencmd_read_response

FUNCTION
   Block until something comes back

RETURNS
   Error code from dequeue message
******************************************************************************/
int vc_gencmd_read_response (char *response, int maxlen) {
   int i = 0;
   int success = -1;
   int ret_code = 0;
   int32_t sem_ok = 0;

   if(lock_obtain() == 0)
   {
      //Note this will ALWAYS reset response buffer and overwrite any partially read responses
      use_gencmd_service();
      do {
         //TODO : we need to deal with messages coming through on more than one connections properly
         //At the moment it will always try to read the first connection if there is something there
         for(i = 0; i < gencmd_client.num_connections; i++) {
            //Check if there is something in the queue, if so return immediately
            //otherwise wait for the event and read again
            success = (int) vchi_msg_dequeue( gencmd_client.open_handle[i], gencmd_client.response_buffer,
                                              sizeof(gencmd_client.response_buffer), &gencmd_client.response_length, VCHI_FLAGS_NONE);

            if(success == 0) {
#ifdef __NetBSD__
	       uint32_t v;
#endif
#ifdef __NetBSD__
	       memcpy(&v, gencmd_client.response_buffer, sizeof(v));
               ret_code = VC_VTOH32(v);
#else
               ret_code = VC_VTOH32( *(int *)gencmd_client.response_buffer );
#endif
               break;
            } else {
               gencmd_client.response_length = 0;
            }
         }
      } while(!gencmd_client.response_length && vcos_event_wait(&gencmd_client.message_available_event) == VCOS_SUCCESS);
      
      if(gencmd_client.response_length && sem_ok == 0) {
         gencmd_client.response_length -= sizeof(int); //first word is error code
         memcpy(response, gencmd_client.response_buffer+sizeof(int), (size_t) vcos_min((int)gencmd_client.response_length, (int)maxlen));
      }

      release_gencmd_service();
      lock_release();
   }

   // If we read anything, return the VideoCore code. Error codes < 0 mean we failed to
   // read anything...
   //How do we let the caller know the response code of gencmd?
   //return ret_code;

   return success;
}
Example #10
0
/***********************************************************
 * Name: dispmanx_wait_for_reply
 *
 * Arguments: response buffer, buffer length
 *
 * Description: blocked until something is in the buffer
 *
 * Returns error code of vchi
 *
 ***********************************************************/
static int32_t dispmanx_wait_for_reply(void *response, uint32_t max_length) {
   int32_t success = 0;
   uint32_t length_read = 0;
   do {
      //TODO : we need to deal with messages coming through on more than one connections properly
      //At the moment it will always try to read the first connection if there is something there
      //Check if there is something in the queue, if so return immediately
      //otherwise wait for the semaphore and read again
      success = vchi_msg_dequeue( dispmanx_client.client_handle[0], response, max_length, &length_read, VCHI_FLAGS_NONE );
   } while( length_read == 0 && vcos_event_wait(&dispmanx_message_available_event) == VCOS_SUCCESS );

   return success;

}
static void recv_bulk(CLIENT_THREAD_STATE_T *thread, void *out, uint32_t len)
{
    if (len <= CTRL_THRESHOLD) {
        VCHIQ_HEADER_T *header = vchiu_queue_pop(get_queue(thread));
        assert(header->size == len);
        memcpy(out, header->data, len);
        vchiq_release_message(get_handle(thread), header);
    } else {
        VCHIQ_STATUS_T vchiq_status = vchiq_queue_bulk_receive(get_handle(thread), out, 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);
    }
}
Example #12
0
VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
{
   VCHIQ_HEADER_T *header;

   while (queue->write == queue->read)
      vcos_event_wait(&queue->push);

   header = queue->storage[queue->read & (queue->size - 1)];

   queue->read++;

   vcos_event_signal(&queue->pop);

   return header;
}
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);
    }
}
Example #14
0
/***********************************************************
 * Name: dispmanx_notify_handle
 *
 * Arguments: not used
 *
 * Description: this purely notifies the update callback
 *
 * Returns: does not return
 *
 ***********************************************************/
static void *dispmanx_notify_func( void *arg ) {
   int32_t success;
   VCOS_STATUS_T status;

   (void)arg;

   while(1) {
      status = vcos_event_wait(&dispmanx_notify_available_event);
      if(status != VCOS_SUCCESS || !dispmanx_client.initialised)
         break;
      success = vchi_msg_dequeue( dispmanx_client.notify_handle[0], dispmanx_client.notify_buffer, sizeof(dispmanx_client.notify_buffer), &dispmanx_client.notify_length, VCHI_FLAGS_NONE );
      vchi_service_release(dispmanx_client.notify_handle[0]); // corresponding use in vc_dispmanx_update_submit
      if(success != 0)
         continue;
   
      if(dispmanx_client.update_callback ) {
         vcos_assert( dispmanx_client.pending_update_handle == (DISPMANX_UPDATE_HANDLE_T) dispmanx_client.notify_buffer[1]);
         dispmanx_client.update_callback((DISPMANX_UPDATE_HANDLE_T) dispmanx_client.notify_buffer[1], dispmanx_client.update_callback_param);
      }
   }
   return 0;
}
Example #15
0
VCHIQ_STATUS_T vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance)
{
   VCHIQ_CHANNEL_T *local = state->local;
   int i;

   /* Find all services registered to this client and enable them. */
   for (i = 0; i < VCHIQ_MAX_SERVICES; i++)
      if (local->services[i].instance == instance)
      {
         if (local->services[i].srvstate == VCHIQ_SRVSTATE_HIDDEN)
            vchiq_set_service_state(&local->services[i], VCHIQ_SRVSTATE_LISTENING);
      }

   if (!state->connected)
   {
      if (queue_message(state, VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0, 0) == VCHIQ_RETRY)
         return VCHIQ_RETRY;
      vcos_event_wait(&state->connect);
      state->connected = 1;
   }

   return VCHIQ_SUCCESS;
}
Example #16
0
int main( int argc, char **argv )
{
   int32_t ret;
   char optstring[OPTSTRING_LEN];
   int  opt;
   int  opt_alloc = 0;
   int  opt_status = 0;
   uint32_t alloc_size = 0;
   int  opt_pid = -1;
   VCSM_STATUS_T status_mode = VCSM_STATUS_NONE;

   void *usr_ptr_1;
   unsigned int usr_hdl_1;
#if defined(DOUBLE_ALLOC) || defined(RESIZE_ALLOC)
   void *usr_ptr_2;
   unsigned int usr_hdl_2;
#endif

   // Initialize VCOS
   vcos_init();

   vcos_log_set_level(&smem_log_category, VCOS_LOG_INFO);
   smem_log_category.flags.want_prefix = 0;
   vcos_log_register( "smem", &smem_log_category );

   // Create the option string that we will be using to parse the arguments
   create_optstring( optstring );

   // Parse the command line arguments
   while (( opt = getopt_long_only( argc, argv, optstring, long_opts,
                                    NULL )) != -1 )
   {
      switch ( opt )
      {
         case 0:
         {
            // getopt_long returns 0 for entries where flag is non-NULL
            break;
         }
         case OPT_ALLOC:
         {
            char *end;
            alloc_size = (uint32_t)strtoul( optarg, &end, 10 );
            if (end == optarg)
            {
               vcos_log_info( "Invalid arguments '%s'", optarg );
               goto err_out;
            }

            opt_alloc = 1;
            break;
         }
         case OPT_PID:
         {
            char *end;
            opt_pid = (int)strtol( optarg, &end, 10 );
            if (end == optarg)
            {
               vcos_log_info( "Invalid arguments '%s'", optarg );
               goto err_out;
            }

            break;
         }
         case OPT_STATUS:
         {
            char status_str[32];

            /* coverity[secure_coding] String length specified, so can't overflow */
            if ( sscanf( optarg, "%31s", status_str ) != 1 )
            {
               vcos_log_info( "Invalid arguments '%s'", optarg );
               goto err_out;
            }

            if ( vcos_strcasecmp( status_str, "all" ) == 0 )
            {
               status_mode = VCSM_STATUS_VC_MAP_ALL;
            }
            else if ( vcos_strcasecmp( status_str, "vc" ) == 0 )
            {
               status_mode = VCSM_STATUS_VC_WALK_ALLOC;
            }
            else if ( vcos_strcasecmp( status_str, "map" ) == 0 )
            {
               status_mode = VCSM_STATUS_HOST_WALK_MAP;
            }
            else if ( vcos_strcasecmp( status_str, "host" ) == 0 )
            {
               status_mode = VCSM_STATUS_HOST_WALK_PID_ALLOC;
            }
            else
            {
               goto err_out;
            }

            opt_status = 1;
            break;
         }
         default:
         {
            vcos_log_info( "Unrecognized option '%d'", opt );
            goto err_usage;
         }
         case '?':
         case OPT_HELP:
         {
            goto err_usage;
         }
      } // end switch
   } // end while

   argc -= optind;
   argv += optind;

   if (( optind == 1 ) || ( argc > 0 ))
   {
      if ( argc > 0 )
      {
         vcos_log_info( "Unrecognized argument -- '%s'", *argv );
      }

      goto err_usage;
   }

   // Start the shared memory support.
   if ( vcsm_init() == -1 )
   {
      vcos_log_info( "Cannot initialize smem device" );
      goto err_out;
   }

   if ( opt_alloc == 1 )
   {
      vcos_log_info( "Allocating 2 times %u-bytes in shared memory", alloc_size );

      usr_hdl_1 = vcsm_malloc( alloc_size,
                               "smem-test-alloc" );

      vcos_log_info( "Allocation 1 result: user %x, vc-hdl %x",
                     usr_hdl_1, vcsm_vc_hdl_from_hdl( usr_hdl_1 ) );

#if defined(DOUBLE_ALLOC) || defined(RESIZE_ALLOC)
      usr_hdl_2 = vcsm_malloc( alloc_size,
                               NULL );
      vcos_log_info( "Allocation 2 result: user %x",
                     usr_hdl_2 );

      usr_ptr_2 = vcsm_lock( usr_hdl_2 );
      vcos_log_info( "Allocation 2 : lock %p",
                     usr_ptr_2 );
      vcos_log_info( "Allocation 2 : unlock %d",
                     vcsm_unlock_hdl( usr_hdl_2 ) );
#endif

      // Do a simple write/read test.
      if ( usr_hdl_1 != 0 )
      {
         usr_ptr_1 = vcsm_lock( usr_hdl_1 );
         vcos_log_info( "Allocation 1 : lock %p",
                        usr_ptr_1 );
         if ( usr_ptr_1 )
         {
            memset ( usr_ptr_1,
                     0,
                     alloc_size );
            memcpy ( usr_ptr_1,
                     blah_blah,
                     32 );
            vcos_log_info( "Allocation 1 contains: \"%s\"",
                           (char *)usr_ptr_1 );

            vcos_log_info( "Allocation 1: vc-hdl %x",
                           vcsm_vc_hdl_from_ptr ( usr_ptr_1 ) );
            vcos_log_info( "Allocation 1: usr-hdl %x",
                           vcsm_usr_handle ( usr_ptr_1 ) );
            vcos_log_info( "Allocation 1 : unlock %d",
                           vcsm_unlock_ptr( usr_ptr_1 ) );
         }

         usr_ptr_1 = vcsm_lock( usr_hdl_1 );
         vcos_log_info( "Allocation 1 (relock) : lock %p",
                        usr_ptr_1 );
         if ( usr_ptr_1 )
         {
            vcos_log_info( "Allocation 1 (relock) : unlock %d",
                           vcsm_unlock_hdl( usr_hdl_1 ) );
         }
      }

#if defined(RESIZE_ALLOC)
      ret = vcsm_resize( usr_hdl_1, 2 * alloc_size );
      vcos_log_info( "Allocation 1 : resize %d", ret );
      if ( ret == 0 )
      {
         usr_ptr_1 = vcsm_lock( usr_hdl_1 );
         vcos_log_info( "Allocation 1 (resize) : lock %p",
                        usr_ptr_1 );
         if ( usr_ptr_1 )
         {
            memset ( usr_ptr_1,
                     0,
                     2 * alloc_size );
            memcpy ( usr_ptr_1,
                     blah_blah,
                     32 );
            vcos_log_info( "Allocation 1 (resized) contains: \"%s\"",
                           (char *)usr_ptr_1 );
            vcos_log_info( "Allocation 1 (resized) : unlock %d",
                           vcsm_unlock_ptr( usr_ptr_1 ) );
         }
      }

      // This checks that the memory can be remapped properly
      // because the Block 1 expanded beyond Block 2 boundary.
      //
      usr_ptr_2 = vcsm_lock( usr_hdl_2 );
      vcos_log_info( "Allocation 2 : lock %p",
                     usr_ptr_2 );
      vcos_log_info( "Allocation 2 : unlock %d",
                     vcsm_unlock_hdl( usr_hdl_2 ) );

      // This checks that we can free a memory block even if it
      // is locked, which could be the case if the application 
      // dies.
      //
      usr_ptr_2 = vcsm_lock( usr_hdl_2 );
      vcos_log_info( "Allocation 2 : lock %p",
                     usr_ptr_2 );
      vcsm_free ( usr_hdl_2 );
#endif

#if defined(DOUBLE_ALLOC)
#endif
   }

   if ( opt_status == 1 )
   {
      get_status( status_mode, opt_pid );
   }
   
   // If we allocated something, wait for the signal to exit to give chance for the
   // user to poke around the allocation test.
   //
   if ( opt_alloc == 1 )
   {
      start_monitor();
      
      vcos_event_wait( &quit_event );
      vcos_event_delete( &quit_event );
   }

   // Terminate the shared memory support.
   vcsm_exit ();
   goto err_out;

err_usage:
   show_usage();

err_out:
   exit( 1 );
}
int main( int argc, char **argv )
{
   int32_t ret;
   char optstring[OPTSTRING_LEN];
   int  opt;
   int  opt_preferred = 0;
   int  opt_explicit = 0;
   int  opt_sdtvon = 0;
   int  opt_off = 0;
   int  opt_modes = 0;
   int  opt_monitor = 0;
   int  opt_status = 0;
   int  opt_audiosup = 0;
   int  opt_dumpedid = 0;
   int  opt_showinfo = 0;
   int  opt_3d = 0;
   int  opt_json = 0;
   int  opt_name = 0;

   char *dumpedid_filename = NULL;
   VCHI_INSTANCE_T    vchi_instance;
   VCHI_CONNECTION_T *vchi_connection;
   HDMI_RES_GROUP_T power_on_explicit_group = HDMI_RES_GROUP_INVALID;
   uint32_t         power_on_explicit_mode;
   uint32_t         power_on_explicit_drive = HDMI_MODE_HDMI;
   HDMI_RES_GROUP_T get_modes_group = HDMI_RES_GROUP_INVALID;
   SDTV_MODE_T sdtvon_mode;
   SDTV_ASPECT_T sdtvon_aspect;

   // Initialize VCOS
   vcos_init();

   // Create the option string that we will be using to parse the arguments
   create_optstring( optstring );

   // Parse the command line arguments
   while (( opt = getopt_long_only( argc, argv, optstring, long_opts,
                                    NULL )) != -1 )
   {
      switch ( opt )
      {
         case 0:
         {
            // getopt_long returns 0 for entries where flag is non-NULL
            break;
         }
         case OPT_PREFERRED:
         {
            opt_preferred = 1;
            break;
         }
         case OPT_EXPLICIT:
         {
            char group_str[32], drive_str[32];

            /* coverity[secure_coding] String length specified, so can't overflow */
            int s = sscanf( optarg, "%31s %u %31s", group_str, &power_on_explicit_mode, drive_str );
            if ( s != 2 && s != 3 )
            {
               LOG_ERR( "Invalid arguments '%s'", optarg );
               goto err_out;
            }

            // Check the group first
            if ( vcos_strcasecmp( "CEA", group_str ) == 0 )
            {
               power_on_explicit_group = HDMI_RES_GROUP_CEA;
            }
            else if ( vcos_strcasecmp( "DMT", group_str ) == 0 )
            {
               power_on_explicit_group = HDMI_RES_GROUP_DMT;
            }
            else if ( vcos_strcasecmp( "CEA_3D", group_str ) == 0  ||
                      vcos_strcasecmp( "CEA_3D_SBS", group_str ) == 0)
            {
               power_on_explicit_group = HDMI_RES_GROUP_CEA;
               opt_3d = 1;
            }
            else if ( vcos_strcasecmp( "CEA_3D_TB", group_str ) == 0 )
            {
               power_on_explicit_group = HDMI_RES_GROUP_CEA;
               opt_3d = 2;
            }
            else
            {
               LOG_ERR( "Invalid group '%s'", group_str );
               goto err_out;
            }
            if (s==3)
            {
               if (vcos_strcasecmp( "HDMI", drive_str ) == 0 )
               {
                  power_on_explicit_drive = HDMI_MODE_HDMI;
               }
               else if (vcos_strcasecmp( "DVI", drive_str ) == 0 )
               {
                  power_on_explicit_drive = HDMI_MODE_DVI;
               }
               else
               {
                  LOG_ERR( "Invalid drive '%s'", drive_str );
                  goto err_out;
               }
            }
            // Then check if mode is a sane number
            if ( power_on_explicit_mode > MAX_MODE_ID )
            {
               LOG_ERR( "Invalid mode '%u'", power_on_explicit_mode );
               goto err_out;
            }

            opt_explicit = 1;
            break;
         }
         case OPT_SDTVON:
         {
            char mode_str[32], aspect_str[32];

            if ( sscanf( optarg, "%s %s", mode_str,
                         aspect_str ) != 2 )
            {
               LOG_ERR( "Invalid arguments '%s'", optarg );
               goto err_out;
            }

            // Check the group first
            if ( vcos_strcasecmp( "NTSC", mode_str ) == 0 )
            {
               sdtvon_mode = SDTV_MODE_NTSC;
            }
            else if ( vcos_strcasecmp( "NTSC_J", mode_str ) == 0 )
            {
               sdtvon_mode = SDTV_MODE_NTSC_J;
            }
            else if ( vcos_strcasecmp( "PAL", mode_str ) == 0 )
            {
               sdtvon_mode = SDTV_MODE_PAL;
            }
            else if ( vcos_strcasecmp( "PAL_M", mode_str ) == 0 )
            {
               sdtvon_mode = SDTV_MODE_PAL_M;
            }
            else
            {
               LOG_ERR( "Invalid mode '%s'", mode_str );
               goto err_out;
            }

            if ( vcos_strcasecmp( "4:3", aspect_str ) == 0 )
            {
               sdtvon_aspect = SDTV_ASPECT_4_3;
            }
            else if ( vcos_strcasecmp( "14:9", aspect_str ) == 0 )
            {
               sdtvon_aspect = SDTV_ASPECT_14_9;
            }
            else if ( vcos_strcasecmp( "16:9", aspect_str ) == 0 )
            {
               sdtvon_aspect = SDTV_ASPECT_16_9;
            }

            opt_sdtvon = 1;
            break;
         }
         case OPT_OFF:
         {
            opt_off = 1;
            break;
         }
         case OPT_MODES:
         {
            if ( vcos_strcasecmp( "CEA", optarg ) == 0 )
            {
               get_modes_group = HDMI_RES_GROUP_CEA;
            }
            else if ( vcos_strcasecmp( "DMT", optarg ) == 0 )
            {
               get_modes_group = HDMI_RES_GROUP_DMT;
            }
            else
            {
               LOG_ERR( "Invalid group '%s'", optarg );
               goto err_out;
            }

            opt_modes = 1;
            break;
         }
         case OPT_MONITOR:
         {
            opt_monitor = 1;
            break;
         }
         case OPT_STATUS:
         {
            opt_status = 1;
            break;
         }
         case OPT_AUDIOSUP:
         {
            opt_audiosup = 1;
            break;
         }
         case OPT_DUMPEDID:
         {
            opt_dumpedid = 1;
            dumpedid_filename = optarg;
            break;
         }
         case OPT_SHOWINFO:
         {
            opt_showinfo = atoi(optarg)+1;
            break;
         }
         case OPT_JSON:
         {
            opt_json = 1;
            break;
         }
         case OPT_NAME:
         {
            opt_name = 1;
            break;
         }
         default:
         {
            LOG_ERR( "Unrecognized option '%d'\n", opt );
            goto err_usage;
         }
         case '?':
         case OPT_HELP:
         {
            goto err_usage;
         }
      } // end switch
   } // end while

   argc -= optind;
   argv += optind;

   if (( optind == 1 ) || ( argc > 0 ))
   {
      if ( argc > 0 )
      {
         LOG_ERR( "Unrecognized argument -- '%s'", *argv );
      }

      goto err_usage;
   }

   if (( opt_preferred + opt_explicit + opt_sdtvon > 1 ))
   {
      LOG_ERR( "Conflicting power on options" );
      goto err_usage;
   }

   if ((( opt_preferred == 1 ) || ( opt_explicit == 1 ) || ( opt_sdtvon == 1)) && ( opt_off == 1 ))
   {
      LOG_ERR( "Cannot power on and power off simultaneously" );
      goto err_out;
   }

   // Initialize the VCHI connection
   ret = vchi_initialise( &vchi_instance );
   if ( ret != 0 )
   {
      LOG_ERR( "Failed to initialize VCHI (ret=%d)", ret );
      goto err_out;
   }

   ret = vchi_connect( NULL, 0, vchi_instance );
   if ( ret != 0)
   {
      LOG_ERR( "Failed to create VCHI connection (ret=%d)", ret );
      goto err_out;
   }

//   LOG_INFO( "Starting tvservice" );

   // Initialize the tvservice
   vc_vchi_tv_init( vchi_instance, &vchi_connection, 1 );

   if ( opt_monitor == 1 )
   {
      LOG_STD( "Starting to monitor for HDMI events" );

      if ( start_monitor() != 0 )
      {
         goto err_stop_service;
      }
   }

   if ( opt_modes == 1 )
   {
      if ( get_modes( get_modes_group, opt_json ) != 0 )
      {
         goto err_stop_service;
      }
   }

   if ( opt_preferred == 1 )
   {
      if ( power_on_preferred() != 0 )
      {
         goto err_stop_service;
      }
   }
   else if ( opt_explicit == 1 )
   {
      //Distinguish between turning on 3D side by side and 3D top/bottom
      if(opt_3d == 1 && set_property( HDMI_PROPERTY_3D_STRUCTURE, HDMI_3D_FORMAT_SBS_HALF, 0) != 0)
      {
         goto err_stop_service;
      }
      else if(opt_3d == 2 && set_property( HDMI_PROPERTY_3D_STRUCTURE, HDMI_3D_FORMAT_TB_HALF, 0) != 0)
      {
         goto err_stop_service;
      }

      if ( power_on_explicit( power_on_explicit_group,
                              power_on_explicit_mode, power_on_explicit_drive ) != 0 )
      {
         goto err_stop_service;
      }
   }
   else if ( opt_sdtvon == 1 )
   {
      if ( power_on_sdtv( sdtvon_mode,
                              sdtvon_aspect ) != 0 )
      {
         goto err_stop_service;
      }
   }
   else if (opt_off == 1 )
   {
      if ( power_off() != 0 )
      {
         goto err_stop_service;
      }
   }

   if ( opt_status == 1 )
   {
      if ( get_status() != 0 )
      {
         goto err_stop_service;
      }
   }
   
   if ( opt_audiosup == 1 )
   {
      if ( get_audiosup() != 0 )
      {
         goto err_stop_service;
      }
   }
   
   if ( opt_dumpedid == 1 )
   {
      if ( dump_edid(dumpedid_filename) != 0 )
      {
         goto err_stop_service;
      }
   }

   if ( opt_showinfo )
   {
      if ( show_info(opt_showinfo-1) != 0 )
      {
         goto err_stop_service;
      }
   }

   if ( opt_name == 1 )
   {
      TV_DEVICE_ID_T id;
      memset(&id, 0, sizeof(id));
      if(vc_tv_get_device_id(&id) == 0) {
         if(id.vendor[0] == '\0' || id.monitor_name[0] == '\0') {
            LOG_ERR( "No device present" );
         } else {
            LOG_STD( "device_name=%s-%s", id.vendor, id.monitor_name);
         }
      } else {
         LOG_ERR( "Failed to obtain device name" );
      }
   }

   if ( opt_monitor == 1 )
   {
      // Wait until we get the signal to exit
      vcos_event_wait( &quit_event );

      vcos_event_delete( &quit_event );
   }

err_stop_service:
//   LOG_INFO( "Stopping tvservice" );

   // Stop the tvservice
   vc_vchi_tv_stop();

   // Disconnect the VCHI connection
   vchi_disconnect( vchi_instance );

   exit( 0 );

err_usage:
   show_usage();

err_out:
   exit( 1 );
}
Example #18
0
static int __inline local_event_wait(LOCAL_EVENT_T *event)
{
   return (vcos_event_wait(&event->event) == VCOS_SUCCESS);
}