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