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

📄 serial.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	.bLength =		sizeof(gs_otg_descriptor),	.bDescriptorType =	USB_DT_OTG,	.bmAttributes =		USB_OTG_SRP,};static struct usb_config_descriptor gs_bulk_config_desc = {	.bLength =		USB_DT_CONFIG_SIZE,	.bDescriptorType =	USB_DT_CONFIG,	/* .wTotalLength computed dynamically */	.bNumInterfaces =	1,	.bConfigurationValue =	GS_BULK_CONFIG_ID,	.iConfiguration =	GS_BULK_CONFIG_STR_ID,	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,	.bMaxPower =		1,};static struct usb_config_descriptor gs_acm_config_desc = {	.bLength =		USB_DT_CONFIG_SIZE,	.bDescriptorType =	USB_DT_CONFIG,	/* .wTotalLength computed dynamically */	.bNumInterfaces =	2,	.bConfigurationValue =	GS_ACM_CONFIG_ID,	.iConfiguration =	GS_ACM_CONFIG_STR_ID,	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,	.bMaxPower =		1,};static const struct usb_interface_descriptor gs_bulk_interface_desc = {	.bLength =		USB_DT_INTERFACE_SIZE,	.bDescriptorType =	USB_DT_INTERFACE,	.bInterfaceNumber =	GS_BULK_INTERFACE_ID,	.bNumEndpoints =	2,	.bInterfaceClass =	USB_CLASS_CDC_DATA,	.bInterfaceSubClass =	0,	.bInterfaceProtocol =	0,	.iInterface =		GS_DATA_STR_ID,};static const struct usb_interface_descriptor gs_control_interface_desc = {	.bLength =		USB_DT_INTERFACE_SIZE,	.bDescriptorType =	USB_DT_INTERFACE,	.bInterfaceNumber =	GS_CONTROL_INTERFACE_ID,	.bNumEndpoints =	1,	.bInterfaceClass =	USB_CLASS_COMM,	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ACM,	.bInterfaceProtocol =	USB_CDC_CTRL_PROTO_AT,	.iInterface =		GS_CONTROL_STR_ID,};static const struct usb_interface_descriptor gs_data_interface_desc = {	.bLength =		USB_DT_INTERFACE_SIZE,	.bDescriptorType =	USB_DT_INTERFACE,	.bInterfaceNumber =	GS_DATA_INTERFACE_ID,	.bNumEndpoints =	2,	.bInterfaceClass =	USB_CLASS_CDC_DATA,	.bInterfaceSubClass =	0,	.bInterfaceProtocol =	0,	.iInterface =		GS_DATA_STR_ID,};static const struct usb_cdc_header_desc gs_header_desc = {	.bLength =		sizeof(gs_header_desc),	.bDescriptorType =	USB_DT_CS_INTERFACE,	.bDescriptorSubType =	USB_CDC_SUBTYPE_HEADER,	.bcdCDC =		__constant_cpu_to_le16(0x0110),};static const struct usb_cdc_call_mgmt_desc gs_call_mgmt_descriptor = {	.bLength =  		sizeof(gs_call_mgmt_descriptor),	.bDescriptorType = 	USB_DT_CS_INTERFACE,	.bDescriptorSubType = 	USB_CDC_SUBTYPE_CALL_MGMT,	.bmCapabilities = 	0,	.bDataInterface = 	1,	/* index of data interface */};static struct usb_cdc_acm_desc gs_acm_descriptor = {	.bLength =  		sizeof(gs_acm_descriptor),	.bDescriptorType = 	USB_DT_CS_INTERFACE,	.bDescriptorSubType = 	USB_CDC_SUBTYPE_ACM,	.bmCapabilities = 	0,};static const struct usb_cdc_union_desc gs_union_desc = {	.bLength =		sizeof(gs_union_desc),	.bDescriptorType =	USB_DT_CS_INTERFACE,	.bDescriptorSubType =	USB_CDC_SUBTYPE_UNION,	.bMasterInterface0 =	0,	/* index of control interface */	.bSlaveInterface0 =	1,	/* index of data interface */}; static struct usb_endpoint_descriptor gs_fullspeed_notify_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bEndpointAddress =	USB_DIR_IN,	.bmAttributes =		USB_ENDPOINT_XFER_INT,	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,};static struct usb_endpoint_descriptor gs_fullspeed_in_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bEndpointAddress =	USB_DIR_IN,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,};static struct usb_endpoint_descriptor gs_fullspeed_out_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bEndpointAddress =	USB_DIR_OUT,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,};static const struct usb_descriptor_header *gs_bulk_fullspeed_function[] = {	(struct usb_descriptor_header *) &gs_otg_descriptor,	(struct usb_descriptor_header *) &gs_bulk_interface_desc,	(struct usb_descriptor_header *) &gs_fullspeed_in_desc,	(struct usb_descriptor_header *) &gs_fullspeed_out_desc,	NULL,};static const struct usb_descriptor_header *gs_acm_fullspeed_function[] = {	(struct usb_descriptor_header *) &gs_otg_descriptor,	(struct usb_descriptor_header *) &gs_control_interface_desc,	(struct usb_descriptor_header *) &gs_header_desc,	(struct usb_descriptor_header *) &gs_call_mgmt_descriptor,	(struct usb_descriptor_header *) &gs_acm_descriptor,	(struct usb_descriptor_header *) &gs_union_desc,	(struct usb_descriptor_header *) &gs_fullspeed_notify_desc,	(struct usb_descriptor_header *) &gs_data_interface_desc,	(struct usb_descriptor_header *) &gs_fullspeed_in_desc,	(struct usb_descriptor_header *) &gs_fullspeed_out_desc,	NULL,};#ifdef CONFIG_USB_GADGET_DUALSPEEDstatic struct usb_endpoint_descriptor gs_highspeed_notify_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bEndpointAddress =	USB_DIR_IN,	.bmAttributes =		USB_ENDPOINT_XFER_INT,	.wMaxPacketSize =	__constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,};static struct usb_endpoint_descriptor gs_highspeed_in_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,	.wMaxPacketSize =	__constant_cpu_to_le16(512),};static struct usb_endpoint_descriptor gs_highspeed_out_desc = {	.bLength =		USB_DT_ENDPOINT_SIZE,	.bDescriptorType =	USB_DT_ENDPOINT,	.bmAttributes =		USB_ENDPOINT_XFER_BULK,	.wMaxPacketSize =	__constant_cpu_to_le16(512),};static struct usb_qualifier_descriptor gs_qualifier_desc = {	.bLength =		sizeof(struct usb_qualifier_descriptor),	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,	.bcdUSB =		__constant_cpu_to_le16 (0x0200),	/* assumes ep0 uses the same value for both speeds ... */	.bNumConfigurations =	GS_NUM_CONFIGS,};static const struct usb_descriptor_header *gs_bulk_highspeed_function[] = {	(struct usb_descriptor_header *) &gs_otg_descriptor,	(struct usb_descriptor_header *) &gs_bulk_interface_desc,	(struct usb_descriptor_header *) &gs_highspeed_in_desc,	(struct usb_descriptor_header *) &gs_highspeed_out_desc,	NULL,};static const struct usb_descriptor_header *gs_acm_highspeed_function[] = {	(struct usb_descriptor_header *) &gs_otg_descriptor,	(struct usb_descriptor_header *) &gs_control_interface_desc,	(struct usb_descriptor_header *) &gs_header_desc,	(struct usb_descriptor_header *) &gs_call_mgmt_descriptor,	(struct usb_descriptor_header *) &gs_acm_descriptor,	(struct usb_descriptor_header *) &gs_union_desc,	(struct usb_descriptor_header *) &gs_highspeed_notify_desc,	(struct usb_descriptor_header *) &gs_data_interface_desc,	(struct usb_descriptor_header *) &gs_highspeed_in_desc,	(struct usb_descriptor_header *) &gs_highspeed_out_desc,	NULL,};#endif /* CONFIG_USB_GADGET_DUALSPEED *//* Module */MODULE_DESCRIPTION(GS_LONG_NAME);MODULE_AUTHOR("Al Borchers");MODULE_LICENSE("GPL");#ifdef GS_DEBUGmodule_param(debug, int, S_IRUGO|S_IWUSR);MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");#endifmodule_param(read_q_size, uint, S_IRUGO);MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32");module_param(write_q_size, uint, S_IRUGO);MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32");module_param(write_buf_size, uint, S_IRUGO);MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192");module_param(use_acm, uint, S_IRUGO);MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no");module_init(gs_module_init);module_exit(gs_module_exit);/**  gs_module_init**  Register as a USB gadget driver and a tty driver.*/static int __init gs_module_init(void){	int i;	int retval;	retval = usb_gadget_register_driver(&gs_gadget_driver);	if (retval) {		printk(KERN_ERR "gs_module_init: cannot register gadget driver, ret=%d\n", retval);		return retval;	}	gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS);	if (!gs_tty_driver)		return -ENOMEM;	gs_tty_driver->owner = THIS_MODULE;	gs_tty_driver->driver_name = GS_SHORT_NAME;	gs_tty_driver->name = "ttygs";	gs_tty_driver->devfs_name = "usb/ttygs/";	gs_tty_driver->major = GS_MAJOR;	gs_tty_driver->minor_start = GS_MINOR_START;	gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;	gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;	gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;	gs_tty_driver->init_termios = tty_std_termios;	gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;	tty_set_operations(gs_tty_driver, &gs_tty_ops);	for (i=0; i < GS_NUM_PORTS; i++)		sema_init(&gs_open_close_sem[i], 1);	retval = tty_register_driver(gs_tty_driver);	if (retval) {		usb_gadget_unregister_driver(&gs_gadget_driver);		put_tty_driver(gs_tty_driver);		printk(KERN_ERR "gs_module_init: cannot register tty driver, ret=%d\n", retval);		return retval;	}	printk(KERN_INFO "gs_module_init: %s %s loaded\n", GS_LONG_NAME, GS_VERSION_STR);	return 0;}/** gs_module_exit** Unregister as a tty driver and a USB gadget driver.*/static void __exit gs_module_exit(void){	tty_unregister_driver(gs_tty_driver);	put_tty_driver(gs_tty_driver);	usb_gadget_unregister_driver(&gs_gadget_driver);	printk(KERN_INFO "gs_module_exit: %s %s unloaded\n", GS_LONG_NAME, GS_VERSION_STR);}/* TTY Driver *//* * gs_open */static int gs_open(struct tty_struct *tty, struct file *file){	int port_num;	unsigned long flags;	struct gs_port *port;	struct gs_dev *dev;	struct gs_buf *buf;	struct semaphore *sem;	int ret;	port_num = tty->index;	gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);	if (port_num < 0 || port_num >= GS_NUM_PORTS) {		printk(KERN_ERR "gs_open: (%d,%p,%p) invalid port number\n",			port_num, tty, file);		return -ENODEV;	}	dev = gs_device;	if (dev == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL device pointer\n",			port_num, tty, file);		return -ENODEV;	}	sem = &gs_open_close_sem[port_num];	if (down_interruptible(sem)) {		printk(KERN_ERR		"gs_open: (%d,%p,%p) interrupted waiting for semaphore\n",			port_num, tty, file);		return -ERESTARTSYS;	}	spin_lock_irqsave(&dev->dev_lock, flags);	if (dev->dev_config == GS_NO_CONFIG_ID) {		printk(KERN_ERR			"gs_open: (%d,%p,%p) device is not connected\n",			port_num, tty, file);		ret = -ENODEV;		goto exit_unlock_dev;	}	port = dev->dev_port[port_num];	if (port == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL port pointer\n",			port_num, tty, file);		ret = -ENODEV;		goto exit_unlock_dev;	}	spin_lock(&port->port_lock);	spin_unlock(&dev->dev_lock);	if (port->port_dev == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (1)\n",			port_num, tty, file);		ret = -EIO;		goto exit_unlock_port;	}	if (port->port_open_count > 0) {		++port->port_open_count;		gs_debug("gs_open: (%d,%p,%p) already open\n",			port_num, tty, file);		ret = 0;		goto exit_unlock_port;	}	tty->driver_data = NULL;	/* mark port as in use, we can drop port lock and sleep if necessary */	port->port_in_use = 1;	/* allocate write buffer on first open */	if (port->port_write_buf == NULL) {		spin_unlock_irqrestore(&port->port_lock, flags);		buf = gs_buf_alloc(write_buf_size, GFP_KERNEL);		spin_lock_irqsave(&port->port_lock, flags);		/* might have been disconnected while asleep, check */		if (port->port_dev == NULL) {			printk(KERN_ERR				"gs_open: (%d,%p,%p) port disconnected (2)\n",				port_num, tty, file);			port->port_in_use = 0;			ret = -EIO;			goto exit_unlock_port;		}		if ((port->port_write_buf=buf) == NULL) {			printk(KERN_ERR "gs_open: (%d,%p,%p) cannot allocate port write buffer\n",				port_num, tty, file);			port->port_in_use = 0;			ret = -ENOMEM;			goto exit_unlock_port;		}	}	/* wait for carrier detect (not implemented) */	/* might have been disconnected while asleep, check */	if (port->port_dev == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (3)\n",			port_num, tty, file);		port->port_in_use = 0;		ret = -EIO;		goto exit_unlock_port;	}	tty->driver_data = port;	port->port_tty = tty;	port->port_open_count = 1;	port->port_in_use = 0;	gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file);	ret = 0;exit_unlock_port:	spin_unlock_irqrestore(&port->port_lock, flags);	up(sem);	return ret;exit_unlock_dev:	spin_unlock_irqrestore(&dev->dev_lock, flags);	up(sem);	return ret;}/* * gs_close */static void gs_close(struct tty_struct *tty, struct file *file){	unsigned long flags;	struct gs_port *port = tty->driver_data;	struct semaphore *sem;	if (port == NULL) {		printk(KERN_ERR "gs_close: NULL port pointer\n");		return;	}	gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file);	sem = &gs_open_close_sem[port->port_num];	down(sem);	spin_lock_irqsave(&port->port_lock, flags);	if (port->port_open_count == 0) {		printk(KERN_ERR			"gs_close: (%d,%p,%p) port is already closed\n",			port->port_num, tty, file);		goto exit;	}	if (port->port_open_count > 1) {		--port->port_open_count;		goto exit;	}	/* free disconnected port on final close */	if (port->port_dev == NULL) {		kfree(port);		goto exit;	}	/* mark port as closed but in use, we can drop port lock */	/* and sleep if necessary */	port->port_in_use = 1;	port->port_open_count = 0;	/* wait for write buffer to drain, or */	/* at most GS_CLOSE_TIMEOUT seconds */	if (gs_buf_data_avail(port->port_write_buf) > 0) {		wait_cond_interruptible_timeout(port->port_write_wait,		port->port_dev == NULL		|| gs_buf_data_avail(port->port_write_buf) == 0,		&port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ);	}	/* free disconnected port on final close */	/* (might have happened during the above sleep) */	if (port->port_dev == NULL) {		kfree(port);		goto exit;	}	gs_buf_clear(port->port_write_buf);	tty->driver_data = NULL;	port->port_tty = NULL;	port->port_in_use = 0;	gs_debug("gs_close: (%d,%p,%p) completed\n",		port->port_num, tty, file);exit:	spin_unlock_irqrestore(&port->port_lock, flags);	up(sem);}/* * gs_write */static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count){	unsigned long flags;

⌨️ 快捷键说明

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