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

📄 serial.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* device specific */	if (gadget_is_net2280(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0001);	} else if (gadget_is_pxa(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0002);	} else if (gadget_is_sh(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0003);		/* sh doesn't support multiple interfaces or configs */		use_acm = 0;	} else if (gadget_is_sa1100(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0004);		/* sa1100 doesn't support necessary endpoints */		use_acm = 0;	} else if (gadget_is_goku(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0005);	} else if (gadget_is_mq11xx(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0006);	} else if (gadget_is_omap(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0007);	} else if (gadget_is_lh7a40x(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0008);	} else if (gadget_is_n9604(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0009);	} else if (gadget_is_pxa27x(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0011);	} else {		printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",			gadget->name);		/* unrecognized, but safe unless bulk is REALLY quirky */		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0099);	}	usb_ep_autoconfig_reset(gadget);	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);	if (!ep)		goto autoconf_fail;	EP_IN_NAME = ep->name;	ep->driver_data = ep;	/* claim the endpoint */	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);	if (!ep)		goto autoconf_fail;	EP_OUT_NAME = ep->name;	ep->driver_data = ep;	/* claim the endpoint */	if (use_acm) {		ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc);		if (!ep) {			printk(KERN_ERR "gs_bind: cannot run ACM on %s\n", gadget->name);			goto autoconf_fail;		}		gs_device_desc.idProduct = __constant_cpu_to_le16(						GS_CDC_PRODUCT_ID),		EP_NOTIFY_NAME = ep->name;		ep->driver_data = ep;	/* claim the endpoint */	}	gs_device_desc.bDeviceClass = use_acm		? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;	gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;#ifdef CONFIG_USB_GADGET_DUALSPEED	gs_qualifier_desc.bDeviceClass = use_acm		? USB_CLASS_COMM : USB_CLASS_VENDOR_SPEC;	/* assume ep0 uses the same packet size for both speeds */	gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0;	/* assume endpoints are dual-speed */	gs_highspeed_notify_desc.bEndpointAddress =		gs_fullspeed_notify_desc.bEndpointAddress;	gs_highspeed_in_desc.bEndpointAddress =		gs_fullspeed_in_desc.bEndpointAddress;	gs_highspeed_out_desc.bEndpointAddress =		gs_fullspeed_out_desc.bEndpointAddress;#endif /* CONFIG_USB_GADGET_DUALSPEED */	usb_gadget_set_selfpowered(gadget);	if (gadget->is_otg) {		gs_otg_descriptor.bmAttributes |= USB_OTG_HNP,		gs_bulk_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;		gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;	}	gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL);	if (dev == NULL)		return -ENOMEM;	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",		system_utsname.sysname, system_utsname.release,		gadget->name);	memset(dev, 0, sizeof(struct gs_dev));	dev->dev_gadget = gadget;	spin_lock_init(&dev->dev_lock);	INIT_LIST_HEAD(&dev->dev_req_list);	set_gadget_data(gadget, dev);	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {		printk(KERN_ERR "gs_bind: cannot allocate ports\n");		gs_unbind(gadget);		return ret;	}	/* preallocate control response and buffer */	dev->dev_ctrl_req = gs_alloc_req(gadget->ep0, GS_MAX_DESC_LEN,		GFP_KERNEL);	if (dev->dev_ctrl_req == NULL) {		gs_unbind(gadget);		return -ENOMEM;	}	dev->dev_ctrl_req->complete = gs_setup_complete;	gadget->ep0->driver_data = dev;	printk(KERN_INFO "gs_bind: %s %s bound\n",		GS_LONG_NAME, GS_VERSION_STR);	return 0;autoconf_fail:	printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name);	return -ENODEV;}/* * gs_unbind * * Called on module unload.  Frees the control request and device * structure. */static void gs_unbind(struct usb_gadget *gadget){	struct gs_dev *dev = get_gadget_data(gadget);	gs_device = NULL;	/* read/write requests already freed, only control request remains */	if (dev != NULL) {		if (dev->dev_ctrl_req != NULL) {			gs_free_req(gadget->ep0, dev->dev_ctrl_req);			dev->dev_ctrl_req = NULL;		}		gs_free_ports(dev);		kfree(dev);		set_gadget_data(gadget, NULL);	}	printk(KERN_INFO "gs_unbind: %s %s unbound\n", GS_LONG_NAME,		GS_VERSION_STR);}/* * gs_setup * * Implements all the control endpoint functionality that's not * handled in hardware or the hardware driver. * * Returns the size of the data sent to the host, or a negative * error number. */static int gs_setup(struct usb_gadget *gadget,	const struct usb_ctrlrequest *ctrl){	int ret = -EOPNOTSUPP;	struct gs_dev *dev = get_gadget_data(gadget);	struct usb_request *req = dev->dev_ctrl_req;	switch (ctrl->bRequestType & USB_TYPE_MASK) {	case USB_TYPE_STANDARD:		ret = gs_setup_standard(gadget,ctrl);		break;	case USB_TYPE_CLASS:		ret = gs_setup_class(gadget,ctrl);		break;	default:		printk(KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",			ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,			ctrl->wIndex, ctrl->wLength);		break;	}	/* respond with data transfer before status phase? */	if (ret >= 0) {		req->length = ret;		req->zero = ret < ctrl->wLength				&& (ret % gadget->ep0->maxpacket) == 0;		ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);		if (ret < 0) {			printk(KERN_ERR "gs_setup: cannot queue response, ret=%d\n",				ret);			req->status = 0;			gs_setup_complete(gadget->ep0, req);		}	}	/* device either stalls (ret < 0) or reports success */	return ret;}static int gs_setup_standard(struct usb_gadget *gadget,	const struct usb_ctrlrequest *ctrl){	int ret = -EOPNOTSUPP;	struct gs_dev *dev = get_gadget_data(gadget);	struct usb_request *req = dev->dev_ctrl_req;	switch (ctrl->bRequest) {	case USB_REQ_GET_DESCRIPTOR:		if (ctrl->bRequestType != USB_DIR_IN)			break;		switch (ctrl->wValue >> 8) {		case USB_DT_DEVICE:			ret = min(ctrl->wLength,				(u16)sizeof(struct usb_device_descriptor));			memcpy(req->buf, &gs_device_desc, ret);			break;#ifdef CONFIG_USB_GADGET_DUALSPEED		case USB_DT_DEVICE_QUALIFIER:			if (!gadget->is_dualspeed)				break;			ret = min(ctrl->wLength,				(u16)sizeof(struct usb_qualifier_descriptor));			memcpy(req->buf, &gs_qualifier_desc, ret);			break;		case USB_DT_OTHER_SPEED_CONFIG:			if (!gadget->is_dualspeed)				break;			/* fall through */#endif /* CONFIG_USB_GADGET_DUALSPEED */		case USB_DT_CONFIG:			ret = gs_build_config_buf(req->buf, gadget->speed,				ctrl->wValue >> 8, ctrl->wValue & 0xff,				gadget->is_otg);			if (ret >= 0)				ret = min(ctrl->wLength, (u16)ret);			break;		case USB_DT_STRING:			/* wIndex == language code. */			ret = usb_gadget_get_string(&gs_string_table,				ctrl->wValue & 0xff, req->buf);			if (ret >= 0)				ret = min(ctrl->wLength, (u16)ret);			break;		}		break;	case USB_REQ_SET_CONFIGURATION:		if (ctrl->bRequestType != 0)			break;		spin_lock(&dev->dev_lock);		ret = gs_set_config(dev, ctrl->wValue);		spin_unlock(&dev->dev_lock);		break;	case USB_REQ_GET_CONFIGURATION:		if (ctrl->bRequestType != USB_DIR_IN)			break;		*(u8 *)req->buf = dev->dev_config;		ret = min(ctrl->wLength, (u16)1);		break;	case USB_REQ_SET_INTERFACE:		if (ctrl->bRequestType != USB_RECIP_INTERFACE		|| !dev->dev_config || ctrl->wIndex >= GS_MAX_NUM_INTERFACES)			break;		if (dev->dev_config == GS_BULK_CONFIG_ID		&& ctrl->wIndex != GS_BULK_INTERFACE_ID)			break;		/* no alternate interface settings */		if (ctrl->wValue != 0)			break;		spin_lock(&dev->dev_lock);		/* PXA hardware partially handles SET_INTERFACE;		 * we need to kluge around that interference.  */		if (gadget_is_pxa(gadget)) {			ret = gs_set_config(dev, use_acm ?				GS_ACM_CONFIG_ID : GS_BULK_CONFIG_ID);			goto set_interface_done;		}		if (dev->dev_config != GS_BULK_CONFIG_ID		&& ctrl->wIndex == GS_CONTROL_INTERFACE_ID) {			if (dev->dev_notify_ep) {				usb_ep_disable(dev->dev_notify_ep);				usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc);			}		} else {			usb_ep_disable(dev->dev_in_ep);			usb_ep_disable(dev->dev_out_ep);			usb_ep_enable(dev->dev_in_ep, dev->dev_in_ep_desc);			usb_ep_enable(dev->dev_out_ep, dev->dev_out_ep_desc);		}		ret = 0;set_interface_done:		spin_unlock(&dev->dev_lock);		break;	case USB_REQ_GET_INTERFACE:		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)		|| dev->dev_config == GS_NO_CONFIG_ID)			break;		if (ctrl->wIndex >= GS_MAX_NUM_INTERFACES		|| (dev->dev_config == GS_BULK_CONFIG_ID		&& ctrl->wIndex != GS_BULK_INTERFACE_ID)) {			ret = -EDOM;			break;		}		/* no alternate interface settings */		*(u8 *)req->buf = 0;		ret = min(ctrl->wLength, (u16)1);		break;	default:		printk(KERN_ERR "gs_setup: unknown standard request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",			ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,			ctrl->wIndex, ctrl->wLength);		break;	}	return ret;}static int gs_setup_class(struct usb_gadget *gadget,	const struct usb_ctrlrequest *ctrl){	int ret = -EOPNOTSUPP;	struct gs_dev *dev = get_gadget_data(gadget);	struct gs_port *port = dev->dev_port[0];	/* ACM only has one port */	struct usb_request *req = dev->dev_ctrl_req;	switch (ctrl->bRequest) {	case USB_CDC_REQ_SET_LINE_CODING:		ret = min(ctrl->wLength,			(u16)sizeof(struct usb_cdc_line_coding));		if (port) {			spin_lock(&port->port_lock);			memcpy(&port->port_line_coding, req->buf, ret);			spin_unlock(&port->port_lock);		}		break;	case USB_CDC_REQ_GET_LINE_CODING:		port = dev->dev_port[0];	/* ACM only has one port */		ret = min(ctrl->wLength,			(u16)sizeof(struct usb_cdc_line_coding));		if (port) {			spin_lock(&port->port_lock);			memcpy(req->buf, &port->port_line_coding, ret);			spin_unlock(&port->port_lock);		}		break;	case USB_CDC_REQ_SET_CONTROL_LINE_STATE:		ret = 0;		break;	default:		printk(KERN_ERR "gs_setup: unknown class request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",			ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,			ctrl->wIndex, ctrl->wLength);		break;	}	return ret;}/* * gs_setup_complete */static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req){	if (req->status || req->actual != req->length) {		printk(KERN_ERR "gs_setup_complete: status error, status=%d, actual=%d, length=%d\n",			req->status, req->actual, req->length);	}}/* * gs_disconnect * * Called when the device is disconnected.  Frees the closed * ports and disconnects open ports.  Open ports will be freed * on close.  Then reallocates the ports for the next connection. */static void gs_disconnect(struct usb_gadget *gadget){	unsigned long flags;	struct gs_dev *dev = get_gadget_data(gadget);	spin_lock_irqsave(&dev->dev_lock, flags);	gs_reset_config(dev);	/* free closed ports and disconnect open ports */	/* (open ports will be freed when closed) */	gs_free_ports(dev);	/* re-allocate ports for the next connection */	if (gs_alloc_ports(dev, GFP_ATOMIC) != 0)		printk(KERN_ERR "gs_disconnect: cannot re-allocate ports\n");	spin_unlock_irqrestore(&dev->dev_lock, flags);	printk(KERN_INFO "gs_disconnect: %s disconnected\n", GS_LONG_NAME);}/* * gs_set_config * * Configures the device by enabling device specific * optimizations, setting up the endpoints, allocating * read and write requests and queuing read requests. * * The device lock must be held when calling this function. */static int gs_set_config(struct gs_dev *dev, unsigned config){	int i;	int ret = 0;	struct usb_gadget *gadget = dev->dev_gadget;	struct usb_ep *ep;	struct usb_endpoint_descriptor *ep_desc;	struct usb_request *req;	struct gs_req_entry *req_entry;	if (dev == NULL) {		printk(KERN_ERR "gs_set_config: NULL device pointer\n");		return 0;	}	if (config == dev->dev_config)		return 0;	gs_reset_config(dev);	switch (config) {	case GS_NO_CONFIG_ID:		return 0;	case GS_BULK_CONFIG_ID:		if (use_acm)			return -EINVAL;		/* device specific optimizations */		if (gadget_is_net2280(gadget))			net2280_set_fifo_mode(gadget, 1);		break;	case GS_ACM_CONFIG_ID:		if (!use_acm)			return -EINVAL;		/* device specific optimizations */		if (gadget_is_net2280(gadget))			net2280_set_fifo_mode(gadget, 1);		break;	default:		return -EINVAL;	}	dev->dev_config = config;	gadget_for_each_ep(ep, gadget) {		if (EP_NOTIFY_NAME		&& strcmp(ep->name, EP_NOTIFY_NAME) == 0) {			ep_desc = GS_SPEED_SELECT(				gadget->speed == USB_SPEED_HIGH,				&gs_highspeed_notify_desc,				&gs_fullspeed_notify_desc);			ret = usb_ep_enable(ep,ep_desc);			if (ret == 0) {				ep->driver_data = dev;				dev->dev_notify_ep = ep;				dev->dev_notify_ep_desc = ep_desc;			} else {				printk(KERN_ERR "gs_set_config: cannot enable notify endpoint %s, ret=%d\n",					ep->name, ret);				goto exit_reset_config;			}		}		else if (strcmp(ep->name, EP_IN_NAME) == 0) {			ep_desc = GS_SPEED_SELECT(				gadget->speed == USB_SPEED_HIGH,

⌨️ 快捷键说明

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