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

📄 audio.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	unsigned int i, maxsize, offs;	maxsize = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format));	//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, purb_t urb){	unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, dmafree;	unsigned char *cp;	ufmtsh = AFMT_BYTESSHIFT(u->format);	dfmtsh = AFMT_BYTESSHIFT(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 >> ufmtsh;		if (!scnt)			continue;		cnt = scnt << dfmtsh;		if (!u->dma.mapped) {			dmafree = u->dma.dmasize - u->dma.count;			if (cnt > dmafree) {				scnt = dmafree >> dfmtsh;				cnt = scnt << dfmtsh;				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, purb_t 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, purb_t 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;	purb_t 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) >> (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 >= 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);	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){	union {		__s16 s[64];		unsigned char b[0];	} tmp;	unsigned int scnt, maxs, ufmtsh, dfmtsh;	ufmtsh = AFMT_BYTESSHIFT(u->format);	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);	maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64;	while (samples > 0) {		scnt = samples;		if (scnt > maxs)			scnt = maxs;		dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh);		conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt);		buffer += scnt << ufmtsh;		samples -= scnt;	}}		static int usbout_prepare_desc(struct usbout *u, purb_t urb){	unsigned int i, ufmtsh, dfmtsh, err = 0, cnt, scnt, offs;	unsigned char *cp = urb->transfer_buffer;	ufmtsh = AFMT_BYTESSHIFT(u->format);	dfmtsh = AFMT_BYTESSHIFT(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 << dfmtsh;		if (!u->dma.mapped) {			if (cnt > u->dma.count) {				scnt = u->dma.count >> dfmtsh;				cnt = scnt << dfmtsh;				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 << ufmtsh;		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, purb_t 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)

⌨️ 快捷键说明

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