/***********************************************************
 * Name: vc_cec_receive_message
 *
 * Arguments:
 *       pointer to initiator
 *       pointer to follower
 *       buffer to hold payload (max. 15 bytes)
 *       pointer to length
 *
 * Description
 *       Retrieve the most recent message, if there is no
 *       pending message, both initiator and follower will 
 *       be set to 0xF, otherwise length is set to length 
 *       of message minus the header byte.
 *
 * Returns: if the command is successful (zero) or not (non-zero)
 *          command is deemed successful even if there is no
 *          pending message
 ***********************************************************/
VCHPRE_ int VCHPOST_ vc_cec_receive_message(uint32_t *initiator,
                                            uint32_t *follower,
                                            uint8_t *buffer,
                                            uint32_t *length) {
   int success = -1;  
   vcos_assert(initiator && follower && buffer && length);
   success = cecservice_send_command_reply( VC_CEC_RECEIVE_MSG, NULL, 0, 
                                            &cecservice_client.rx_msg, sizeof(CEC_RECEIVE_MSG_RESP_T));
   if(success == 0) {
      cecservice_client.rx_msg.initiator = VC_VTOH32(cecservice_client.rx_msg.initiator);
      cecservice_client.rx_msg.follower  = VC_VTOH32(cecservice_client.rx_msg.follower);
      cecservice_client.rx_msg.length    = VC_VTOH32(cecservice_client.rx_msg.length);
      *initiator = cecservice_client.rx_msg.initiator;
      *follower  = cecservice_client.rx_msg.follower;
      *length    = cecservice_client.rx_msg.length;
      if(*length > 0) {
         memcpy(buffer, cecservice_client.rx_msg.payload, *length);
      }
   } else {
      *initiator = (uint32_t) CEC_AllDevices_eUnRegistered;
      *follower  = (uint32_t) CEC_AllDevices_eUnRegistered;
      *length    = 0L;
   }
   return success;
}
/***********************************************************
 * 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)
}
Esempio n. 3
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;
}
Esempio n. 4
0
int vc_host_get_app (void) {
   int status;
   uint32_t buffer;
   // Read app id.
   status = vc_host_read_consecutive(&buffer, VC_APP_ADDRESS, 4, 0);
   vc_assert(status == 0);
   return VC_VTOH32(buffer);
}
/***********************************************************
 * Name: vc_cec_get_physical_address
 *
 * Arguments:
 *       pointer to physical address (returned as 16-bit packed value)
 *
 * Description
 *       Get the physical address
 *
 * Returns: if the command is successful (zero) or not (non-zero)
 *          If failed, physical address argument will not be changed
 *          A physical address of 0xFFFF means CEC is not supported
 ***********************************************************/
VCHPRE_ int VCHPOST_ vc_cec_get_physical_address(uint16_t *physical_address) {
   uint32_t response;
   int32_t success = cecservice_send_command_reply( VC_CEC_GET_PHYSICAL_ADDR, NULL, 0, 
                                                    &response, sizeof(response));
   if(success == 0) {
      *physical_address = (uint16_t)(VC_VTOH32(response) & 0xFFFF);
   }
   return success;
}
/***********************************************************
 * Name: vc_cec_get_logical_address
 *
 * Arguments:
 *       pointer to logical address
 *
 * Description
 *       Get the logical address, if one is being allocated
 *       0xF (unregistered) will be returned
 *
 * Returns: if the command is successful (zero) or not (non-zero)
 *          logical_address is not modified if command failed
 ***********************************************************/
VCHPRE_ int VCHPOST_ vc_cec_get_logical_address(CEC_AllDevices_T *logical_address) {
   uint32_t response;
   int32_t success = cecservice_send_command_reply( VC_CEC_GET_LOGICAL_ADDR, NULL, 0, 
                                                    &response, sizeof(response));
   if(success == 0) {
      *logical_address = (CEC_AllDevices_T)(VC_VTOH32(response) & 0xF);
   }
   return success;
}
Esempio n. 7
0
/***********************************************************
 * Name: vc_dispmanx_display_get_info
 *
 * Arguments:
 *       DISPMANX_DISPLAY_HANDLE_T display
 *       DISPMANX_MODEINFO_T * pinfo
 *
 * Description:
 *
 * Returns: VCHI error
 *
 ***********************************************************/
VCHPRE_ int VCHPOST_
vc_dispmanx_display_get_info (DISPMANX_DISPLAY_HANDLE_T display,
                              DISPMANX_MODEINFO_T *pinfo)
{
   GET_INFO_DATA_T info;
   int32_t success;
   display = VC_HTOV32(display);
   success = dispmanx_send_command_reply (EDispmanDisplayGetInfo,
                                          &display, sizeof(display),
                                          &info, sizeof(info));
   if(success == 0) {
      pinfo->width = VC_VTOH32(info.width);
      pinfo->height = VC_VTOH32(info.height);
      pinfo->transform = (VC_IMAGE_TRANSFORM_T)VC_VTOH32(info.transform);
      pinfo->input_format = (DISPLAY_INPUT_FORMAT_T)VC_VTOH32(info.input_format);
   }

   return (int) success;
}
Esempio n. 8
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);
}
/***********************************************************
 * Name: vc_cec_get_topology
 *
 * Arguments:
 *       pointer to topology struct
 *
 * Description
 *       Get the topology
 *
 * Returns: if the command is successful (zero) or not (non-zero)
 *         If successful, the topology will be set, otherwise it is unchanged
 *         A topology with 1 device (us) means CEC is not supported
 *         If there is no topology available, this also returns a failure.
 ***********************************************************/
VCHPRE_ int VCHPOST_ vc_cec_get_topology( VC_CEC_TOPOLOGY_T* topology) {
   int32_t success = cecservice_send_command( VC_CEC_GET_TOPOLOGY, NULL, 0, 1);
   if(success == 0) {
      success = cecservice_wait_for_bulk_receive(cecservice_client.topology, sizeof(VC_CEC_TOPOLOGY_T));
   }
   if(success == 0) {
      int i;
      cecservice_client.topology->active_mask = VC_VTOH16(cecservice_client.topology->active_mask);
      cecservice_client.topology->num_devices = VC_VTOH16(cecservice_client.topology->num_devices);
      for(i = 0; i < 15; i++) {
         cecservice_client.topology->device_attr[i] = VC_VTOH32(cecservice_client.topology->device_attr[i]);
      }
      memcpy(topology, cecservice_client.topology, sizeof(VC_CEC_TOPOLOGY_T));
   }
   return success;
}
Esempio n. 10
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);
}
Esempio n. 11
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;
}