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

📄 gserial.c

📁 LINUX2.4.18内核下的usb GADGET驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	spin_unlock_irqrestore(&dev->dev_lock, flags );	return( 0 );}/* * gs_send_packet * * If there is data to send, a packet is built in the given * buffer and the size is returned.  If there is no data to * send, 0 is returned.  If there is any error a negative * error number is returned. * * Called during USB completion routine, on interrupt time. * * We assume that disconnect will not happen until all completion * routines have completed, so we can assume that the dev_port * array does not change during the lifetime of this function. */static int gs_send_packet( struct gs_dev *dev, char *packet, unsigned int size ){	unsigned int len;	struct gs_port *port;	/* TEMPORARY -- only port 0 is supported right now */	port = dev->dev_port[0];	if( port == NULL ) {		printk( KERN_ERR			"gs_send_packet: port=%d, NULL port pointer\n",			0 );		return( -EIO );	}	spin_lock(&port->port_lock );	len = gs_buf_data_avail( port->port_write_buf );	if( len < size )		size = len;	if( size == 0 ) {		spin_unlock(&port->port_lock );		return( 0 );	}	size = gs_buf_get( port->port_write_buf, packet, size );	wake_up_interruptible( &port->port_tty->write_wait );	spin_unlock(&port->port_lock );	return( size );}/* * gs_recv_packet * * Called for each USB packet received.  Reads the packet * header and stuffs the data in the appropriate tty buffer. * Returns 0 if successful, or a negative error number. * * Called during USB completion routine, on interrupt time. * * We assume that disconnect will not happen until all completion * routines have completed, so we can assume that the dev_port * array does not change during the lifetime of this function. */static int gs_recv_packet( struct gs_dev *dev, char *packet, unsigned int size ){	unsigned int len;	struct gs_port *port;	/* TEMPORARY -- only port 0 is supported right now */	port = dev->dev_port[0];	if( port == NULL ) {		printk( KERN_ERR "gs_recv_packet: port=%d, NULL port pointer\n",			port->port_num );		return( -EIO );	}	spin_lock(&port->port_lock );	if( port->port_tty == NULL ) {		printk( KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",			port->port_num );		spin_unlock(&port->port_lock );		return( -EIO );	}	if( port->port_tty->magic != TTY_MAGIC ) {		printk( KERN_ERR "gs_recv_packet: port=%d, bad tty magic\n",			port->port_num );		spin_unlock(&port->port_lock );		return( -EIO );	}	len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count);	if( len < size )		size = len;	if( size > 0 ) {		memcpy( port->port_tty->flip.char_buf_ptr, packet, size );		port->port_tty->flip.char_buf_ptr += size;		port->port_tty->flip.count += size;		tty_flip_buffer_push( port->port_tty );		wake_up_interruptible( &port->port_tty->read_wait );	}	spin_unlock(&port->port_lock );	return( 0 );}/** gs_read_complete*/static void gs_read_complete( struct usb_ep *ep, struct usb_request *req ){	int ret;	struct gs_dev *dev = ep->driver_data;	if( dev == NULL ) {		printk( KERN_ERR "gs_read_complete: NULL device pointer\n" );		return;	}	switch( req->status ) {	case 0: 		/* normal completion */		gs_recv_packet( dev, req->buf, req->actual );requeue:		req->length = ep->maxpacket;		if( (ret=usb_ep_queue( ep, req, GFP_ATOMIC )) ) {			printk( KERN_ERR			"gs_read_complete: cannot queue read request, ret=%d\n",				ret );		}		break;	case -ESHUTDOWN:		/* disconnect */		gs_debug( "gs_read_complete: shutdown\n" );		gs_free_req( ep, req );		break;	default:		/* unexpected */		printk( KERN_ERR		"gs_read_complete: unexpected status error, status=%d\n",			req->status );		goto requeue;		break;	}}/** gs_write_complete*/static void gs_write_complete( struct usb_ep *ep, struct usb_request *req ){	struct gs_dev *dev = ep->driver_data;	struct gs_req_entry *gs_req = req->context;	if( dev == NULL ) {		printk( KERN_ERR "gs_write_complete: NULL device pointer\n" );		return;	}	switch( req->status ) {	case 0:		/* normal completion */requeue:		if( gs_req == NULL ) {			printk( KERN_ERR				"gs_write_complete: NULL request pointer\n" );			return;		}		spin_lock(&dev->dev_lock );		list_add( &gs_req->re_entry, &dev->dev_req_list );		spin_unlock(&dev->dev_lock );		gs_send( dev );		break;	case -ESHUTDOWN:		/* disconnect */		gs_debug( "gs_write_complete: shutdown\n" );		gs_free_req( ep, req );		break;	default:		printk( KERN_ERR		"gs_write_complete: unexpected status error, status=%d\n",			req->status );		goto requeue;		break;	}}/* Gadget Driver *//* * gs_bind * * Called on module load.  Allocates and initializes the device * structure and a control request. */static int gs_bind(struct usb_gadget *gadget){	int ret;	struct usb_ep *ep;	struct gs_dev *dev;	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 */	/* device specific bcdDevice value in device descriptor */	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);	} else if (gadget_is_sa1100(gadget)) {		gs_device_desc.bcdDevice =			__constant_cpu_to_le16(GS_VERSION_NUM|0x0004);	} 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 {		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);	}	gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;#ifdef CONFIG_USB_GADGET_DUALSPEED	/* 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_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);	gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL);	if (dev == NULL)		return -ENOMEM;	snprintf (manufacturer, sizeof(manufacturer),		UTS_SYSNAME " " UTS_RELEASE " with %s", 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 );		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;	unsigned int sv_config;	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:#endif /* CONFIG_USB_GADGET_DUALSPEED */		case USB_DT_CONFIG:			ret = gs_build_config_desc( req->buf, gadget->speed,				ctrl->wValue >> 8, ctrl->wValue & 0xff );			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 )			break;		spin_lock( &dev->dev_lock );		if( dev->dev_config == GS_BULK_CONFIG_ID		&& ctrl->wIndex == GS_INTERFACE_ID		&& ctrl->wValue == GS_ALT_INTERFACE_ID ) {			sv_config = dev->dev_config;			/* since there is only one interface, setting the */			/* interface is equivalent to setting the config */			gs_reset_config( dev );			gs_set_config( dev, sv_config );			ret = 0;		}		spin_unlock( &dev->dev_lock );		break;	case USB_REQ_GET_INTERFACE:		if( ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE) )			break;		if( dev->dev_config == GS_NO_CONFIG_ID )			break;		if( ctrl->wIndex != GS_INTERFACE_ID ) {			ret = -EDOM;			break;		}		*(u8 *)req->buf = GS_ALT_INTERFACE_ID;		ret = min( ctrl->wLength, (u16)1 );		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;		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 );}/* * 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_request *req;	struct gs_req_entry *req_entry;	if( dev == NULL ) {		printk( KERN_ERR "gs_set_config: NULL device pointer\n" );

⌨️ 快捷键说明

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