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

📄 dummy_audio.c

📁 host usb 主设备程序 支持sd卡 mouse keyboard 的最单单的驱动程序 gcc编译
💻 C
📖 第 1 页 / 共 3 页
字号:
				req->status, req->actual, req->length);}/* * The setup() callback implements all the ep0 functionality that's * not handled lower down, in hardware or the hardware driver (like * device and endpoint feature flags, and their status).  It's all * housekeeping for the gadget function we're implementing.  Most of * the work is in config-specific setup. */static intzero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl){	struct zero_dev		*dev = get_gadget_data (gadget);	struct usb_request	*req = dev->req;	int			value = -EOPNOTSUPP;	/* usually this stores reply data in the pre-allocated ep0 buffer,	 * but config change events will reconfigure hardware.	 */	req->zero = 0;	switch (ctrl->bRequest) {	case USB_REQ_GET_DESCRIPTOR:		switch (ctrl->wValue >> 8) {		case USB_DT_DEVICE:			value = min (ctrl->wLength, (u16) sizeof device_desc);			memcpy (req->buf, &device_desc, value);			break;#ifdef CONFIG_USB_GADGET_DUALSPEED		case USB_DT_DEVICE_QUALIFIER:			if (!gadget->is_dualspeed)				break;			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);			memcpy (req->buf, &dev_qualifier, value);			break;		case USB_DT_OTHER_SPEED_CONFIG:			if (!gadget->is_dualspeed)				break;			// FALLTHROUGH#endif /* CONFIG_USB_GADGET_DUALSPEED */		case USB_DT_CONFIG:			value = config_buf (gadget, req->buf,					ctrl->wValue >> 8,					ctrl->wValue & 0xff);			if (value >= 0)				value = min (ctrl->wLength, (u16) value);			break;		case USB_DT_STRING:			/* wIndex == language code.			 * this driver only handles one language, you can			 * add string tables for other languages, using			 * any UTF-8 characters			 */			value = usb_gadget_get_string (&stringtab,					ctrl->wValue & 0xff, req->buf);			if (value >= 0) {				value = min (ctrl->wLength, (u16) value);			}			break;		}		break;	/* currently two configs, two speeds */	case USB_REQ_SET_CONFIGURATION:		if (ctrl->bRequestType != 0)			goto unknown;		spin_lock (&dev->lock);		value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);		spin_unlock (&dev->lock);		break;	case USB_REQ_GET_CONFIGURATION:		if (ctrl->bRequestType != USB_DIR_IN)			goto unknown;		*(u8 *)req->buf = dev->config;		value = min (ctrl->wLength, (u16) 1);		break;	/* until we add altsetting support, or other interfaces,	 * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)	 * and already killed pending endpoint I/O.	 */	case USB_REQ_SET_INTERFACE:		if (ctrl->bRequestType != USB_RECIP_INTERFACE)			goto unknown;		spin_lock (&dev->lock);		if (dev->config) {			u8		config = dev->config;			/* resets interface configuration, forgets about			 * previous transaction state (queued bufs, etc)			 * and re-inits endpoint state (toggle etc)			 * no response queued, just zero status == success.			 * if we had more than one interface we couldn't			 * use this "reset the config" shortcut.			 */			zero_reset_config (dev);			zero_set_config (dev, config, GFP_ATOMIC);			value = 0;		}		spin_unlock (&dev->lock);		break;	case USB_REQ_GET_INTERFACE:		if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) {			value = ctrl->wLength;			break;		}		else {			if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))				goto unknown;			if (!dev->config)				break;			if (ctrl->wIndex != 0) {				value = -EDOM;				break;			}			*(u8 *)req->buf = 0;			value = min (ctrl->wLength, (u16) 1);		}		break;	/*	 * These are the same vendor-specific requests supported by	 * Intel's USB 2.0 compliance test devices.  We exceed that	 * device spec by allowing multiple-packet requests.	 */	case 0x5b:	/* control WRITE test -- fill the buffer */		if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))			goto unknown;		if (ctrl->wValue || ctrl->wIndex)			break;		/* just read that many bytes into the buffer */		if (ctrl->wLength > USB_BUFSIZ)			break;		value = ctrl->wLength;		break;	case 0x5c:	/* control READ test -- return the buffer */		if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))			goto unknown;		if (ctrl->wValue || ctrl->wIndex)			break;		/* expect those bytes are still in the buffer; send back */		if (ctrl->wLength > USB_BUFSIZ				|| ctrl->wLength != req->length)			break;		value = ctrl->wLength;		break;	case 0x01: // SET_CUR	case 0x02:	case 0x03:	case 0x04:	case 0x05:		value = ctrl->wLength;		break;	case 0x81:		switch (ctrl->wValue) {		case 0x0201:		case 0x0202:			((u8*)req->buf)[0] = 0x00;			((u8*)req->buf)[1] = 0xe3;			break;		case 0x0300:		case 0x0500:			((u8*)req->buf)[0] = 0x00;			break;		}		//((u8*)req->buf)[0] = 0x81;		//((u8*)req->buf)[1] = 0x81;		value = ctrl->wLength;		break;	case 0x82:		switch (ctrl->wValue) {		case 0x0201:		case 0x0202:			((u8*)req->buf)[0] = 0x00;			((u8*)req->buf)[1] = 0xc3;			break;		case 0x0300:		case 0x0500:			((u8*)req->buf)[0] = 0x00;			break;		}		//((u8*)req->buf)[0] = 0x82;		//((u8*)req->buf)[1] = 0x82;		value = ctrl->wLength;		break;	case 0x83:		switch (ctrl->wValue) {		case 0x0201:		case 0x0202:			((u8*)req->buf)[0] = 0x00;			((u8*)req->buf)[1] = 0x00;			break;		case 0x0300:			((u8*)req->buf)[0] = 0x60;			break;		case 0x0500:				((u8*)req->buf)[0] = 0x18;			break;		}		//((u8*)req->buf)[0] = 0x83;		//((u8*)req->buf)[1] = 0x83;		value = ctrl->wLength;		break;	case 0x84:		switch (ctrl->wValue) {		case 0x0201:		case 0x0202:			((u8*)req->buf)[0] = 0x00;			((u8*)req->buf)[1] = 0x01;			break;		case 0x0300:		case 0x0500:			((u8*)req->buf)[0] = 0x08;			break;		}		//((u8*)req->buf)[0] = 0x84;		//((u8*)req->buf)[1] = 0x84;		value = ctrl->wLength;		break;	case 0x85:		((u8*)req->buf)[0] = 0x85;		((u8*)req->buf)[1] = 0x85;		value = ctrl->wLength;		break;		default:unknown:		printk("unknown control req%02x.%02x v%04x i%04x l%d\n",			ctrl->bRequestType, ctrl->bRequest,			ctrl->wValue, ctrl->wIndex, ctrl->wLength);	}	/* respond with data transfer before status phase? */	if (value >= 0) {		req->length = value;		req->zero = value < ctrl->wLength				&& (value % gadget->ep0->maxpacket) == 0;		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);		if (value < 0) {			DBG (dev, "ep_queue < 0 --> %d\n", value);			req->status = 0;			zero_setup_complete (gadget->ep0, req);		}	}	/* device either stalls (value < 0) or reports success */	return value;}static voidzero_disconnect (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	unsigned long		flags;	spin_lock_irqsave (&dev->lock, flags);	zero_reset_config (dev);	/* a more significant application might have some non-usb	 * activities to quiesce here, saving resources like power	 * or pushing the notification up a network stack.	 */	spin_unlock_irqrestore (&dev->lock, flags);	/* next we may get setup() calls to enumerate new connections;	 * or an unbind() during shutdown (including removing module).	 */}static voidzero_autoresume (unsigned long _dev){	struct zero_dev	*dev = (struct zero_dev *) _dev;	int		status;	/* normally the host would be woken up for something	 * more significant than just a timer firing...	 */	if (dev->gadget->speed != USB_SPEED_UNKNOWN) {		status = usb_gadget_wakeup (dev->gadget);		DBG (dev, "wakeup --> %d\n", status);	}}/*-------------------------------------------------------------------------*/static voidzero_unbind (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	DBG (dev, "unbind\n");	/* we've already been disconnected ... no i/o is active */	if (dev->req)		free_ep_req (gadget->ep0, dev->req);	del_timer_sync (&dev->resume);	kfree (dev);	set_gadget_data (gadget, NULL);}static intzero_bind (struct usb_gadget *gadget){	struct zero_dev		*dev;	//struct usb_ep		*ep;	printk("binding\n");	/*	 * DRIVER POLICY CHOICE:  you may want to do this differently.	 * One thing to avoid is reusing a bcdDevice revision code	 * with different host-visible configurations or behavior	 * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc	 */	//device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);	/* ok, we made sense of the hardware ... */	dev = kmalloc (sizeof *dev, SLAB_KERNEL);	if (!dev)		return -ENOMEM;	memset (dev, 0, sizeof *dev);	spin_lock_init (&dev->lock);	dev->gadget = gadget;	set_gadget_data (gadget, dev);	/* preallocate control response and buffer */	dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);	if (!dev->req)		goto enomem;	dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,				&dev->req->dma, GFP_KERNEL);	if (!dev->req->buf)		goto enomem;	dev->req->complete = zero_setup_complete;	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;#ifdef CONFIG_USB_GADGET_DUALSPEED	/* assume ep0 uses the same value for both speeds ... */	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;	/* and that all endpoints are dual-speed */	//hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;	//hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;#endif	usb_gadget_set_selfpowered (gadget);	init_timer (&dev->resume);	dev->resume.function = zero_autoresume;	dev->resume.data = (unsigned long) dev;	gadget->ep0->driver_data = dev;	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);	INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,		EP_OUT_NAME, EP_IN_NAME);	snprintf (manufacturer, sizeof manufacturer,		UTS_SYSNAME " " UTS_RELEASE " with %s",		gadget->name);	return 0;enomem:	zero_unbind (gadget);	return -ENOMEM;}/*-------------------------------------------------------------------------*/static voidzero_suspend (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	if (gadget->speed == USB_SPEED_UNKNOWN)		return;	if (autoresume) {		mod_timer (&dev->resume, jiffies + (HZ * autoresume));		DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);	} else		DBG (dev, "suspend\n");}static voidzero_resume (struct usb_gadget *gadget){	struct zero_dev		*dev = get_gadget_data (gadget);	DBG (dev, "resume\n");	del_timer (&dev->resume);}/*-------------------------------------------------------------------------*/static struct usb_gadget_driver zero_driver = {#ifdef CONFIG_USB_GADGET_DUALSPEED	.speed		= USB_SPEED_HIGH,#else	.speed		= USB_SPEED_FULL,#endif	.function	= (char *) longname,	.bind		= zero_bind,	.unbind		= zero_unbind,	.setup		= zero_setup,	.disconnect	= zero_disconnect,	.suspend	= zero_suspend,	.resume		= zero_resume,	.driver 	= {		.name		= (char *) shortname,		// .shutdown = ...		// .suspend = ...		// .resume = ...	},};MODULE_AUTHOR ("David Brownell");MODULE_LICENSE ("Dual BSD/GPL");static struct proc_dir_entry *pdir, *pfile;static int isoc_read_data (char *page, char **start,			   off_t off, int count,			   int *eof, void *data){	int i;	static int c = 0;	static int done = 0;	static int s = 0;/*	printk ("\ncount: %d\n", count);	printk ("rbuf_start: %d\n", rbuf_start);	printk ("rbuf_len: %d\n", rbuf_len);	printk ("off: %d\n", off);	printk ("start: %p\n\n", *start);*/	if (done) {		c = 0;		done = 0;		*eof = 1;		return 0;	}	if (c == 0) {		if (rbuf_len == RBUF_LEN)			s = rbuf_start;		else s = 0;	}	for (i=0; i<count && c<rbuf_len; i++, c++) {		page[i] = rbuf[(c+s) % RBUF_LEN];	}	*start = page;		if (c >= rbuf_len) {		*eof = 1;		done = 1;	}	return i;}static int __init init (void){	int retval = 0;	pdir = proc_mkdir("isoc_test", NULL);	if(pdir == NULL) {		retval = -ENOMEM;		printk("Error creating dir\n");		goto done;	}	pdir->owner = THIS_MODULE;	pfile = create_proc_read_entry("isoc_data",				       0444, pdir,				       isoc_read_data,				       NULL);	if (pfile == NULL) {		retval = -ENOMEM;		printk("Error creating file\n");		goto no_file;	}	pfile->owner = THIS_MODULE;	return usb_gadget_register_driver (&zero_driver); no_file:	remove_proc_entry("isoc_data", NULL); done:	return retval;}module_init (init);static void __exit cleanup (void){	usb_gadget_unregister_driver (&zero_driver);		remove_proc_entry("isoc_data", pdir);	remove_proc_entry("isoc_test", NULL);}module_exit (cleanup);

⌨️ 快捷键说明

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