⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtpav.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		portp->mode |= MTPAV_MODE_INPUT_TRIGGERED;	else		portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED;	spin_unlock_irqrestore(&mtp_card->spinlock, flags);}/* * timer interrupt for outputs */static void snd_mtpav_output_timer(unsigned long data){	unsigned long flags;	struct mtpav *chip = (struct mtpav *)data;	int p;	spin_lock_irqsave(&chip->spinlock, flags);	/* reprogram timer */	chip->timer.expires = 1 + jiffies;	add_timer(&chip->timer);	/* process each port */	for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) {		struct mtpav_port *portp = &chip->ports[p];		if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)			snd_mtpav_output_port_write(chip, portp, portp->output);	}	spin_unlock_irqrestore(&chip->spinlock, flags);}/* spinlock held! */static void snd_mtpav_add_output_timer(struct mtpav *chip){	chip->timer.expires = 1 + jiffies;	add_timer(&chip->timer);}/* spinlock held! */static void snd_mtpav_remove_output_timer(struct mtpav *chip){	del_timer(&chip->timer);}/* */static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream){	struct mtpav *mtp_card = substream->rmidi->private_data;	struct mtpav_port *portp = &mtp_card->ports[substream->number];	unsigned long flags;	spin_lock_irqsave(&mtp_card->spinlock, flags);	portp->mode |= MTPAV_MODE_OUTPUT_OPENED;	portp->output = substream;	spin_unlock_irqrestore(&mtp_card->spinlock, flags);	return 0;};/* */static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream){	struct mtpav *mtp_card = substream->rmidi->private_data;	struct mtpav_port *portp = &mtp_card->ports[substream->number];	unsigned long flags;	spin_lock_irqsave(&mtp_card->spinlock, flags);	portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED;	portp->output = NULL;	spin_unlock_irqrestore(&mtp_card->spinlock, flags);	return 0;};/* */static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up){	struct mtpav *mtp_card = substream->rmidi->private_data;	struct mtpav_port *portp = &mtp_card->ports[substream->number];	unsigned long flags;	spin_lock_irqsave(&mtp_card->spinlock, flags);	if (up) {		if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) {			if (mtp_card->istimer++ == 0)				snd_mtpav_add_output_timer(mtp_card);			portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED;		}	} else {		portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED;		if (--mtp_card->istimer == 0)			snd_mtpav_remove_output_timer(mtp_card);	}	spin_unlock_irqrestore(&mtp_card->spinlock, flags);	if (up)		snd_mtpav_output_write(substream);}/* * midi interrupt for inputs */static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte){	struct mtpav_port *portp;	if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST)		return;	portp = &mcrd->ports[mcrd->inmidiport];	if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED)		snd_rawmidi_receive(portp->input, &inbyte, 1);}static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte){	if (inbyte >= 0xf8) {		/* real-time midi code */		snd_mtpav_inmidi_process(mcrd, inbyte);		return;	}	if (mcrd->inmidistate == 0) {	// awaiting command		if (inbyte == 0xf5)	// MTP port #			mcrd->inmidistate = 1;		else			snd_mtpav_inmidi_process(mcrd, inbyte);	} else if (mcrd->inmidistate) {		mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte);		mcrd->inmidistate = 0;	}}static void snd_mtpav_read_bytes(struct mtpav *mcrd){	u8 clrread, setread;	u8 mtp_read_byte;	u8 sr, cbyt;	int i;	u8 sbyt = snd_mtpav_getreg(mcrd, SREG);	//printk("snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt);	if (!(sbyt & SIGS_BYTE))		return;	cbyt = snd_mtpav_getreg(mcrd, CREG);	clrread = cbyt & (SIGC_READ ^ 0xff);	setread = cbyt | SIGC_READ;	do {		mtp_read_byte = 0;		for (i = 0; i < 4; i++) {			snd_mtpav_mputreg(mcrd, CREG, setread);			sr = snd_mtpav_getreg(mcrd, SREG);			snd_mtpav_mputreg(mcrd, CREG, clrread);			sr &= SIGS_IN0 | SIGS_IN1;			sr >>= 4;			mtp_read_byte |= sr << (i * 2);		}		snd_mtpav_inmidi_h(mcrd, mtp_read_byte);		sbyt = snd_mtpav_getreg(mcrd, SREG);	} while (sbyt & SIGS_BYTE);}static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id){	struct mtpav *mcard = dev_id;	spin_lock(&mcard->spinlock);	snd_mtpav_read_bytes(mcard);	spin_unlock(&mcard->spinlock);	return IRQ_HANDLED;}/* * get ISA resources */static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard){	if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {		snd_printk("MTVAP port 0x%lx is busy\n", port);		return -EBUSY;	}	mcard->port = port;	if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) {		snd_printk("MTVAP IRQ %d busy\n", irq);		return -EBUSY;	}	mcard->irq = irq;	return 0;}/* */static struct snd_rawmidi_ops snd_mtpav_output = {	.open =		snd_mtpav_output_open,	.close =	snd_mtpav_output_close,	.trigger =	snd_mtpav_output_trigger,};static struct snd_rawmidi_ops snd_mtpav_input = {	.open =		snd_mtpav_input_open,	.close =	snd_mtpav_input_close,	.trigger =	snd_mtpav_input_trigger,};/* * get RAWMIDI resources */static void __devinit snd_mtpav_set_name(struct mtpav *chip,				      struct snd_rawmidi_substream *substream){	if (substream->number >= 0 && substream->number < chip->num_ports)		sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);	else if (substream->number >= 8 && substream->number < chip->num_ports * 2)		sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1);	else if (substream->number == chip->num_ports * 2)		strcpy(substream->name, "MTP computer");	else if (substream->number == chip->num_ports * 2 + 1)		strcpy(substream->name, "MTP ADAT");	else		strcpy(substream->name, "MTP broadcast");}static int __devinit snd_mtpav_get_RAWMIDI(struct mtpav *mcard){	int rval;	struct snd_rawmidi *rawmidi;	struct snd_rawmidi_substream *substream;	struct list_head *list;	if (hwports < 1)		hwports = 1;	else if (hwports > 8)		hwports = 8;	mcard->num_ports = hwports;	if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0,				    mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,				    mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,				    &mcard->rmidi)) < 0)		return rval;	rawmidi = mcard->rmidi;	rawmidi->private_data = mcard;	list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {		substream = list_entry(list, struct snd_rawmidi_substream, list);		snd_mtpav_set_name(mcard, substream);		substream->ops = &snd_mtpav_input;	}	list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {		substream = list_entry(list, struct snd_rawmidi_substream, list);		snd_mtpav_set_name(mcard, substream);		substream->ops = &snd_mtpav_output;		mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number);	}	rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |			       SNDRV_RAWMIDI_INFO_DUPLEX;	sprintf(rawmidi->name, "MTP AV MIDI");	return 0;}/* */static void snd_mtpav_free(struct snd_card *card){	struct mtpav *crd = card->private_data;	unsigned long flags;	spin_lock_irqsave(&crd->spinlock, flags);	if (crd->istimer > 0)		snd_mtpav_remove_output_timer(crd);	spin_unlock_irqrestore(&crd->spinlock, flags);	if (crd->irq >= 0)		free_irq(crd->irq, (void *)crd);	release_and_free_resource(crd->res_port);}/* */static int __devinit snd_mtpav_probe(struct platform_device *dev){	struct snd_card *card;	int err;	struct mtpav *mtp_card;	card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card));	if (! card)		return -ENOMEM;	mtp_card = card->private_data;	spin_lock_init(&mtp_card->spinlock);	init_timer(&mtp_card->timer);	mtp_card->card = card;	mtp_card->irq = -1;	mtp_card->share_irq = 0;	mtp_card->inmidiport = 0xffffffff;	mtp_card->inmidistate = 0;	mtp_card->outmidihwport = 0xffffffff;	init_timer(&mtp_card->timer);	mtp_card->timer.function = snd_mtpav_output_timer;	mtp_card->timer.data = (unsigned long) mtp_card;	card->private_free = snd_mtpav_free;	err = snd_mtpav_get_ISA(mtp_card);	if (err < 0)		goto __error;	strcpy(card->driver, "MTPAV");	strcpy(card->shortname, "MTPAV on parallel port");	snprintf(card->longname, sizeof(card->longname),		 "MTPAV on parallel port at 0x%lx", port);	err = snd_mtpav_get_RAWMIDI(mtp_card);	if (err < 0)		goto __error;	snd_mtpav_portscan(mtp_card);	snd_card_set_dev(card, &dev->dev);	err = snd_card_register(mtp_card->card);	if (err < 0)		goto __error;	platform_set_drvdata(dev, card);	printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);	return 0; __error:	snd_card_free(card);	return err;}static int __devexit snd_mtpav_remove(struct platform_device *devptr){	snd_card_free(platform_get_drvdata(devptr));	platform_set_drvdata(devptr, NULL);	return 0;}#define SND_MTPAV_DRIVER	"snd_mtpav"static struct platform_driver snd_mtpav_driver = {	.probe		= snd_mtpav_probe,	.remove		= __devexit_p(snd_mtpav_remove),	.driver		= {		.name	= SND_MTPAV_DRIVER	},};static int __init alsa_card_mtpav_init(void){	int err;	if ((err = platform_driver_register(&snd_mtpav_driver)) < 0)		return err;	device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);	if (!IS_ERR(device)) {		if (platform_get_drvdata(device))			return 0;		platform_device_unregister(device);		err = -ENODEV;	} else		err = PTR_ERR(device);	platform_driver_unregister(&snd_mtpav_driver);	return err;}static void __exit alsa_card_mtpav_exit(void){	platform_device_unregister(device);	platform_driver_unregister(&snd_mtpav_driver);}module_init(alsa_card_mtpav_init)module_exit(alsa_card_mtpav_exit)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -