//Receiver thread
static void hostreqclient_func(unsigned int argc, void *argv) {
   int32_t success;
   int32_t i, nothing;

   while(1) { //Run forever waiting for a callback to happen
      // wait for the semaphore to say that there is a message
      success = os_semaphore_obtain(&hostreq_client_message_available);
      assert( success == 0 );

      while(1) { //Read until we can read no more on all interfaces
         nothing = 0;
         for(i=0;i<hostreq_client.num_connections;i++) {
            success = vchi_msg_dequeue(hostreq_client.client_handle[i], hostreq_client.response_buffer, sizeof(hostreq_client.response_buffer), &hostreq_client.response_length, VCHI_FLAGS_NONE);
            if(success == 0) {
               hostreq_request_handler(i, &hostreq_client);
            } else {
               nothing++;
            }
         }
         //When there is nothing on all interfaces, wait for a callback
         if(nothing == hostreq_client.num_connections) {
            break;
         }
      }
   }
}
Beispiel #2
0
static void
bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *msg_handle)
{
	struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)param;
	int32_t status;
	uint32_t msg_len;
	VC_AUDIO_MSG_T m;

	if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
		return;

	status = vchi_msg_dequeue(sc->vchi_handle,
	    &m, sizeof m, &msg_len, VCHI_FLAGS_NONE);
	if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
		sc->msg_result = m.u.result.success;
		cv_signal(&sc->msg_avail_cv);
	} else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
		struct bcm2835_audio_chinfo *ch = m.u.complete.cookie;

		int count = m.u.complete.count & 0xffff;
		int perr = (m.u.complete.count & (1U << 30)) != 0;

		ch->complete_pos = (ch->complete_pos + count) % sndbuf_getsize(ch->buffer);
		ch->free_buffer += count;

		if (perr || ch->free_buffer >= VCHIQ_AUDIO_PACKET_SIZE) {
			chn_intr(ch->channel);
			cv_signal(&sc->data_cv);
		}
	} else
		printf("%s: unknown m.type: %d\n", __func__, m.type);
}
/******************************************************************************
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 = 0;
   int ret_code = 0;
   int32_t sem_ok = 0;

   //Note this will ALWAYS reset response buffer and overwrite any partially read responses

   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 semaphore 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) {
            ret_code = VC_VTOH32( *(int *)gencmd_client.response_buffer );
            break;
         } else {
            gencmd_client.response_length = 0;
         }
      }
   } while(!gencmd_client.response_length && (sem_ok = os_semaphore_obtain( &gencmd_message_available_semaphore)) == 0);

   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) OS_MIN((int)gencmd_client.response_length, (int)maxlen));
   }
   // 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;
}
/***********************************************************
 * 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)
}
Beispiel #5
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;
}
Beispiel #6
0
static void
bcm2835_audio_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *msg_handle)
{
	struct bcm2835_audio_info *sc = (struct bcm2835_audio_info *)param;
	int32_t status;
	uint32_t msg_len;
	VC_AUDIO_MSG_T m;

	if (reason != VCHI_CALLBACK_MSG_AVAILABLE)
		return;

	status = vchi_msg_dequeue(sc->vchi_handle,
	    &m, sizeof m, &msg_len, VCHI_FLAGS_NONE);
	if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
		if (m.u.result.success) {
			device_printf(sc->dev,
			    "msg type %08x failed\n",
			    m.type);
		}
	} else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
		struct bcm2835_audio_chinfo *ch = m.u.complete.cookie;

		int count = m.u.complete.count & 0xffff;
		int perr = (m.u.complete.count & (1U << 30)) != 0;
		ch->callbacks++;
		if (perr)
			ch->underruns++;

		BCM2835_AUDIO_LOCK(sc);
		if (ch->playback_state != PLAYBACK_IDLE) {
			/* Prevent LOR */
			BCM2835_AUDIO_UNLOCK(sc);
			chn_intr(sc->pch.channel);
			BCM2835_AUDIO_LOCK(sc);
		}
		/* We should check again, state might have changed */
		if (ch->playback_state != PLAYBACK_IDLE) {
			if (!perr) {
				if ((ch->available_space + count)> VCHIQ_AUDIO_BUFFER_SIZE) {
					device_printf(sc->dev, "inconsistent data in callback:\n");
					device_printf(sc->dev, "available_space == %d, count = %d, perr=%d\n",
					    ch->available_space, count, perr);
					device_printf(sc->dev,
					    "retrieved_samples = %lld, submitted_samples = %lld\n",
					    ch->retrieved_samples, ch->submitted_samples);
				}
				ch->available_space += count;
				ch->retrieved_samples += count;
			}
			if (perr || (ch->available_space >= VCHIQ_AUDIO_PACKET_SIZE))
				cv_signal(&sc->worker_cv);
		}
		BCM2835_AUDIO_UNLOCK(sc);
	} else
		printf("%s: unknown m.type: %d\n", __func__, m.type);
}
Beispiel #7
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 audio_vchi_callback(void *param,
				const VCHI_CALLBACK_REASON_T reason,
				void *msg_handle)
{
	AUDIO_INSTANCE_T *instance = (AUDIO_INSTANCE_T *) param;
	int32_t status;
	int32_t msg_len;
	VC_AUDIO_MSG_T m;
	LOG_DBG(" .. IN instance=%p, handle=%p, alsa=%p, reason=%d, handle=%p\n",
		instance, instance ? instance->vchi_handle[0] : NULL, instance ? instance->alsa_stream : NULL, reason, msg_handle);

	if (reason != VCHI_CALLBACK_MSG_AVAILABLE) {
		return;
	}
	if (!instance) {
		LOG_ERR(" .. instance is null\n");
		BUG();
		return;
  }
  if (!instance->vchi_handle[0]) {
		LOG_ERR(" .. instance->vchi_handle[0] is null\n");
		BUG();
		return;
  }
	status = vchi_msg_dequeue(instance->vchi_handle[0],
				  &m, sizeof m, &msg_len, VCHI_FLAGS_NONE);
	if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
		LOG_DBG
		    (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
		     instance, m.u.result.success);
		instance->result = m.u.result.success;
		complete(&instance->msg_avail_comp);
	} else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
		bcm2835_alsa_stream_t *alsa_stream = instance->alsa_stream;
		irq_handler_t callback = (irq_handler_t) m.u.complete.callback;
		LOG_DBG
		    (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
		     instance, m.u.complete.count);
		if (alsa_stream && callback) {
			atomic_add(m.u.complete.count, &alsa_stream->retrieved);
			callback(0, alsa_stream);
		} else {
			LOG_ERR(" .. unexpected alsa_stream=%p, callback=%p\n",
				alsa_stream, callback);
		}
	} else {
		LOG_ERR(" .. unexpected m.type=%d\n", m.type);
	}
	LOG_DBG(" .. OUT\n");
}
/***********************************************************
 * Name: cecservice_wait_for_reply
 *
 * Arguments: response buffer, buffer length
 *
 * Description: blocked until something is in the buffer
 *
 * Returns error code of vchi
 *
 ***********************************************************/
