Exemplo n.º 1
0
/*
 * close the midi device if already opened
 */
int
snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
{
	struct seq_oss_midi *mdev;
	struct snd_seq_port_subscribe subs;

	if ((mdev = get_mididev(dp, dev)) == NULL)
		return -ENODEV;
	if (! mdev->opened || mdev->devinfo != dp) {
		snd_use_lock_free(&mdev->use_lock);
		return 0;
	}

	memset(&subs, 0, sizeof(subs));
	if (mdev->opened & PERM_WRITE) {
		subs.sender = dp->addr;
		subs.dest.client = mdev->client;
		subs.dest.port = mdev->port;
		snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
	}
	if (mdev->opened & PERM_READ) {
		subs.sender.client = mdev->client;
		subs.sender.port = mdev->port;
		subs.dest = dp->addr;
		snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
	}

	mdev->opened = 0;
	mdev->devinfo = NULL;

	snd_use_lock_free(&mdev->use_lock);
	return 0;
}
Exemplo n.º 2
0
/*
 * look up the existing ports
 * this looks a very exhausting job.
 */
int
snd_seq_oss_midi_lookup_ports(int client)
{
	struct snd_seq_client_info *clinfo;
	struct snd_seq_port_info *pinfo;

	clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
	if (! clinfo || ! pinfo) {
		kfree(clinfo);
		kfree(pinfo);
		return -ENOMEM;
	}
	clinfo->client = -1;
	while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
		if (clinfo->client == client)
			continue; /* ignore myself */
		pinfo->addr.client = clinfo->client;
		pinfo->addr.port = -1;
		while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
			snd_seq_oss_midi_check_new_port(pinfo);
	}
	kfree(clinfo);
	kfree(pinfo);
	return 0;
}
Exemplo n.º 3
0
/* 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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/*
 * create a port
 */
static int _create_port(int my_client, int idx, int type, void *drv)
{

	struct snd_seq_port_info pinfo;
	struct snd_seq_port_callback pcb;

	pr_debug("register alsa port\n");
	memset(&pinfo, 0, sizeof(pinfo));
	pinfo.addr.client = my_client;

	sprintf(pinfo.name, "AppleMidi Port-%d", idx);

	pinfo.capability |=
	    SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
	pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
		     SNDRV_SEQ_PORT_TYPE_SOFTWARE | SNDRV_SEQ_PORT_TYPE_PORT;
	memset(&pcb, 0, sizeof(pcb));
	pcb.owner = THIS_MODULE;
	pcb.unuse = _dummy_unuse;
	pcb.event_input = _alsa_input;
	// pcb.private_free = dummy_free;
	pcb.private_data = drv;
	pinfo.kernel = &pcb;
	if (snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_CREATE_PORT,
				      &pinfo) < 0) {
		pr_err("could not register port\n");
		return -1;
	}
	return 0;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
