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

📄 audio.c

📁 Usb1.1驱动c语言源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (!p)				return -ENOMEM;			db->sgbuf[nr] = p;			mem_map_reserve(MAP_NR(p));		}		memset(db->sgbuf[nr], AFMT_ISUNSIGNED(db->format) ? 0x80 : 0, PAGE_SIZE);		if ((nr << PAGE_SHIFT) >= db->dmasize)			break;	}	db->bufsize = nr << PAGE_SHIFT;	db->ready = 1;	printk(KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d "	       "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d\n",	       bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize,	       db->numfrag, db->dmasize, db->bufsize);	return 0;}static int dmabuf_mmap(struct dmabuf *db, unsigned long start, unsigned long size, pgprot_t prot){	unsigned int nr;	if (!db->ready || db->mapped || (start | size) & (PAGE_SIZE-1) || size > db->bufsize)		return -EINVAL;	size >>= PAGE_SHIFT;	for(nr = 0; nr < size; nr++)		if (!db->sgbuf[nr])			return -EINVAL;	db->mapped = 1;	for(nr = 0; nr < size; nr++) {		if (remap_page_range(start, virt_to_phys(db->sgbuf[nr]), PAGE_SIZE, prot))			return -EAGAIN;		start += PAGE_SIZE;	}	return 0;}static void dmabuf_copyin(struct dmabuf *db, const void *buffer, unsigned int size){	unsigned int pgrem, rem;	db->total_bytes += size;	for (;;) {		if (size <= 0)			return;		pgrem = ((~db->wrptr) & (PAGE_SIZE-1)) + 1;		if (pgrem > size)			pgrem = size;		rem = db->dmasize - db->wrptr;		if (pgrem > rem)			pgrem = rem;		memcpy((db->sgbuf[db->wrptr >> PAGE_SHIFT]) + (db->wrptr & (PAGE_SIZE-1)), buffer, pgrem);		size -= pgrem;		(char *)buffer += pgrem;		db->wrptr += pgrem;		if (db->wrptr >= db->dmasize)			db->wrptr = 0;	}}static void dmabuf_copyout(struct dmabuf *db, void *buffer, unsigned int size){	unsigned int pgrem, rem;	db->total_bytes += size;	for (;;) {		if (size <= 0)			return;		pgrem = ((~db->rdptr) & (PAGE_SIZE-1)) + 1;		if (pgrem > size)			pgrem = size;		rem = db->dmasize - db->rdptr;		if (pgrem > rem)			pgrem = rem;		memcpy(buffer, (db->sgbuf[db->rdptr >> PAGE_SHIFT]) + (db->rdptr & (PAGE_SIZE-1)), pgrem);		size -= pgrem;		(char *)buffer += pgrem;		db->rdptr += pgrem;		if (db->rdptr >= db->dmasize)			db->rdptr = 0;	}}static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void *buffer, unsigned int size){	unsigned int pgrem, rem;	if (!db->ready || db->mapped)		return -EINVAL;	for (;;) {		if (size <= 0)			return 0;		pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1;		if (pgrem > size)			pgrem = size;		rem = db->dmasize - ptr;		if (pgrem > rem)			pgrem = rem;		copy_from_user_ret((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem, -EFAULT);		size -= pgrem;		(char *)buffer += pgrem;		ptr += pgrem;		if (ptr >= db->dmasize)			ptr = 0;	}}static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void *buffer, unsigned int size){	unsigned int pgrem, rem;	if (!db->ready || db->mapped)		return -EINVAL;	for (;;) {		if (size <= 0)			return 0;		pgrem = ((~ptr) & (PAGE_SIZE-1)) + 1;		if (pgrem > size)			pgrem = size;		rem = db->dmasize - ptr;		if (pgrem > rem)			pgrem = rem;		copy_to_user_ret(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem, -EFAULT);		size -= pgrem;		(char *)buffer += pgrem;		ptr += pgrem;		if (ptr >= db->dmasize)			ptr = 0;	}}/* --------------------------------------------------------------------- *//* * USB I/O code. We do sample format conversion if necessary */static void usbin_stop(struct usb_audiodev *as){	struct usbin *u = &as->usbin;	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 usbin_release(struct usb_audiodev *as){	usbin_stop(as);}static void usbin_disc(struct usb_audiodev *as){	struct usbin *u = &as->usbin;	unsigned long flags;	spin_lock_irqsave(&as->lock, flags);	u->flags &= ~(FLG_RUNNING | FLG_CONNECTED);	spin_unlock_irqrestore(&as->lock, flags);	usbin_stop(as);}static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt){	unsigned int cnt, i;	__s16 *sp, *sp2, s;	unsigned char *bp;	cnt = scnt;	if (AFMT_ISSTEREO(ifmt))		cnt <<= 1;	sp = ((__s16 *)tmp) + cnt;	switch (ifmt & ~AFMT_STEREO) {	case AFMT_U8:		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {			bp--;			sp--;			*sp = (*bp ^ 0x80) << 8;		}		break;				case AFMT_S8:		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {			bp--;			sp--;			*sp = *bp << 8;		}		break;			case AFMT_U16_LE:		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {			bp -= 2;			sp--;			*sp = (bp[0] | (bp[1] << 8)) ^ 0x8000;		}		break;	case AFMT_U16_BE:		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {			bp -= 2;			sp--;			*sp = (bp[1] | (bp[0] << 8)) ^ 0x8000;		}		break;	case AFMT_S16_LE:		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {			bp -= 2;			sp--;			*sp = bp[0] | (bp[1] << 8);		}		break;	case AFMT_S16_BE:		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {			bp -= 2;			sp--;			*sp = bp[1] | (bp[0] << 8);		}		break;	}	if (!AFMT_ISSTEREO(ifmt) && AFMT_ISSTEREO(ofmt)) {		/* expand from mono to stereo */		for (sp = ((__s16 *)tmp)+scnt, sp2 = ((__s16 *)tmp)+2*scnt, i = 0; i < scnt; i++) {			sp--;			sp2 -= 2;			sp2[0] = sp2[1] = sp[0];		}	}	if (AFMT_ISSTEREO(ifmt) && !AFMT_ISSTEREO(ofmt)) {		/* contract from stereo to mono */		for (sp = sp2 = ((__s16 *)tmp), i = 0; i < scnt; i++, sp++, sp2 += 2)			sp[0] = (sp2[0] + sp2[1]) >> 1;	}	cnt = scnt;	if (AFMT_ISSTEREO(ofmt))		cnt <<= 1;	sp = ((__s16 *)tmp);	bp = ((unsigned char *)obuf);	switch (ofmt & ~AFMT_STEREO) {	case AFMT_U8:		for (i = 0; i < cnt; i++, sp++, bp++)			*bp = (*sp >> 8) ^ 0x80;		break;	case AFMT_S8:		for (i = 0; i < cnt; i++, sp++, bp++)			*bp = *sp >> 8;		break;	case AFMT_U16_LE:		for (i = 0; i < cnt; i++, sp++, bp += 2) {			s = *sp;			bp[0] = s;			bp[1] = (s >> 8) ^ 0x80;		}		break;	case AFMT_U16_BE:		for (i = 0; i < cnt; i++, sp++, bp += 2) {			s = *sp;			bp[1] = s;			bp[0] = (s >> 8) ^ 0x80;		}		break;	case AFMT_S16_LE:		for (i = 0; i < cnt; i++, sp++, bp += 2) {			s = *sp;			bp[0] = s;			bp[1] = s >> 8;		}		break;	case AFMT_S16_BE:		for (i = 0; i < cnt; i++, sp++, bp += 2) {			s = *sp;			bp[1] = s;			bp[0] = s >> 8;		}		break;	}	}static void usbin_convert(struct usbin *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;		conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt);		dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh);		buffer += scnt << ufmtsh;		samples -= scnt;	}}		static int usbin_prepare_desc(struct usbin *u, purb_t urb){	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) {			printk(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 */			dmabuf_copyin(&u->dma, cp, cnt);		} else {			/* we need sampling format conversion */			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");	}	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);}/*

⌨️ 快捷键说明

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