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; } debug_printk(("closing client %d port %d mode %d\n", mdev->client, mdev->port, mdev->opened)); 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; }
/******************************************************************** * t1_getreg_isr() * * Called in interrupt context to retrieve a value already requested * by the normal t1_getreg(). *******************************************************************/ static inline int t1_getreg_isr(struct t1 *wc, int addr) { int hit=-1; int ret; unsigned int x; /* find our requested command */ for (x = 0;x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if ((wc->cmdq.cmds[x].flags & __CMD_RD) && (wc->cmdq.cmds[x].address==addr)) { if (wc->cmdq.cmds[x].flags & __CMD_FIN) { hit = x; break; } else { /* still in progress. */ return -1; } } } if (hit < 0) { debug_printk(2, "t1_getreg_isr() no addr=%02x\n", addr); return -1; /* oops, couldn't find it */ } ret = wc->cmdq.cmds[hit].data; memset(&wc->cmdq.cmds[hit], 0, sizeof(struct command)); return ret; }
static int __init register_device(void) { int rc; mutex_lock(®ister_mutex); if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0, &seq_oss_f_ops, NULL, SNDRV_SEQ_OSS_DEVNAME)) < 0) { snd_printk(KERN_ERR "can't register device seq\n"); mutex_unlock(®ister_mutex); return rc; } if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0, &seq_oss_f_ops, NULL, SNDRV_SEQ_OSS_DEVNAME)) < 0) { snd_printk(KERN_ERR "can't register device music\n"); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); mutex_unlock(®ister_mutex); return rc; } debug_printk(("device registered\n")); mutex_unlock(®ister_mutex); return 0; }
static void free_mem(void *mem, struct memory_block *heap, void *base) { struct alloc_header *header = (struct alloc_header *)((unsigned int *)mem - sizeof(struct alloc_header)); unsigned int chunks = header->chunks; unsigned int index_block = addr_to_block((void *)header, base); unsigned int block_to_free; int i; if (header->magic != MAGIC) debug_printk("Corrupted or invalid object to be free !\n"); if (chunks < CHUNK_PER_BLOCK) { heap[index_block].free_mask &= ~(MASK(chunks) << addr_to_chunks_offset((void *)header, base)); heap[index_block].free_chunks += chunks; } else { block_to_free = chunks / CHUNK_PER_BLOCK; chunks = chunks % CHUNK_PER_BLOCK; for (i = 0; i < block_to_free; i++) { heap[index_block + i].free_mask = 0; heap[index_block + i].free_chunks = CHUNK_PER_BLOCK; } heap[index_block + block_to_free].free_mask &= ~MASK(chunks); heap[index_block + block_to_free].free_chunks += chunks; } }
void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp) { int i; struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; dp->max_synthdev = max_synth_devs; dp->synth_opened = 0; memset(dp->synths, 0, sizeof(dp->synths)); for (i = 0; i < dp->max_synthdev; i++) { rec = get_sdev(i); if (rec == NULL) continue; if (rec->oper.open == NULL || rec->oper.close == NULL) { snd_use_lock_free(&rec->use_lock); continue; } info = &dp->synths[i]; info->arg.app_index = dp->port; info->arg.file_mode = dp->file_mode; info->arg.seq_mode = dp->seq_mode; if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS; else info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS; info->opened = 0; if (!try_module_get(rec->oper.owner)) { snd_use_lock_free(&rec->use_lock); continue; } if (rec->oper.open(&info->arg, rec->private_data) < 0) { module_put(rec->oper.owner); snd_use_lock_free(&rec->use_lock); continue; } info->nr_voices = rec->nr_voices; if (info->nr_voices > 0) { info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL); if (!info->ch) { snd_printk(KERN_ERR "Cannot malloc\n"); rec->oper.close(&info->arg); module_put(rec->oper.owner); snd_use_lock_free(&rec->use_lock); continue; } reset_channels(info); } #ifdef CONFIG_DEBUG_PRINTK debug_printk(("synth %d assigned\n", i)); #else debug_; #endif info->opened++; rec->opened++; dp->synth_opened++; snd_use_lock_free(&rec->use_lock); } }
/* * 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 void unregister_device(void) { mutex_lock(®ister_mutex); debug_printk(("device unregistered\n")); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0) snd_printk(KERN_ERR "error unregister device music\n"); if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0) snd_printk(KERN_ERR "error unregister device seq\n"); mutex_unlock(®ister_mutex); }
/* * registration of the synth device */ int snd_seq_oss_synth_register(struct snd_seq_device *dev) { int i; struct seq_oss_synth *rec; struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev); unsigned long flags; if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) { snd_printk(KERN_ERR "can't malloc synth info\n"); return -ENOMEM; } rec->seq_device = -1; rec->synth_type = reg->type; rec->synth_subtype = reg->subtype; rec->nr_voices = reg->nvoices; rec->oper = reg->oper; rec->private_data = reg->private_data; rec->opened = 0; snd_use_lock_init(&rec->use_lock); /* copy and truncate the name of synth device */ strlcpy(rec->name, dev->name, sizeof(rec->name)); /* registration */ spin_lock_irqsave(®ister_lock, flags); for (i = 0; i < max_synth_devs; i++) { if (synth_devs[i] == NULL) break; } if (i >= max_synth_devs) { if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) { spin_unlock_irqrestore(®ister_lock, flags); snd_printk(KERN_ERR "no more synth slot\n"); kfree(rec); return -ENOMEM; } max_synth_devs++; } rec->seq_device = i; synth_devs[i] = rec; #ifdef CONFIG_DEBUG_PRINTK debug_printk(("synth %s registered %d\n", rec->name, i)); #else debug_; #endif spin_unlock_irqrestore(®ister_lock, flags); dev->driver_data = rec; #ifdef SNDRV_OSS_INFO_DEV_SYNTH if (i < SNDRV_CARDS) snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name); #endif return 0; }
/*************************************************************************** * clean_leftovers() * * Check for unconsumed isr register reads and clean them up. **************************************************************************/ static inline void clean_leftovers(struct t1 *wc) { unsigned int x; int count = 0; /* find our requested command */ for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if ((wc->cmdq.cmds[x].flags & __CMD_RD) && (wc->cmdq.cmds[x].flags & __CMD_ISR) && !(wc->cmdq.cmds[x].flags & __CMD_FIN)) { debug_printk(1,"leftover isr read! %d", count); memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); } } }
static int t1xxp_startup(struct zt_span *span) { struct t1 *wc = span->pvt; int i; /* initialize the start value for the entire chunk of last ec buffer */ for (i = 0; i < span->channels; i++) { memset(wc->ec_chunk1[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); memset(wc->ec_chunk2[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); } /* Reset framer with proper parameters and start */ t1xxp_framer_start(wc, span); debug_printk(1, "Calling startup (flags is %d)\n", span->flags); return 0; }
/* * reset the midi device and close it: * so far, only close the device. */ void snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev) { struct seq_oss_midi *mdev; if ((mdev = get_mididev(dp, dev)) == NULL) return; if (! mdev->opened) { snd_use_lock_free(&mdev->use_lock); return; } if (mdev->opened & PERM_WRITE) { struct snd_seq_event ev; int c; debug_printk(("resetting client %d port %d\n", mdev->client, mdev->port)); memset(&ev, 0, sizeof(ev)); ev.dest.client = mdev->client; ev.dest.port = mdev->port; ev.queue = dp->queue; ev.source.port = dp->port; if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) { ev.type = SNDRV_SEQ_EVENT_SENSING; snd_seq_oss_dispatch(dp, &ev, 0, 0); } for (c = 0; c < 16; c++) { ev.type = SNDRV_SEQ_EVENT_CONTROLLER; ev.data.control.channel = c; ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF; snd_seq_oss_dispatch(dp, &ev, 0, 0); if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS; snd_seq_oss_dispatch(dp, &ev, 0, 0); ev.type = SNDRV_SEQ_EVENT_PITCHBEND; ev.data.control.value = 0; snd_seq_oss_dispatch(dp, &ev, 0, 0); } } } // snd_seq_oss_midi_close(dp, dev); snd_use_lock_free(&mdev->use_lock); }
void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) { int i; struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) return; for (i = 0; i < dp->max_synthdev; i++) { info = &dp->synths[i]; if (! info->opened) continue; if (info->is_midi) { if (midi_synth_dev.opened > 0) { snd_seq_oss_midi_close(dp, info->midi_mapped); midi_synth_dev.opened--; } } else { rec = get_sdev(i); if (rec == NULL) continue; if (rec->opened > 0) { #ifdef CONFIG_DEBUG_PRINTK debug_printk(("synth %d closed\n", i)); #else debug_; #endif rec->oper.close(&info->arg); module_put(rec->oper.owner); rec->opened = 0; } snd_use_lock_free(&rec->use_lock); } kfree(info->sysex); info->sysex = NULL; kfree(info->ch); info->ch = NULL; } dp->synth_opened = 0; dp->max_synthdev = 0; }
void svc_sem_wait(struct semaphore *sem) { struct thread *current_thread; thread_lock(state); if (--sem->count < 0) { debug_printk("unable to got sem (%p)(%d)\r\n", sem, sem->count); current_thread = get_current_thread(); current_thread->state = THREAD_BLOCKED; insert_waiting_thread(sem, current_thread); sem->waiting++; arch_system_call(SVC_THREAD_SWITCH, NULL, NULL, NULL); } thread_unlock(state); }
void snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp) { int i; seq_oss_synth_t *rec; seq_oss_synthinfo_t *info; snd_assert(dp->max_synthdev <= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS, return); for (i = 0; i < dp->max_synthdev; i++) { info = &dp->synths[i]; if (! info->opened) continue; if (info->is_midi) { if (midi_synth_dev.opened > 0) { snd_seq_oss_midi_close(dp, info->midi_mapped); midi_synth_dev.opened--; } } else { rec = get_sdev(i); if (rec == NULL) continue; if (rec->opened > 0) { debug_printk(("synth %d closed\n", i)); rec->oper.close(&info->arg); module_put(rec->oper.owner); rec->opened = 0; } snd_use_lock_free(&rec->use_lock); } if (info->sysex) { kfree(info->sysex); info->sysex = NULL; } if (info->ch) { kfree(info->ch); info->ch = NULL; } } dp->synth_opened = 0; dp->max_synthdev = 0; }
int main(void) { #ifdef CONFIG_INITCALL int ret; initcall_t *initcall; for (initcall = __rnk_initcalls_start; initcall < __rnk_initcalls_end; initcall++) { debug_printk("initcall-> %pS\n", *initcall); ret = (*initcall)(); if (ret < 0) error_printk("initcall %pS failed: %d\n", *initcall, ret); } #endif /* CONFIG_INITCALL */ printk("Welcome to rnk\r\n"); printk("- Initialise scheduler...\r\n"); #ifndef CONFIG_INITCALL schedule_init(); time_init(); #endif /* CONFIG_INITCALL */ #ifdef CONFIG_UNWIND unwind_init(); #endif /* CONFIG_UNWIND */ printk("- Add thread to scheduler\r\n"); add_thread(&loading_thread, 1); printk("- Start scheduling...\r\n"); start_schedule(); while(1) ; return 0; //Never reach }
static int t1xxp_rbsbits(struct zt_chan *chan, int bits) { u_char m,c; int n,b; struct t1 *wc = chan->pvt; unsigned long flags; debug_printk(2, "Setting bits to %d on channel %s\n", bits, chan->name); if (wc->spantype == TYPE_E1) { /* do it E1 way */ if (chan->chanpos == 16) return 0; n = chan->chanpos - 1; if (chan->chanpos > 15) n--; b = (n % 15); spin_lock_irqsave(&wc->reglock, flags); c = wc->txsigs[b]; m = (n / 15) << 2; /* nibble selector */ c &= (0xf << m); /* keep the other nibble */ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ wc->txsigs[b] = c; spin_unlock_irqrestore(&wc->reglock, flags); /* output them to the chip */ t1_setreg_full(wc,0x71 + b,c,1,NOT_VPM); } else if (wc->span.lineconfig & ZT_CONFIG_D4) { n = chan->chanpos - 1; b = (n / 4); spin_lock_irqsave(&wc->reglock, flags); c = wc->txsigs[b]; m = ((3 - (n % 4)) << 1); /* nibble selector */ c &= ~(0x3 << m); /* keep the other nibble */ c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ wc->txsigs[b] = c; spin_unlock_irqrestore(&wc->reglock, flags); /* output them to the chip */ t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); t1_setreg_full(wc,0x70 + b + 6,c,1,NOT_VPM); } else if (wc->span.lineconfig & ZT_CONFIG_ESF) {
int snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg) { int dev, val; void __user *arg = (void __user *)carg; int __user *p = arg; switch (cmd) { case SNDCTL_TMR_TIMEBASE: case SNDCTL_TMR_TEMPO: case SNDCTL_TMR_START: case SNDCTL_TMR_STOP: case SNDCTL_TMR_CONTINUE: case SNDCTL_TMR_METRONOME: case SNDCTL_TMR_SOURCE: case SNDCTL_TMR_SELECT: case SNDCTL_SEQ_CTRLRATE: return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg); case SNDCTL_SEQ_PANIC: debug_printk(("panic\n")); snd_seq_oss_reset(dp); return -EINVAL; case SNDCTL_SEQ_SYNC: debug_printk(("sync\n")); if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) return 0; while (snd_seq_oss_writeq_sync(dp->writeq)) ; if (signal_pending(current)) return -ERESTARTSYS; return 0; case SNDCTL_SEQ_RESET: debug_printk(("reset\n")); snd_seq_oss_reset(dp); return 0; case SNDCTL_SEQ_TESTMIDI: debug_printk(("test midi\n")); if (get_user(dev, p)) return -EFAULT; return snd_seq_oss_midi_open(dp, dev, dp->file_mode); case SNDCTL_SEQ_GETINCOUNT: debug_printk(("get in count\n")); if (dp->readq == NULL || ! is_read_mode(dp->file_mode)) return 0; return put_user(dp->readq->qlen, p) ? -EFAULT : 0; case SNDCTL_SEQ_GETOUTCOUNT: debug_printk(("get out count\n")); if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) return 0; return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0; case SNDCTL_SEQ_GETTIME: debug_printk(("get time\n")); return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0; case SNDCTL_SEQ_RESETSAMPLES: debug_printk(("reset samples\n")); if (get_user(dev, p)) return -EFAULT; return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); case SNDCTL_SEQ_NRSYNTHS: debug_printk(("nr synths\n")); return put_user(dp->max_synthdev, p) ? -EFAULT : 0; case SNDCTL_SEQ_NRMIDIS: debug_printk(("nr midis\n")); return put_user(dp->max_mididev, p) ? -EFAULT : 0; case SNDCTL_SYNTH_MEMAVL: debug_printk(("mem avail\n")); if (get_user(dev, p)) return -EFAULT; val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); return put_user(val, p) ? -EFAULT : 0; case SNDCTL_FM_4OP_ENABLE: debug_printk(("4op\n")); if (get_user(dev, p)) return -EFAULT; snd_seq_oss_synth_ioctl(dp, dev, cmd, carg); return 0; case SNDCTL_SYNTH_INFO: case SNDCTL_SYNTH_ID: debug_printk(("synth info\n")); return snd_seq_oss_synth_info_user(dp, arg); case SNDCTL_SEQ_OUTOFBAND: debug_printk(("out of band\n")); return snd_seq_oss_oob_user(dp, arg); case SNDCTL_MIDI_INFO: debug_printk(("midi info\n")); return snd_seq_oss_midi_info_user(dp, arg); case SNDCTL_SEQ_THRESHOLD: debug_printk(("threshold\n")); if (! is_write_mode(dp->file_mode)) return 0; if (get_user(val, p)) return -EFAULT; if (val < 1) val = 1; if (val >= dp->writeq->maxlen) val = dp->writeq->maxlen - 1; snd_seq_oss_writeq_set_output(dp->writeq, val); return 0; case SNDCTL_MIDI_PRETIME: debug_printk(("pretime\n")); if (dp->readq == NULL || !is_read_mode(dp->file_mode)) return 0; if (get_user(val, p)) return -EFAULT; if (val <= 0) val = -1; else val = (HZ * val) / 10; dp->readq->pre_event_timeout = val; return put_user(val, p) ? -EFAULT : 0; default: debug_printk(("others\n")); if (! is_write_mode(dp->file_mode)) return -EIO; return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg); } return 0; }
/* * 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; }
int snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) { int i; struct seq_oss_midi *mdev; unsigned long flags; debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port)); /* */ if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC)) return 0; /* */ if ((pinfo->capability & PERM_WRITE) != PERM_WRITE && (pinfo->capability & PERM_READ) != PERM_READ) return 0; /* */ if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) { /* */ snd_use_lock_free(&mdev->use_lock); return 0; } /* */ if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) { snd_printk(KERN_ERR "can't malloc midi info\n"); return -ENOMEM; } /* */ mdev->client = pinfo->addr.client; mdev->port = pinfo->addr.port; mdev->flags = pinfo->capability; mdev->opened = 0; snd_use_lock_init(&mdev->use_lock); /* */ strlcpy(mdev->name, pinfo->name, sizeof(mdev->name)); /* */ if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) { snd_printk(KERN_ERR "can't malloc midi coder\n"); kfree(mdev); return -ENOMEM; } /* */ snd_midi_event_no_status(mdev->coder, 1); /* */ spin_lock_irqsave(®ister_lock, flags); for (i = 0; i < max_midi_devs; i++) { if (midi_devs[i] == NULL) break; } if (i >= max_midi_devs) { if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) { spin_unlock_irqrestore(®ister_lock, flags); snd_midi_event_free(mdev->coder); kfree(mdev); return -ENOMEM; } max_midi_devs++; } mdev->seq_device = i; midi_devs[mdev->seq_device] = mdev; spin_unlock_irqrestore(®ister_lock, flags); return 0; }
/* * register a new port if it doesn't exist yet */ int snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo) { int i; struct seq_oss_midi *mdev; unsigned long flags; debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port)); /* the port must include generic midi */ if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC)) return 0; /* either read or write subscribable */ if ((pinfo->capability & PERM_WRITE) != PERM_WRITE && (pinfo->capability & PERM_READ) != PERM_READ) return 0; /* * look for the identical slot */ if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) { /* already exists */ snd_use_lock_free(&mdev->use_lock); return 0; } /* * allocate midi info record */ if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) { snd_printk(KERN_ERR "can't malloc midi info\n"); return -ENOMEM; } /* copy the port information */ mdev->client = pinfo->addr.client; mdev->port = pinfo->addr.port; mdev->flags = pinfo->capability; mdev->opened = 0; snd_use_lock_init(&mdev->use_lock); /* copy and truncate the name of synth device */ strlcpy(mdev->name, pinfo->name, sizeof(mdev->name)); /* create MIDI coder */ if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) { snd_printk(KERN_ERR "can't malloc midi coder\n"); kfree(mdev); return -ENOMEM; } /* OSS sequencer adds running status to all sequences */ snd_midi_event_no_status(mdev->coder, 1); /* * look for en empty slot */ spin_lock_irqsave(®ister_lock, flags); for (i = 0; i < max_midi_devs; i++) { if (midi_devs[i] == NULL) break; } if (i >= max_midi_devs) { if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) { spin_unlock_irqrestore(®ister_lock, flags); snd_midi_event_free(mdev->coder); kfree(mdev); return -ENOMEM; } max_midi_devs++; } mdev->seq_device = i; midi_devs[mdev->seq_device] = mdev; spin_unlock_irqrestore(®ister_lock, flags); return 0; }