static int init_midi(void) { int err; struct snd_seq_port_info *pinfo; err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(struct snd_card), &card); if (err < 0) { printk(KERN_INFO LOGPREFIX "error creating card: %d\n", err); return err; } client = snd_seq_create_kernel_client(card, 0, "new_midi-client"); if (client < 0) { printk(KERN_INFO LOGPREFIX "error creating client: %d\n", err); return err; } pinfo = kzalloc(sizeof(struct snd_seq_port_info), GFP_KERNEL); if (!pinfo) { err = -ENOMEM; return err; } pinfo->addr.client = client; //pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo); if (err < 0) { printk(KERN_INFO LOGPREFIX "error creating port: %d\n", err); return err; } return 0; }
/* * Create a sequencer client */ static int get_client(snd_card_t *card, int index, char *name) { snd_seq_client_callback_t callbacks; snd_seq_client_info_t cinfo; int client; memset(&callbacks, 0, sizeof(callbacks)); callbacks.private_data = NULL; callbacks.allow_input = 1; callbacks.allow_output = 1; /* Find a free client, start from 1 as the MPU expects to use 0 */ client = snd_seq_create_kernel_client(card, index, &callbacks); if (client < 0) return client; memset(&cinfo, 0, sizeof(cinfo)); cinfo.client = client; cinfo.type = KERNEL_CLIENT; strcpy(cinfo.name, name); snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo); return client; }
/* register our internal client */ int __init snd_seq_system_client_init(void) { snd_seq_client_callback_t callbacks; snd_seq_port_callback_t pcallbacks; snd_seq_client_info_t *inf; snd_seq_port_info_t *port; inf = kcalloc(1, sizeof(*inf), GFP_KERNEL); port = kcalloc(1, sizeof(*port), GFP_KERNEL); if (! inf || ! port) { kfree(inf); kfree(port); return -ENOMEM; } memset(&callbacks, 0, sizeof(callbacks)); memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; pcallbacks.event_input = event_input_timer; /* register client */ callbacks.allow_input = callbacks.allow_output = 1; sysclient = snd_seq_create_kernel_client(NULL, 0, &callbacks); /* set our name */ inf->client = 0; inf->type = KERNEL_CLIENT; strcpy(inf->name, "System"); snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, inf); /* register timer */ strcpy(port->name, "Timer"); port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */ port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */ port->kernel = &pcallbacks; port->type = 0; port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; port->addr.client = sysclient; port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); /* register announcement port */ strcpy(port->name, "Announce"); port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */ port->kernel = NULL; port->type = 0; port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; port->addr.client = sysclient; port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); announce_port = port->addr.port; kfree(inf); kfree(port); return 0; }
/* * create sequencer client for OSS sequencer */ int __init snd_seq_oss_create_client(void) { int rc; struct snd_seq_port_info *port; struct snd_seq_port_callback port_callback; port = kmalloc(sizeof(*port), GFP_KERNEL); if (!port) { rc = -ENOMEM; goto __error; } /* create ALSA client */ rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, "OSS sequencer"); if (rc < 0) goto __error; system_client = rc; debug_printk(("new client = %d\n", rc)); /* look up midi devices */ snd_seq_oss_midi_lookup_ports(system_client); /* create annoucement receiver port */ memset(port, 0, sizeof(*port)); strcpy(port->name, "Receiver"); port->addr.client = system_client; port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */ port->type = 0; memset(&port_callback, 0, sizeof(port_callback)); /* don't set port_callback.owner here. otherwise the module counter * is incremented and we can no longer release the module.. */ port_callback.event_input = receive_announce; port->kernel = &port_callback; call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port); if ((system_port = port->addr.port) >= 0) { struct snd_seq_port_subscribe subs; memset(&subs, 0, sizeof(subs)); subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; subs.dest.client = system_client; subs.dest.port = system_port; call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs); } rc = 0; __error: kfree(port); return rc; }
static int snd_opl4_seq_new_device(struct snd_seq_device *dev) { struct snd_opl4 *opl4; int client; struct snd_seq_port_callback pcallbacks; opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); if (!opl4) return -EINVAL; if (snd_yrw801_detect(opl4) < 0) return -ENODEV; opl4->chset = snd_midi_channel_alloc_set(16); if (!opl4->chset) return -ENOMEM; opl4->chset->private_data = opl4; /* allocate new client */ client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num, "OPL4 Wavetable"); if (client < 0) { snd_midi_channel_free_set(opl4->chset); return client; } opl4->seq_client = client; opl4->chset->client = client; /* create new port */ memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; pcallbacks.use = snd_opl4_seq_use; pcallbacks.unuse = snd_opl4_seq_unuse; pcallbacks.event_input = snd_opl4_seq_event_input; pcallbacks.private_free = snd_opl4_seq_free_port; pcallbacks.private_data = opl4; opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks, SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | SNDRV_SEQ_PORT_TYPE_MIDI_GM | SNDRV_SEQ_PORT_TYPE_HARDWARE | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, 16, 24, "OPL4 Wavetable Port"); if (opl4->chset->port < 0) { int err = opl4->chset->port; snd_midi_channel_free_set(opl4->chset); snd_seq_delete_kernel_client(client); opl4->seq_client = -1; return err; } return 0; }
static int snd_opl3_seq_new_device(struct snd_seq_device *dev) { struct snd_opl3 *opl3; int client, err; char name[32]; int opl_ver; opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); if (opl3 == NULL) return -EINVAL; spin_lock_init(&opl3->voice_lock); opl3->seq_client = -1; /* allocate new client */ opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; sprintf(name, "OPL%i FM synth", opl_ver); client = opl3->seq_client = snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num, name); if (client < 0) return client; if ((err = snd_opl3_synth_create_port(opl3)) < 0) { snd_seq_delete_kernel_client(client); opl3->seq_client = -1; return err; } /* initialize instrument list */ opl3->ilist = snd_seq_instr_list_new(); if (opl3->ilist == NULL) { snd_seq_delete_kernel_client(client); opl3->seq_client = -1; return -ENOMEM; } opl3->ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT; snd_seq_fm_init(&opl3->fm_ops, NULL); /* setup system timer */ init_timer(&opl3->tlist); opl3->tlist.function = snd_opl3_timer_func; opl3->tlist.data = (unsigned long) opl3; spin_lock_init(&opl3->sys_timer_lock); opl3->sys_timer_status = 0; #ifdef CONFIG_SND_SEQUENCER_OSS snd_opl3_init_seq_oss(opl3, name); #endif return 0; }
/* * register client and create ports */ static int __init register_client(void) { snd_seq_client_callback_t cb; snd_seq_client_info_t cinfo; snd_seq_dummy_port_t *rec1, *rec2; int i; if (ports < 1) { snd_printk(KERN_ERR "invalid number of ports %d\n", ports); return -EINVAL; } /* create client */ memset(&cb, 0, sizeof(cb)); cb.allow_input = 1; cb.allow_output = 1; my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY, &cb); if (my_client < 0) return my_client; /* set client name */ memset(&cinfo, 0, sizeof(cinfo)); cinfo.client = my_client; cinfo.type = KERNEL_CLIENT; strcpy(cinfo.name, "Midi Through"); snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo); /* create ports */ for (i = 0; i < ports; i++) { rec1 = create_port(i, 0); if (rec1 == NULL) { snd_seq_delete_kernel_client(my_client); return -ENOMEM; } if (duplex) { rec2 = create_port(i, 1); if (rec2 == NULL) { snd_seq_delete_kernel_client(my_client); return -ENOMEM; } rec1->connect = rec2->port; rec2->connect = rec1->port; } } return 0; }
/* * Initialise the EMUX Synth by creating a client and registering * a series of ports. * Each of the ports will contain the 16 midi channels. Applications * can connect to these ports to play midi data. */ int snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index) { int i; struct snd_seq_port_callback pinfo; char tmpname[64]; emu->client = snd_seq_create_kernel_client(card, index, "%s WaveTable", emu->name); if (emu->client < 0) { snd_printk(KERN_ERR "can't create client\n"); return -ENODEV; } if (emu->num_ports < 0) { snd_printk(KERN_WARNING "seqports must be greater than zero\n"); emu->num_ports = 1; } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) { snd_printk(KERN_WARNING "too many ports." "limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS); emu->num_ports = SNDRV_EMUX_MAX_PORTS; } memset(&pinfo, 0, sizeof(pinfo)); pinfo.owner = THIS_MODULE; pinfo.use = snd_emux_use; pinfo.unuse = snd_emux_unuse; pinfo.event_input = snd_emux_event_input; for (i = 0; i < emu->num_ports; i++) { struct snd_emux_port *p; sprintf(tmpname, "%s Port %d", emu->name, i); p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS, 0, &pinfo); if (p == NULL) { snd_printk(KERN_ERR "can't create port\n"); return -ENOMEM; } p->port_mode = SNDRV_EMUX_PORT_MODE_MIDI; snd_emux_init_port(p); emu->ports[i] = p->chset.port; emu->portptrs[i] = p; } return 0; }
/* register our internal client */ int __init snd_seq_system_client_init(void) { struct snd_seq_port_callback pcallbacks; struct snd_seq_port_info *port; port = kzalloc(sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM; memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; pcallbacks.event_input = event_input_timer; /* register client */ sysclient = snd_seq_create_kernel_client(NULL, 0, "System"); /* register timer */ strcpy(port->name, "Timer"); port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */ port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */ port->kernel = &pcallbacks; port->type = 0; port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; port->addr.client = sysclient; port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER; snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); /* register announcement port */ strcpy(port->name, "Announce"); port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */ port->kernel = NULL; port->type = 0; port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; port->addr.client = sysclient; port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port); announce_port = port->addr.port; kfree(port); return 0; }
static int snd_opl3_seq_probe(struct device *_dev) { struct snd_seq_device *dev = to_seq_dev(_dev); struct snd_opl3 *opl3; int client, err; char name[32]; int opl_ver; opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev); if (opl3 == NULL) return -EINVAL; spin_lock_init(&opl3->voice_lock); opl3->seq_client = -1; /* allocate new client */ opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8; sprintf(name, "OPL%i FM synth", opl_ver); client = opl3->seq_client = snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num, name); if (client < 0) return client; if ((err = snd_opl3_synth_create_port(opl3)) < 0) { snd_seq_delete_kernel_client(client); opl3->seq_client = -1; return err; } /* setup system timer */ setup_timer(&opl3->tlist, snd_opl3_timer_func, (unsigned long) opl3); spin_lock_init(&opl3->sys_timer_lock); opl3->sys_timer_status = 0; #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) snd_opl3_init_seq_oss(opl3, name); #endif return 0; }
/* * register client and create ports */ static int __init register_client(void) { struct snd_seq_dummy_port *rec1, *rec2; int i; if (ports < 1) { snd_printk(KERN_ERR "invalid number of ports %d\n", ports); return -EINVAL; } /* create client */ my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY, "Midi Through"); if (my_client < 0) return my_client; /* create ports */ for (i = 0; i < ports; i++) { rec1 = create_port(i, 0); if (rec1 == NULL) { snd_seq_delete_kernel_client(my_client); return -ENOMEM; } if (duplex) { rec2 = create_port(i, 1); if (rec2 == NULL) { snd_seq_delete_kernel_client(my_client); return -ENOMEM; } rec1->connect = rec2->port; rec2->connect = rec1->port; } } return 0; }
/* 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; }
/* register new midi synth port */ static int snd_seq_midisynth_register_port(struct snd_seq_device *dev) { struct seq_midisynth_client *client; struct seq_midisynth *msynth, *ms; struct snd_seq_port_info *port; struct snd_rawmidi_info *info; struct snd_rawmidi *rmidi = dev->private_data; int newclient = 0; unsigned int p, ports; struct snd_seq_port_callback pcallbacks; struct snd_card *card = dev->card; int device = dev->device; unsigned int input_count = 0, output_count = 0; if (snd_BUG_ON(!card || device < 0 || device >= SNDRV_RAWMIDI_DEVICES)) return -EINVAL; info = kmalloc(sizeof(*info), GFP_KERNEL); if (! info) return -ENOMEM; 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) { kfree(info); return -ENODEV; } if (ports > (256 / SNDRV_RAWMIDI_DEVICES)) ports = 256 / SNDRV_RAWMIDI_DEVICES; mutex_lock(®ister_mutex); client = synths[card->number]; if (client == NULL) { newclient = 1; client = kzalloc(sizeof(*client), GFP_KERNEL); if (client == NULL) { mutex_unlock(®ister_mutex); kfree(info); return -ENOMEM; } client->seq_client = snd_seq_create_kernel_client( card, 0, "%s", card->shortname[0] ? (const char *)card->shortname : "External MIDI"); if (client->seq_client < 0) { kfree(client); mutex_unlock(®ister_mutex); kfree(info); return -ENOMEM; } } msynth = kcalloc(ports, sizeof(struct seq_midisynth), GFP_KERNEL); port = kmalloc(sizeof(*port), GFP_KERNEL); if (msynth == NULL || port == 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 (info->name[0]) { if (ports > 1) snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p); else snprintf(port->name, sizeof(port->name), "%s", info->name); } else { /* last resort */ 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 | SNDRV_SEQ_PORT_TYPE_HARDWARE | SNDRV_SEQ_PORT_TYPE_PORT; 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 (rmidi->ops && rmidi->ops->get_port_info) rmidi->ops->get_port_info(rmidi, p, port); 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; mutex_unlock(®ister_mutex); kfree(info); kfree(port); 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); } kfree(info); kfree(port); mutex_unlock(®ister_mutex); return -ENOMEM; }
/* * create sequencer client for OSS sequencer */ int __init snd_seq_oss_create_client(void) { int rc; snd_seq_client_callback_t callback; snd_seq_client_info_t info; snd_seq_port_info_t port; snd_seq_port_callback_t port_callback; /* create ALSA client */ memset(&callback, 0, sizeof(callback)); callback.private_data = NULL; callback.allow_input = 1; callback.allow_output = 1; rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, &callback); if (rc < 0) return rc; system_client = rc; debug_printk(("new client = %d\n", rc)); /* set client information */ memset(&info, 0, sizeof(info)); info.client = system_client; info.type = KERNEL_CLIENT; strcpy(info.name, "OSS sequencer"); rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info); /* look up midi devices */ snd_seq_oss_midi_lookup_ports(system_client); /* create annoucement receiver port */ memset(&port, 0, sizeof(port)); strcpy(port.name, "Receiver"); port.addr.client = system_client; port.capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */ port.type = 0; memset(&port_callback, 0, sizeof(port_callback)); /* don't set port_callback.owner here. otherwise the module counter * is incremented and we can no longer release the module.. */ port_callback.event_input = receive_announce; port.kernel = &port_callback; call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port); if ((system_port = port.addr.port) >= 0) { snd_seq_port_subscribe_t subs; memset(&subs, 0, sizeof(subs)); subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; subs.dest.client = system_client; subs.dest.port = system_port; call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs); } return 0; }
static int snd_gus_synth_new_device(snd_seq_device_t *dev) { snd_gus_card_t *gus; int client, i; snd_seq_client_callback_t callbacks; snd_seq_client_info_t *cinfo; snd_seq_port_subscribe_t sub; snd_iwffff_ops_t *iwops; snd_gf1_ops_t *gf1ops; snd_simple_ops_t *simpleops; gus = *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev); if (gus == NULL) return -EINVAL; init_MUTEX(&gus->register_mutex); gus->gf1.seq_client = -1; cinfo = kmalloc(sizeof(*cinfo), GFP_KERNEL); if (! cinfo) return -ENOMEM; /* allocate new client */ memset(&callbacks, 0, sizeof(callbacks)); callbacks.private_data = gus; callbacks.allow_output = callbacks.allow_input = 1; client = gus->gf1.seq_client = snd_seq_create_kernel_client(gus->card, 1, &callbacks); if (client < 0) { kfree(cinfo); return client; } /* change name of client */ memset(cinfo, 0, sizeof(*cinfo)); cinfo->client = client; cinfo->type = KERNEL_CLIENT; sprintf(cinfo->name, gus->interwave ? "AMD InterWave" : "GF1"); snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, cinfo); kfree(cinfo); for (i = 0; i < 4; i++) snd_gus_synth_create_port(gus, i); gus->gf1.ilist = snd_seq_instr_list_new(); if (gus->gf1.ilist == NULL) { snd_seq_delete_kernel_client(client); gus->gf1.seq_client = -1; return -ENOMEM; } gus->gf1.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT; simpleops = &gus->gf1.simple_ops; snd_seq_simple_init(simpleops, gus, NULL); simpleops->put_sample = snd_gus_simple_put_sample; simpleops->get_sample = snd_gus_simple_get_sample; simpleops->remove_sample = snd_gus_simple_remove_sample; simpleops->notify = snd_gus_synth_instr_notify; gf1ops = &gus->gf1.gf1_ops; snd_seq_gf1_init(gf1ops, gus, &simpleops->kops); gf1ops->put_sample = snd_gus_gf1_put_sample; gf1ops->get_sample = snd_gus_gf1_get_sample; gf1ops->remove_sample = snd_gus_gf1_remove_sample; gf1ops->notify = snd_gus_synth_instr_notify; iwops = &gus->gf1.iwffff_ops; snd_seq_iwffff_init(iwops, gus, &gf1ops->kops); iwops->put_sample = snd_gus_iwffff_put_sample; iwops->get_sample = snd_gus_iwffff_get_sample; iwops->remove_sample = snd_gus_iwffff_remove_sample; iwops->notify = snd_gus_synth_instr_notify; memset(&sub, 0, sizeof(sub)); sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; sub.dest.client = client; sub.dest.port = 0; snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub); return 0; }
/* * register client and create port */ struct ALSADriver *ALSARegisterClient(void *drv) { struct ALSADriver *driver; int ret, err; printk("registering alsa client\n"); driver = kmalloc(sizeof(struct ALSADriver), GFP_KERNEL); driver->priv = kmalloc(sizeof(struct privateData), GFP_KERNEL); driver->priv->list.message = &(driver->priv->msg); driver->priv->list.next = NULL; driver->priv->drv = drv; err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(struct snd_card), &(driver->card)); if (err < 0) { pr_err("alsa error creating card: %d\n", err); goto fail_card; } /* create client */ driver->client = snd_seq_create_kernel_client(driver->card, 0, "AppleMidi"); if (driver->client < 0) { pr_err("failed to register alsa client : %d\n", driver->client); goto fail_client; } /* create port */ pr_debug("register alsa port\n"); ret = _create_port(driver->client, 0, 0, driver->priv); if (ret < 0) { goto fail_port; } pr_debug("registering snd card\n"); err = snd_card_register(driver->card); if (err < 0) { pr_err("failed to register card:err:%d\n", err); goto fail_port; } pr_debug("registered alsa client\n"); return driver; fail_port: snd_seq_delete_kernel_client(driver->client); fail_client: snd_card_free(driver->card); fail_card: kfree(driver->priv); kfree(driver); return (NULL); }