📄 mtpav.c
字号:
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 + -