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

📄 audio.c

📁 ep9315平台下USB驱动的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    *y++ = value >> 8;  case 6:    /* 16 bit LE */    *y++ = value >> 16;    *y++ = value >> 24;    break;  }  *yy=y;}/* capable of any-to-any conversion */static void conversion(const void *ibuf, unsigned int ifmt, 		       void *obuf, unsigned int ofmt, unsigned int scnt){  /* some conversion is indeed needed */  unsigned int i,j;  unsigned char *x=(unsigned char *)ibuf;  unsigned char *y=(unsigned char *)obuf;  int ichannels = AFMT_CHANNELS(ifmt);  int ochannels = AFMT_CHANNELS(ofmt);  int ibytes    = AFMT_BYTES(ifmt);  int obytes    = AFMT_BYTES(ofmt);  int iendian   = AFMT_ENDIAN(ifmt);  int oendian   = AFMT_ENDIAN(ofmt);  int isign     = AFMT_SIGN(ifmt)?0:0x80000000UL;  int osign     = AFMT_SIGN(ofmt)?0:0x80000000UL;  int sign      = (isign==osign?0:0x80000000UL);    /* build the byte/endian jump table offsets */  int ijump = (iendian ? 4-ibytes : 8-ibytes);  int ojump = (oendian ? 4-obytes : 8-obytes);    if(ichannels == 2 && ochannels == 1){    /* Stereo -> mono is a special case loop; we downmix */    for(i=0;i<scnt;i++){      int valueL = iconvert(&x,ijump) ^ isign; /* side effect; increments x */      int valueR = iconvert(&x,ijump) ^ isign; /* side effect; increments x */      int value  = (valueL>>1) + (valueR>>1);      oconvert(&y,ojump,value^osign);  /* side effect; increments y */		}    return;		}  if(ichannels == 1 && ochannels == 2){    /* mono->stereo is a special case loop; we replicate */    for(i=0;i<scnt;i++){      int value = iconvert(&x,ijump) ^ sign; /* side effect; increments x */      oconvert(&y,ojump,value);  /* side effect; increments y */      oconvert(&y,ojump,value);  /* side effect; increments y */	}    return;		}  if(ichannels<ochannels){    /* zero out extra output channels */    for(i=0;i<scnt;i++){      for(j=0;j<ichannels;j++){	int value = iconvert(&x,ijump) ^ sign; /* side effect; increments x */	oconvert(&y,ojump,value);  /* side effect; increments y */		}      for(;j<ochannels;j++){	oconvert(&y,ojump,osign);  /* side effect; increments y */	}		}    return;		}  if(ichannels>=ochannels){    /* discard extra input channels */    int xincrement=ibytes*(ichannels-ochannels);    for(i=0;i<scnt;i++){      for(j=0;j<ichannels;j++){	int value = iconvert(&x,ijump) ^ sign; /* side effect; increments x */	oconvert(&y,ojump,value);  /* side effect; increments y */		}      x+=xincrement;		}    return;	}}static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples){        unsigned int scnt;	unsigned int ufmtb = AFMT_SAMPLEBYTES(u->format);	unsigned int dfmtb = AFMT_SAMPLEBYTES(u->dma.format);        unsigned char tmp[TMPCOPYWIDTH];	unsigned int maxs  = sizeof(tmp)/dfmtb;	while (samples > 0) {		scnt = samples;		if (scnt > maxs)			scnt = maxs;	        conversion(buffer, u->format, tmp, u->dma.format, scnt);                dmabuf_copyin(&u->dma, tmp, scnt * dfmtb);                buffer += scnt * ufmtb;		samples -= scnt;	}}		static int usbin_prepare_desc(struct usbin *u, struct urb *urb){	unsigned int i, maxsize, offs;	maxsize = ((u->freqmax + 0x3fff) * AFMT_SAMPLEBYTES(u->format)) >> 14;	//printk(KERN_DEBUG "usbin_prepare_desc: maxsize %d freq 0x%x format 0x%x\n", maxsize, u->freqn, u->format);	for (i = offs = 0; i < DESCFRAMES; i++, offs += maxsize) {		urb->iso_frame_desc[i].length = maxsize;		urb->iso_frame_desc[i].offset = offs;	}	return 0;}/* * return value: 0 if descriptor should be restarted, -1 otherwise * convert sample format on the fly if necessary */static int usbin_retire_desc(struct usbin *u, struct urb *urb){	unsigned int i, ufmtb, dfmtb, err = 0, cnt, scnt, dmafree;	unsigned char *cp;	ufmtb = AFMT_SAMPLEBYTES(u->format);	dfmtb = AFMT_SAMPLEBYTES(u->dma.format);	for (i = 0; i < DESCFRAMES; i++) {		cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset;		if (urb->iso_frame_desc[i].status) {			dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));			continue;		}		scnt = urb->iso_frame_desc[i].actual_length / ufmtb;		if (!scnt)			continue;		cnt = scnt * dfmtb;		if (!u->dma.mapped) {			dmafree = u->dma.dmasize - u->dma.count;			if (cnt > dmafree) {				scnt = dmafree / dfmtb;				cnt = scnt * dfmtb;				err++;			}		}		u->dma.count += cnt;		if (u->format == u->dma.format) {			/* we do not need format conversion */			dprintk((KERN_DEBUG "usbaudio: no sample format conversion\n"));			dmabuf_copyin(&u->dma, cp, cnt);		} else {			/* we need sampling format conversion */			dprintk((KERN_DEBUG "usbaudio: sample format conversion %x != %x\n", u->format, u->dma.format));			usbin_convert(u, cp, scnt);		}	}	if (err)		u->dma.error++;	if (u->dma.count >= (signed)u->dma.fragsize)		wake_up(&u->dma.wait);	return err ? -1 : 0;}static void usbin_completed(struct urb *urb){	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;	struct usbin *u = &as->usbin;	unsigned long flags;	unsigned int mask;	int suret = USB_ST_NOERROR;#if 0	printk(KERN_DEBUG "usbin_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 "usbin_completed: panic: unknown URB\n");	}	urb->dev = as->state->usbdev;	spin_lock_irqsave(&as->lock, flags);	if (!usbin_retire_desc(u, urb) &&	    u->flags & FLG_RUNNING &&	    !usbin_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);		printk(KERN_DEBUG "usbin_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret);	}	spin_unlock_irqrestore(&as->lock, flags);}/* * we output sync data */static int usbin_sync_prepare_desc(struct usbin *u, struct urb *urb){	unsigned char *cp = urb->transfer_buffer;	unsigned int i, offs;		for (i = offs = 0; i < SYNCFRAMES; i++, offs += 3, cp += 3) {		urb->iso_frame_desc[i].length = 3;		urb->iso_frame_desc[i].offset = offs;		cp[0] = u->freqn;		cp[1] = u->freqn >> 8;		cp[2] = u->freqn >> 16;	}	return 0;}/* * return value: 0 if descriptor should be restarted, -1 otherwise */static int usbin_sync_retire_desc(struct usbin *u, struct urb *urb){	unsigned int i;		for (i = 0; i < SYNCFRAMES; i++)		if (urb->iso_frame_desc[0].status)			dprintk((KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status));	return 0;}static void usbin_sync_completed(struct urb *urb){	struct usb_audiodev *as = (struct usb_audiodev *)urb->context;	struct usbin *u = &as->usbin;	unsigned long flags;	unsigned int mask;	int suret = USB_ST_NOERROR;#if 0	printk(KERN_DEBUG "usbin_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 "usbin_sync_completed: panic: unknown URB\n");	}	urb->dev = as->state->usbdev;	spin_lock_irqsave(&as->lock, flags);	if (!usbin_sync_retire_desc(u, urb) &&	    u->flags & FLG_RUNNING &&	    !usbin_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 "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret));	}	spin_unlock_irqrestore(&as->lock, flags);}static int usbin_start(struct usb_audiodev *as){	struct usb_device *dev = as->state->usbdev;	struct usbin *u = &as->usbin;	struct urb *urb;	unsigned long flags;	unsigned int maxsze, bufsz;#if 0	printk(KERN_DEBUG "usbin_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->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 >= u->dma.dmasize && !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 = usbin_completed;		if (!usbin_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 = usbin_completed;		if (!usbin_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 = usbin_sync_completed;			/* stride: u->syncinterval */			if (!usbin_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 = usbin_sync_completed;			/* stride: u->syncinterval */			if (!usbin_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 void usbout_stop(struct usb_audiodev *as){	struct usbout *u = &as->usbout;	unsigned long flags;	unsigned int i, notkilled = 1;	spin_lock_irqsave(&as->lock, flags);	u->flags &= ~FLG_RUNNING;	i = u->flags;	spin_unlock_irqrestore(&as->lock, flags);	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);		schedule_timeout(1);		spin_lock_irqsave(&as->lock, flags);		i = u->flags;		spin_unlock_irqrestore(&as->lock, flags);		if (notkilled && signal_pending(current)) {			if (i & FLG_URB0RUNNING)				usb_unlink_urb(&u->durb[0].urb);			if (i & FLG_URB1RUNNING)				usb_unlink_urb(&u->durb[1].urb);			if (i & FLG_SYNC0RUNNING)				usb_unlink_urb(&u->surb[0].urb);			if (i & FLG_SYNC1RUNNING)				usb_unlink_urb(&u->surb[1].urb);			notkilled = 0;		}	}	set_current_state(TASK_RUNNING);	if (u->durb[0].urb.transfer_buffer)		kfree(u->durb[0].urb.transfer_buffer);

⌨️ 快捷键说明

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