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

📄 usx2yhwdeppcm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	smp_wmb();	// Make shure above modifications are seen by i_usX2Y_subs_startup()	usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup);}static int usX2Y_usbpcm_urbs_start(snd_usX2Y_substream_t *subs){	int	p, u, err,		stream = subs->pcm_substream->stream;	usX2Ydev_t *usX2Y = subs->usX2Y;	if (SNDRV_PCM_STREAM_CAPTURE == stream) {		usX2Y->hwdep_pcm_shm->captured_iso_head = -1;		usX2Y->hwdep_pcm_shm->captured_iso_frames = 0;	}	for (p = 0; 3 >= (stream + p); p += 2) {		snd_usX2Y_substream_t *subs = usX2Y->subs[stream + p];		if (subs != NULL) {			if ((err = usX2Y_usbpcm_urbs_allocate(subs)) < 0)				return err;			subs->completed_urb = NULL;		}	}	for (p = 0; p < 4; p++) {		snd_usX2Y_substream_t *subs = usX2Y->subs[p];		if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)			goto start;	}	usX2Y->wait_iso_frame = -1; start:	usX2Y_usbpcm_subs_startup(subs);	for (u = 0; u < NRURBS; u++) {		for (p = 0; 3 >= (stream + p); p += 2) {			snd_usX2Y_substream_t *subs = usX2Y->subs[stream + p];			if (subs != NULL) {				struct urb *urb = subs->urb[u];				if (usb_pipein(urb->pipe)) {					unsigned long pack;					if (0 == u)						atomic_set(&subs->state, state_STARTING3);					urb->dev = usX2Y->chip.dev;					urb->transfer_flags = URB_ISO_ASAP;					for (pack = 0; pack < nr_of_packs(); pack++) {						urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs());						urb->iso_frame_desc[pack].length = subs->maxpacksize;					}					urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs(); 					if ((err = usb_submit_urb(urb, GFP_KERNEL)) < 0) {						snd_printk (KERN_ERR "cannot usb_submit_urb() for urb %d, err = %d\n", u, err);						err = -EPIPE;						goto cleanup;					}  else {						snd_printdd("%i\n", urb->start_frame);						if (0 > usX2Y->wait_iso_frame)							usX2Y->wait_iso_frame = urb->start_frame;					}					urb->transfer_flags = 0;				} else {					atomic_set(&subs->state, state_STARTING1);					break;				}						}		}	}	err = 0;	wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs);	if (atomic_read(&subs->state) != state_PREPARED)		err = -EPIPE;		 cleanup:	if (err) {		usX2Y_subs_startup_finish(usX2Y);	// Call it now		usX2Y_clients_stop(usX2Y);		// something is completely wroong > stop evrything				}	return err;}/* * prepare callback * * set format and initialize urbs */static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;	usX2Ydev_t *usX2Y = subs->usX2Y;	snd_usX2Y_substream_t *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];	int err = 0;	snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);	if (NULL == usX2Y->hwdep_pcm_shm) {		if (NULL == (usX2Y->hwdep_pcm_shm = snd_malloc_pages(sizeof(snd_usX2Y_hwdep_pcm_shm_t), GFP_KERNEL)))			return -ENOMEM;		memset(usX2Y->hwdep_pcm_shm, 0, sizeof(snd_usX2Y_hwdep_pcm_shm_t));	}	down(&usX2Y->prepare_mutex);	usX2Y_subs_prepare(subs);// Start hardware streams// SyncStream first....	if (atomic_read(&capsubs->state) < state_PREPARED) {		if (usX2Y->format != runtime->format)			if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0)				goto up_prepare_mutex;		if (usX2Y->rate != runtime->rate)			if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0)				goto up_prepare_mutex;		snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe");		if (0 > (err = usX2Y_usbpcm_urbs_start(capsubs)))			goto up_prepare_mutex;	}	if (subs != capsubs) {		usX2Y->hwdep_pcm_shm->playback_iso_start = -1;		if (atomic_read(&subs->state) < state_PREPARED) {			while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > usX2Y->hwdep_pcm_shm->captured_iso_frames) {				snd_printd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames);				if (msleep_interruptible(10)) {					err = -ERESTARTSYS;					goto up_prepare_mutex;				}			} 			if (0 > (err = usX2Y_usbpcm_urbs_start(subs)))				goto up_prepare_mutex;		}		snd_printd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames);	} else		usX2Y->hwdep_pcm_shm->capture_iso_start = -1; up_prepare_mutex:	up(&usX2Y->prepare_mutex);	return err;}static snd_pcm_hardware_t snd_usX2Y_4c ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =                 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,	.rates =                   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,	.rate_min =                44100,	.rate_max =                48000,	.channels_min =            2,	.channels_max =            4,	.buffer_bytes_max =	(2*128*1024),	.period_bytes_min =	64,	.period_bytes_max =	(128*1024),	.periods_min =		2,	.periods_max =		1024,	.fifo_size =              0};static int snd_usX2Y_usbpcm_open(snd_pcm_substream_t *substream){	snd_usX2Y_substream_t	*subs = ((snd_usX2Y_substream_t **)					 snd_pcm_substream_chip(substream))[substream->stream];	snd_pcm_runtime_t	*runtime = substream->runtime;	if (!(subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS))		return -EBUSY;	runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usX2Y_2c :		(subs->usX2Y->subs[3] ? snd_usX2Y_4c : snd_usX2Y_2c);	runtime->private_data = subs;	subs->pcm_substream = substream;	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000);	return 0;}static int snd_usX2Y_usbpcm_close(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime = substream->runtime;	snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;	int err = 0;	snd_printd("\n");	subs->pcm_substream = NULL;	return err;}static snd_pcm_ops_t snd_usX2Y_usbpcm_ops = {	.open =		snd_usX2Y_usbpcm_open,	.close =	snd_usX2Y_usbpcm_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_usX2Y_pcm_hw_params,	.hw_free =	snd_usX2Y_usbpcm_hw_free,	.prepare =	snd_usX2Y_usbpcm_prepare,	.trigger =	snd_usX2Y_pcm_trigger,	.pointer =	snd_usX2Y_pcm_pointer,};static int usX2Y_pcms_lock_check(snd_card_t *card){	struct list_head *list;	snd_device_t *dev;	snd_pcm_t *pcm;	int err = 0;	list_for_each(list, &card->devices) {		dev = snd_device(list);		if (dev->type != SNDRV_DEV_PCM)			continue;		pcm = dev->device_data;		down(&pcm->open_mutex);	}	list_for_each(list, &card->devices) {		int s;		dev = snd_device(list);		if (dev->type != SNDRV_DEV_PCM)			continue;		pcm = dev->device_data;		for (s = 0; s < 2; ++s) {			snd_pcm_substream_t *substream;			substream = pcm->streams[s].substream;			if (substream && substream->ffile != NULL)				err = -EBUSY;		}	}	return err;}static void usX2Y_pcms_unlock(snd_card_t *card){	struct list_head *list;	snd_device_t *dev;	snd_pcm_t *pcm;	list_for_each(list, &card->devices) {		dev = snd_device(list);		if (dev->type != SNDRV_DEV_PCM)			continue;		pcm = dev->device_data;		up(&pcm->open_mutex);	}}static int snd_usX2Y_hwdep_pcm_open(snd_hwdep_t *hw, struct file *file){	// we need to be the first 	snd_card_t *card = hw->card;	int err = usX2Y_pcms_lock_check(card);	if (0 == err)		usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS;	usX2Y_pcms_unlock(card);	return err;}static int snd_usX2Y_hwdep_pcm_release(snd_hwdep_t *hw, struct file *file){	snd_card_t *card = hw->card;	int err = usX2Y_pcms_lock_check(card);	if (0 == err)		usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS;	usX2Y_pcms_unlock(card);	return err;}static void snd_usX2Y_hwdep_pcm_vm_open(struct vm_area_struct *area){}static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area){}static struct page * snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area, unsigned long address, int *type){	unsigned long offset;	struct page *page;	void *vaddr;	offset = area->vm_pgoff << PAGE_SHIFT;	offset += address - area->vm_start;	snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);	vaddr = (char*)((usX2Ydev_t*)area->vm_private_data)->hwdep_pcm_shm + offset;	page = virt_to_page(vaddr);	get_page(page);	if (type)		*type = VM_FAULT_MINOR;	return page;}static struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = {	.open = snd_usX2Y_hwdep_pcm_vm_open,	.close = snd_usX2Y_hwdep_pcm_vm_close,	.nopage = snd_usX2Y_hwdep_pcm_vm_nopage,};static int snd_usX2Y_hwdep_pcm_mmap(snd_hwdep_t * hw, struct file *filp, struct vm_area_struct *area){	unsigned long	size = (unsigned long)(area->vm_end - area->vm_start);	usX2Ydev_t	*usX2Y = (usX2Ydev_t*)hw->private_data;	if (!(((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT))		return -EBUSY;	/* if userspace tries to mmap beyond end of our buffer, fail */ 	if (size > PAGE_ALIGN(sizeof(snd_usX2Y_hwdep_pcm_shm_t))) {		snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(snd_usX2Y_hwdep_pcm_shm_t)); 		return -EINVAL;	}	if (!usX2Y->hwdep_pcm_shm) {		return -ENODEV;	}	area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops;	area->vm_flags |= VM_RESERVED;	snd_printd("vm_flags=0x%lX\n", area->vm_flags);	area->vm_private_data = hw->private_data;	return 0;}static void snd_usX2Y_hwdep_pcm_private_free(snd_hwdep_t *hwdep){	usX2Ydev_t *usX2Y = (usX2Ydev_t *)hwdep->private_data;	if (NULL != usX2Y->hwdep_pcm_shm)		snd_free_pages(usX2Y->hwdep_pcm_shm, sizeof(snd_usX2Y_hwdep_pcm_shm_t));}static void snd_usX2Y_usbpcm_private_free(snd_pcm_t *pcm){	snd_pcm_lib_preallocate_free_for_all(pcm);}int usX2Y_hwdep_pcm_new(snd_card_t* card){	int err;	snd_hwdep_t *hw;	snd_pcm_t *pcm;	struct usb_device *dev = usX2Y(card)->chip.dev;	if (1 != nr_of_packs())		return 0;	if ((err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw)) < 0) {		snd_printd("\n");		return err;	}	hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM;	hw->private_data = usX2Y(card);	hw->private_free = snd_usX2Y_hwdep_pcm_private_free;	hw->ops.open = snd_usX2Y_hwdep_pcm_open;	hw->ops.release = snd_usX2Y_hwdep_pcm_release;	hw->ops.mmap = snd_usX2Y_hwdep_pcm_mmap;	hw->exclusive = 1;	sprintf(hw->name, "/proc/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum);	err = snd_pcm_new(card, NAME_ALLCAPS" hwdep Audio", 2, 1, 1, &pcm);	if (err < 0) {		return err;	}	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_usbpcm_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_usbpcm_ops);	pcm->private_data = usX2Y(card)->subs;	pcm->private_free = snd_usX2Y_usbpcm_private_free;	pcm->info_flags = 0;	sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio");	if (0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,						     SNDRV_DMA_TYPE_CONTINUOUS,						     snd_dma_continuous_data(GFP_KERNEL),						     64*1024, 128*1024)) ||	    0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,	    					     SNDRV_DMA_TYPE_CONTINUOUS,	    					     snd_dma_continuous_data(GFP_KERNEL),						     64*1024, 128*1024))) {		snd_usX2Y_usbpcm_private_free(pcm);		return err;	}	return 0;}#elseint usX2Y_hwdep_pcm_new(snd_card_t* card){	return 0;}#endif

⌨️ 快捷键说明

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