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

📄 audio.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		data[1] = d->srate >> 8;		data[2] = d->srate >> 16;		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {			printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n",			       ret, dev->devnum, u->interface, ep, d->srate);			return -1;		}		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {			printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n",			       ret, dev->devnum, u->interface, ep);			return -1;		}		dprintk((KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n",		        dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)));		d->srate = data[0] | (data[1] << 8) | (data[2] << 16);	}	dprintk((KERN_DEBUG "usbaudio: set_format_out: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));	return 0;}static int set_format(struct usb_audiodev *s, unsigned int fmode, unsigned int fmt, unsigned int srate){	int ret1 = 0, ret2 = 0;	if (!(fmode & (FMODE_READ|FMODE_WRITE)))		return -EINVAL;	if (fmode & FMODE_READ) {		usbin_stop(s);		s->usbin.dma.ready = 0;		if (fmt == AFMT_QUERY)			fmt = s->usbin.dma.format;		else			s->usbin.dma.format = fmt;		if (!srate)			srate = s->usbin.dma.srate;		else			s->usbin.dma.srate = srate;	}	if (fmode & FMODE_WRITE) {		usbout_stop(s);		s->usbout.dma.ready = 0;		if (fmt == AFMT_QUERY)			fmt = s->usbout.dma.format;		else			s->usbout.dma.format = fmt;		if (!srate)			srate = s->usbout.dma.srate;		else			s->usbout.dma.srate = srate;	}	if (fmode & FMODE_READ)		ret1 = set_format_in(s);	if (fmode & FMODE_WRITE)		ret2 = set_format_out(s);	return ret1 ? ret1 : ret2;}/* --------------------------------------------------------------------- */static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value){	struct usb_device *dev = ms->state->usbdev;	unsigned char data[2];	struct mixerchannel *ch;	int v1, v2, v3;	if (mixch >= ms->numch)		return -1;	ch = &ms->ch[mixch];	v3 = ch->maxval - ch->minval;	v1 = value & 0xff;	v2 = (value >> 8) & 0xff;	if (v1 > 100)		v1 = 100;	if (v2 > 100)		v2 = 100;	if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))		v2 = v1;	ch->value = v1 | (v2 << 8);	v1 = (v1 * v3) / 100 + ch->minval;	v2 = (v2 * v3) / 100 + ch->minval;	switch (ch->selector) {	case 0:  /* mixer unit request */		data[0] = v1;		data[1] = v1 >> 8;		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,				    (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)			goto err;		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))			return 0;		data[0] = v2;		data[1] = v2 >> 8;		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,				    ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),				    ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)			goto err;		return 0;		/* various feature unit controls */	case VOLUME_CONTROL:		data[0] = v1;		data[1] = v1 >> 8;		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)			goto err;		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))			return 0;		data[0] = v2;		data[1] = v2 >> 8;		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)			goto err;		return 0;                	case BASS_CONTROL:	case MID_CONTROL:	case TREBLE_CONTROL:		data[0] = v1 >> 8;		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)			goto err;		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))			return 0;		data[0] = v2 >> 8;		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)			goto err;		return 0;	default:		return -1;	}	return 0; err:	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 		dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector);	return -1;}static int get_rec_src(struct usb_mixerdev *ms){	struct usb_device *dev = ms->state->usbdev;	unsigned int mask = 0, retmask = 0;	unsigned int i, j;	unsigned char buf;	int err = 0;	for (i = 0; i < ms->numch; i++) {		if (!ms->ch[i].slctunitid || (mask & (1 << i)))			continue;		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {			err = -EIO;			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);			continue;		}		for (j = i; j < ms->numch; j++) {			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)				continue;			mask |= 1 << j;			if (buf == (ms->ch[j].slctunitid >> 8))				retmask |= 1 << ms->ch[j].osschannel;		}	}	if (err)		return -EIO;	return retmask;}static int set_rec_src(struct usb_mixerdev *ms, int srcmask){	struct usb_device *dev = ms->state->usbdev;	unsigned int mask = 0, smask, bmask;	unsigned int i, j;	unsigned char buf;	int err = 0;	for (i = 0; i < ms->numch; i++) {		if (!ms->ch[i].slctunitid || (mask & (1 << i)))			continue;		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {			err = -EIO;			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);			continue;		}		/* first generate smask */		smask = bmask = 0;		for (j = i; j < ms->numch; j++) {			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)				continue;			smask |= 1 << ms->ch[j].osschannel;			if (buf == (ms->ch[j].slctunitid >> 8))				bmask |= 1 << ms->ch[j].osschannel;			mask |= 1 << j;		}		/* check for multiple set sources */		j = hweight32(srcmask & smask);		if (j == 0)			continue;		if (j > 1)			srcmask &= ~bmask;		for (j = i; j < ms->numch; j++) {			if ((ms->ch[i].slctunitid ^ ms->ch[j].slctunitid) & 0xff)				continue;			if (!(srcmask & (1 << ms->ch[j].osschannel)))				continue;			buf = ms->ch[j].slctunitid >> 8;			if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,				    0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, HZ) < 0) {				err = -EIO;				printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n", 				       dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff);				continue;			}		}	}	return err ? -EIO : 0;}/* --------------------------------------------------------------------- *//* * should be called with open_sem hold, so that no new processes * look at the audio device to be destroyed */static void release(struct usb_audio_state *s){	struct usb_audiodev *as;	struct usb_mixerdev *ms;	s->count--;	if (s->count) {		up(&open_sem);		return;	}	up(&open_sem);	wake_up(&open_wait);	while (!list_empty(&s->audiolist)) {		as = list_entry(s->audiolist.next, struct usb_audiodev, list);		list_del(&as->list);		usbin_release(as);		usbout_release(as);		dmabuf_release(&as->usbin.dma);		dmabuf_release(&as->usbout.dma);		kfree(as);	}	while (!list_empty(&s->mixerlist)) {		ms = list_entry(s->mixerlist.next, struct usb_mixerdev, list);		list_del(&ms->list);		kfree(ms);	}	kfree(s);}extern inline int prog_dmabuf_in(struct usb_audiodev *as){	usbin_stop(as);	return dmabuf_init(&as->usbin.dma);}extern inline int prog_dmabuf_out(struct usb_audiodev *as){	usbout_stop(as);	return dmabuf_init(&as->usbout.dma);}/* --------------------------------------------------------------------- */static int usb_audio_open_mixdev(struct inode *inode, struct file *file){	int minor = MINOR(inode->i_rdev);	struct list_head *devs, *mdevs;	struct usb_mixerdev *ms;	struct usb_audio_state *s;	down(&open_sem);	for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {		s = list_entry(devs, struct usb_audio_state, audiodev);		for (mdevs = s->mixerlist.next; mdevs != &s->mixerlist; mdevs = mdevs->next) {			ms = list_entry(mdevs, struct usb_mixerdev, list);			if (ms->dev_mixer == minor)				goto mixer_found;		}	}	up(&open_sem);	return -ENODEV; mixer_found:	if (!s->usbdev) {		up(&open_sem);		return -EIO;	}	file->private_data = ms;	s->count++;	up(&open_sem);	return 0;}static int usb_audio_release_mixdev(struct inode *inode, struct file *file){	struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;	struct usb_audio_state *s;	lock_kernel();	s = ms->state;	down(&open_sem);	release(s);	unlock_kernel();	return 0;}static int usb_audio_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct usb_mixerdev *ms = (struct usb_mixerdev *)file->private_data;	int i, j, val;	if (!ms->state->usbdev)		return -ENODEV;  	if (cmd == SOUND_MIXER_INFO) {		mixer_info info;		strncpy(info.id, "USB_AUDIO", sizeof(info.id));		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));		info.modify_counter = ms->modcnt;		if (copy_to_user((void *)arg, &info, sizeof(info)))			return -EFAULT;		return 0;	}	if (cmd == SOUND_OLD_MIXER_INFO) {		_old_mixer_info info;		strncpy(info.id, "USB_AUDIO", sizeof(info.id));		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));		if (copy_to_user((void *)arg, &info, sizeof(info)))			return -EFAULT;		return 0;	}	if (cmd == OSS_GETVERSION)		return put_user(SOUND_VERSION, (int *)arg);	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))		return -EINVAL;	if (_IOC_DIR(cmd) == _IOC_READ) {		switch (_IOC_NR(cmd)) {		case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */			val = get_rec_src(ms);			if (val < 0)				return val;			return put_user(val, (int *)arg);		case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */			for (val = i = 0; i < ms->numch; i++)				val |= 1 << ms->ch[i].osschannel;			return put_user(val, (int *)arg);		case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */			for (val = i = 0; i < ms->numch; i++)				if (ms->ch[i].slctunitid)					val |= 1 << ms->ch[i].osschannel;			return put_user(val, (int *)arg);		case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */			for (val = i = 0; i < ms->numch; i++)				if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))					val |= 1 << ms->ch[i].osschannel;			return put_user(val, (int *)arg);					case SOUND_MIXER_CAPS:			return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);		default:			i = _IOC_NR(cmd);			if (i >= SOUND_MIXER_NRDEVICES)				return -EINVAL;			for (j = 0; j < ms->numch; j++) {				if (ms->ch[j].osschannel == i) {					return put_user(ms->ch[j].value, (int *)arg);				}			}			return -EINVAL;		}	}	if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 		return -EINVAL;	ms->modcnt++;	switch (_IOC_NR(cmd)) {	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */		if (get_user(val, (int *)arg))			return -EFAULT;		return set_rec_src(ms, val);	default:		i = _IOC_NR(cmd);		if (i >= SOUND_MIXER_NRDEVICES)			return -EINVAL;		for (j = 0; j < ms->numch && ms->ch[j].osschannel != i; j++);		if (j >= ms->numch)			return -EINVAL;		if (get_user(val, (int *)arg))			return -EFAULT;		if (wrmixer(ms, j, val))			return -EIO;		return put_user(ms->ch[j].value, (int *)arg);	}}static /*const*/ struct file_operations usb_mixer_fops = {	owner

⌨️ 快捷键说明

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