audio.c

来自「ep9315平台下USB驱动的源码」· C语言 代码 · 共 2,032 行 · 第 1/5 页

C
2,032
字号
	if (u->durb[1].urb.transfer_buffer)		kfree(u->durb[1].urb.transfer_buffer);	if (u->surb[0].urb.transfer_buffer)		kfree(u->surb[0].urb.transfer_buffer);	if (u->surb[1].urb.transfer_buffer)		kfree(u->surb[1].urb.transfer_buffer);	u->durb[0].urb.transfer_buffer = u->durb[1].urb.transfer_buffer = 		u->surb[0].urb.transfer_buffer = u->surb[1].urb.transfer_buffer = NULL;}static inline void usbout_release(struct usb_audiodev *as){	usbout_stop(as);}static void usbout_disc(struct usb_audiodev *as){	struct usbout *u = &as->usbout;	unsigned long flags;	spin_lock_irqsave(&as->lock, flags);	u->flags &= ~(FLG_RUNNING | FLG_CONNECTED);	spin_unlock_irqrestore(&as->lock, flags);	usbout_stop(as);}static void usbout_convert(struct usbout *u, unsigned char *buffer, unsigned int samples){        unsigned char tmp[TMPCOPYWIDTH];        unsigned int scnt;	unsigned int ufmtb = AFMT_SAMPLEBYTES(u->format);	unsigned int dfmtb = AFMT_SAMPLEBYTES(u->dma.format);	unsigned int maxs  = sizeof(tmp)/dfmtb;		while (samples > 0) {		scnt = samples;		if (scnt > maxs)			scnt = maxs;		dmabuf_copyout(&u->dma, tmp, scnt * dfmtb);		conversion(tmp, u->dma.format, buffer, u->format, scnt);                buffer += scnt * ufmtb;		samples -= scnt;	}}		static int usbout_prepare_desc(struct usbout *u, struct urb *urb){	unsigned int i, ufmtb, dfmtb, err = 0, cnt, scnt, offs;	unsigned char *cp = urb->transfer_buffer;	ufmtb = AFMT_SAMPLEBYTES(u->format);	dfmtb = AFMT_SAMPLEBYTES(u->dma.format);	for (i = offs = 0; i < DESCFRAMES; i++) {		urb->iso_frame_desc[i].offset = offs;		u->phase = (u->phase & 0x3fff) + u->freqm;		scnt = u->phase >> 14;		if (!scnt) {			urb->iso_frame_desc[i].length = 0;			continue;		}		cnt = scnt * dfmtb;		if (!u->dma.mapped) {			if (cnt > u->dma.count) {				scnt = u->dma.count / dfmtb;				cnt = scnt * dfmtb;				err++;			}			u->dma.count -= cnt;		} else			u->dma.count += cnt;		if (u->format == u->dma.format) {			/* we do not need format conversion */			dmabuf_copyout(&u->dma, cp, cnt);		} else {			/* we need sampling format conversion */			usbout_convert(u, cp, scnt);		}		cnt = scnt * ufmtb;		urb->iso_frame_desc[i].length = cnt;		offs += cnt;		cp += cnt;	}	if (err)		u->dma.error++;	if (u->dma.mapped) {		if (u->dma.count >= (signed)u->dma.fragsize)			wake_up(&u->dma.wait);	} else {		if ((signed)u->dma.dmasize >= u->dma.count + (signed)u->dma.fragsize)			wake_up(&u->dma.wait);	}	return err ? -1 : 0;}/* * return value: 0 if descriptor should be restarted, -1 otherwise */static int usbout_retire_desc(struct usbout *u, struct urb *urb){	unsigned int i;	for (i = 0; i < DESCFRAMES; i++) {		if (urb->iso_frame_desc[i].status) {			dprintk((KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));			continue;		}	}	return 0;}static void usbout_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_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, struct urb *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, struct urb *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;	struct urb *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) * AFMT_SAMPLEBYTES(u->format)) >>14;		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;}/* --------------------------------------------------------------------- *//* allowed conversions (sign, endian, width, channels), and relative   weighting penalties against fuzzy match selection.  For the   purposes of not confusing users, 'lossy' format translation is   disallowed, eg, don't allow a mono 8 bit device to successfully   open as 5.1, 24 bit... Never allow a mode that tries to deliver greater   than the hard capabilities of the device.   device --=> app   signed   => unsigned : 1   unsigned => signed   : 1   le       => be       : 1   be       => le       : 1   8        => 16       : not allowed   8        => 24       : not allowed   8        => 32       : not allowed   16       => 24       : not allowed   16       => 32       : not allowed   24       => 32       : not allowed   16       => 8        : 4   24       => 16       : 4   24       => 8        : 5   32       => 24       : 4   32       => 16       : 5   32       => 8        : 5   mono     => stereo   : not allowed   stereo   => mono     : 32 (downmix to L+R/2)   N        => >N       : not allowed   N        => <N       : 32 */static unsigned int format_goodness(struct audioformat *afp, unsigned int app,				    unsigned int srate){	unsigned int g = 0;	unsigned int sratelo=afp->sratelo;	unsigned int sratehi=afp->sratehi;	unsigned int dev=afp->format;	if(AFMT_SIGN(dev) && !AFMT_SIGN(app))     g += 1;	if(!AFMT_SIGN(dev) && AFMT_SIGN(app))     g += 1;	if(AFMT_ENDIAN(dev) && !AFMT_ENDIAN(app)) g += 1;	if(!AFMT_ENDIAN(dev) && AFMT_ENDIAN(app)) g += 1;	switch(AFMT_BYTES(app)+AFMT_BYTES(dev)*10){	case 12: return ~0;	case 13: return ~0;	case 14: return ~0;	case 21: g += 4; break;	case 23: return ~0;	case 24: return ~0;	case 31: g += 5; break;	case 32: g += 4; break;	case 34: return ~0;	case 41: g += 6; break;	case 42: g += 5; break;	case 43: g += 4; break;	}	if(AFMT_CHANNELS(dev) > AFMT_CHANNELS(app)){	        g+=32;	}else if(AFMT_CHANNELS(dev) < AFMT_CHANNELS(app)){	        return ~0;	}	  	g<<=20;	if (srate < sratelo)	        g += sratelo - srate;        if (srate > sratehi)

⌨️ 快捷键说明

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