dabusb.c

来自「Usb1.1驱动c语言源代码」· C语言 代码 · 共 877 行 · 第 1/2 页

C
877
字号
	if(s->pending_io.counter>0)		err("timed out\n");	dbg("pending_io: %d", s->pending_io.counter);	s->pending_io.counter = 0;	return 0;}static int dabusb_startrek (pdabusb_t s){	if (!s->got_mem && s->state != _started) {		dbg("dabusb_startrek");		if (dabusb_alloc_buffers (s) < 0)			return -ENOMEM;		dabusb_stop (s);		s->state = _started;		s->readptr = 0;	}	if (!list_empty (&s->free_buff_list)) {		pbuff_t end;		int ret;				while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {						dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);						end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);						ret = usb_submit_urb (end->purb);			if (ret) {				err("usb_submit_urb returned:%d", ret);				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))					err("startrek: dabusb_add_buf_tail failed");				break;			}			else {				atomic_inc (&s->pending_io);			}		}		dbg("pending_io: %d",s->pending_io.counter);	}	return 0;}static ssize_t dabusb_read (struct file *file, char *buf, size_t count, loff_t * ppos){	pdabusb_t s = (pdabusb_t) file->private_data;	unsigned long flags;	unsigned ret = 0;	int rem;	int cnt;	pbuff_t b;	purb_t purb = NULL;	dbg("dabusb_read");	if (*ppos)		return -ESPIPE;	if (s->remove_pending)		return -EIO;	if (!s->usbdev)		return -EIO;	while (count > 0) {		dabusb_startrek (s);		spin_lock_irqsave (&s->lock, flags);		if (list_empty (&s->rec_buff_list)) {			spin_unlock_irqrestore(&s->lock, flags);			err("error: rec_buf_list is empty");			goto err;		}				b = list_entry (s->rec_buff_list.next, buff_t, buff_list);		purb = b->purb;		spin_unlock_irqrestore(&s->lock, flags);		if (purb->status == -EINPROGRESS) {			if (file->f_flags & O_NONBLOCK)		// return nonblocking			 {				if (!ret)					ret = -EAGAIN;				goto err;			}			interruptible_sleep_on (&s->wait);			if (signal_pending (current)) {				if (!ret)					ret = -ERESTARTSYS;				goto err;			}			spin_lock_irqsave (&s->lock, flags);			if (list_empty (&s->rec_buff_list)) {				spin_unlock_irqrestore(&s->lock, flags);				err("error: still no buffer available.");				goto err;			}			spin_unlock_irqrestore(&s->lock, flags);						s->readptr = 0;		}		if (s->remove_pending) {			ret = -EIO;			goto err;		}		rem = purb->actual_length - s->readptr;		// set remaining bytes to copy		if (count >= rem)			cnt = rem;		else			cnt = count;		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {			err("read: copy_to_user failed");			if (!ret)				ret = -EFAULT;			goto err;		}		s->readptr += cnt;		count -= cnt;		buf += cnt;		ret += cnt;		if (s->readptr == purb->actual_length) {			// finished, take next buffer			if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))				err("read: dabusb_add_buf_tail failed");						s->readptr = 0;			dabusb_startrek (s);					}	}      err:			//up(&s->mutex);	return ret;}static int dabusb_open (struct inode *inode, struct file *file){	int devnum = MINOR (inode->i_rdev);	pdabusb_t s;	if (devnum < DABUSB_MINOR || devnum > (DABUSB_MINOR + NRDABUSB))		return -EIO;	MOD_INC_USE_COUNT;	s = &dabusb[devnum - DABUSB_MINOR];	dbg("dabusb_open");	down (&s->mutex);	while (!s->usbdev || s->opened) {		up (&s->mutex);		if (file->f_flags & O_NONBLOCK) {			MOD_DEC_USE_COUNT;			return -EBUSY;		}		schedule_timeout (HZ / 2);		if (signal_pending (current)) {			MOD_DEC_USE_COUNT;			return -EAGAIN;		}		down (&s->mutex);	}	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {		err("set_interface failed");		MOD_DEC_USE_COUNT;		return -EINVAL;	}	s->opened = 1;	up (&s->mutex);	file->f_pos = 0;	file->private_data = s;	return 0;}static int dabusb_release (struct inode *inode, struct file *file){	pdabusb_t s = (pdabusb_t) file->private_data;	dbg("dabusb_release");	down (&s->mutex);	dabusb_stop (s);	dabusb_free_buffers (s);	up (&s->mutex);	if (!s->remove_pending) {		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)			err("set_interface failed");	}	else		wake_up (&s->remove_ok);	MOD_DEC_USE_COUNT;	s->opened = 0;	return 0;}static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	pdabusb_t s = (pdabusb_t) file->private_data;	pbulk_transfer_t pbulk;	int ret = 0;	int version = DABUSB_VERSION;	DECLARE_WAITQUEUE (wait, current);	dbg("dabusb_ioctl");	if (s->remove_pending)		return -EIO;	down (&s->mutex);	if (!s->usbdev) {		up (&s->mutex);		return -EIO;	}	switch (cmd) {	case IOCTL_DAB_BULK:		pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);		if (!pbulk) {			ret = -ENOMEM;			break;		}		if (copy_from_user (pbulk, (void *) arg, sizeof (bulk_transfer_t))) {			ret = -EFAULT;			kfree (pbulk);			break;		}		dabusb_bulk (s, pbulk);		ret = copy_to_user ((void *) arg, pbulk, sizeof (bulk_transfer_t));		kfree (pbulk);		break;	case IOCTL_DAB_OVERRUNS:		ret = put_user (s->overruns, (unsigned int *) arg);		break;	case IOCTL_DAB_VERSION:		ret = put_user (version, (unsigned int *) arg);		break;	default:		ret = -ENOIOCTLCMD;		break;	}	up (&s->mutex);	return ret;}static struct file_operations dabusb_fops ={	llseek: dabusb_llseek,	read: dabusb_read,	ioctl: dabusb_ioctl,	open: dabusb_open,	release: dabusb_release,};static int dabusb_find_struct (void){	int u;	for (u = 0; u < NRDABUSB; u++) {		pdabusb_t s = &dabusb[u];		if (!s->usbdev)			return u;	}	return -1;}/* --------------------------------------------------------------------- */static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum){	int devnum;	pdabusb_t s;	dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",	  usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);	/* the 1234:5678 is just a self assigned test ID */	if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) &&	    (usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x9999))		return NULL;	/* We don't handle multiple configurations */	if (usbdev->descriptor.bNumConfigurations != 1)		return NULL;	if (ifnum != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)		return NULL;	devnum = dabusb_find_struct ();	if (devnum == -1)		return NULL;	s = &dabusb[devnum];	down (&s->mutex);	s->remove_pending = 0;	s->usbdev = usbdev;	if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {		err("set_configuration failed");		goto reject;	}	if (usbdev->descriptor.idProduct == 0x2131) {		dabusb_loadmem (s, NULL);		goto reject;	}	else {		dabusb_fpga_download (s, NULL);		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {			err("set_interface failed");			goto reject;		}	}	dbg("bound to interface: %d", ifnum);	up (&s->mutex);	MOD_INC_USE_COUNT;	return s;      reject:	up (&s->mutex);	s->usbdev = NULL;	return NULL;}static void dabusb_disconnect (struct usb_device *usbdev, void *ptr){	pdabusb_t s = (pdabusb_t) ptr;	dbg("dabusb_disconnect");	s->remove_pending = 1;	wake_up (&s->wait);	if (s->state == _started)		sleep_on (&s->remove_ok);	s->usbdev = NULL;	s->overruns = 0;	MOD_DEC_USE_COUNT;}static struct usb_driver dabusb_driver ={	"dabusb",	dabusb_probe,	dabusb_disconnect,	{NULL, NULL},	&dabusb_fops,	DABUSB_MINOR};/* --------------------------------------------------------------------- */int __init dabusb_init (void){	unsigned u;	/* initialize struct */	for (u = 0; u < NRDABUSB; u++) {		pdabusb_t s = &dabusb[u];		memset (s, 0, sizeof (dabusb_t));		init_MUTEX (&s->mutex);		s->usbdev = NULL;		s->total_buffer_size = buffers;		init_waitqueue_head (&s->wait);		init_waitqueue_head (&s->remove_ok);		spin_lock_init (&s->lock);		INIT_LIST_HEAD (&s->free_buff_list);		INIT_LIST_HEAD (&s->rec_buff_list);	}	/* register misc device */	usb_register (&dabusb_driver);	dbg("dabusb_init: driver registered");	return 0;}void __exit dabusb_cleanup (void){	dbg("dabusb_cleanup");	usb_deregister (&dabusb_driver);}/* --------------------------------------------------------------------- */#ifdef MODULEMODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");MODULE_PARM (buffers, "i");int __init init_module (void){	return dabusb_init ();}void __exit cleanup_module (void){	dabusb_cleanup ();}#endif/* --------------------------------------------------------------------- */

⌨️ 快捷键说明

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