static int32_t cecservice_wait_for_reply(void *response, uint32_t max_length) {
   int32_t success = 0;
   int32_t sem_ok = 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( cecservice_client.client_handle[0], response, max_length, &length_read, VCHI_FLAGS_NONE );
   } while( length_read == 0 && (sem_ok = os_semaphore_obtain( &cecservice_message_available_semaphore)) == 0);
   
   return success;
}
/**
 * <DFN>vc_hdcp2_service_wait_for_reply</DFN> blocks until a response comes back
 * from Videocore.
 *
 * @param client_handle is the vchi client handle
 * 
 * @param sema is the signalling semaphore indicating a reply
 *
 * @param response is the reponse buffer
 *
 * @param max_length is the maximum length of the buffer
 *
 * @param actual_length will be set to the actual length of the buffer (or zero if error)
 *
 * @return zero if successful, vchi error code otherwise
 */
int32_t vc_hdcp2_service_wait_for_reply(VCHI_SERVICE_HANDLE_T client_handle,
                                        VCOS_SEMAPHORE_T *sema,
                                        void *response, uint32_t max_length, uint32_t *actual_length) {
   int32_t success = 0;
   VCOS_STATUS_T status;
   uint32_t length_read = 0;
   vcos_assert(sema);
   vcos_assert(response && max_length);
   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( client_handle, response, max_length, &length_read, VCHI_FLAGS_NONE );
   } while( length_read == 0 || (status = vcos_semaphore_trywait(sema)) != VCOS_SUCCESS);

   if(vcos_verify(*actual_length)) {
      *actual_length = (success == 0)? length_read : 0;
   }
   return success;
}
Beispiel #11
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;
}
Beispiel #12
0
int32_t vc_vchi_fb_read(VC_VCHI_FB_HANDLE_T handle, uint32_t res_handle,
			void *buf, int32_t size)
{
	int32_t ret, success = 0;
	FB_INSTANCE_T *instance = handle;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	VC_FB_READ_T *fb_read;
	VC_FB_RESULT_T result;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle", __func__);

		ret = -1;
		goto out;
	}

	if (buf == NULL) {
		LOG_ERR("%s: invalid buffer pointer", __func__);

		ret = -1;
		goto out;
	}

	if (size <= 0) {
		LOG_ERR("%s: invalid buffer size %d", __func__, size);

		ret = -1;
		goto out;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	LOG_INFO("%s: enter", __func__);

	msg_len = sizeof(*msg_hdr) + sizeof(*fb_read);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_READ;

	fb_read = (VC_FB_READ_T *) msg_hdr->body;
	fb_read->res_handle = res_handle;
	fb_read->size = size;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	LOG_INFO("%s: done sending msg", __func__);
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   &result, sizeof(result),
				   &msg_len, VCHI_FLAGS_NONE);

	LOG_INFO("%s: got reply message %x", __func__, result.success);

	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(result));

		ret = -1;
		goto unlock;
	}

	LOG_INFO("%s: all good do bulk_receive %x", __func__, result.success);
	success = vchi_bulk_queue_receive(instance->vchi_handle[0],
					  buf,
					  size,
					  VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
					  0);

	if (success != 0)
		LOG_ERR("%s: vchi_bulk_queue_receive failed", __func__);

