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

📄 gserial.c

📁 LINUX2.4.18内核下的usb GADGET驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	int port_num;	unsigned long flags;	struct gs_port *port;	struct gs_dev *dev;	struct gs_buf *buf;	struct semaphore *sem;	port_num = MINOR( tty->device ) - GS_MINOR_START;	gs_debug( "gs_open: (%d,%p,%p)\n", port_num, tty, file );	tty->driver_data = NULL;	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 );		spin_unlock_irqrestore(&dev->dev_lock, flags );		up( sem );		return( -ENODEV );	}	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 );		spin_unlock_irqrestore(&dev->dev_lock, flags );		up( sem );		return( -ENODEV );	}	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 );		spin_unlock_irqrestore(&port->port_lock, flags );		up( sem );		return( -EIO );	}	if( port->port_open_count > 0 ) {		++port->port_open_count;		spin_unlock_irqrestore(&port->port_lock, flags );		gs_debug( "gs_open: (%d,%p,%p) already open\n",			port_num, tty, file );		up( sem );		return( 0 );	}	/* 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;			spin_unlock_irqrestore(&port->port_lock, flags );			up( sem );			return( -EIO );		}		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;			spin_unlock_irqrestore(&port->port_lock, flags );			up( sem );			return( -ENOMEM );		}	}	/* 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;		spin_unlock_irqrestore(&port->port_lock, flags );		up( sem );		return( -EIO );	}	tty->driver_data = port;	port->port_tty = tty;	port->port_open_count = 1;	port->port_in_use = 0;	spin_unlock_irqrestore(&port->port_lock, flags );	up( sem );	gs_debug( "gs_open: (%d,%p,%p) completed\n", port_num, tty, file );	return( 0 ); }/* * 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 );		spin_unlock_irqrestore(&port->port_lock, flags );		up( sem );		return;	}	if( port->port_open_count > 0 ) {		--port->port_open_count;		spin_unlock_irqrestore(&port->port_lock, flags );		up( sem );		return;	}	/* free disconnected port on final close */	if( port->port_dev == NULL ) {		kfree( port );		spin_unlock_irqrestore(&port->port_lock, flags );		up( sem );		return;	}	/* 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 );		spin_unlock_irqrestore(&port->port_lock, flags );		up( sem );		return;	}	gs_buf_clear( port->port_write_buf );	tty->driver_data = NULL;	port->port_tty = NULL;	port->port_in_use = 0;	spin_unlock_irqrestore(&port->port_lock, flags );	up( sem );	gs_debug( "gs_close: (%d,%p,%p) completed\n",		port->port_num, tty, file );}/* * gs_write */static int gs_write( struct tty_struct *tty, int from_user,	const unsigned char *buf, int count ){	unsigned long flags;	struct gs_port *port = tty->driver_data;	if( port == NULL ) {		printk( KERN_ERR "gs_write: NULL port pointer\n" );		return( -EIO );	}	gs_debug( "gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty,		count );	if( count == 0 )		return( 0 );	/* copy from user into tmp buffer, get tmp_buf semaphore */	if( from_user ) {		if( count > GS_TMP_BUF_SIZE )			count = GS_TMP_BUF_SIZE;		down( &gs_tmp_buf_sem );		if( copy_from_user( gs_tmp_buf, buf, count ) != 0 ) {			up( &gs_tmp_buf_sem );			printk( KERN_ERR			"gs_write: (%d,%p) cannot copy from user space\n",				port->port_num, tty );			return( -EFAULT );		}		buf = gs_tmp_buf;	}	spin_lock_irqsave(&port->port_lock, flags );	if( port->port_dev == NULL ) {		printk( KERN_ERR "gs_write: (%d,%p) port is not connected\n",			port->port_num, tty );		spin_unlock_irqrestore(&port->port_lock, flags );		if( from_user )			up( &gs_tmp_buf_sem );		return( -EIO );	}	if( port->port_open_count == 0 ) {		printk( KERN_ERR "gs_write: (%d,%p) port is closed\n",			port->port_num, tty );		spin_unlock_irqrestore(&port->port_lock, flags );		if( from_user )			up( &gs_tmp_buf_sem );		return( -EBADF );	}	count = gs_buf_put( port->port_write_buf, buf, count );	spin_unlock_irqrestore(&port->port_lock, flags );	if( from_user )		up( &gs_tmp_buf_sem );	gs_send( gs_device );	gs_debug( "gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty,		count );	return( count );}/* * gs_put_char */static void gs_put_char( struct tty_struct *tty, unsigned char ch ){	unsigned long flags;	struct gs_port *port = tty->driver_data;	if( port == NULL ) {		printk( KERN_ERR "gs_put_char: NULL port pointer\n" );		return;	}	gs_debug( "gs_put_char: (%d,%p) char=0x%x, called from %p, %p, %p\n", port->port_num, tty, ch, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2) );	spin_lock_irqsave(&port->port_lock, flags );	if( port->port_dev == NULL ) {		printk( KERN_ERR "gs_put_char: (%d,%p) port is not connected\n",			port->port_num, tty );		spin_unlock_irqrestore(&port->port_lock, flags );		return;	}	if( port->port_open_count == 0 ) {		printk( KERN_ERR "gs_put_char: (%d,%p) port is closed\n",			port->port_num, tty );		spin_unlock_irqrestore(&port->port_lock, flags );		return;	}	gs_buf_put( port->port_write_buf, &ch, 1 );	spin_unlock_irqrestore(&port->port_lock, flags );}/* * gs_flush_chars */static void gs_flush_chars( struct tty_struct *tty ){	unsigned long flags;	struct gs_port *port = tty->driver_data;	if( port == NULL ) {		printk( KERN_ERR "gs_flush_chars: NULL port pointer\n" );		return;	}	gs_debug( "gs_flush_chars: (%d,%p)\n", port->port_num, tty );	spin_lock_irqsave(&port->port_lock, flags );	if( port->port_dev == NULL ) {		printk( KERN_ERR			"gs_flush_chars: (%d,%p) port is not connected\n",			port->port_num, tty );		spin_unlock_irqrestore(&port->port_lock, flags );		return;	}	if( port->port_open_count == 0 ) {		printk( KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n",			port->port_num, tty );		spin_unlock_irqrestore(&port->port_lock, flags );		return;	}	spin_unlock_irqrestore(&port->port_lock, flags );	gs_send( gs_device );}/* * gs_write_room */static int gs_write_room( struct tty_struct *tty ){	int room = 0;	unsigned long flags;	struct gs_port *port = tty->driver_data;	if( port == NULL )		return( 0 );	spin_lock_irqsave(&port->port_lock, flags );	if( port->port_dev != NULL && port->port_open_count > 0	&& port->port_write_buf != NULL )		room = gs_buf_space_avail( port->port_write_buf );	spin_unlock_irqrestore(&port->port_lock, flags );	gs_debug( "gs_write_room: (%d,%p) room=%d\n",		port->port_num, tty, room );	return( room );}/* * gs_chars_in_buffer */static int gs_chars_in_buffer( struct tty_struct *tty ){	int chars = 0;	unsigned long flags;	struct gs_port *port = tty->driver_data;	if( port == NULL )		return( 0 );	spin_lock_irqsave(&port->port_lock, flags );	if( port->port_dev != NULL && port->port_open_count > 0	&& port->port_write_buf != NULL )		chars = gs_buf_data_avail( port->port_write_buf );	spin_unlock_irqrestore(&port->port_lock, flags );	gs_debug( "gs_chars_in_buffer: (%d,%p) chars=%d\n",		port->port_num, tty, chars );	return( chars );}/* * gs_throttle */static void gs_throttle( struct tty_struct *tty ){}/* * gs_unthrottle */static void gs_unthrottle( struct tty_struct *tty ){}/* * gs_break */static void gs_break( struct tty_struct *tty, int break_state ){}/* * gs_ioctl */static int  gs_ioctl( struct tty_struct *tty, struct file *file,	unsigned int cmd, unsigned long arg ){	struct gs_port *port = tty->driver_data;	if( port == NULL ) {		printk( KERN_ERR "gs_ioctl: NULL port pointer\n" );		return( -EIO );	}	gs_debug( "gs_ioctl: (%d,%p,%p) cmd=0x%4.4x, arg=%lu\n",		port->port_num, tty, file, cmd, arg );	/* handle ioctls */	/* could not handle ioctl */	return( -ENOIOCTLCMD );}/* * gs_set_termios */static void gs_set_termios( struct tty_struct *tty, struct termios *old ){}/* * gs_read_proc */static int gs_read_proc( char *page, char **start, off_t off, int count,	int *eof, void *data ){	return( 0 );}/** gs_send** This function finds available write requests, calls* gs_send_packet to fill these packets with data, and* continues until either there are no more write requests* available or no more data to send.  This function is* run whenever data arrives or write requests are available.*/static int gs_send( struct gs_dev *dev ){	int ret,len;	unsigned long flags;	struct usb_ep *ep;	struct usb_request *req;	struct gs_req_entry *req_entry;	if( dev == NULL ) {		printk( KERN_ERR "gs_send: NULL device pointer\n" );		return( -ENODEV );	}	spin_lock_irqsave(&dev->dev_lock, flags );	ep = dev->dev_in_ep;	while( !list_empty( &dev->dev_req_list ) ) {		req_entry = list_entry( dev->dev_req_list.next,			struct gs_req_entry, re_entry );		req = req_entry->re_req;		len = gs_send_packet( dev, req->buf, ep->maxpacket );		if( len > 0 ) {gs_debug_level( 3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2) );			list_del( &req_entry->re_entry );			req->length = len;			if( (ret=usb_ep_queue( ep, req, GFP_ATOMIC )) ) {				printk( KERN_ERR				"gs_send: cannot queue read request, ret=%d\n",					ret );				break;			}		} else {			break;		}	}

⌨️ 快捷键说明

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