/* set our client name */
static int set_client_name(seq_midisynth_client_t *client, snd_card_t *card,
			   snd_rawmidi_info_t *rmidi)
{
	snd_seq_client_info_t cinfo;
	const char *name;

	memset(&cinfo, 0, sizeof(cinfo));
	cinfo.client = client->seq_client;
	cinfo.type = KERNEL_CLIENT;
	name = rmidi->name[0] ? (const char *)rmidi->name : "External MIDI";
	snprintf(cinfo.name, sizeof(cinfo.name), "%s - Rawmidi %d", name, card->number);
	return snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
/* delete given midi synth port */
static void snd_seq_midisynth_delete(seq_midisynth_t *msynth)
{
	snd_seq_port_info_t port;
	
	if (msynth == NULL)
		return;

	if (msynth->seq_client > 0) {
		/* delete port */
		memset(&port, 0, sizeof(port));
		port.addr.client = msynth->seq_client;
		port.addr.port = msynth->seq_port;
		snd_seq_kernel_client_ctl(port.addr.client, SNDRV_SEQ_IOCTL_DELETE_PORT, &port);
	}

	if (msynth->parser)
		snd_midi_event_free(msynth->parser);
}
Exemplo n.º 11
0
/*
 * create a port
 */
static struct snd_seq_dummy_port __init *
create_port(int idx, int type)
{
	struct snd_seq_port_info pinfo;
	struct snd_seq_port_callback pcb;
	struct snd_seq_dummy_port *rec;

	if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL)
		return NULL;

	rec->client = my_client;
	rec->duplex = duplex;
	rec->connect = 0;
	memset(&pinfo, 0, sizeof(pinfo));
	pinfo.addr.client = my_client;
	if (duplex)
		sprintf(pinfo.name, "Midi Through Port-%d:%c", idx,
			(type ? 'B' : 'A'));
	else
		sprintf(pinfo.name, "Midi Through Port-%d", idx);
	pinfo.capability = SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
	pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
	if (duplex)
		pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
	pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
		| SNDRV_SEQ_PORT_TYPE_SOFTWARE
		| SNDRV_SEQ_PORT_TYPE_PORT;
	memset(&pcb, 0, sizeof(pcb));
	pcb.owner = THIS_MODULE;
	pcb.unuse = dummy_unuse;
	pcb.event_input = dummy_input;
	pcb.private_free = dummy_free;
	pcb.private_data = rec;
	pinfo.kernel = &pcb;
	if (snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo) < 0) {
		kfree(rec);
		return NULL;
	}
	rec->port = pinfo.addr.port;
	return rec;
}
Exemplo n.º 12
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(&register_mutex);
	client = synths[card->number];
	if (client == NULL) {
		newclient = 1;
		client = snd_kcalloc(sizeof(seq_midisynth_client_t), GFP_KERNEL);
		if (client == NULL) {
			up(&register_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(&register_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(&register_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(&register_mutex);
	return -ENOMEM;
}
Exemplo n.º 13
0
/* 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(&register_mutex);
	client = synths[card->number];
	if (client == NULL) {
		newclient = 1;
		client = kzalloc(sizeof(*client), GFP_KERNEL);
		if (client == NULL) {
			mutex_unlock(&register_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(&register_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(&register_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(&register_mutex);
	return -ENOMEM;
}
Exemplo n.º 14
0
/*
 * open the midi device if not opened yet
 */
int
snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
{
	int perm;
	struct seq_oss_midi *mdev;
	struct snd_seq_port_subscribe subs;

	if ((mdev = get_mididev(dp, dev)) == NULL)
		return -ENODEV;

	/* already used? */
	if (mdev->opened && mdev->devinfo != dp) {
		snd_use_lock_free(&mdev->use_lock);
		return -EBUSY;
	}

	perm = 0;
	if (is_write_mode(fmode))
		perm |= PERM_WRITE;
	if (is_read_mode(fmode))
		perm |= PERM_READ;
	perm &= mdev->flags;
	if (perm == 0) {
		snd_use_lock_free(&mdev->use_lock);
		return -ENXIO;
	}

	/* already opened? */
	if ((mdev->opened & perm) == perm) {
		snd_use_lock_free(&mdev->use_lock);
		return 0;
	}

	perm &= ~mdev->opened;

	memset(&subs, 0, sizeof(subs));

	if (perm & PERM_WRITE) {
		subs.sender = dp->addr;
		subs.dest.client = mdev->client;
		subs.dest.port = mdev->port;
		if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
			mdev->opened |= PERM_WRITE;
	}
	if (perm & PERM_READ) {
		subs.sender.client = mdev->client;
		subs.sender.port = mdev->port;
		subs.dest = dp->addr;
		subs.flags = SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
		subs.queue = dp->queue;		/* queue for timestamps */
		if (snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) >= 0)
			mdev->opened |= PERM_READ;
	}

	if (! mdev->opened) {
		snd_use_lock_free(&mdev->use_lock);
		return -ENXIO;
	}

	mdev->devinfo = dp;
	snd_use_lock_free(&mdev->use_lock);
	return 0;
}
Exemplo n.º 15
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;
}