/* create new fifo */ fifo_t *snd_seq_fifo_new(int poolsize) { fifo_t *f; f = snd_kcalloc(sizeof(fifo_t), GFP_KERNEL); if (f == NULL) { snd_printd("malloc failed for snd_seq_fifo_new() \n"); return NULL; } f->pool = snd_seq_pool_new(poolsize); if (f->pool == NULL) { kfree(f); return NULL; } if (snd_seq_pool_init(f->pool) < 0) { snd_seq_pool_delete(&f->pool); kfree(f); return NULL; } spin_lock_init(&f->lock); snd_use_lock_init(&f->use_lock); init_waitqueue_head(&f->input_sleep); atomic_set(&f->overflow, 0); f->head = NULL; f->tail = NULL; f->cells = 0; return f; }
/* allocate event chunk */ static snd_seq_event_chunk_t *snd_seq_chunk_allocate(int numcells) { snd_seq_event_chunk_t *chunkptr; chunkptr = snd_kcalloc(sizeof(snd_seq_event_chunk_t) + sizeof(snd_seq_event_cell_t) * numcells, GFP_KERNEL); if (chunkptr) chunkptr->cells = numcells; return chunkptr; }
static snd_info_entry_t *snd_info_create_entry(const char *name) { snd_info_entry_t *entry; entry = (snd_info_entry_t *) snd_kcalloc(sizeof(snd_info_entry_t), GFP_KERNEL); if (entry == NULL) return NULL; entry->name = snd_kmalloc_strdup(name, GFP_KERNEL); if (entry->name == NULL) { kfree(entry); return NULL; } entry->mode = S_IFREG | S_IRUGO; entry->content = SNDRV_INFO_CONTENT_TEXT; init_MUTEX(&entry->access); return entry; }
/* create new prioq (constructor) */ prioq_t *snd_seq_prioq_new(void) { prioq_t *f; f = snd_kcalloc(sizeof(prioq_t), GFP_KERNEL); if (f == NULL) { snd_printd("oops: malloc failed for snd_seq_prioq_new()\n"); return NULL; } spin_lock_init(&f->lock); f->head = NULL; f->tail = NULL; f->cells = 0; return f; }
snd_emux_port_t * snd_emux_create_port(snd_emux_t *emu, char *name, int max_channels, int oss_port, snd_seq_port_callback_t *callback) { snd_emux_port_t *p; int i, type, cap; /* Allocate structures for this channel */ if ((p = snd_magic_kcalloc(snd_emux_port_t, 0, GFP_KERNEL)) == NULL) { snd_printk("no memory\n"); return NULL; } p->chset.channels = snd_kcalloc(max_channels * sizeof(snd_midi_channel_t), GFP_KERNEL); if (p->chset.channels == NULL) { snd_printk("no memory\n"); snd_magic_kfree(p); return NULL; } for (i = 0; i < max_channels; i++) p->chset.channels[i].number = i; p->chset.private_data = p; p->chset.max_channels = max_channels; p->emu = emu; p->chset.client = emu->client; #ifdef SNDRV_EMUX_USE_RAW_EFFECT snd_emux_create_effect(p); #endif callback->private_free = free_port; callback->private_data = p; cap = SNDRV_SEQ_PORT_CAP_WRITE; if (oss_port) { type = SNDRV_SEQ_PORT_TYPE_SPECIFIC; } else { type = DEFAULT_MIDI_TYPE; cap |= SNDRV_SEQ_PORT_CAP_SUBS_WRITE; } p->chset.port = snd_seq_event_port_attach(emu->client, callback, cap, type, max_channels, emu->max_voices, name); return p; }
/* * create and register a new timer. * if queue is not started yet, start it. */ seq_oss_timer_t * snd_seq_oss_timer_new(seq_oss_devinfo_t *dp) { seq_oss_timer_t *rec; rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL); if (rec == NULL) return NULL; rec->dp = dp; rec->cur_tick = 0; rec->realtime = 0; rec->running = 0; rec->oss_tempo = 60; rec->oss_timebase = 100; calc_alsa_tempo(rec); return rec; }
/* init new memory pool */ pool_t *snd_seq_pool_new(int poolsize) { pool_t *pool; /* create pool block */ pool = snd_kcalloc(sizeof(pool_t), GFP_KERNEL); if (pool == NULL) { snd_printd("seq: malloc failed for pool\n"); return NULL; } spin_lock_init(&pool->lock); pool->ptr = NULL; pool->free = NULL; pool->total_elements = 0; atomic_set(&pool->counter, 0); pool->closing = 0; init_waitqueue_head(&pool->output_sleep); pool->size = poolsize; /* init statistics */ pool->max_used = 0; return pool; }
/* * attach virtual rawmidi devices */ int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card) { int i; emu->vmidi = NULL; if (emu->midi_ports <= 0) return 0; emu->vmidi = snd_kcalloc(sizeof(snd_rawmidi_t*) * emu->midi_ports, GFP_KERNEL); if (emu->vmidi == NULL) return -ENOMEM; for (i = 0; i < emu->midi_ports; i++) { snd_rawmidi_t *rmidi; snd_virmidi_dev_t *rdev; if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0) goto __error; rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, continue); sprintf(rmidi->name, "%s Synth MIDI", emu->name); rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH; rdev->client = emu->client; rdev->port = emu->ports[i]; if (snd_device_register(card, rmidi) < 0) { snd_device_free(card, rmidi); goto __error; } emu->vmidi[i] = rmidi; //snd_printk("virmidi %d ok\n", i); } return 0; __error: //snd_printk("error init..\n"); snd_emux_delete_virmidi(emu); return -ENOMEM; }
/* register new midi synth port */ int snd_seq_midisynth_register_port(snd_seq_device_t *dev) { seq_midisynth_client_t *client; seq_midisynth_t *msynth, *ms; snd_seq_port_info_t port; snd_rawmidi_info_t info; int newclient = 0, p, ports; snd_seq_client_callback_t callbacks; snd_seq_port_callback_t pcallbacks; snd_seq_client_info_t inf; snd_card_t *card = dev->card; int device = dev->device; unsigned int input_count = 0, output_count = 0; snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL); info.device = device; info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT; info.subdevice = 0; if (snd_rawmidi_info_select(card, &info) >= 0) output_count = info.subdevices_count; info.stream = SNDRV_RAWMIDI_STREAM_INPUT; if (snd_rawmidi_info_select(card, &info) >= 0) { input_count = info.subdevices_count; } ports = output_count; if (ports < input_count) ports = input_count; if (ports == 0) return -ENODEV; if (ports > (256 / SNDRV_RAWMIDI_DEVICES)) ports = 256 / SNDRV_RAWMIDI_DEVICES; down(®ister_mutex); client = synths[card->number]; if (client == NULL) { newclient = 1; client = snd_kcalloc(sizeof(seq_midisynth_client_t), GFP_KERNEL); if (client == NULL) { up(®ister_mutex); return -ENOMEM; } memset(&callbacks, 0, sizeof(callbacks)); callbacks.private_data = client; callbacks.allow_input = callbacks.allow_output = 1; client->seq_client = snd_seq_create_kernel_client(card, 0, &callbacks); if (client->seq_client < 0) { kfree(client); up(®ister_mutex); return -ENOMEM; } /* set our client name */ memset(&inf,0,sizeof(snd_seq_client_info_t)); inf.client = client->seq_client; inf.type = KERNEL_CLIENT; sprintf(inf.name, "External MIDI %i", card->number); snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &inf); } msynth = snd_kcalloc(sizeof(seq_midisynth_t) * ports, GFP_KERNEL); if (msynth == NULL) goto __nomem; for (p = 0; p < ports; p++) { ms = &msynth[p]; if (snd_seq_midisynth_new(ms, card, device, p) < 0) goto __nomem; /* declare port */ memset(&port, 0, sizeof(port)); port.addr.client = client->seq_client; port.addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p; port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; memset(&info, 0, sizeof(info)); info.device = device; if (p < output_count) info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT; else info.stream = SNDRV_RAWMIDI_STREAM_INPUT; info.subdevice = p; if (snd_rawmidi_info_select(card, &info) >= 0) strcpy(port.name, info.subname); if (! port.name[0]) { if (ports > 1) sprintf(port.name, "MIDI %d-%d-%d", card->number, device, p); else sprintf(port.name, "MIDI %d-%d", card->number, device); } if ((info.flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count) port.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; if ((info.flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count) port.capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; if ((port.capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && info.flags & SNDRV_RAWMIDI_INFO_DUPLEX) port.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; port.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; port.midi_channels = 16; memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; pcallbacks.private_data = ms; pcallbacks.subscribe = midisynth_subscribe; pcallbacks.unsubscribe = midisynth_unsubscribe; pcallbacks.use = midisynth_use; pcallbacks.unuse = midisynth_unuse; pcallbacks.event_input = event_process_midi; port.kernel = &pcallbacks; if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &port)<0) goto __nomem; ms->seq_client = client->seq_client; ms->seq_port = port.addr.port; } client->ports_per_device[device] = ports; client->ports[device] = msynth; client->num_ports++; if (newclient) synths[card->number] = client; up(®ister_mutex); return 0; /* success */ __nomem: if (msynth != NULL) { for (p = 0; p < ports; p++) snd_seq_midisynth_delete(&msynth[p]); kfree(msynth); } if (newclient) { snd_seq_delete_kernel_client(client->seq_client); kfree(client); } up(®ister_mutex); return -ENOMEM; }
static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops, gf1_instrument_t *ip, char **data, long *len, int atomic) { gf1_wave_t *wp, *prev; gf1_xwave_t xp; int err, gfp_mask; unsigned int real_size; gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; if (*len < sizeof(xp)) return -EINVAL; if (copy_from_user(&xp, *data, sizeof(xp))) return -EFAULT; *data += sizeof(xp); *len -= sizeof(xp); wp = (gf1_wave_t *)snd_kcalloc(sizeof(*wp), gfp_mask); if (wp == NULL) return -ENOMEM; wp->share_id[0] = le32_to_cpu(xp.share_id[0]); wp->share_id[1] = le32_to_cpu(xp.share_id[1]); wp->share_id[2] = le32_to_cpu(xp.share_id[2]); wp->share_id[3] = le32_to_cpu(xp.share_id[3]); wp->format = le32_to_cpu(xp.format); wp->size = le32_to_cpu(xp.size); wp->start = le32_to_cpu(xp.start); wp->loop_start = le32_to_cpu(xp.loop_start); wp->loop_end = le32_to_cpu(xp.loop_end); wp->loop_repeat = le16_to_cpu(xp.loop_repeat); wp->flags = xp.flags; wp->sample_rate = le32_to_cpu(xp.sample_rate); wp->low_frequency = le32_to_cpu(xp.low_frequency); wp->high_frequency = le32_to_cpu(xp.high_frequency); wp->root_frequency = le32_to_cpu(xp.root_frequency); wp->tune = le16_to_cpu(xp.tune); wp->balance = xp.balance; memcpy(wp->envelope_rate, xp.envelope_rate, 6); memcpy(wp->envelope_offset, xp.envelope_offset, 6); wp->tremolo_sweep = xp.tremolo_sweep; wp->tremolo_rate = xp.tremolo_rate; wp->tremolo_depth = xp.tremolo_depth; wp->vibrato_sweep = xp.vibrato_sweep; wp->vibrato_rate = xp.vibrato_rate; wp->vibrato_depth = xp.vibrato_depth; wp->scale_frequency = le16_to_cpu(xp.scale_frequency); wp->scale_factor = le16_to_cpu(xp.scale_factor); real_size = snd_seq_gf1_size(wp->size, wp->format); if (real_size > *len) { kfree(wp); return -ENOMEM; } if (ops->put_sample) { err = ops->put_sample(ops->private_data, wp, *data, real_size, atomic); if (err < 0) { kfree(wp); return err; } } *data += real_size; *len -= real_size; prev = ip->wave; if (prev) { while (prev->next) prev = prev->next; prev->next = wp; } else { ip->wave = wp; } return 0; }
static int snd_info_entry_open(struct inode *inode, struct file *file) { snd_info_entry_t *entry; snd_info_private_data_t *data; snd_info_buffer_t *buffer; struct proc_dir_entry *p; int mode, err; down(&info_mutex); p = (struct proc_dir_entry *) inode->u.generic_ip; entry = p == NULL ? NULL : (snd_info_entry_t *)p->data; if (entry == NULL) { up(&info_mutex); return -ENODEV; } #ifndef LINUX_2_3 MOD_INC_USE_COUNT; #endif if (entry->module && !try_inc_mod_count(entry->module)) { err = -EFAULT; goto __error1; } mode = file->f_flags & O_ACCMODE; if (mode == O_RDONLY || mode == O_RDWR) { if ((entry->content == SNDRV_INFO_CONTENT_TEXT && !entry->c.text.read_size) || (entry->content == SNDRV_INFO_CONTENT_DATA && entry->c.ops->read == NULL) || entry->content == SNDRV_INFO_CONTENT_DEVICE) { err = -ENODEV; goto __error; } } if (mode == O_WRONLY || mode == O_RDWR) { if ((entry->content == SNDRV_INFO_CONTENT_TEXT && !entry->c.text.write_size) || (entry->content == SNDRV_INFO_CONTENT_DATA && entry->c.ops->write == NULL) || entry->content == SNDRV_INFO_CONTENT_DEVICE) { err = -ENODEV; goto __error; } } data = snd_magic_kcalloc(snd_info_private_data_t, 0, GFP_KERNEL); if (data == NULL) { err = -ENOMEM; goto __error; } data->entry = entry; switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: if (mode == O_RDONLY || mode == O_RDWR) { buffer = (snd_info_buffer_t *) snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL); if (buffer == NULL) { snd_magic_kfree(data); err = -ENOMEM; goto __error; } buffer->len = (entry->c.text.read_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); buffer->buffer = vmalloc(buffer->len); if (buffer->buffer == NULL) { kfree(buffer); snd_magic_kfree(data); err = -ENOMEM; goto __error; } buffer->curr = buffer->buffer; data->rbuffer = buffer; } if (mode == O_WRONLY || mode == O_RDWR) { buffer = (snd_info_buffer_t *) snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL); if (buffer == NULL) { if (mode == O_RDWR) { vfree(data->rbuffer->buffer); kfree(data->rbuffer); } snd_magic_kfree(data); err = -ENOMEM; goto __error; } buffer->len = (entry->c.text.write_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); buffer->buffer = vmalloc(buffer->len); if (buffer->buffer == NULL) { if (mode == O_RDWR) { vfree(data->rbuffer->buffer); kfree(data->rbuffer); } kfree(buffer); snd_magic_kfree(data); err = -ENOMEM; goto __error; } buffer->curr = buffer->buffer; data->wbuffer = buffer; } break; case SNDRV_INFO_CONTENT_DATA: /* data */ if (entry->c.ops->open) { if ((err = entry->c.ops->open(entry, mode, &data->file_private_data)) < 0) { snd_magic_kfree(data); goto __error; } } break; } file->private_data = data; up(&info_mutex); if (entry->content == SNDRV_INFO_CONTENT_TEXT && (mode == O_RDONLY || mode == O_RDWR)) { if (entry->c.text.read) { down(&entry->access); entry->c.text.read(entry, data->rbuffer); up(&entry->access); } } return 0; __error: dec_mod_count(entry->module); __error1: #ifndef LINUX_2_3 MOD_DEC_USE_COUNT; #endif up(&info_mutex); return err; }