Exemplo n.º 1
0
/******************************************************************************
NAME
   vc_gencmd_send

SYNOPSIS
   int vc_gencmd_send( const char *format, ... )

FUNCTION
   Send a string to general command service.

RETURNS
   int
******************************************************************************/
int vc_gencmd_send_list ( const char *format, va_list a )
{
   int success = -1;

   // Obtain the lock and keep it so no one else can butt in while we await the response.
   if(lock_obtain() == 0)
   {
      int length = vsnprintf( gencmd_client.command_buffer, GENCMD_MAX_LENGTH, format, a );
      
      if (length >= 0 && length < GENCMD_MAX_LENGTH)
      {
         int i;
         use_gencmd_service();
         for( i=0; i<gencmd_client.num_connections; i++ ) {
            success = vchi_msg_queue( gencmd_client.open_handle[i],
                                           gencmd_client.command_buffer,
                                           length+1,
                                           VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );

            if(success == 0)
            { // only want to send on one connection, so break on success
               break;
            }
         }
         release_gencmd_service();
      }

      lock_release();
   }

   return success;
}
Exemplo n.º 2
0
/***********************************************************
 * Name: cecservice_notify_func
 *
 * Arguments: CEC service state
 *
 * Description: This is the notification task which receives all CEC
 *              service notifications
 *
 * Returns: does not return
 *
 ***********************************************************/
static void cecservice_notify_func( unsigned int argc, void *argv ) {
   int32_t success;
   CECSERVICE_HOST_STATE_T *state = (CECSERVICE_HOST_STATE_T *) argv;

   //first send a dummy message to the Videocore to let it know we are ready
   cecservice_send_command(VC_CEC_END_OF_LIST, NULL, 0, 0);

   while(1) {
      success = os_semaphore_obtain(&cecservice_notify_available_semaphore);
      vcos_assert(!success && state->initialised);

      do {
         uint32_t reason, param1, param2;
         //Get all notifications in the queue
         success = vchi_msg_dequeue( state->notify_handle[0], state->notify_buffer, sizeof(state->notify_buffer), &state->notify_length, VCHI_FLAGS_NONE );
         if(success != 0 || state->notify_length < sizeof(uint32_t)*3 ) {
            continue;
         }

         lock_obtain();
         //Check what notification it is and update ourselves accordingly before notifying the host app
         //All notifications are of format: reason, param1, param2 (all 32-bit unsigned int)
         reason = VC_VTOH32(state->notify_buffer[0]), param1 = VC_VTOH32(state->notify_buffer[1]), param2 = VC_VTOH32(state->notify_buffer[2]);

         //Unlike the TV service we have nothing to store here, so just call the callback

         lock_release();

         //Now callback the host app
         if(state->notify_fn) {
            (*state->notify_fn)(state->notify_data, reason, param1, param2);
         }
      } while(success == 0 && state->notify_length >= sizeof(uint32_t)*3); //read the next message if any
   } //while (1)
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
/***********************************************************
 * 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;
}
Exemplo n.º 5
0
/***********************************************************
 * Name: vc_dispmanx_stop
 *
 * Arguments:
 *       -
 *
 * Description: Stops the Host side part of dispmanx
 *
 * Returns: -
 *
 ***********************************************************/
VCHPRE_ void VCHPOST_ vc_dispmanx_stop( void ) {
   // Wait for the current lock-holder to finish before zapping dispmanx.
   //TODO: kill the notifier task
   void *dummy;
   uint32_t i;

   if (!dispmanx_client.initialised)
      return;

   lock_obtain();
   for (i=0; i<dispmanx_client.num_connections; i++) {
      int32_t result;
      result = vchi_service_close(dispmanx_client.client_handle[i]);
      vcos_assert( result == 0 );
      result = vchi_service_close(dispmanx_client.notify_handle[i]);
      vcos_assert( result == 0 );
   }
   lock_release();
   dispmanx_client.initialised = 0;

   vcos_event_signal(&dispmanx_notify_available_event); 
   vcos_thread_join(&dispmanx_notify_task, &dummy);
   vcos_mutex_delete(&dispmanx_client.lock);
   vcos_event_delete(&dispmanx_message_available_event);
   vcos_event_delete(&dispmanx_notify_available_event);
}
Exemplo n.º 6
0
void vc_gencmd_stop () {
   // Assume a "power down" gencmd has been sent and the lock is held. There will
   // be no response so this should be called instead.
   int32_t success,i;

   if (!gencmd_client.initialised)
      return;

   if(lock_obtain() == 0)
   {
      use_gencmd_service();

      for(i = 0; i< (int32_t)gencmd_client.num_connections; i++) {
         success = vchi_service_close( gencmd_client.open_handle[i]);
         assert(success == 0);
      }

      gencmd_client.initialised = 0;

      lock_release();

      vcos_mutex_delete(&gencmd_client.lock);
      vcos_event_delete(&gencmd_client.message_available_event);
   }
}
Exemplo n.º 7
0
VCHPRE_ int VCHPOST_ vc_dispmanx_resource_write_data_handle( DISPMANX_RESOURCE_HANDLE_T handle, VC_IMAGE_TYPE_T src_type /* not used */,
                                                             int src_pitch, VCHI_MEM_HANDLE_T mem_handle, uint32_t offset,
                                                             const VC_RECT_T * rect ) {
   int32_t bulk_len;
   uint32_t param[3];
   uint32_t success = 0;

   //Note that x coordinate of the rect is NOT used
   //Address of data in host
   offset += src_pitch * rect->y;
   bulk_len = src_pitch * rect->height;

   //Now send the bulk transfer across
   //command parameters: resource handle, destination y, bulk length
   param[0] = VC_HTOV32(handle);
   param[1] = VC_HTOV32(rect->y);
   param[2] = 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_reloc( dispmanx_client.client_handle[0],
                                                mem_handle, offset,
                                                bulk_len,
                                                VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
                                                NULL );
      lock_release();
   }
   return (int) success;
}
Exemplo n.º 8
0
void vc_hostreq_stop () {
   // Don't want anyone to be using this when we zap it.
   int i, success;
   lock_obtain();
   for(i = 0; i < hostreq_client.num_connections; i++) {
      success = vchi_service_close(hostreq_client.client_handle[i]);
      assert(success == 0);
   }
   lock_release();
   memset(&hostreq_client, 0, sizeof(hostreq_client));

}
Exemplo n.º 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;
}
Exemplo n.º 10
0
/***********************************************************
 * Name: vc_vchi_cec_stop
 *
 * Arguments:
 *       -
 *
 * Description: Stops the Host side part of CEC service
 *
 * Returns: -
 *
 ***********************************************************/
VCHPRE_ void VCHPOST_ vc_vchi_cec_stop( void ) {
   // Wait for the current lock-holder to finish before zapping TV service
   uint32_t i;
   lock_obtain();
   //TODO: there is no API to stop the notifier task at the moment
   for (i=0; i < cecservice_client.num_connections; i++) {
      int32_t result;
      result = vchi_service_close(cecservice_client.client_handle[i]);
      assert( result == 0 );
      result = vchi_service_close(cecservice_client.notify_handle[i]);
      assert( result == 0 );
   }
   cecservice_client.initialised = 0;
   lock_release();
}
Exemplo n.º 11
0
/***********************************************************
 * Name: dispmanx_get_handle
 *
 * Arguments: command, parameter buffer, parameter legnth
 *
 * Description: same as dispmanx_send_command but returns uint instead
 *
 * Returns: handle
 *
 ***********************************************************/
static uint32_t dispmanx_get_handle(  uint32_t command, void *buffer, uint32_t length) {
   VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
                                   {buffer, length} };
   uint32_t success = 0;
   uint32_t response = 0;
   lock_obtain();
   success += vchi_msg_queuev( dispmanx_client.client_handle[0],
                               vector, sizeof(vector)/sizeof(vector[0]),
                               VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
   if(success == 0)
      success = dispmanx_wait_for_reply(&response, sizeof(response));

   lock_release();
   return VC_VTOH32(response);
}
Exemplo n.º 12
0
static int32_t dispmanx_send_command_reply(  uint32_t command, void *buffer, uint32_t length,
                                            void *response, uint32_t max_length) {
   VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
                                   {buffer, length} };

   int32_t success = 0;
   lock_obtain();
   success = vchi_msg_queuev( dispmanx_client.client_handle[0],
                               vector, sizeof(vector)/sizeof(vector[0]),
                               VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
   if(success == 0)
      success = dispmanx_wait_for_reply(response, max_length);

   lock_release();

   return success;
}
Exemplo n.º 13
0
static int32_t dispmanx_send_command(  uint32_t command, void *buffer, uint32_t length) {
   VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
                                  {buffer, length} };
   int32_t success = 0, response = -1;
   lock_obtain();
   success = vchi_msg_queuev( dispmanx_client.client_handle[0],
                              vector, sizeof(vector)/sizeof(vector[0]),
                              VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
   if(success == 0 && !(command & DISPMANX_NO_REPLY_MASK)) {
      //otherwise only wait for a reply if we ask for one
      success = dispmanx_wait_for_reply(&response, sizeof(response));
   } else {
      //Not waiting for a reply, send the success code back instead
      response = success;
   }
   lock_release();
   return VC_VTOH32(response);
}
Exemplo n.º 14
0
//Send replies/commands across to VMCS
static int32_t hostreq_send_command(uint32_t command, void *buffer, uint32_t length) {
   int success = 0, i;
   VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
                                  {buffer, length} };

   assert(hostreq_client.initialised);
   lock_obtain();
   for( i=0; i<hostreq_client.num_connections; i++ ) {
      success = vchi_msg_queuev(hostreq_client.client_handle[i],
                                vector,
                                sizeof(vector)/sizeof(vector[0]),
                                VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
      assert(!success);
      if(success != 0)
         break;
   }
   lock_release();
   return success;

}
Exemplo n.º 15
0
static int32_t cecservice_send_command(  uint32_t command, const void *buffer, uint32_t length, uint32_t has_reply) {
   VCHI_MSG_VECTOR_T vector[] = { {&command, sizeof(command)},
                                  {buffer, length} };
   int32_t success = 0;
   int32_t response;
   lock_obtain();
   success = vchi_msg_queuev(cecservice_client.client_handle[0],
                             vector, sizeof(vector)/sizeof(vector[0]),
                             VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
   vcos_assert( success == 0 );
   if(success == 0 && has_reply) {
      //otherwise only wait for a reply if we ask for one
      success = cecservice_wait_for_reply(&response, sizeof(response));
      response = VC_VTOH32(response);
   } else {
      //No reply expected or failed to send, send the success code back instead
      response = success;
   }
   vcos_assert(success == 0);
   lock_release();
   return response;
}
Exemplo n.º 16
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;
}
// original function broken into two parts so that a higher level interface
// can be implemented and re-use the code
int vc_gencmd_send_list ( const char *format, va_list a )
{
   int length;

   // Obtain the lock and keep it so no one else can butt in while we await the response.
   lock_obtain();

   if (gencmd_client.open_handle[0] == 0) {
      lock_release();
      return -1;
   }

   length = vsnprintf( gencmd_client.command_buffer, GENCMD_MAX_LENGTH, format, a );

   if ( (length < 0) || (length >= GENCMD_MAX_LENGTH ) )
   {
      assert(0);
      lock_release();
      return -1;
   }

   /* send message back to caller */
   return vc_gencmd_send_string (gencmd_client.command_buffer);
}
Exemplo n.º 18
0
/***********************************************************
 * Name: vc_cec_register_callaback
 *
 * Arguments:
 *       callback function, context to be passed when function is called
 *
 * Description: Register a callback function for all CEC notifications
 *
 * Returns: -
 *
 ***********************************************************/
VCHPRE_ void VCHPOST_ vc_cec_register_callback(CECSERVICE_CALLBACK_T callback, void *callback_data) {
   lock_obtain();
   cecservice_client.notify_fn   = callback;
   cecservice_client.notify_data = callback_data;
   lock_release();
}