📄 seq_clientmgr.c
字号:
return snd_seq_queue_delete(client->number, info.queue);}/* GET_QUEUE_INFO ioctl() */static int snd_seq_ioctl_get_queue_info(client_t *client, void __user *arg){ snd_seq_queue_info_t info; queue_t *q; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; q = queueptr(info.queue); if (q == NULL) return -EINVAL; memset(&info, 0, sizeof(info)); info.queue = q->queue; info.owner = q->owner; info.locked = q->locked; strlcpy(info.name, q->name, sizeof(info.name)); queuefree(q); if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0;}/* SET_QUEUE_INFO ioctl() */static int snd_seq_ioctl_set_queue_info(client_t *client, void __user *arg){ snd_seq_queue_info_t info; queue_t *q; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; if (info.owner != client->number) return -EINVAL; /* change owner/locked permission */ if (snd_seq_queue_check_access(info.queue, client->number)) { if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0) return -EPERM; if (info.locked) snd_seq_queue_use(info.queue, client->number, 1); } else { return -EPERM; } q = queueptr(info.queue); if (! q) return -EINVAL; if (q->owner != client->number) { queuefree(q); return -EPERM; } strlcpy(q->name, info.name, sizeof(q->name)); queuefree(q); return 0;}/* GET_NAMED_QUEUE ioctl() */static int snd_seq_ioctl_get_named_queue(client_t *client, void __user *arg){ snd_seq_queue_info_t info; queue_t *q; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; q = snd_seq_queue_find_name(info.name); if (q == NULL) return -EINVAL; info.queue = q->queue; info.owner = q->owner; info.locked = q->locked; queuefree(q); if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0;}/* GET_QUEUE_STATUS ioctl() */static int snd_seq_ioctl_get_queue_status(client_t * client, void __user *arg){ snd_seq_queue_status_t status; queue_t *queue; seq_timer_t *tmr; if (copy_from_user(&status, arg, sizeof(status))) return -EFAULT; queue = queueptr(status.queue); if (queue == NULL) return -EINVAL; memset(&status, 0, sizeof(status)); status.queue = queue->queue; tmr = queue->timer; status.events = queue->tickq->cells + queue->timeq->cells; status.time = snd_seq_timer_get_cur_time(tmr); status.tick = snd_seq_timer_get_cur_tick(tmr); status.running = tmr->running; status.flags = queue->flags; queuefree(queue); if (copy_to_user(arg, &status, sizeof(status))) return -EFAULT; return 0;}/* GET_QUEUE_TEMPO ioctl() */static int snd_seq_ioctl_get_queue_tempo(client_t * client, void __user *arg){ snd_seq_queue_tempo_t tempo; queue_t *queue; seq_timer_t *tmr; if (copy_from_user(&tempo, arg, sizeof(tempo))) return -EFAULT; queue = queueptr(tempo.queue); if (queue == NULL) return -EINVAL; memset(&tempo, 0, sizeof(tempo)); tempo.queue = queue->queue; tmr = queue->timer; tempo.tempo = tmr->tempo; tempo.ppq = tmr->ppq; tempo.skew_value = tmr->skew; tempo.skew_base = tmr->skew_base; queuefree(queue); if (copy_to_user(arg, &tempo, sizeof(tempo))) return -EFAULT; return 0;}/* SET_QUEUE_TEMPO ioctl() */int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo){ if (!snd_seq_queue_check_access(tempo->queue, client)) return -EPERM; return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);}static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg){ int result; snd_seq_queue_tempo_t tempo; if (copy_from_user(&tempo, arg, sizeof(tempo))) return -EFAULT; result = snd_seq_set_queue_tempo(client->number, &tempo); return result < 0 ? result : 0;}/* GET_QUEUE_TIMER ioctl() */static int snd_seq_ioctl_get_queue_timer(client_t * client, void __user *arg){ snd_seq_queue_timer_t timer; queue_t *queue; seq_timer_t *tmr; if (copy_from_user(&timer, arg, sizeof(timer))) return -EFAULT; queue = queueptr(timer.queue); if (queue == NULL) return -EINVAL; if (down_interruptible(&queue->timer_mutex)) { queuefree(queue); return -ERESTARTSYS; } tmr = queue->timer; memset(&timer, 0, sizeof(timer)); timer.queue = queue->queue; timer.type = tmr->type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { timer.u.alsa.id = tmr->alsa_id; timer.u.alsa.resolution = tmr->preferred_resolution; } up(&queue->timer_mutex); queuefree(queue); if (copy_to_user(arg, &timer, sizeof(timer))) return -EFAULT; return 0;}/* SET_QUEUE_TIMER ioctl() */static int snd_seq_ioctl_set_queue_timer(client_t * client, void __user *arg){ int result = 0; snd_seq_queue_timer_t timer; if (copy_from_user(&timer, arg, sizeof(timer))) return -EFAULT; if (timer.type != SNDRV_SEQ_TIMER_ALSA) return -EINVAL; if (snd_seq_queue_check_access(timer.queue, client->number)) { queue_t *q; seq_timer_t *tmr; q = queueptr(timer.queue); if (q == NULL) return -ENXIO; if (down_interruptible(&q->timer_mutex)) { queuefree(q); return -ERESTARTSYS; } tmr = q->timer; snd_seq_queue_timer_close(timer.queue); tmr->type = timer.type; if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { tmr->alsa_id = timer.u.alsa.id; tmr->preferred_resolution = timer.u.alsa.resolution; } result = snd_seq_queue_timer_open(timer.queue); up(&q->timer_mutex); queuefree(q); } else { return -EPERM; } return result;}/* GET_QUEUE_CLIENT ioctl() */static int snd_seq_ioctl_get_queue_client(client_t * client, void __user *arg){ snd_seq_queue_client_t info; int used; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; used = snd_seq_queue_is_used(info.queue, client->number); if (used < 0) return -EINVAL; info.used = used; info.client = client->number; if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0;}/* SET_QUEUE_CLIENT ioctl() */static int snd_seq_ioctl_set_queue_client(client_t * client, void __user *arg){ int err; snd_seq_queue_client_t info; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; if (info.used >= 0) { err = snd_seq_queue_use(info.queue, client->number, info.used); if (err < 0) return err; } return snd_seq_ioctl_get_queue_client(client, arg);}/* GET_CLIENT_POOL ioctl() */static int snd_seq_ioctl_get_client_pool(client_t * client, void __user *arg){ snd_seq_client_pool_t info; client_t *cptr; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; cptr = snd_seq_client_use_ptr(info.client); if (cptr == NULL) return -ENOENT; memset(&info, 0, sizeof(info)); info.output_pool = cptr->pool->size; info.output_room = cptr->pool->room; info.output_free = info.output_pool; if (cptr->pool) info.output_free = snd_seq_unused_cells(cptr->pool); if (cptr->type == USER_CLIENT) { info.input_pool = cptr->data.user.fifo_pool_size; info.input_free = info.input_pool; if (cptr->data.user.fifo) info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); } else { info.input_pool = 0; info.input_free = 0; } snd_seq_client_unlock(cptr); if (copy_to_user(arg, &info, sizeof(info))) return -EFAULT; return 0;}/* SET_CLIENT_POOL ioctl() */static int snd_seq_ioctl_set_client_pool(client_t * client, void __user *arg){ snd_seq_client_pool_t info; int rc; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; if (client->number != info.client) return -EINVAL; /* can't change other clients */ if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS && (! snd_seq_write_pool_allocated(client) || info.output_pool != client->pool->size)) { if (snd_seq_write_pool_allocated(client)) { /* remove all existing cells */ snd_seq_queue_client_leave_cells(client->number); snd_seq_pool_done(client->pool); } client->pool->size = info.output_pool; rc = snd_seq_pool_init(client->pool); if (rc < 0) return rc; } if (client->type == USER_CLIENT && client->data.user.fifo != NULL && info.input_pool >= 1 && info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && info.input_pool != client->data.user.fifo_pool_size) { /* change pool size */ rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool); if (rc < 0) return rc; client->data.user.fifo_pool_size = info.input_pool; } if (info.output_room >= 1 && info.output_room <= client->pool->size) { client->pool->room = info.output_room; } return snd_seq_ioctl_get_client_pool(client, arg);}/* REMOVE_EVENTS ioctl() */static int snd_seq_ioctl_remove_events(client_t * client, void __user *arg){ snd_seq_remove_events_t info; if (copy_from_user(&info, arg, sizeof(info))) return -EFAULT; /* * Input mostly not implemented XXX. */ if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) { /* * No restrictions so for a user client we can clear * the whole fifo */ if (client->type == USER_CLIENT) snd_seq_fifo_clear(client->data.user.fifo); } if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) snd_seq_queue_remove_cells(client->number, &info); return 0;}/* * get subscription info */static int snd_seq_ioctl_get_subscription(client_t *client, void __user *arg){ int result; client_t *sender = NULL; client_port_t *sport = NULL; snd_seq_port_subscribe_t subs; subscribers_t *p; if (copy_from_user(&subs, arg, sizeof(subs))) return -EFAULT; result = -EINVAL; if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) goto __end; if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) goto __end; p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest); if (p) { result = 0; subs = p->info; } else result = -ENOENT; __end: if (sport) snd_seq_port_unlock(sport); if (sender) snd_seq_client_unlock(sender); if (result >= 0) { if (copy_to_user(arg, &subs, sizeof(subs))) return -EFAULT; } return result;}/* * get subscription info - check only its presence */static int snd_seq_ioctl_query_subs(client_t *client, void __user *arg){ int result = -ENXIO; client_t *cptr = NULL; client_port_t *port = NULL; snd_seq_query_subs_t subs; port_subs_info_t *group; struct list_head *p; int i; if (copy_from_user(&subs, arg, sizeof(subs))) return -EFAULT; if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL) goto __end; if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL) goto __end; switch (subs.type) { case SNDRV_SEQ_QUERY_SUBS_READ: group = &port->c_src; break; case SNDRV_SEQ_QUERY_SUBS_WRITE: group = &port->c_dest; break; default: goto __end; } down_read(&group->list_mutex); /* search for the subscriber */ subs.num_subs = group->count; i = 0; result = -ENOENT; list_for_each(p, &group->list_head) { if (i++ == subs.index) { /* found! */ subscribers_t *s; if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) { s = list_entry(p, subscribers_t, src_list); subs.addr = s->info.dest; } else { s = list_entry(p, subscribers_t, dest_list); subs.addr = s->info.sender; } subs.flags = s->info.flags; subs.queue = s->info.queue; result = 0; break; } } up_read(&group->list_mutex); __end: if (port) snd_seq_port_unlock(port); if (cptr) snd_seq_client_unlock(cptr); if (result >= 0) { if (copy_to_user(arg, &subs, sizeof(subs))) return -EFAULT; } return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -