📄 seq_instr.c
字号:
int atomic){ snd_seq_event_t sev; memset(&sev, 0, sizeof(sev)); sev.type = SNDRV_SEQ_EVENT_RESULT; sev.flags = SNDRV_SEQ_TIME_STAMP_REAL | SNDRV_SEQ_EVENT_LENGTH_FIXED | SNDRV_SEQ_PRIORITY_NORMAL; sev.source = ev->dest; sev.dest = ev->source; sev.data.result.event = type; sev.data.result.result = result;#if 0 printk("instr result - type = %i, result = %i, queue = %i, source.client:port = %i:%i, dest.client:port = %i:%i\n", type, result, sev.queue, sev.source.client, sev.source.port, sev.dest.client, sev.dest.port);#endif return snd_seq_kernel_client_dispatch(sev.source.client, &sev, atomic, 0);}static int instr_begin(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ unsigned long flags; spin_lock_irqsave(&list->lock, flags); if (list->owner >= 0 && list->owner != ev->source.client) { spin_unlock_irqrestore(&list->lock, flags); return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, -EBUSY, atomic); } list->owner = ev->source.client; spin_unlock_irqrestore(&list->lock, flags); return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, 0, atomic);}static int instr_end(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ unsigned long flags; /* TODO: timeout handling */ spin_lock_irqsave(&list->lock, flags); if (list->owner == ev->source.client) { list->owner = -1; spin_unlock_irqrestore(&list->lock, flags); return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, 0, atomic); } spin_unlock_irqrestore(&list->lock, flags); return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, -EINVAL, atomic);}static int instr_info(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ return -ENXIO;}static int instr_format_info(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ return -ENXIO;}static int instr_reset(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ return -ENXIO;}static int instr_status(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ return -ENXIO;}static int instr_put(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ unsigned long flags; snd_seq_instr_header_t put; snd_seq_kinstr_t *instr; int result = -EINVAL, len, key; if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR) goto __return; if (ev->data.ext.len < sizeof(snd_seq_instr_header_t)) goto __return; if (copy_from_user(&put, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) { result = -EFAULT; goto __return; } snd_instr_lock_ops(list); if (put.id.instr.std & 0xff000000) { /* private instrument */ put.id.instr.std &= 0x00ffffff; put.id.instr.std |= (unsigned int)ev->source.client << 24; } if ((instr = snd_seq_instr_find(list, &put.id.instr, 1, 0))) { snd_seq_instr_free_use(list, instr); snd_instr_unlock_ops(list); result = -EBUSY; goto __return; } ops = instr_ops(ops, put.data.data.format); if (ops == NULL) { snd_instr_unlock_ops(list); goto __return; } len = ops->add_len; if (put.data.type == SNDRV_SEQ_INSTR_ATYPE_ALIAS) len = sizeof(snd_seq_instr_t); instr = snd_seq_instr_new(len, atomic); if (instr == NULL) { snd_instr_unlock_ops(list); result = -ENOMEM; goto __return; } instr->ops = ops; instr->instr = put.id.instr; strlcpy(instr->name, put.data.name, sizeof(instr->name)); instr->type = put.data.type; if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) { result = ops->put(ops->private_data, instr, (void __user *)ev->data.ext.ptr + sizeof(snd_seq_instr_header_t), ev->data.ext.len - sizeof(snd_seq_instr_header_t), atomic, put.cmd); if (result < 0) { snd_seq_instr_free(instr, atomic); snd_instr_unlock_ops(list); goto __return; } } key = compute_hash_instr_key(&instr->instr); spin_lock_irqsave(&list->lock, flags); instr->next = list->hash[key]; list->hash[key] = instr; list->count++; spin_unlock_irqrestore(&list->lock, flags); snd_instr_unlock_ops(list); result = 0; __return: instr_result(ev, SNDRV_SEQ_EVENT_INSTR_PUT, result, atomic); return result;}static int instr_get(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ return -ENXIO;}static int instr_free(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ snd_seq_instr_header_t ifree; snd_seq_kinstr_t *instr, *prev; int result = -EINVAL; unsigned long flags; unsigned int hash; if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR) goto __return; if (ev->data.ext.len < sizeof(snd_seq_instr_header_t)) goto __return; if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) { result = -EFAULT; goto __return; } if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_ALL || ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE || ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER) { result = snd_seq_instr_list_free_cond(list, &ifree, ev->dest.client, atomic); goto __return; } if (ifree.cmd == SNDRV_SEQ_INSTR_FREE_CMD_SINGLE) { if (ifree.id.instr.std & 0xff000000) { ifree.id.instr.std &= 0x00ffffff; ifree.id.instr.std |= (unsigned int)ev->source.client << 24; } hash = compute_hash_instr_key(&ifree.id.instr); snd_instr_lock_ops(list); spin_lock_irqsave(&list->lock, flags); instr = list->hash[hash]; prev = NULL; while (instr) { if (!compare_instr(&instr->instr, &ifree.id.instr, 1)) goto __free_single; prev = instr; instr = instr->next; } result = -ENOENT; spin_unlock_irqrestore(&list->lock, flags); snd_instr_unlock_ops(list); goto __return; __free_single: if (prev) { prev->next = instr->next; } else { list->hash[hash] = instr->next; } if (instr->ops && instr->ops->notify) instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE); while (instr->use) { spin_unlock_irqrestore(&list->lock, flags); schedule_timeout_interruptible(1); spin_lock_irqsave(&list->lock, flags); } spin_unlock_irqrestore(&list->lock, flags); result = snd_seq_instr_free(instr, atomic); snd_instr_unlock_ops(list); goto __return; } __return: instr_result(ev, SNDRV_SEQ_EVENT_INSTR_FREE, result, atomic); return result;}static int instr_list(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ return -ENXIO;}static int instr_cluster(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int atomic, int hop){ return -ENXIO;}int snd_seq_instr_event(snd_seq_kinstr_ops_t *ops, snd_seq_kinstr_list_t *list, snd_seq_event_t *ev, int client, int atomic, int hop){ int direct = 0; snd_assert(ops != NULL && list != NULL && ev != NULL, return -EINVAL); if (snd_seq_ev_is_direct(ev)) { direct = 1; switch (ev->type) { case SNDRV_SEQ_EVENT_INSTR_BEGIN: return instr_begin(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_END: return instr_end(ops, list, ev, atomic, hop); } } if ((list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT) && !direct) return -EINVAL; switch (ev->type) { case SNDRV_SEQ_EVENT_INSTR_INFO: return instr_info(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_FINFO: return instr_format_info(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_RESET: return instr_reset(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_STATUS: return instr_status(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_PUT: return instr_put(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_GET: return instr_get(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_FREE: return instr_free(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_LIST: return instr_list(ops, list, ev, atomic, hop); case SNDRV_SEQ_EVENT_INSTR_CLUSTER: return instr_cluster(ops, list, ev, atomic, hop); } return -EINVAL;} /* * Init part */static int __init alsa_seq_instr_init(void){ return 0;}static void __exit alsa_seq_instr_exit(void){}module_init(alsa_seq_instr_init)module_exit(alsa_seq_instr_exit)EXPORT_SYMBOL(snd_seq_instr_list_new);EXPORT_SYMBOL(snd_seq_instr_list_free);EXPORT_SYMBOL(snd_seq_instr_list_free_cond);EXPORT_SYMBOL(snd_seq_instr_find);EXPORT_SYMBOL(snd_seq_instr_free_use);EXPORT_SYMBOL(snd_seq_instr_event);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -