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

📄 audio.c

📁 自己根据lkd和情境分析
💻 C
📖 第 1 页 / 共 5 页
字号:
                        wake_up_interruptible(&drv->output_write_wait);        }        return bytes_read;}static void sparcaudio_sync_output(struct sparcaudio_driver * drv){        unsigned long flags;        /* If the low-level driver is not active, activate it. */        save_and_cli(flags);        if ((!drv->output_active) && (drv->output_count > 0)) {                drv->ops->start_output(drv,                                        drv->output_buffers[drv->output_front],                                       drv->output_sizes[drv->output_front]);                drv->output_active = 1;        }        restore_flags(flags);}static ssize_t sparcaudio_write(struct file * file, const char *buf,                                size_t count, loff_t *ppos){        struct inode *inode = file->f_dentry->d_inode;        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>                                                 SPARCAUDIO_DEVICE_SHIFT)];        int bytes_written = 0, bytes_to_copy, err;          if (! (file->f_mode & FMODE_WRITE))                return -EINVAL;        /* A signal they want notification when this is processed. Too bad         * sys_write doesn't tell us unless you patch it, in 2.0 kernels.         */        if (count == 0) {#ifndef notdef                drv->output_eof++;                kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);#else                /* Nice code, but the world isn't ready yet... */                drv->output_notify[drv->output_rear] = 1;#endif        }        /* Loop until all output is written to device. */        while (count > 0) {                /* Check to make sure that an output buffer is available. */                if (drv->num_output_buffers == (drv->output_count+drv->playing_count)) {                        /* We need buffers, so... */                        sparcaudio_sync_output(drv);                        if (file->f_flags & O_NONBLOCK)                                return -EAGAIN;                        interruptible_sleep_on(&drv->output_write_wait);                        if (signal_pending(current))                                return bytes_written > 0 ? bytes_written : -EINTR;                }                /* No buffers were freed. Go back to sleep */                if (drv->num_output_buffers == (drv->output_count+drv->playing_count))                         continue;                /* Deal with the weird case of a reader in the write area by trying to                 * let them keep ahead of us... Go to sleep until they start servicing.                 */                if ((drv->duplex == 2) && (drv->flags & SDF_OPEN_READ) &&                    (drv->output_rear == drv->input_rear) && (drv->input_count > 0)) {                        if (file->f_flags & O_NONBLOCK)                                return -EAGAIN;                        interruptible_sleep_on(&drv->output_write_wait);                        if (signal_pending(current))                                return bytes_written > 0 ? bytes_written : -EINTR;                }                /* Determine how much we can copy in this iteration. */                bytes_to_copy = count;                if (bytes_to_copy > drv->output_buffer_size - drv->output_offset)                        bytes_to_copy = drv->output_buffer_size - drv->output_offset;                    err = verify_area(VERIFY_READ, buf, bytes_to_copy);                if (err)                        return err;                copy_from_user(drv->output_buffers[drv->output_rear]+drv->output_offset,                               buf, bytes_to_copy);                    /* Update the queue pointers. */                buf += bytes_to_copy;                count -= bytes_to_copy;                bytes_written += bytes_to_copy;                /* A block can get orphaned in a flush and not cleaned up. */                if (drv->output_offset)                        drv->output_sizes[drv->output_rear] += bytes_to_copy;                else                        drv->output_sizes[drv->output_rear] = bytes_to_copy;                drv->output_notify[drv->output_rear] = 0;                if (drv->output_sizes[drv->output_rear] == drv->output_buffer_size) {                        drv->output_rear = (drv->output_rear + 1)                                 % drv->num_output_buffers;                        drv->output_count++;                        drv->output_offset = 0;                } else {                        drv->output_offset += bytes_to_copy;                }                drv->output_size += bytes_to_copy;        }        sparcaudio_sync_output(drv);          /* Return the number of bytes written to the caller. */        return bytes_written;}/* Add these in as new devices are supported. Belongs in audioio.h, actually */#define MONO_DEVICES (SOUND_MASK_SPEAKER | SOUND_MASK_MIC)static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file,                                  unsigned int cmd, unsigned int *arg){        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>                                                 SPARCAUDIO_DEVICE_SHIFT)];        unsigned long i = 0, j = 0, l = 0, m = 0;        unsigned int k = 0;        if (_SIOC_DIR(cmd) & _SIOC_WRITE)                drv->mixer_modify_counter++;        if(cmd == SOUND_MIXER_INFO) {                audio_device_t tmp;                mixer_info info;                int retval = -EINVAL;                if(drv->ops->sunaudio_getdev) {                        drv->ops->sunaudio_getdev(drv, &tmp);                        memset(&info, 0, sizeof(info));                        strncpy(info.id, tmp.name, sizeof(info.id));                        strncpy(info.name, "Sparc Audio", sizeof(info.name));                        info.modify_counter = drv->mixer_modify_counter;                        if(copy_to_user((char *)arg, &info, sizeof(info)))                                retval = -EFAULT;                        else                                retval = 0;                }                return retval;  }        switch (cmd) {        case SOUND_MIXER_WRITE_RECLEV:                if (get_user(k, (int *)arg))                        return -EFAULT;        iretry:                oprintk(("setting input volume (0x%x)", k));                if (drv->ops->get_input_channels)                        j = drv->ops->get_input_channels(drv);                if (drv->ops->get_input_volume)                        l = drv->ops->get_input_volume(drv);                if (drv->ops->get_input_balance)                        m = drv->ops->get_input_balance(drv);                i = OSS_TO_GAIN(k);                j = OSS_TO_BAL(k);                oprintk((" for stereo to do %d (bal %d):", i, j));                if (drv->ops->set_input_volume)                        drv->ops->set_input_volume(drv, i);                if (drv->ops->set_input_balance)                        drv->ops->set_input_balance(drv, j);        case SOUND_MIXER_READ_RECLEV:                if (drv->ops->get_input_volume)                        i = drv->ops->get_input_volume(drv);                if (drv->ops->get_input_balance)                        j = drv->ops->get_input_balance(drv);                oprintk((" got (0x%x)\n", BAL_TO_OSS(i,j)));                i = BAL_TO_OSS(i,j);                /* Try to be reasonable about volume changes */                if ((cmd == SOUND_MIXER_WRITE_RECLEV) && (i != k) &&                     (i == BAL_TO_OSS(l,m))) {                        k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256;                        k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1;                        oprintk((" try 0x%x\n", k));                        goto iretry;                }                return put_user(i, (int *)arg);        case SOUND_MIXER_WRITE_VOLUME:                if (get_user(k, (int *)arg))                        return -EFAULT;                if (drv->ops->get_output_muted && drv->ops->set_output_muted) {                        i = drv->ops->get_output_muted(drv);                        if ((k == 0) || ((i == 0) && (OSS_LEFT(k) < 100)))                                drv->ops->set_output_muted(drv, 1);                        else                                drv->ops->set_output_muted(drv, 0);                }        case SOUND_MIXER_READ_VOLUME:                if (drv->ops->get_output_muted)                         i = drv->ops->get_output_muted(drv);                k = 0x6464 * (1 - i);                return put_user(k, (int *)arg);        case SOUND_MIXER_WRITE_PCM:                if (get_user(k, (int *)arg))                        return -EFAULT;        oretry:                oprintk(("setting output volume (0x%x)\n", k));                if (drv->ops->get_output_channels)                        j = drv->ops->get_output_channels(drv);                if (drv->ops->get_output_volume)                        l = drv->ops->get_output_volume(drv);                if (drv->ops->get_output_balance)                        m = drv->ops->get_output_balance(drv);                oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m)));                i = OSS_TO_GAIN(k);                j = OSS_TO_BAL(k);                oprintk((" for stereo to %d (bal %d)\n", i, j));                if (drv->ops->set_output_volume)                        drv->ops->set_output_volume(drv, i);                if (drv->ops->set_output_balance)                        drv->ops->set_output_balance(drv, j);        case SOUND_MIXER_READ_PCM:                if (drv->ops->get_output_volume)                        i = drv->ops->get_output_volume(drv);                if (drv->ops->get_output_balance)                        j = drv->ops->get_output_balance(drv);                oprintk((" got 0x%x\n", BAL_TO_OSS(i,j)));                i = BAL_TO_OSS(i,j);                /* Try to be reasonable about volume changes */                if ((cmd == SOUND_MIXER_WRITE_PCM) && (i != k) &&                     (i == BAL_TO_OSS(l,m))) {                        k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256;                        k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1;                        oprintk((" try 0x%x\n", k));                        goto oretry;                }                return put_user(i, (int *)arg);        case SOUND_MIXER_READ_SPEAKER:                k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER);                return put_user(k, (int *)arg);        case SOUND_MIXER_READ_MIC:                k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE);                return put_user(k, (int *)arg);        case SOUND_MIXER_READ_CD:                k = OSS_IPORT_AUDIO(drv, AUDIO_CD);                return put_user(k, (int *)arg);        case SOUND_MIXER_READ_LINE:                k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN);                return put_user(k, (int *)arg);        case SOUND_MIXER_READ_LINE1:                k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE);                return put_user(k, (int *)arg);        case SOUND_MIXER_READ_LINE2:                k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT);                return put_user(k, (int *)arg);        case SOUND_MIXER_WRITE_MIC:        case SOUND_MIXER_WRITE_CD:        case SOUND_MIXER_WRITE_LINE:        case SOUND_MIXER_WRITE_LINE1:        case SOUND_MIXER_WRITE_LINE2:        case SOUND_MIXER_WRITE_SPEAKER:                if (get_user(k, (int *)arg))                        return -EFAULT;                OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k);                OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k);                OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_CD, AUDIO_CD, k);                OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k);                OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k);                OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k);

⌨️ 快捷键说明

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