static void bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch, void *buf, uint32_t count) { struct bcm2835_audio_info *sc = ch->parent; VC_AUDIO_MSG_T m; int ret; if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) { return; } m.type = VC_AUDIO_MSG_TYPE_WRITE; m.u.write.count = count; m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE; m.u.write.callback = NULL; m.u.write.cookie = ch; m.u.write.silence = 0; ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); while (count > 0) { int bytes = MIN((int)m.u.write.max_packet, (int)count); ret = vchi_msg_queue(sc->vchi_handle, buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed: %d\n", __func__, ret); buf = (char *)buf + bytes; count -= bytes; } }
static void bcm2835_audio_update_params(struct bcm2835_audio_info *sc, struct bcm2835_audio_chinfo *ch) { VC_AUDIO_MSG_T m; int ret; VCHIQ_VCHI_LOCK(sc); if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { vchi_service_use(sc->vchi_handle); sc->msg_result = -1; m.type = VC_AUDIO_MSG_TYPE_CONFIG; m.u.config.channels = AFMT_CHANNEL(ch->fmt); m.u.config.samplerate = ch->spd; m.u.config.bps = AFMT_BIT(ch->fmt); ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); mtx_lock(&sc->msg_avail_lock); cv_wait_sig(&sc->msg_avail_cv, &sc->msg_avail_lock); if (sc->msg_result) printf("%s failed: %d\n", __func__, sc->msg_result); mtx_unlock(&sc->msg_avail_lock); vchi_service_release(sc->vchi_handle); } VCHIQ_VCHI_UNLOCK(sc); }
/****************************************************************************** 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; }
static void bcm2835_audio_update_controls(struct bcm2835_audio_info *sc) { VC_AUDIO_MSG_T m; int ret, db; VCHIQ_VCHI_LOCK(sc); if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { vchi_service_use(sc->vchi_handle); sc->msg_result = -1; m.type = VC_AUDIO_MSG_TYPE_CONTROL; m.u.control.dest = sc->dest; if (sc->volume > 99) sc->volume = 99; db = db_levels[sc->volume/5]; m.u.control.volume = VCHIQ_AUDIO_VOLUME(db); ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); mtx_lock(&sc->msg_avail_lock); cv_wait_sig(&sc->msg_avail_cv, &sc->msg_avail_lock); if (sc->msg_result) printf("%s failed: %d\n", __func__, sc->msg_result); mtx_unlock(&sc->msg_avail_lock); vchi_service_release(sc->vchi_handle); } VCHIQ_VCHI_UNLOCK(sc); }
static void bcm2835_audio_start(struct bcm2835_audio_chinfo *ch) { VC_AUDIO_MSG_T m; int ret; struct bcm2835_audio_info *sc = ch->parent; VCHIQ_VCHI_LOCK(sc); if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { vchi_service_use(sc->vchi_handle); bcm2835_audio_reset_channel(ch); m.type = VC_AUDIO_MSG_TYPE_START; ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); vchi_service_release(sc->vchi_handle); } VCHIQ_VCHI_UNLOCK(sc); }
int vchi_queue_kernel_message(VCHI_SERVICE_HANDLE_T handle, void *data, unsigned int size) { return vchi_msg_queue(handle, vchi_queue_kernel_message_callback, data, size); }
int vchi_queue_user_message(VCHI_SERVICE_HANDLE_T handle, void __user *data, unsigned int size) { struct vchi_queue_user_message_context copycontext = { .data = data }; return vchi_msg_queue(handle, vchi_queue_user_message_callback, ©context, size); }
int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream) { AUDIO_INSTANCE_T *instance; VC_AUDIO_MSG_T m; int32_t success; int ret; LOG_DBG(" .. IN\n"); my_workqueue_init(alsa_stream); ret = bcm2835_audio_open_connection(alsa_stream); if (ret != 0) { ret = -1; goto exit; } instance = alsa_stream->instance; LOG_DBG(" instance (%p)\n", instance); 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_OPEN; /* 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 = 0; unlock: vchi_service_release(instance->vchi_handle[0]); mutex_unlock(&instance->vchi_mutex); exit: LOG_DBG(" .. OUT\n"); return ret; }
static int vc_gencmd_send_string(char *command) { int success = 0, i; for( i=0; i<gencmd_client.num_connections; i++ ) { success += vchi_msg_queue( gencmd_client.open_handle[i], command, strlen(command)+1, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ); assert(!success); if(success != 0) break; } lock_release(); return success; }
static void bcm2835_audio_open(struct bcm2835_audio_info *sc) { VC_AUDIO_MSG_T m; int ret; if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { m.type = VC_AUDIO_MSG_TYPE_OPEN; ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); } }
static void bcm2835_audio_stop(struct bcm2835_audio_chinfo *ch) { VC_AUDIO_MSG_T m; int ret; struct bcm2835_audio_info *sc = ch->parent; if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { m.type = VC_AUDIO_MSG_TYPE_STOP; m.u.stop.draining = 0; ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); } }
static void bcm2835_audio_update_params(struct bcm2835_audio_info *sc, uint32_t fmt, uint32_t speed) { VC_AUDIO_MSG_T m; int ret; if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { m.type = VC_AUDIO_MSG_TYPE_CONFIG; m.u.config.channels = AFMT_CHANNEL(fmt); m.u.config.samplerate = speed; m.u.config.bps = AFMT_BIT(fmt); ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); } }
static void bcm2835_audio_update_controls(struct bcm2835_audio_info *sc, uint32_t volume, uint32_t dest) { VC_AUDIO_MSG_T m; int ret, db; if (sc->vchi_handle != VCHIQ_SERVICE_HANDLE_INVALID) { m.type = VC_AUDIO_MSG_TYPE_CONTROL; m.u.control.dest = dest; if (volume > 99) volume = 99; db = db_levels[volume/5]; m.u.control.volume = VCHIQ_AUDIO_VOLUME(db); ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, 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; }
static void bcm2835_audio_write_samples(struct bcm2835_audio_chinfo *ch) { struct bcm2835_audio_info *sc = ch->parent; VC_AUDIO_MSG_T m; void *buf; uint32_t count, size; int ret; VCHIQ_VCHI_LOCK(sc); if (sc->vchi_handle == VCHIQ_SERVICE_HANDLE_INVALID) { VCHIQ_VCHI_UNLOCK(sc); return; } vchi_service_use(sc->vchi_handle); size = sndbuf_getsize(ch->buffer); count = vchiq_unbuffered_bytes(ch); buf = (uint8_t*)sndbuf_getbuf(ch->buffer) + ch->buffered_ptr; if (ch->buffered_ptr + count > size) count = size - ch->buffered_ptr; if (count < VCHIQ_AUDIO_PACKET_SIZE) goto done; count = min(count, ch->free_buffer); count -= count % VCHIQ_AUDIO_PACKET_SIZE; m.type = VC_AUDIO_MSG_TYPE_WRITE; m.u.write.count = count; m.u.write.max_packet = VCHIQ_AUDIO_PACKET_SIZE; m.u.write.callback = NULL; m.u.write.cookie = ch; if (buf) m.u.write.silence = 0; else m.u.write.silence = 1; ret = vchi_msg_queue(sc->vchi_handle, &m, sizeof m, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed (err %d)\n", __func__, ret); if (buf) { while (count > 0) { int bytes = MIN((int)m.u.write.max_packet, (int)count); ch->free_buffer -= bytes; ch->buffered_ptr += bytes; ch->buffered_ptr = ch->buffered_ptr % size; ret = vchi_msg_queue(sc->vchi_handle, buf, bytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); if (ret != 0) printf("%s: vchi_msg_queue failed: %d\n", __func__, ret); buf = (char *)buf + bytes; count -= bytes; } } done: vchi_service_release(sc->vchi_handle); VCHIQ_VCHI_UNLOCK(sc); }
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; }
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_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; }
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; }