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

📄 serial.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * g_serial.c -- USB gadget serial driver * * Copyright 2003 (C) Al Borchers (alborchers@steinerpoint.com) * * This code is based in part on the Gadget Zero driver, which * is Copyright (C) 2003 by David Brownell, all rights reserved. * * This code also borrows from usbserial.c, which is * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2000 Peter Berger (pberger@brimson.com) * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com) * * This software is distributed under the terms of the GNU General * Public License ("GPL") as published by the Free Software Foundation, * either version 2 of that License or (at your option) any later version. * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/timer.h>#include <linux/list.h>#include <linux/interrupt.h>#include <linux/utsname.h>#include <linux/wait.h>#include <linux/proc_fs.h>#include <linux/device.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/unaligned.h>#include <asm/uaccess.h>#include <linux/usb_ch9.h>#include <linux/usb_gadget.h>#include "gadget_chips.h"/* Wait Cond */#define __wait_cond_interruptible(wq, condition, lock, flags, ret)	\do {									\	wait_queue_t __wait;						\	init_waitqueue_entry(&__wait, current);				\									\	add_wait_queue(&wq, &__wait);					\	for (;;) {							\		set_current_state(TASK_INTERRUPTIBLE);			\		if (condition)						\			break;						\		if (!signal_pending(current)) {				\			spin_unlock_irqrestore(lock, flags);		\			schedule();					\			spin_lock_irqsave(lock, flags);			\			continue;					\		}							\		ret = -ERESTARTSYS;					\		break;							\	}								\	current->state = TASK_RUNNING;					\	remove_wait_queue(&wq, &__wait);				\} while (0)	#define wait_cond_interruptible(wq, condition, lock, flags)		\({									\	int __ret = 0;							\	if (!(condition))						\		__wait_cond_interruptible(wq, condition, lock, flags,	\						__ret);			\	__ret;								\})#define __wait_cond_interruptible_timeout(wq, condition, lock, flags, 	\						timeout, ret)		\do {									\	signed long __timeout = timeout;				\	wait_queue_t __wait;						\	init_waitqueue_entry(&__wait, current);				\									\	add_wait_queue(&wq, &__wait);					\	for (;;) {							\		set_current_state(TASK_INTERRUPTIBLE);			\		if (__timeout == 0)					\			break;						\		if (condition)						\			break;						\		if (!signal_pending(current)) {				\			spin_unlock_irqrestore(lock, flags);		\			__timeout = schedule_timeout(__timeout);	\			spin_lock_irqsave(lock, flags);			\			continue;					\		}							\		ret = -ERESTARTSYS;					\		break;							\	}								\	current->state = TASK_RUNNING;					\	remove_wait_queue(&wq, &__wait);				\} while (0)	#define wait_cond_interruptible_timeout(wq, condition, lock, flags,	\						timeout)		\({									\	int __ret = 0;							\	if (!(condition))						\		__wait_cond_interruptible_timeout(wq, condition, lock,	\						flags, timeout, __ret);	\	__ret;								\})/* CDC-ACM Defines and Structures */#define USB_CDC_SUBCLASS_ACM			2#define USB_CDC_CTRL_PROTO_NONE			0#define USB_CDC_CTRL_PROTO_AT			1#define USB_CDC_CTRL_PROTO_VENDOR		0xff#define USB_CDC_SUBTYPE_HEADER			0#define USB_CDC_SUBTYPE_CALL_MGMT		1#define USB_CDC_SUBTYPE_ACM			2#define USB_CDC_SUBTYPE_UNION			6#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT		0x01#define USB_CDC_CALL_MGMT_CAP_DATA_INTF		0x02#define USB_CDC_REQ_SET_LINE_CODING		0x20#define USB_CDC_REQ_GET_LINE_CODING		0x21#define USB_CDC_REQ_SET_CONTROL_LINE_STATE	0x22#define USB_CDC_1_STOP_BITS			0#define USB_CDC_1_5_STOP_BITS			1#define USB_CDC_2_STOP_BITS			2#define USB_CDC_NO_PARITY			0#define USB_CDC_ODD_PARITY			1#define USB_CDC_EVEN_PARITY			2#define USB_CDC_MARK_PARITY			3#define USB_CDC_SPACE_PARITY			4/* Header Functional Descriptor from CDC spec 5.2.3.1 */struct usb_cdc_header_desc {	u8	bLength;	u8	bDescriptorType;	u8	bDescriptorSubType;	u16	bcdCDC;} __attribute__ ((packed));/* Call Management Descriptor from CDC spec 5.2.3.3 */struct usb_cdc_call_mgmt_desc {	u8  bLength;	u8  bDescriptorType;	u8  bDescriptorSubType;	u8  bmCapabilities;	u8  bDataInterface;} __attribute__ ((packed));/* Abstract Control Management Descriptor from CDC spec 5.2.3.4 */struct usb_cdc_acm_desc {	u8  bLength;	u8  bDescriptorType;	u8  bDescriptorSubType;	u8  bmCapabilities;} __attribute__ ((packed));/* Union Functional Descriptor from CDC spec 5.2.3.8 */struct usb_cdc_union_desc {	u8	bLength;	u8	bDescriptorType;	u8	bDescriptorSubType;	u8	bMasterInterface0;	u8	bSlaveInterface0;	/* ... and there could be other slave interfaces */} __attribute__ ((packed));/* Line Coding Structure from CDC spec 6.2.13 */struct usb_cdc_line_coding {	u32 dwDTERate;	u8 bCharFormat;	u8 bParityType;	u8 bDataBits;} __attribute__ ((packed));/* Defines */#define GS_VERSION_STR			"v2.0"#define GS_VERSION_NUM			0x0200#define GS_LONG_NAME			"Gadget Serial"#define GS_SHORT_NAME			"g_serial"#define GS_MAJOR			127#define GS_MINOR_START			0#define GS_NUM_PORTS			16#define GS_NUM_CONFIGS			1#define GS_NO_CONFIG_ID			0#define GS_BULK_CONFIG_ID		1#define GS_ACM_CONFIG_ID		2#define GS_MAX_NUM_INTERFACES		2#define GS_BULK_INTERFACE_ID		0#define GS_CONTROL_INTERFACE_ID		0#define GS_DATA_INTERFACE_ID		1#define GS_MAX_DESC_LEN			256#define GS_DEFAULT_READ_Q_SIZE		32#define GS_DEFAULT_WRITE_Q_SIZE		32#define GS_DEFAULT_WRITE_BUF_SIZE	8192#define GS_TMP_BUF_SIZE			8192#define GS_CLOSE_TIMEOUT		15#define GS_DEFAULT_USE_ACM		0#define GS_DEFAULT_DTE_RATE		9600#define GS_DEFAULT_DATA_BITS		8#define GS_DEFAULT_PARITY		USB_CDC_NO_PARITY#define GS_DEFAULT_CHAR_FORMAT		USB_CDC_1_STOP_BITS/* select highspeed/fullspeed, hiding highspeed if not configured */#ifdef CONFIG_USB_GADGET_DUALSPEED#define GS_SPEED_SELECT(is_hs,hs,fs) ((is_hs) ? (hs) : (fs))#else#define GS_SPEED_SELECT(is_hs,hs,fs) (fs)#endif /* CONFIG_USB_GADGET_DUALSPEED *//* debug settings */#ifdef GS_DEBUGstatic int debug = 1;#define gs_debug(format, arg...) \	do { if (debug) printk(KERN_DEBUG format, ## arg); } while(0)#define gs_debug_level(level, format, arg...) \	do { if (debug>=level) printk(KERN_DEBUG format, ## arg); } while(0)#else#define gs_debug(format, arg...) \	do { } while(0)#define gs_debug_level(level, format, arg...) \	do { } while(0)#endif /* GS_DEBUG *//* Thanks to NetChip Technologies for donating this product ID. * * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!! * Instead:  allocate your own, using normal USB-IF procedures. */#define GS_VENDOR_ID			0x0525	/* NetChip */#define GS_PRODUCT_ID			0xa4a6	/* Linux-USB Serial Gadget */#define GS_CDC_PRODUCT_ID		0xa4a7	/* ... as CDC-ACM */#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */#define GS_NOTIFY_MAXPACKET		8/* Structures */struct gs_dev;/* circular buffer */struct gs_buf {	unsigned int		buf_size;	char			*buf_buf;	char			*buf_get;	char			*buf_put;};/* list of requests */struct gs_req_entry {	struct list_head	re_entry;	struct usb_request	*re_req;};/* the port structure holds info for each port, one for each minor number */struct gs_port {	struct gs_dev 		*port_dev;	/* pointer to device struct */	struct tty_struct	*port_tty;	/* pointer to tty struct */	spinlock_t		port_lock;	int 			port_num;	int			port_open_count;	int			port_in_use;	/* open/close in progress */	wait_queue_head_t	port_write_wait;/* waiting to write */	struct gs_buf		*port_write_buf;	struct usb_cdc_line_coding	port_line_coding;};/* the device structure holds info for the USB device */struct gs_dev {	struct usb_gadget	*dev_gadget;	/* gadget device pointer */	spinlock_t		dev_lock;	/* lock for set/reset config */	int			dev_config;	/* configuration number */	struct usb_ep		*dev_notify_ep;	/* address of notify endpoint */	struct usb_ep		*dev_in_ep;	/* address of in endpoint */	struct usb_ep		*dev_out_ep;	/* address of out endpoint */	struct usb_endpoint_descriptor		/* desciptor of notify ep */				*dev_notify_ep_desc;	struct usb_endpoint_descriptor		/* descriptor of in endpoint */				*dev_in_ep_desc;	struct usb_endpoint_descriptor		/* descriptor of out endpoint */				*dev_out_ep_desc;	struct usb_request	*dev_ctrl_req;	/* control request */	struct list_head	dev_req_list;	/* list of write requests */	int			dev_sched_port;	/* round robin port scheduled */	struct gs_port		*dev_port[GS_NUM_PORTS]; /* the ports */};/* Functions *//* module */static int __init gs_module_init(void);static void __exit gs_module_exit(void);/* tty driver */static int gs_open(struct tty_struct *tty, struct file *file);static void gs_close(struct tty_struct *tty, struct file *file);static int gs_write(struct tty_struct *tty, 	const unsigned char *buf, int count);static void gs_put_char(struct tty_struct *tty, unsigned char ch);static void gs_flush_chars(struct tty_struct *tty);static int gs_write_room(struct tty_struct *tty);static int gs_chars_in_buffer(struct tty_struct *tty);static void gs_throttle(struct tty_struct * tty);static void gs_unthrottle(struct tty_struct * tty);static void gs_break(struct tty_struct *tty, int break_state);static int  gs_ioctl(struct tty_struct *tty, struct file *file,	unsigned int cmd, unsigned long arg);static void gs_set_termios(struct tty_struct *tty, struct termios *old);static int gs_send(struct gs_dev *dev);static int gs_send_packet(struct gs_dev *dev, char *packet,	unsigned int size);static int gs_recv_packet(struct gs_dev *dev, char *packet,	unsigned int size);static void gs_read_complete(struct usb_ep *ep, struct usb_request *req);static void gs_write_complete(struct usb_ep *ep, struct usb_request *req);/* gadget driver */static int gs_bind(struct usb_gadget *gadget);static void gs_unbind(struct usb_gadget *gadget);static int gs_setup(struct usb_gadget *gadget,	const struct usb_ctrlrequest *ctrl);static int gs_setup_standard(struct usb_gadget *gadget,	const struct usb_ctrlrequest *ctrl);static int gs_setup_class(struct usb_gadget *gadget,	const struct usb_ctrlrequest *ctrl);static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req);static void gs_disconnect(struct usb_gadget *gadget);static int gs_set_config(struct gs_dev *dev, unsigned config);static void gs_reset_config(struct gs_dev *dev);static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,		u8 type, unsigned int index, int is_otg);static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len,	int kmalloc_flags);static void gs_free_req(struct usb_ep *ep, struct usb_request *req);static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len,	int kmalloc_flags);static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req);static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags);static void gs_free_ports(struct gs_dev *dev);/* circular buffer */static struct gs_buf *gs_buf_alloc(unsigned int size, int kmalloc_flags);static void gs_buf_free(struct gs_buf *gb);static void gs_buf_clear(struct gs_buf *gb);static unsigned int gs_buf_data_avail(struct gs_buf *gb);static unsigned int gs_buf_space_avail(struct gs_buf *gb);static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf,	unsigned int count);static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,	unsigned int count);/* external functions */extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode);/* Globals */static struct gs_dev *gs_device;static const char *EP_IN_NAME;static const char *EP_OUT_NAME;static const char *EP_NOTIFY_NAME;static struct semaphore	gs_open_close_sem[GS_NUM_PORTS];static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE;static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE;static unsigned int use_acm = GS_DEFAULT_USE_ACM;/* tty driver struct */static struct tty_operations gs_tty_ops = {	.open =			gs_open,	.close =		gs_close,	.write =		gs_write,	.put_char =		gs_put_char,	.flush_chars =		gs_flush_chars,	.write_room =		gs_write_room,	.ioctl =		gs_ioctl,	.set_termios =		gs_set_termios,	.throttle =		gs_throttle,	.unthrottle =		gs_unthrottle,	.break_ctl =		gs_break,	.chars_in_buffer =	gs_chars_in_buffer,};static struct tty_driver *gs_tty_driver;/* gadget driver struct */static struct usb_gadget_driver gs_gadget_driver = {#ifdef CONFIG_USB_GADGET_DUALSPEED	.speed =		USB_SPEED_HIGH,#else	.speed =		USB_SPEED_FULL,#endif /* CONFIG_USB_GADGET_DUALSPEED */	.function =		GS_LONG_NAME,	.bind =			gs_bind,	.unbind =		gs_unbind,	.setup =		gs_setup,	.disconnect =		gs_disconnect,	.driver = {		.name =		GS_SHORT_NAME,		/* .shutdown = ... */		/* .suspend = ...  */		/* .resume = ...   */	},};/* USB descriptors */#define GS_MANUFACTURER_STR_ID	1#define GS_PRODUCT_STR_ID	2#define GS_SERIAL_STR_ID	3#define GS_BULK_CONFIG_STR_ID	4#define GS_ACM_CONFIG_STR_ID	5#define GS_CONTROL_STR_ID	6#define GS_DATA_STR_ID		7/* static strings, in UTF-8 */static char manufacturer[50];static struct usb_string gs_strings[] = {	{ GS_MANUFACTURER_STR_ID, manufacturer },	{ GS_PRODUCT_STR_ID, GS_LONG_NAME },	{ GS_SERIAL_STR_ID, "0" },	{ GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" },	{ GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" },	{ GS_CONTROL_STR_ID, "Gadget Serial Control" },	{ GS_DATA_STR_ID, "Gadget Serial Data" },	{  } /* end of list */};static struct usb_gadget_strings gs_string_table = {	.language =		0x0409,	/* en-us */	.strings =		gs_strings,};static struct usb_device_descriptor gs_device_desc = {	.bLength =		USB_DT_DEVICE_SIZE,	.bDescriptorType =	USB_DT_DEVICE,	.bcdUSB =		__constant_cpu_to_le16(0x0200),	.bDeviceSubClass =	0,	.bDeviceProtocol =	0,	.idVendor =		__constant_cpu_to_le16(GS_VENDOR_ID),	.idProduct =		__constant_cpu_to_le16(GS_PRODUCT_ID),	.iManufacturer =	GS_MANUFACTURER_STR_ID,	.iProduct =		GS_PRODUCT_STR_ID,	.iSerialNumber =	GS_SERIAL_STR_ID,	.bNumConfigurations =	GS_NUM_CONFIGS,};static struct usb_otg_descriptor gs_otg_descriptor = {

⌨️ 快捷键说明

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