unlock:

	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	ret = success;
	LOG_INFO("%s: exit", __func__);
out:
	return ret;
}
Beispiel #13
0
int32_t vc_vchi_fb_cfg(VC_VCHI_FB_HANDLE_T handle,
		       VC_FB_CFG_T * cfg, VC_FB_CFG_RESULT_T * cfg_result)
{
	int32_t ret;
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle", __func__);

		ret = -1;
		goto out;
	}

	if (cfg == NULL) {
		LOG_ERR("%s: invalid cfg pointer", __func__);

		ret = -1;
		goto out;
	}

	if (cfg_result == NULL) {
		LOG_ERR("%s: invalid cfg_result pointer", __func__);

		ret = -1;
		goto out;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*cfg);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_CFG;

	/* Copy the user buffer into the message buffer */
	memcpy(msg_hdr->body, cfg, sizeof(*cfg));

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   cfg_result, sizeof(*cfg_result),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(*cfg_result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(*cfg_result));

		ret = -1;
		goto unlock;
	}

	ret = cfg_result->success ? -1 : 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

out:
	return ret;
}
Beispiel #14
0
int32_t vc_vchi_fb_swap(VC_VCHI_FB_HANDLE_T handle,
			uint32_t res_handle, uint32_t active_frame)
{
	int ret;
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	VC_FB_SWAP_T *swap;
	VC_FB_RESULT_T result;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle %p", __func__, handle);

		return -1;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*swap);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_SWAP;

	swap = (VC_FB_SWAP_T *) msg_hdr->body;
	swap->res_handle = res_handle;
	swap->active_frame = active_frame;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   &result, sizeof(result),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(result));

		ret = -1;
		goto unlock;
	}

	ret = result.success ? -1 : 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	return ret;
}
Beispiel #15
0
int32_t vc_vchi_fb_alloc(VC_VCHI_FB_HANDLE_T handle,
			 VC_FB_ALLOC_T * alloc,
			 VC_FB_ALLOC_RESULT_T * alloc_result)
{
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	int32_t ret = -1;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle %p", __func__, handle);

		return -1;
	}

	if (alloc == NULL) {
		LOG_ERR("%s: invalid alloc pointer %p", __func__, alloc);

		return -1;
	}
	/* TODO check individual alloc member values */

	if (alloc_result == NULL) {
		LOG_ERR("%s: invalid alloc_result pointer 0x%p", __func__,
			alloc_result);

		return -1;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*alloc);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_ALLOC;

	/* Copy the user buffer into the message buffer */
	memcpy(msg_hdr->body, alloc, sizeof(*alloc));

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		goto unlock;
	}
	/*  We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   alloc_result, sizeof(*alloc_result),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		goto unlock;
	} else if (msg_len != sizeof(*alloc_result)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(*alloc_result));

		goto unlock;
	}
	/* success if we got to here */
	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	return ret;
}
Beispiel #16
0
int32_t vc_vchi_fb_get_scrn_info(VC_VCHI_FB_HANDLE_T handle,
				 VC_FB_SCRN scrn, VC_FB_SCRN_INFO_T * info)
{
	int ret;
	FB_INSTANCE_T *instance = handle;
	int32_t success;
	uint32_t msg_len;
	VC_FB_MSG_HDR_T *msg_hdr;
	VC_FB_GET_SCRN_INFO_T *get_scrn_info;

	if (handle == NULL) {
		LOG_ERR("%s: invalid handle %p", __func__, handle);

		return -1;
	}

	if (scrn >= VC_FB_SCRN_MAX) {
		LOG_ERR("%s: invalid screen %u", __func__, scrn);

		return -1;
	}

	if (info == NULL) {
		LOG_ERR("%s: invalid info pointer %p", __func__, info);

		return -1;
	}

	mutex_lock(&instance->vchi_mutex);
	vchi_service_use(instance->vchi_handle[0]);

	msg_len = sizeof(*msg_hdr) + sizeof(*get_scrn_info);
	memset(instance->msg_buf, 0, msg_len);

	msg_hdr = (VC_FB_MSG_HDR_T *) instance->msg_buf;
	msg_hdr->type = VC_FB_MSG_TYPE_GET_SCRN_INFO;

	get_scrn_info = (VC_FB_GET_SCRN_INFO_T *) msg_hdr->body;
	get_scrn_info->scrn = scrn;

	/* Send the message to the videocore */
	success = vchi_msg_queue(instance->vchi_handle[0],
				 instance->msg_buf, msg_len,
				 VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
	if (success != 0) {
		LOG_ERR("%s: failed to queue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	}
	/* We are expecting a reply from the videocore */
	down(&instance->msg_avail);

	success = vchi_msg_dequeue(instance->vchi_handle[0],
				   info, sizeof(*info),
				   &msg_len, VCHI_FLAGS_NONE);
	if (success != 0) {
		LOG_ERR("%s: failed to dequeue message (success=%d)",
			__func__, success);

		ret = -1;
		goto unlock;
	} else if (msg_len != sizeof(*info)) {
		LOG_ERR("%s: incorrect message length %u (expected=%u)",
			__func__, msg_len, sizeof(*info));

		ret = -1;
		goto unlock;
	}

	ret = 0;

unlock:
	vchi_service_release(instance->vchi_handle[0]);
	mutex_unlock(&instance->vchi_mutex);

	return ret;
}