int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream) { VC_AUDIO_MSG_T m; AUDIO_INSTANCE_T *instance = alsa_stream->instance; int32_t success; int ret; LOG_DBG(" .. IN\n"); my_workqueue_quit(alsa_stream); if(mutex_lock_interruptible(&instance->vchi_mutex)) { LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); return -EINTR; } vchi_service_use(instance->vchi_handle[0]); m.type = VC_AUDIO_MSG_TYPE_CLOSE; /* Create the message available completion */ init_completion(&instance->msg_avail_comp); /* Send the message to the videocore */ success = vchi_msg_queue(instance->vchi_handle[0], &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (success != 0) { LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", __func__, success); ret = -1; goto unlock; } ret = wait_for_completion_interruptible(&instance->msg_avail_comp); if (ret) { LOG_DBG("%s: failed on waiting for event (status=%d)\n", __func__, success); goto unlock; } if (instance->result != 0) { LOG_ERR("%s: failed result (status=%d)\n", __func__, instance->result); ret = -1; goto unlock; } ret = 0; unlock: vchi_service_release(instance->vchi_handle[0]); mutex_unlock(&instance->vchi_mutex); /* Stop the audio service */ if (instance) { vc_vchi_audio_deinit(instance); alsa_stream->instance = NULL; } LOG_DBG(" .. OUT\n"); return ret; }
int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream, uint32_t count, void *src) { VC_AUDIO_MSG_T m; AUDIO_INSTANCE_T *instance = alsa_stream->instance; int32_t success; int ret; LOG_DBG(" .. IN\n"); LOG_INFO(" Writing %d bytes from %p\n", count, src); if(mutex_lock_interruptible(&instance->vchi_mutex)) { LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); return -EINTR; } vchi_service_use(instance->vchi_handle[0]); if ( instance->peer_version==0 && vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0 ) { LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version); } m.type = VC_AUDIO_MSG_TYPE_WRITE; m.u.write.count = count; // old version uses bulk, new version uses control m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0:4000; m.u.write.callback = alsa_stream->fifo_irq_handler; m.u.write.cookie = alsa_stream; m.u.write.silence = src == NULL; /* Send the message to the videocore */ success = vchi_msg_queue(instance->vchi_handle[0], &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (success != 0) { LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", __func__, success); ret = -1; goto unlock; } if (!m.u.write.silence) { if (m.u.write.max_packet == 0) { /* Send the message to the videocore */ success = vchi_bulk_queue_transmit(instance->vchi_handle[0], src, count, 0 * VCHI_FLAGS_BLOCK_UNTIL_QUEUED + 1 * VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, NULL); } else { while (count > 0) { int bytes = min((int)m.u.write.max_packet, (int)count); success = vchi_msg_queue(instance->vchi_handle[0], src, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); src = (char *)src + bytes; count -= bytes; } } if (success != 0) { LOG_ERR ("%s: failed on vchi_bulk_queue_transmit (status=%d)\n", __func__, success); ret = -1; goto unlock; } } ret = 0; unlock: vchi_service_release(instance->vchi_handle[0]); mutex_unlock(&instance->vchi_mutex); LOG_DBG(" .. OUT\n"); return ret; }
static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream, bcm2835_chip_t * chip) { VC_AUDIO_MSG_T m; AUDIO_INSTANCE_T *instance = alsa_stream->instance; int32_t success; int ret; LOG_DBG(" .. IN\n"); LOG_INFO (" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume); if(mutex_lock_interruptible(&instance->vchi_mutex)) { LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); return -EINTR; } vchi_service_use(instance->vchi_handle[0]); instance->result = -1; m.type = VC_AUDIO_MSG_TYPE_CONTROL; m.u.control.dest = chip->dest; m.u.control.volume = chip->volume; /* Create the message available completion */ init_completion(&instance->msg_avail_comp); /* Send the message to the videocore */ success = vchi_msg_queue(instance->vchi_handle[0], &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (success != 0) { LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", __func__, success); ret = -1; goto unlock; } /* We are expecting a reply from the videocore */ ret = wait_for_completion_interruptible(&instance->msg_avail_comp); if (ret) { LOG_DBG("%s: failed on waiting for event (status=%d)\n", __func__, success); goto unlock; } if (instance->result != 0) { LOG_ERR("%s: result=%d\n", __func__, instance->result); ret = -1; goto unlock; } ret = 0; unlock: vchi_service_release(instance->vchi_handle[0]); mutex_unlock(&instance->vchi_mutex); LOG_DBG(" .. OUT\n"); return ret; }
int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream, uint32_t channels, uint32_t samplerate, uint32_t bps) { VC_AUDIO_MSG_T m; AUDIO_INSTANCE_T *instance = alsa_stream->instance; int32_t success; int ret; LOG_DBG(" .. IN\n"); LOG_INFO (" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n", channels, samplerate, bps); /* resend ctls - alsa_stream may not have been open when first send */ ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip); if (ret != 0) { LOG_ERR(" Alsa controls not supported\n"); return -EINVAL; } if(mutex_lock_interruptible(&instance->vchi_mutex)) { LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); return -EINTR; } vchi_service_use(instance->vchi_handle[0]); instance->result = -1; m.type = VC_AUDIO_MSG_TYPE_CONFIG; m.u.config.channels = channels; m.u.config.samplerate = samplerate; m.u.config.bps = bps; /* Create the message available completion */ init_completion(&instance->msg_avail_comp); /* Send the message to the videocore */ success = vchi_msg_queue(instance->vchi_handle[0], &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (success != 0) { LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", __func__, success); ret = -1; goto unlock; } /* We are expecting a reply from the videocore */ ret = wait_for_completion_interruptible(&instance->msg_avail_comp); if (ret) { LOG_DBG("%s: failed on waiting for event (status=%d)\n", __func__, success); goto unlock; } if (instance->result != 0) { LOG_ERR("%s: result=%d", __func__, instance->result); ret = -1; goto unlock; } ret = 0; unlock: vchi_service_release(instance->vchi_handle[0]); mutex_unlock(&instance->vchi_mutex); LOG_DBG(" .. OUT\n"); return ret; }
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; }
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; }
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; }
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; }
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; }