📄 gserial.c
字号:
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 + -