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

📄 vivi_usb_drv.c

📁 可以写s3c2410 USB device的PC端USB驱动和程序
💻 C
📖 第 1 页 / 共 2 页
字号:
			ret = 0;			break;		}	}	up(&(vivi->sem));	return ret ? ret : bytes_read;}static intioctl_vivi_s3c2410(struct inode *inode, struct file *file,	      unsigned int cmd, unsigned long arg){	struct usb_device *dev;	kdev_t vivi_minor;	vivi_minor = USB_VIVI_MINOR(inode);	if (!p_vivi_table[vivi_minor]) {		err("ioctl_vivi_s3c2410(%d): invalid vivi_minor", vivi_minor);		return -ENODEV;	}	dev = p_vivi_table[vivi_minor]->vivi_dev;	switch (cmd)	{	case VIVI_IOCTL_VENDOR :		return (put_user(dev->descriptor.idVendor, (unsigned int *) arg));	case VIVI_IOCTL_PRODUCT :		return (put_user(dev->descriptor.idProduct, (unsigned int *) arg)); 	case VIVI_IOCTL_CTRLMSG: 	{ 		struct ctrlmsg_ioctl { 			usb_devrequest      req; 			void		*data; 		} cmsg; 		int pipe, nb, ret; 		unsigned char buf[64];  		if (copy_from_user(&cmsg, (void *)arg, sizeof(cmsg))) 			return -EFAULT; 		nb = le16_to_cpup(&cmsg.req.length); 		if (nb > sizeof(buf)) 			return -EINVAL; 		if ((cmsg.req.requesttype & 0x80) == 0) { 			pipe = usb_sndctrlpipe(dev, 0); 			if (nb > 0 && copy_from_user(buf, cmsg.data, nb)) 				return -EFAULT; 		} else { 			pipe = usb_rcvctrlpipe(dev, 0);		} 		ret = usb_control_msg(dev, pipe, cmsg.req.request, 				      cmsg.req.requesttype, 				      le16_to_cpup(&cmsg.req.value), 				      le16_to_cpup(&cmsg.req.index), 				      buf, nb, HZ); 		if (ret < 0) { 			err("ioctl_vivi_s3c2410(%d): control_msg returned %d\n", vivi_minor, ret); 			return -EIO; 		} 		if (nb > 0 && (cmsg.req.requesttype & 0x80) && copy_to_user(cmsg.data, buf, nb)) 			return -EFAULT; 		return 0; 	}	default:		return -ENOTTY;	}	return 0;}static structfile_operations usb_vivi_s3c2410_fops = {	read:		read_vivi_s3c2410,	write:		write_vivi_s3c2410,	ioctl:		ioctl_vivi_s3c2410,	open:		open_vivi_s3c2410,	release:	close_vivi_s3c2410,};static void *probe_vivi_s3c2410(struct usb_device *dev, unsigned int ifnum,	      const struct usb_device_id *id){	struct vivi_usb_data *vivi;	struct usb_interface_descriptor *interface;	struct usb_endpoint_descriptor *endpoint;	int ep_cnt;	int ix;	kdev_t vivi_minor;	char valid_device = 0;	char have_bulk_in, have_bulk_out, have_intr;	char name[10];	if (vendor != -1 && product != -1) {		info("probe_vivi_s3c2410: User specified USB vivi_s3c2410 -- Vendor:Product - %x:%x", vendor, product);	}	dbg("probe_vivi_s3c2410: USB dev address:%p", dev);	dbg("probe_vivi_s3c2410: ifnum:%u", ifnum);/* * 1. Check Vendor/Product * 2. Determine/Assign Bulk Endpoints */ 	for (ix = 0; ix < sizeof (vivi_s3c2410_device_ids) / sizeof (struct usb_device_id); ix++) {		if ((dev->descriptor.idVendor == vivi_s3c2410_device_ids [ix].idVendor) &&		    (dev->descriptor.idProduct == vivi_s3c2410_device_ids [ix].idProduct)) {			valid_device = 1;			break;                }	}	if (dev->descriptor.idVendor == vendor &&   /* User specified */	    dev->descriptor.idProduct == product) { /* User specified */		valid_device = 1;	}        if (!valid_device)                return NULL;    /* We didn't find anything pleasing *//* * After this point we can be a little noisy about what we are trying to *  configure. */	if (dev->descriptor.bNumConfigurations != 1) {		info("probe_vivi_s3c2410: Only one device configuration is supported.");		return NULL;	}	if (dev->config[0].bNumInterfaces != 1) {		info("probe_vivi_s3c2410: Only one device interface is supported.");		return NULL;	}	interface = dev->config[0].interface[ifnum].altsetting;	endpoint = interface[ifnum].endpoint;/* * Start checking for two bulk endpoints: bulk in and/or bulk out */	info("probe_vivi_s3c2410: Number of Endpoints:%d", (int) interface->bNumEndpoints);	ep_cnt = have_bulk_in = have_bulk_out = 0;	while (ep_cnt < interface->bNumEndpoints) {		if (!have_bulk_in && IS_EP_BULK_IN(endpoint[ep_cnt])) {			have_bulk_in = endpoint[ep_cnt].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;			ep_cnt++;			info("probe_vivi_s3c2410: bulk_in_ep:%d", have_bulk_in);			continue;		}		if (!have_bulk_out && IS_EP_BULK_OUT(endpoint[ep_cnt])) {			have_bulk_out = endpoint[ep_cnt].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;			ep_cnt++;			info("probe_vivi_s3c2410: bulk_out_ep:%d", have_bulk_out);			continue;		}		info("probe_vivi_s3c2410: Undetected endpoint -- consult Documentation/usb/scanner.txt.");		return NULL;	/* Shouldn't ever get here unless we have something weird */	}/* * Perform a quick check to make sure that everything worked as it * should have. */	if (!have_bulk_in || !have_bulk_out) {		info("probe_vivi_s3c2410: Two bulk endpoints required.");		return NULL;	}/* * Determine a minor number and initialize the structure associated * with it.  The problem with this is that we are counting on the fact * that the user will sequentially add device nodes for the vivi_s3c2410 * devices.  */		down(&vivi_mutex);	for (vivi_minor = 0; vivi_minor < VIVI_MAX_MNR; vivi_minor++) {		if (!p_vivi_table[vivi_minor])			break;	}/* Check to make sure that the last slot isn't already taken */	if (p_vivi_table[vivi_minor]) {		err("probe_vivi_s3c2410: No more minor devices remaining.");		up(&vivi_mutex);		return NULL;	}	dbg("probe_vivi_s3c2410: Allocated minor:%d", vivi_minor);	if (!(vivi = kmalloc (sizeof (struct vivi_usb_data), GFP_KERNEL))) {		err("probe_vivi_s3c2410: Out of memory.");		up(&vivi_mutex);		return NULL;	}	memset (vivi, 0, sizeof(struct vivi_usb_data));	init_MUTEX(&(vivi->sem)); /* Initializes to unlocked */	dbg ("probe_vivi_s3c2410(%d): Address of vivi:%p", vivi_minor, vivi);/* Ok, now initialize all the relevant values */	if (!(vivi->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {		err("probe_vivi_s3c2410(%d): Not enough memory for the output buffer.", vivi_minor);		kfree(vivi);		up(&vivi_mutex);		return NULL;	}	dbg("probe_vivi_s3c2410(%d): obuf address:%p", vivi_minor, vivi->obuf);	if (!(vivi->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {		err("probe_vivi_s3c2410(%d): Not enough memory for the input buffer.", vivi_minor);		kfree(vivi->obuf);		kfree(vivi);		up(&vivi_mutex);		return NULL;	}	dbg("probe_vivi_s3c2410(%d): ibuf address:%p", vivi_minor, vivi->ibuf);		vivi->rd_nak_timeout = HZ * 40;	if (read_timeout > 0) {	/* User specified read timeout overrides everything */		info("probe_vivi_s3c2410: User specified USB read timeout - %d", read_timeout);		vivi->rd_nak_timeout = read_timeout;	}	vivi->bulk_in_ep = have_bulk_in;	vivi->bulk_out_ep = have_bulk_out;	vivi->intr_ep = have_intr;	vivi->present = 1;	vivi->vivi_dev = dev;	vivi->vivi_minor = vivi_minor;	vivi->isopen = 0;	sprintf(name, "vivi_s3c2410%d", vivi->vivi_minor);		vivi->devfs = devfs_register(usb_devfs_handle, name,				    DEVFS_FL_DEFAULT, USB_MAJOR,				    VIVI_BASE_MNR + vivi->vivi_minor,				    S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |				    S_IWGRP | S_IROTH | S_IWOTH, &usb_vivi_s3c2410_fops, NULL);	if (vivi->devfs == NULL)		dbg("vivi_s3c2410%d: device node registration failed", vivi_minor);	p_vivi_table[vivi_minor] = vivi;	up(&vivi_mutex);	return vivi;}static voiddisconnect_vivi_s3c2410(struct usb_device *dev, void *ptr){	struct vivi_usb_data *vivi = (struct vivi_usb_data *) ptr;	down (&vivi_mutex);	down (&(vivi->sem));	if(vivi->intr_ep) {		dbg("disconnect_vivi_s3c2410(%d): Unlinking IRQ URB", vivi->vivi_minor);		usb_unlink_urb(&vivi->vivi_irq);	}        usb_driver_release_interface(&vivi_s3c2410_driver,                &vivi->vivi_dev->actconfig->interface[vivi->ifnum]);	kfree(vivi->ibuf);	kfree(vivi->obuf);	dbg("disconnect_vivi_s3c2410: De-allocating minor:%d", vivi->vivi_minor);	devfs_unregister(vivi->devfs);	p_vivi_table[vivi->vivi_minor] = NULL;	up (&(vivi->sem));	kfree (vivi);	up (&vivi_mutex);}static structusb_driver vivi_s3c2410_driver = {	name:		"usb_vivi_s3c2410",	probe:		probe_vivi_s3c2410,	disconnect:	disconnect_vivi_s3c2410,	fops:		&usb_vivi_s3c2410_fops,	minor:		VIVI_BASE_MNR,	id_table:	NULL, /* This would be vivi_s3c2410_device_ids, but we				 need to check every USB device, in case				 we match a user defined vendor/product ID. */};void __exitusb_vivi_s3c2410_exit(void){	usb_deregister(&vivi_s3c2410_driver);}int __initusb_vivi_s3c2410_init (void){        if (usb_register(&vivi_s3c2410_driver) < 0)                return -1;	info(DRIVER_VERSION ":" DRIVER_DESC);	return 0;}module_init(usb_vivi_s3c2410_init);module_exit(usb_vivi_s3c2410_exit);

⌨️ 快捷键说明

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