?? audio.c
字號:
} return put_user(val, (int *) arg); } else { if (file->f_mode & FMODE_READ) val = wiinst->format.channels; else if (file->f_mode & FMODE_WRITE) val = woinst->format.channels; return put_user(val, (int *) arg); } break; case SNDCTL_DSP_GETFMTS: DPF(2, "SNDCTL_DSP_GETFMTS:\n"); if (file->f_mode & FMODE_READ) val = AFMT_S16_LE; else if (file->f_mode & FMODE_WRITE) val = AFMT_S16_LE | AFMT_U8; return put_user(val, (int *) arg); case SNDCTL_DSP_SETFMT: /* Same as SNDCTL_DSP_SAMPLESIZE */ DPF(2, "SNDCTL_DSP_SETFMT:\n"); if (get_user(val, (int *) arg)) return -EFAULT; DPD(2, " val is %d\n", val); if (val != AFMT_QUERY) { if (file->f_mode & FMODE_READ) { struct wave_format format; spin_lock_irqsave(&wiinst->lock, flags); format = wiinst->format; format.bitsperchannel = val; if (emu10k1_wavein_setformat(wave_dev, &format) < 0) return -EINVAL; val = wiinst->format.bitsperchannel; spin_unlock_irqrestore(&wiinst->lock, flags); DPD(2, "set recording sample size -> %d\n", val); } if (file->f_mode & FMODE_WRITE) { struct wave_format format; spin_lock_irqsave(&woinst->lock, flags); format = woinst->format; format.bitsperchannel = val; if (emu10k1_waveout_setformat(wave_dev, &format) < 0) return -EINVAL; val = woinst->format.bitsperchannel; spin_unlock_irqrestore(&woinst->lock, flags); DPD(2, "set playback sample size -> %d\n", val); } return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg); } else { if (file->f_mode & FMODE_READ) val = wiinst->format.bitsperchannel; else if (file->f_mode & FMODE_WRITE) val = woinst->format.bitsperchannel; return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg); } break; case SOUND_PCM_READ_BITS: if (file->f_mode & FMODE_READ) val = wiinst->format.bitsperchannel; else if (file->f_mode & FMODE_WRITE) val = woinst->format.bitsperchannel; return put_user((val == 16) ? AFMT_S16_LE : AFMT_U8, (int *) arg); case SOUND_PCM_READ_RATE: if (file->f_mode & FMODE_READ) val = wiinst->format.samplingrate; else if (file->f_mode & FMODE_WRITE) val = woinst->format.samplingrate; return put_user(val, (int *) arg); case SOUND_PCM_READ_CHANNELS: if (file->f_mode & FMODE_READ) val = wiinst->format.channels; else if (file->f_mode & FMODE_WRITE) val = woinst->format.channels; return put_user(val, (int *) arg); case SOUND_PCM_WRITE_FILTER: DPF(2, "SOUND_PCM_WRITE_FILTER: not implemented\n"); break; case SOUND_PCM_READ_FILTER: DPF(2, "SOUND_PCM_READ_FILTER: not implemented\n"); break; case SNDCTL_DSP_SETSYNCRO: DPF(2, "SNDCTL_DSP_SETSYNCRO: not implemented\n"); break; case SNDCTL_DSP_GETTRIGGER: DPF(2, "SNDCTL_DSP_GETTRIGGER:\n"); if (file->f_mode & FMODE_WRITE && (wave_dev->enablebits & PCM_ENABLE_OUTPUT)) val |= PCM_ENABLE_OUTPUT; if (file->f_mode & FMODE_READ && (wave_dev->enablebits & PCM_ENABLE_INPUT)) val |= PCM_ENABLE_INPUT; return put_user(val, (int *) arg); case SNDCTL_DSP_SETTRIGGER: DPF(2, "SNDCTL_DSP_SETTRIGGER:\n"); if (get_user(val, (int *) arg)) return -EFAULT; if (file->f_mode & FMODE_WRITE) { spin_lock_irqsave(&woinst->lock, flags); if (val & PCM_ENABLE_OUTPUT) { wave_dev->enablebits |= PCM_ENABLE_OUTPUT; if (woinst->state & WAVE_STATE_OPEN) emu10k1_waveout_start(wave_dev); } else { wave_dev->enablebits &= ~PCM_ENABLE_OUTPUT; if (woinst->state & WAVE_STATE_STARTED) emu10k1_waveout_stop(wave_dev); } spin_unlock_irqrestore(&woinst->lock, flags); } if (file->f_mode & FMODE_READ) { spin_lock_irqsave(&wiinst->lock, flags); if (val & PCM_ENABLE_INPUT) { wave_dev->enablebits |= PCM_ENABLE_INPUT; if (wiinst->state & WAVE_STATE_OPEN) emu10k1_wavein_start(wave_dev); } else { wave_dev->enablebits &= ~PCM_ENABLE_INPUT; if (wiinst->state & WAVE_STATE_STARTED) emu10k1_wavein_stop(wave_dev); } spin_unlock_irqrestore(&wiinst->lock, flags); } break; case SNDCTL_DSP_GETOSPACE: { audio_buf_info info; DPF(4, "SNDCTL_DSP_GETOSPACE:\n"); if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; spin_lock_irqsave(&woinst->lock, flags); if (woinst->state & WAVE_STATE_OPEN) { emu10k1_waveout_update(woinst); emu10k1_waveout_getxfersize(woinst, &bytestocopy); info.bytes = bytestocopy; } else { calculate_ofrag(woinst); info.bytes = woinst->buffer.size; } spin_unlock_irqrestore(&woinst->lock, flags); info.fragstotal = woinst->buffer.numfrags; info.fragments = info.bytes / woinst->buffer.fragment_size; info.fragsize = woinst->buffer.fragment_size; if (copy_to_user((int *) arg, &info, sizeof(info))) return -EFAULT; } break; case SNDCTL_DSP_GETISPACE: { audio_buf_info info; DPF(4, "SNDCTL_DSP_GETISPACE:\n"); if (!(file->f_mode & FMODE_READ)) return -EINVAL; spin_lock_irqsave(&wiinst->lock, flags); if (wiinst->state & WAVE_STATE_OPEN) { emu10k1_wavein_update(wave_dev->card, wiinst); emu10k1_wavein_getxfersize(wiinst, &bytestocopy); info.bytes = bytestocopy; } else { calculate_ifrag(wiinst); info.bytes = 0; } spin_unlock_irqrestore(&wiinst->lock, flags); info.fragstotal = wiinst->buffer.numfrags; info.fragments = info.bytes / wiinst->buffer.fragment_size; info.fragsize = wiinst->buffer.fragment_size; if (copy_to_user((int *) arg, &info, sizeof(info))) return -EFAULT; } break; case SNDCTL_DSP_NONBLOCK: DPF(2, "SNDCTL_DSP_NONBLOCK:\n"); file->f_flags |= O_NONBLOCK; break; case SNDCTL_DSP_GETODELAY: DPF(4, "SNDCTL_DSP_GETODELAY:\n"); if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; spin_lock_irqsave(&woinst->lock, flags); if (woinst->state & WAVE_STATE_OPEN) { emu10k1_waveout_update(woinst); emu10k1_waveout_getxfersize(woinst, &bytestocopy); val = woinst->buffer.size - bytestocopy; } else val = 0; spin_unlock_irqrestore(&woinst->lock, flags); return put_user(val, (int *) arg); case SNDCTL_DSP_GETIPTR: { count_info cinfo; DPF(4, "SNDCTL_DSP_GETIPTR: \n"); if (!(file->f_mode & FMODE_READ)) return -EINVAL; spin_lock_irqsave(&wiinst->lock, flags); if (wiinst->state & WAVE_STATE_OPEN) { emu10k1_wavein_update(wave_dev->card, wiinst); cinfo.ptr = wiinst->buffer.hw_pos; cinfo.bytes = cinfo.ptr + wiinst->total_recorded - wiinst->total_recorded % wiinst->buffer.size; cinfo.blocks = cinfo.bytes / wiinst->buffer.fragment_size - wiinst->blocks; wiinst->blocks = cinfo.bytes / wiinst->buffer.fragment_size; } else { cinfo.ptr = 0; cinfo.bytes = 0; cinfo.blocks = 0; } spin_unlock_irqrestore(&wiinst->lock, flags); if (copy_to_user((void *) arg, &cinfo, sizeof(cinfo))) return -EFAULT; } break; case SNDCTL_DSP_GETOPTR: { count_info cinfo; DPF(4, "SNDCTL_DSP_GETOPTR:\n"); if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; spin_lock_irqsave(&woinst->lock, flags); if (woinst->state & WAVE_STATE_OPEN) { emu10k1_waveout_update(woinst); cinfo.ptr = woinst->buffer.hw_pos; cinfo.bytes = cinfo.ptr + woinst->total_played - woinst->total_played % woinst->buffer.size; cinfo.blocks = cinfo.bytes / woinst->buffer.fragment_size - woinst->blocks; woinst->blocks = cinfo.bytes / woinst->buffer.fragment_size; } else { cinfo.ptr = 0; cinfo.bytes = 0; cinfo.blocks = 0; } if(woinst->mmapped) woinst->buffer.bytestocopy %= woinst->buffer.fragment_size; spin_unlock_irqrestore(&woinst->lock, flags); if (copy_to_user((void *) arg, &cinfo, sizeof(cinfo))) return -EFAULT; } break; case SNDCTL_DSP_GETBLKSIZE: DPF(2, "SNDCTL_DSP_GETBLKSIZE:\n"); if (file->f_mode & FMODE_WRITE) { spin_lock_irqsave(&woinst->lock, flags); calculate_ofrag(woinst); val = woinst->buffer.fragment_size; spin_unlock_irqrestore(&woinst->lock, flags); } if (file->f_mode & FMODE_READ) { spin_lock_irqsave(&wiinst->lock, flags); calculate_ifrag(wiinst); val = wiinst->buffer.fragment_size; spin_unlock_irqrestore(&wiinst->lock, flags); } return put_user(val, (int *) arg); break; case SNDCTL_DSP_POST: if (file->f_mode & FMODE_WRITE) { spin_lock_irqsave(&woinst->lock, flags); if (!(woinst->state & WAVE_STATE_STARTED) && (wave_dev->enablebits & PCM_ENABLE_OUTPUT) && (woinst->total_copied > 0)) emu10k1_waveout_start(wave_dev); spin_unlock_irqrestore(&woinst->lock, flags); } break; case SNDCTL_DSP_SUBDIVIDE: DPF(2, "SNDCTL_DSP_SUBDIVIDE: not implemented\n"); break; case SNDCTL_DSP_SETFRAGMENT: DPF(2, "SNDCTL_DSP_SETFRAGMENT:\n"); if (get_user(val, (int *) arg)) return -EFAULT; DPD(2, "val is 0x%x\n", val); if (val == 0) return -EIO; if (file->f_mode & FMODE_WRITE) { if (woinst->state & WAVE_STATE_OPEN) return -EINVAL; /* too late to change */ woinst->buffer.ossfragshift = val & 0xffff; woinst->buffer.numfrags = (val >> 16) & 0xffff; } if (file->f_mode & FMODE_READ) { if (wiinst->state & WAVE_STATE_OPEN) return -EINVAL; /* too late to change */ wiinst->buffer.ossfragshift = val & 0xffff; wiinst->buffer.numfrags = (val >> 16) & 0xffff; } break; case SNDCTL_COPR_LOAD: { copr_buffer buf; u32 i; DPF(2, "SNDCTL_COPR_LOAD:\n"); if (copy_from_user(&buf, (copr_buffer *) arg, sizeof(buf))) return -EFAULT; if ((buf.command != 1) && (buf.command != 2)) return -EINVAL; if ((buf.offs < 0x100) || (buf.offs < 0x000) || (buf.offs + buf.len > 0x800) || (buf.len > 1000)) return -EINVAL; if (buf.command == 1) { for (i = 0; i < buf.len; i++) ((u32 *) buf.data)[i] = sblive_readptr(wave_dev->card, buf.offs + i, 0); if (copy_to_user((copr_buffer *) arg, &buf, sizeof(buf))) return -EFAULT; } else { for (i = 0; i < buf.len; i++) sblive_writeptr(wave_dev->card, buf.offs + i, 0, ((u32 *) buf.data)[i]); } break; } default: /* Default is unrecognized command */ DPD(2, "default: 0x%x\n", cmd); return -EINVAL; } return 0;}static int emu10k1_audio_mmap(struct file *file, struct vm_area_struct *vma){ struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; DPF(2, "emu10k1_audio_mmap()\n"); if (vma_get_pgoff(vma) != 0) return -ENXIO; lock_kernel(); if (vma->vm_flags & VM_WRITE) { struct woinst *woinst = wave_dev->woinst; u32 size; unsigned long flags; int i; spin_lock_irqsave(&woinst->lock, flags); if (woinst->state == WAVE_STATE_CLOSED) { calculate_ofrag(woinst); if (emu10k1_waveout_open(wave_dev) < 0) { spin_unlock_irqrestore(&woinst->lock, flags); ERROR(); unlock_kernel(); return -EINVAL; } /* Now mark the pages as reserved, otherwise remap_page_range doesn't do what we want */ for (i = 0; i < woinst->buffer.pages; i++) mem_map_reserve(virt_to_page(woinst->buffer.addr[i])); } size = vma->vm_end - vma->vm_start; if (size > (PAGE_SIZE * woinst->buffer.pages)) { spin_unlock_irqrestore(&woinst->lock, flags); unlock_kernel(); return -EINVAL; } for (i = 0; i < woinst->buffer.pages; i++) { if (remap_page_range(vma->vm_start + (i * PAGE_SIZE), virt_to_phys(woinst->buffer.addr[i]), PAGE_SIZE, vma->vm_page_prot)) { spin_unlock_irqrestore(&woinst->lock, flags); return -EAGAIN; } } woinst->mmapped = 1; spin_unlock_irqrestore(&woinst->lock, flags); } if (vma->vm_flags & VM_READ) { struct wiinst *wiinst = wave_dev->wiinst; unsigned long flags; spin_lock_irqsave(&wiinst->lock, flags); wiinst->mmapped = 1; spin_unlock_irqrestore(&wiinst->lock, flags); } unlock_kernel(); return 0;}static int emu10k1_audio_open(struct inode *inode, struct file *file){ int minor = MINOR(inode->i_rdev); struct emu10k1_card *card; struct list_head *entry; struct emu10k1_wavedevice *wave_dev; DPF(2, "emu10k1_audio_open()\n"); /* Check for correct device to open */ list_for_each(entry, &emu10k1_devs) { card = list_entry(entry, struct emu10k1_card, list); if (!((card->audio_num ^ minor) & ~0xf) || !((card->audio1_num ^ minor) & ~0xf))
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -