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

📄 audio.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;	struct usbout *u = &as->usbout;	unsigned long flags;	unsigned int mask;	int suret = USB_ST_NOERROR;#if 0	printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);#endif	if (urb == &u->durb[0].urb)		mask = FLG_URB0RUNNING;	else if (urb == &u->durb[1].urb)		mask = FLG_URB1RUNNING;	else {		mask = 0;		printk(KERN_ERR "usbout_completed: panic: unknown URB\n");	}	urb->dev = as->state->usbdev;	spin_lock_irqsave(&as->lock, flags);	if (!usbout_retire_desc(u, urb) &&	    u->flags & FLG_RUNNING &&	    !usbout_prepare_desc(u, urb) && 	    (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {		u->flags |= mask;	} else {		u->flags &= ~(mask | FLG_RUNNING);		wake_up(&u->dma.wait);		dprintk((KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));	}	spin_unlock_irqrestore(&as->lock, flags);}static int usbout_sync_prepare_desc(struct usbout *u, purb_t urb){	unsigned int i, offs;	for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3) {		urb->iso_frame_desc[i].length = 3;		urb->iso_frame_desc[i].offset = offs;	}	return 0;}/* * return value: 0 if descriptor should be restarted, -1 otherwise */static int usbout_sync_retire_desc(struct usbout *u, purb_t urb){	unsigned char *cp = urb->transfer_buffer;	unsigned int f, i;	for (i = 0; i < SYNCFRAMES; i++, cp += 3) {		if (urb->iso_frame_desc[i].status) {			dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));			continue;		}		if (urb->iso_frame_desc[i].actual_length < 3) {			dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length));			continue;		}		f = cp[0] | (cp[1] << 8) | (cp[2] << 16);		if (abs(f - u->freqn) > (u->freqn >> 3) || f > u->freqmax) {			printk(KERN_WARNING "usbout_sync_retire_desc: requested frequency %u (nominal %u) out of range!\n", f, u->freqn);			continue;		}		u->freqm = f;	}	return 0;}static void usbout_sync_completed(struct urb *urb){	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;	struct usbout *u = &as->usbout;	unsigned long flags;	unsigned int mask;	int suret = USB_ST_NOERROR;#if 0	printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);#endif	if (urb == &u->surb[0].urb)		mask = FLG_SYNC0RUNNING;	else if (urb == &u->surb[1].urb)		mask = FLG_SYNC1RUNNING;	else {		mask = 0;		printk(KERN_ERR "usbout_sync_completed: panic: unknown URB\n");	}	urb->dev = as->state->usbdev;	spin_lock_irqsave(&as->lock, flags);	if (!usbout_sync_retire_desc(u, urb) &&	    u->flags & FLG_RUNNING &&	    !usbout_sync_prepare_desc(u, urb) && 	    (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {		u->flags |= mask;	} else {		u->flags &= ~(mask | FLG_RUNNING);		wake_up(&u->dma.wait);		dprintk((KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));	}	spin_unlock_irqrestore(&as->lock, flags);}static int usbout_start(struct usb_audiodev *as){	struct usb_device *dev = as->state->usbdev;	struct usbout *u = &as->usbout;	purb_t urb;	unsigned long flags;	unsigned int maxsze, bufsz;#if 0	printk(KERN_DEBUG "usbout_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n",	       dev->devnum, u->format, u->dma.format, u->dma.srate);#endif	/* allocate USB storage if not already done */	spin_lock_irqsave(&as->lock, flags);	if (!(u->flags & FLG_CONNECTED)) {		spin_unlock_irqrestore(&as->lock, flags);		return -EIO;	}	if (!(u->flags & FLG_RUNNING)) {		spin_unlock_irqrestore(&as->lock, flags);		u->freqn = u->freqm = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */		u->freqmax = u->freqn + (u->freqn >> 2);		u->phase = 0;		maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));		bufsz = DESCFRAMES * maxsze;		if (u->durb[0].urb.transfer_buffer)			kfree(u->durb[0].urb.transfer_buffer);		u->durb[0].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL);		u->durb[0].urb.transfer_buffer_length = bufsz;		if (u->durb[1].urb.transfer_buffer)			kfree(u->durb[1].urb.transfer_buffer);		u->durb[1].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL);		u->durb[1].urb.transfer_buffer_length = bufsz;		if (u->syncpipe) {			if (u->surb[0].urb.transfer_buffer)				kfree(u->surb[0].urb.transfer_buffer);			u->surb[0].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);			u->surb[0].urb.transfer_buffer_length = 3*SYNCFRAMES;			if (u->surb[1].urb.transfer_buffer)				kfree(u->surb[1].urb.transfer_buffer);			u->surb[1].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL);			u->surb[1].urb.transfer_buffer_length = 3*SYNCFRAMES;		}		if (!u->durb[0].urb.transfer_buffer || !u->durb[1].urb.transfer_buffer || 		    (u->syncpipe && (!u->surb[0].urb.transfer_buffer || !u->surb[1].urb.transfer_buffer))) {			printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum);			return 0;		}		spin_lock_irqsave(&as->lock, flags);	}	if (u->dma.count <= 0 && !u->dma.mapped) {		spin_unlock_irqrestore(&as->lock, flags);		return 0;	}       	u->flags |= FLG_RUNNING;	if (!(u->flags & FLG_URB0RUNNING)) {		urb = &u->durb[0].urb;		urb->dev = dev;		urb->pipe = u->datapipe;		urb->transfer_flags = USB_ISO_ASAP;		urb->number_of_packets = DESCFRAMES;		urb->context = as;		urb->complete = usbout_completed;		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb))			u->flags |= FLG_URB0RUNNING;		else			u->flags &= ~FLG_RUNNING;	}	if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) {		urb = &u->durb[1].urb;		urb->dev = dev;		urb->pipe = u->datapipe;		urb->transfer_flags = USB_ISO_ASAP;		urb->number_of_packets = DESCFRAMES;		urb->context = as;		urb->complete = usbout_completed;		if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb))			u->flags |= FLG_URB1RUNNING;		else			u->flags &= ~FLG_RUNNING;	}	if (u->syncpipe) {		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) {			urb = &u->surb[0].urb;			urb->dev = dev;			urb->pipe = u->syncpipe;			urb->transfer_flags = USB_ISO_ASAP;			urb->number_of_packets = SYNCFRAMES;			urb->context = as;			urb->complete = usbout_sync_completed;			/* stride: u->syncinterval */			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))				u->flags |= FLG_SYNC0RUNNING;			else				u->flags &= ~FLG_RUNNING;		}		if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) {			urb = &u->surb[1].urb;			urb->dev = dev;			urb->pipe = u->syncpipe;			urb->transfer_flags = USB_ISO_ASAP;			urb->number_of_packets = SYNCFRAMES;			urb->context = as;			urb->complete = usbout_sync_completed;			/* stride: u->syncinterval */			if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb))				u->flags |= FLG_SYNC1RUNNING;			else				u->flags &= ~FLG_RUNNING;		}	}	spin_unlock_irqrestore(&as->lock, flags);	return 0;}/* --------------------------------------------------------------------- */static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate){	unsigned int g = 0;	if (srate < afp->sratelo)		g += afp->sratelo - srate;	if (srate > afp->sratehi)		g += srate - afp->sratehi;	if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt))		g += 0x100000;	if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt))		g += 0x400000;	if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt))		g += 0x100000;	if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt))		g += 0x400000;	return g;}static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate){	unsigned int i, g, gb = ~0;	int j = -1; /* default to failure */	/* find "best" format (according to format_goodness) */	for (i = 0; i < nr; i++) {		g = format_goodness(&afp[i], fmt, srate);		if (g >= gb) 			continue;		j = i;		gb = g;	}       	return j;}static int set_format_in(struct usb_audiodev *as){	struct usb_device *dev = as->state->usbdev;	struct usb_config_descriptor *config = dev->actconfig;	struct usb_interface_descriptor *alts;	struct usb_interface *iface;	struct usbin *u = &as->usbin;	struct dmabuf *d = &u->dma;	struct audioformat *fmt;	unsigned int ep;	unsigned char data[3];	int fmtnr, ret;	if (u->interface < 0 || u->interface >= config->bNumInterfaces)		return 0;	iface = &config->interface[u->interface];	fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate);	if (fmtnr < 0) {		printk(KERN_ERR "usbaudio: set_format_in(): failed to find desired format/speed combination.\n");		return -1;	}	fmt = as->fmtin + fmtnr;	alts = &iface->altsetting[fmt->altsetting];	u->format = fmt->format;	u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf);	u->syncpipe = u->syncinterval = 0;	if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x08) {		if (alts->bNumEndpoints < 2 ||		    alts->endpoint[1].bmAttributes != 0x01 ||		    alts->endpoint[1].bSynchAddress != 0 ||		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress & 0x7f)) {			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",			       dev->devnum, u->interface, fmt->altsetting);			return -1;		}		u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);		u->syncinterval = alts->endpoint[1].bRefresh;	}	if (d->srate < fmt->sratelo)		d->srate = fmt->sratelo;	if (d->srate > fmt->sratehi)		d->srate = fmt->sratehi;	dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));	if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",		       dev->devnum, u->interface, fmt->altsetting);		return -1;	}	if (fmt->sratelo == fmt->sratehi)		return 0;	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);	/* if endpoint has pitch control, enable it */	if (fmt->attributes & 0x02) {		data[0] = 1;		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",			       ret, dev->devnum, u->interface, ep, d->srate);			return -1;		}	}	/* if endpoint has sampling rate control, set it */	if (fmt->attributes & 0x01) {		data[0] = d->srate;		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 input 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 input sampling frequency device %d interface %u endpoint 0x%x\n",			       ret, dev->devnum, u->interface, ep);			return -1;		}		dprintk((KERN_DEBUG "usbaudio: set_format_in: 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_in: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate));	return 0;}static int set_format_out(struct usb_audiodev *as){	struct usb_device *dev = as->state->usbdev;	struct usb_config_descriptor *config = dev->actconfig;	struct usb_interface_descriptor *alts;	struct usb_interface *iface;		struct usbout *u = &as->usbout;	struct dmabuf *d = &u->dma;	struct audioformat *fmt;	unsigned int ep;	unsigned char data[3];	int fmtnr, ret;	if (u->interface < 0 || u->interface >= config->bNumInterfaces)		return 0;	iface = &config->interface[u->interface];	fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate);	if (fmtnr < 0) {		printk(KERN_ERR "usbaudio: set_format_out(): failed to find desired format/speed combination.\n");		return -1;	}	fmt = as->fmtout + fmtnr;	u->format = fmt->format;	alts = &iface->altsetting[fmt->altsetting];	u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf);	u->syncpipe = u->syncinterval = 0;	if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x04) {#if 0		printk(KERN_DEBUG "bNumEndpoints 0x%02x endpoint[1].bmAttributes 0x%02x\n"		       KERN_DEBUG "endpoint[1].bSynchAddress 0x%02x endpoint[1].bEndpointAddress 0x%02x\n"		       KERN_DEBUG "endpoint[0].bSynchAddress 0x%02x\n", alts->bNumEndpoints,		       alts->endpoint[1].bmAttributes, alts->endpoint[1].bSynchAddress,		       alts->endpoint[1].bEndpointAddress, alts->endpoint[0].bSynchAddress);#endif		if (alts->bNumEndpoints < 2 ||		    alts->endpoint[1].bmAttributes != 0x01 ||		    alts->endpoint[1].bSynchAddress != 0 ||		    alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress | 0x80)) {			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",			       dev->devnum, u->interface, fmt->altsetting);			return -1;		}		u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf);		u->syncinterval = alts->endpoint[1].bRefresh;	}	if (d->srate < fmt->sratelo)		d->srate = fmt->sratelo;	if (d->srate > fmt->sratehi)		d->srate = fmt->sratehi;	dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting));	if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",		       dev->devnum, u->interface, fmt->altsetting);		return -1;	}	if (fmt->sratelo == fmt->sratehi)		return 0;	ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN);	/* if endpoint has pitch control, enable it */	if (fmt->attributes & 0x02) {		data[0] = 1;		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",			       ret, dev->devnum, u->interface, ep, d->srate);			return -1;		}	}	/* if endpoint has sampling rate control, set it */	if (fmt->attributes & 0x01) {		data[0] = d->srate;

⌨️ 快捷键说明

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