Esempio n. 1
0
/* n_hdlc_release()
 *
 *	release an n_hdlc per device line discipline info structure
 *
 */
static void n_hdlc_release (struct n_hdlc *n_hdlc)
{
	struct tty_struct *tty = n_hdlc2tty (n_hdlc);
	N_HDLC_BUF *buf;
	
	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_release() called\n",__FILE__,__LINE__);
		
	/* Ensure that the n_hdlcd process is not hanging on select()/poll() */
	wake_up_interruptible (&n_hdlc->read_wait);
	wake_up_interruptible (&n_hdlc->poll_wait);
	wake_up_interruptible (&n_hdlc->write_wait);

	if (tty != NULL && tty->disc_data == n_hdlc)
		tty->disc_data = NULL;	/* Break the tty->n_hdlc link */

	/* Release transmit and receive buffers */
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	
	kfree(n_hdlc);
	
}	/* end of n_hdlc_release() */
static void n_hdlc_release(struct n_hdlc *n_hdlc)
{
	struct tty_struct *tty = n_hdlc2tty (n_hdlc);
	struct n_hdlc_buf *buf;
	
	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_release() called\n",__FILE__,__LINE__);
		
	
	wake_up_interruptible (&tty->read_wait);
	wake_up_interruptible (&tty->write_wait);

	if (tty->disc_data == n_hdlc)
		tty->disc_data = NULL;	

	
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	kfree(n_hdlc->tbuf);
	kfree(n_hdlc);
	
}	
Esempio n. 3
0
static void flush_rx_queue(struct tty_struct *tty)
{
	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
	struct n_hdlc_buf *buf;

	while ((buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list)))
		n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, buf);
}
Esempio n. 4
0
/* n_hdlc_tty_receive()
 * 
 * 	Called by tty low level driver when receive data is
 * 	available. Data is interpreted as one HDLC frame.
 * 	
 * Arguments:	 	tty		pointer to tty isntance data
 * 			data		pointer to received data
 * 			flags		pointer to flags for data
 * 			count		count of received data in bytes
 * 	
 * Return Value:	None
 */
static void n_hdlc_tty_receive(struct tty_struct *tty,
	const __u8 * data, char *flags, int count)
{
	register struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
	register N_HDLC_BUF *buf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_tty_receive() called count=%d\n",
			__FILE__,__LINE__, count);
		
	/* This can happen if stuff comes in on the backup tty */
	if (n_hdlc == 0 || tty != n_hdlc->tty)
		return;
		
	/* verify line is using HDLC discipline */
	if (n_hdlc->magic != HDLC_MAGIC) {
		printk("%s(%d) line not using HDLC discipline\n",
			__FILE__,__LINE__);
		return;
	}
	
	if ( count>maxframe ) {
		if (debuglevel >= DEBUG_LEVEL_INFO)	
			printk("%s(%d) rx count>maxframesize, data discarded\n",
			       __FILE__,__LINE__);
		return;
	}

	/* get a free HDLC buffer */	
	buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);
	if (!buf) {
		/* no buffers in free list, attempt to allocate another rx buffer */
		/* unless the maximum count has been reached */
		if (n_hdlc->rx_buf_list.count < MAX_RX_BUF_COUNT)
			buf = (N_HDLC_BUF*)kmalloc(N_HDLC_BUF_SIZE,GFP_ATOMIC);
	}
	
	if (!buf) {
		if (debuglevel >= DEBUG_LEVEL_INFO)	
			printk("%s(%d) no more rx buffers, data discarded\n",
			       __FILE__,__LINE__);
		return;
	}
		
	/* copy received data to HDLC buffer */
	memcpy(buf->buf,data,count);
	buf->count=count;

	/* add HDLC buffer to list of received frames */
	n_hdlc_buf_put(&n_hdlc->rx_buf_list,buf);
	
	/* wake up any blocked reads and perform async signalling */
	wake_up_interruptible (&n_hdlc->read_wait);
	wake_up_interruptible (&n_hdlc->poll_wait);
	if (n_hdlc->tty->fasync != NULL)
		kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN);

}	/* end of n_hdlc_tty_receive() */
static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
			       char *flags, int count)
{
	register struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
	register struct n_hdlc_buf *buf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_tty_receive() called count=%d\n",
			__FILE__,__LINE__, count);
		
	
	if (!n_hdlc || tty != n_hdlc->tty)
		return;
		
	
	if (n_hdlc->magic != HDLC_MAGIC) {
		printk("%s(%d) line not using HDLC discipline\n",
			__FILE__,__LINE__);
		return;
	}
	
	if ( count>maxframe ) {
		if (debuglevel >= DEBUG_LEVEL_INFO)	
			printk("%s(%d) rx count>maxframesize, data discarded\n",
			       __FILE__,__LINE__);
		return;
	}

		
	buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);
	if (!buf) {
		
		
		if (n_hdlc->rx_buf_list.count < MAX_RX_BUF_COUNT)
			buf = kmalloc(N_HDLC_BUF_SIZE, GFP_ATOMIC);
	}
	
	if (!buf) {
		if (debuglevel >= DEBUG_LEVEL_INFO)	
			printk("%s(%d) no more rx buffers, data discarded\n",
			       __FILE__,__LINE__);
		return;
	}
		
	
	memcpy(buf->buf,data,count);
	buf->count=count;

	
	n_hdlc_buf_put(&n_hdlc->rx_buf_list, buf);
	
	
	wake_up_interruptible (&tty->read_wait);
	if (n_hdlc->tty->fasync != NULL)
		kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN);

}	
Esempio n. 6
0
static size_t vs_sdlc_kernel_write(void *context, const void *buf, size_t count)
{
	struct vl_sync_port *port = (struct vl_sync_port *)context;
        struct vl_sync_port *paired_port = NULL;
	struct n_hdlc *n_hdlc = NULL;
	struct n_hdlc_buf *tbuf;
	//unsigned long flags;

	/* Validate the pointers */
	if(!port || !IS_OPEN(port))
		return -ENODEV;

        paired_port = port->paired_port;
        if (!paired_port || !IS_OPEN(paired_port))
                return -EINVAL;

        // Write into paired_port receive buffer, if available
	n_hdlc = paired_port->n_hdlc;
        if (!n_hdlc)
                return -EIO;
                
	/* Verify frame size */
	if (count > MAX_HDLC_FRAME_SIZE) {
		pr_debug("vs_sdlc_kernel_write: truncating user packet from %lu to %d\n",
				(unsigned long) count, MAX_HDLC_FRAME_SIZE);
		count = MAX_HDLC_FRAME_SIZE;
	}


        // Lock paired_port
	//spin_lock_irqsave(&paired_port->ctrl_lock, flags);

	/* Allocate transmit buffer */
	if (!(tbuf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list))) {
		//spin_unlock_irqrestore(&paired_port->ctrl_lock, flags);
		return -EAGAIN;
	}

	/* Copy the user's buffer */
	memcpy(tbuf->buf, buf, count);

pr_debug("vs_sdlc_kernel_write: %d bytes: %02x\n", count, tbuf->buf[0]);
	/* Send the data */
	tbuf->count = count;
	n_hdlc_buf_put(&n_hdlc->rx_buf_list,tbuf);

	//spin_unlock_irqrestore(&paired_port->ctrl_lock, flags);

        /* Wake up any blocked reads on paired port and perform async signalling */
        wake_up_interruptible (&paired_port->read_wait);
        if (paired_port->fasync_queue != NULL)
                kill_fasync (&paired_port->fasync_queue, SIGIO, POLL_IN);
        
	return count;

}
Esempio n. 7
0
static void n_hdlc_release(struct n_hdlc *n_hdlc)
{
	struct n_hdlc_buf *buf;
	
	/* Release transmit and receive buffers */
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	for(;;) {
		buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
		if (buf) {
			kfree(buf);
		} else
			break;
	}
	kfree(n_hdlc->tbuf);
	kfree(n_hdlc);
	
}	/* end of n_hdlc_release() */
Esempio n. 8
0
static void flush_tx_queue(struct tty_struct *tty)
{
	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
	struct n_hdlc_buf *buf;
	unsigned long flags;

	while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list)))
		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf);
 	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
	if (n_hdlc->tbuf) {
		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, n_hdlc->tbuf);
		n_hdlc->tbuf = NULL;
	}
	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
}
Esempio n. 9
0
static int vs_sdlc_kernel_read( void *context, void *buf, size_t count)
{
	struct vl_sync_port *port = (struct vl_sync_port *)context;
	struct n_hdlc *n_hdlc = port->n_hdlc;
	struct n_hdlc_buf *rbuf;

	pr_debug("%s(%d)vs_sdlc_kernel_read() called\n",__FILE__,__LINE__);

	/* Validate the pointers */
	if(!port || !IS_OPEN(port) || !n_hdlc)
		return -EBADF;

	rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
	if (!rbuf) {
		/* no data */
		return 0;
	}

	/* Copy the data to the caller's buffer */
	if (count > rbuf->count)
		count = rbuf->count;
	memcpy(buf, rbuf->buf, count);
pr_debug("vs_sdlc_kernel_read: %d bytes: %02x\n", count, rbuf->buf[0]);
	/* return HDLC buffer to free list unless the free list */
	/* count has exceeded the default value, in which case the */
	/* buffer is freed back to the OS to conserve memory */
	if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT)
		kfree(rbuf);
	else
		n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);

	// Wake up paired_port write wait queue
        if (port->paired_port && IS_OPEN(port->paired_port))
                /* wake up sleeping writers */
                wake_up_interruptible(&port->paired_port->write_wait);

	return count;
}
Esempio n. 10
0
/**
 * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
 * @tty - pointer to tty instance data
 * @file - pointer to open file object
 * @buf - pointer to returned data buffer
 * @nr - size of returned data buffer
 * 	
 * Returns the number of bytes returned or error code.
 */
static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
			   __u8 __user *buf, size_t nr)
{
	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
	int ret = 0;
	struct n_hdlc_buf *rbuf;
	DECLARE_WAITQUEUE(wait, current);

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__);
		
	/* Validate the pointers */
	if (!n_hdlc)
		return -EIO;

	/* verify user access to buffer */
	if (!access_ok(VERIFY_WRITE, buf, nr)) {
		printk(KERN_WARNING "%s(%d) n_hdlc_tty_read() can't verify user "
		"buffer\n", __FILE__, __LINE__);
		return -EFAULT;
	}

	add_wait_queue(&tty->read_wait, &wait);

	for (;;) {
		if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
			ret = -EIO;
			break;
		}
		if (tty_hung_up_p(file))
			break;

		set_current_state(TASK_INTERRUPTIBLE);

		rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
		if (rbuf) {
			if (rbuf->count > nr) {
				/* too large for caller's buffer */
				ret = -EOVERFLOW;
			} else {
				if (copy_to_user(buf, rbuf->buf, rbuf->count))
					ret = -EFAULT;
				else
					ret = rbuf->count;
			}

			if (n_hdlc->rx_free_buf_list.count >
			    DEFAULT_RX_BUF_COUNT)
				kfree(rbuf);
			else
				n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf);
			break;
		}
			
		/* no data */
		if (file->f_flags & O_NONBLOCK) {
			ret = -EAGAIN;
			break;
		}

		schedule();

		if (signal_pending(current)) {
			ret = -EINTR;
			break;
		}
	}

	remove_wait_queue(&tty->read_wait, &wait);
	__set_current_state(TASK_RUNNING);

	return ret;
	
}	/* end of n_hdlc_tty_read() */
Esempio n. 11
0
/**
 * n_hdlc_tty_write - write a single frame of data to device
 * @tty	- pointer to associated tty device instance data
 * @file - pointer to file object data
 * @data - pointer to transmit data (one frame)
 * @count - size of transmit frame in bytes
 * 		
 * Returns the number of bytes written (or error code).
 */
static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
			    const unsigned char *data, size_t count)
{
	struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
	int error = 0;
	DECLARE_WAITQUEUE(wait, current);
	struct n_hdlc_buf *tbuf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_tty_write() called count=%Zd\n",
			__FILE__,__LINE__,count);
		
	/* Verify pointers */
	if (!n_hdlc)
		return -EIO;

	if (n_hdlc->magic != HDLC_MAGIC)
		return -EIO;

	/* verify frame size */
	if (count > maxframe ) {
		if (debuglevel & DEBUG_LEVEL_INFO)
			printk (KERN_WARNING
				"n_hdlc_tty_write: truncating user packet "
				"from %lu to %d\n", (unsigned long) count,
				maxframe );
		count = maxframe;
	}
	
	add_wait_queue(&tty->write_wait, &wait);

	for (;;) {
		set_current_state(TASK_INTERRUPTIBLE);
	
		tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list);
		if (tbuf)
			break;

		if (file->f_flags & O_NONBLOCK) {
			error = -EAGAIN;
			break;
		}
		schedule();
			
		n_hdlc = tty2n_hdlc (tty);
		if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || 
		    tty != n_hdlc->tty) {
			printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc);
			error = -EIO;
			break;
		}
			
		if (signal_pending(current)) {
			error = -EINTR;
			break;
		}
	}

	__set_current_state(TASK_RUNNING);
	remove_wait_queue(&tty->write_wait, &wait);

	if (!error) {		
		/* Retrieve the user's buffer */
		memcpy(tbuf->buf, data, count);

		/* Send the data */
		tbuf->count = error = count;
		n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
		n_hdlc_send_frames(n_hdlc,tty);
	}

	return error;
	
}	/* end of n_hdlc_tty_write() */
Esempio n. 12
0
/* n_hdlc_tty_read()
 * 
 * 	Called to retreive one frame of data (if available)
 * 	
 * Arguments:
 * 
 * 	tty		pointer to tty instance data
 * 	file		pointer to open file object
 * 	buf		pointer to returned data buffer
 * 	nr		size of returned data buffer
 * 	
 * Return Value:
 * 
 * 	Number of bytes returned or error code
 */
static rw_ret_t n_hdlc_tty_read (struct tty_struct *tty,
	struct file *file, __u8 * buf, rw_count_t nr)
{
	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
	int error;
	rw_ret_t ret;
	N_HDLC_BUF *rbuf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__);
		
	/* Validate the pointers */
	if (!n_hdlc)
		return -EIO;

	/* verify user access to buffer */
	error = verify_area (VERIFY_WRITE, buf, nr);
	if (error != 0) {
		printk(KERN_WARNING"%s(%d) n_hdlc_tty_read() can't verify user "
		"buffer\n",__FILE__,__LINE__);
		return (error);
	}

	for (;;) {
		n_hdlc = tty2n_hdlc (tty);
		if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
			 tty != n_hdlc->tty)
			return 0;

		rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
		if (rbuf)
			break;
			
		/* no data */
		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;
			
		interruptible_sleep_on (&n_hdlc->read_wait);
		if (signal_pending(current))
			return -EINTR;
	}
		
	if (rbuf->count > nr) {
		/* frame too large for caller's buffer (discard frame) */
		ret = (rw_ret_t)-EOVERFLOW;
	} else {
		/* Copy the data to the caller's buffer */
		COPY_TO_USER(error,buf,rbuf->buf,rbuf->count);
		if (error)
			ret = (rw_ret_t)error;
		else
			ret = (rw_ret_t)rbuf->count;
	}
	
	/* return HDLC buffer to free list unless the free list */
	/* count has exceeded the default value, in which case the */
	/* buffer is freed back to the OS to conserve memory */
	if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT)
		kfree(rbuf);
	else	
		n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
	
	return ret;
	
}	/* end of n_hdlc_tty_read() */
Esempio n. 13
0
/**
 * n_hdlc_send_frames - send frames on pending send buffer list
 * @n_hdlc - pointer to ldisc instance data
 * @tty - pointer to tty instance data
 *
 * Send frames on pending send buffer list until the driver does not accept a
 * frame (busy) this function is called after adding a frame to the send buffer
 * list and by the tty wakeup callback.
 */
static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
{
	register int actual;
	unsigned long flags;
	struct n_hdlc_buf *tbuf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_send_frames() called\n",__FILE__,__LINE__);
 check_again:
		
 	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
	if (n_hdlc->tbusy) {
		n_hdlc->woke_up = 1;
 		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
		return;
	}
	n_hdlc->tbusy = 1;
	n_hdlc->woke_up = 0;
	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);

	/* get current transmit buffer or get new transmit */
	/* buffer from list of pending transmit buffers */
		
	tbuf = n_hdlc->tbuf;
	if (!tbuf)
		tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
		
	while (tbuf) {
		if (debuglevel >= DEBUG_LEVEL_INFO)	
			printk("%s(%d)sending frame %p, count=%d\n",
				__FILE__,__LINE__,tbuf,tbuf->count);
			
		/* Send the next block of data to device */
		tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
		actual = tty->ops->write(tty, tbuf->buf, tbuf->count);

		/* rollback was possible and has been done */
		if (actual == -ERESTARTSYS) {
			n_hdlc->tbuf = tbuf;
			break;
		}
		/* if transmit error, throw frame away by */
		/* pretending it was accepted by driver */
		if (actual < 0)
			actual = tbuf->count;
		
		if (actual == tbuf->count) {
			if (debuglevel >= DEBUG_LEVEL_INFO)	
				printk("%s(%d)frame %p completed\n",
					__FILE__,__LINE__,tbuf);
					
			/* free current transmit buffer */
			n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf);
			
			/* this tx buffer is done */
			n_hdlc->tbuf = NULL;
			
			/* wait up sleeping writers */
			wake_up_interruptible(&tty->write_wait);
	
			/* get next pending transmit buffer */
			tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
		} else {
			if (debuglevel >= DEBUG_LEVEL_INFO)	
				printk("%s(%d)frame %p pending\n",
					__FILE__,__LINE__,tbuf);
					
			/* buffer not accepted by driver */
			/* set this buffer as pending buffer */
			n_hdlc->tbuf = tbuf;
			break;
		}
	}
	
	if (!tbuf)
		tty->flags  &= ~(1 << TTY_DO_WRITE_WAKEUP);
	
	/* Clear the re-entry flag */
	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
	n_hdlc->tbusy = 0;
	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); 
	
        if (n_hdlc->woke_up)
	  goto check_again;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_send_frames() exit\n",__FILE__,__LINE__);
		
}	/* end of n_hdlc_send_frames() */
Esempio n. 14
0
/* n_hdlc_tty_write()
 * 
 * 	write a single frame of data to device
 * 	
 * Arguments:	tty	pointer to associated tty device instance data
 * 		file	pointer to file object data
 * 		data	pointer to transmit data (one frame)
 * 		count	size of transmit frame in bytes
 * 		
 * Return Value:	number of bytes written (or error code)
 */
static rw_ret_t n_hdlc_tty_write (struct tty_struct *tty, struct file *file,
	const __u8 * data, rw_count_t count)
{
	struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
	int error = 0;
	DECLARE_WAITQUEUE(wait, current);
	N_HDLC_BUF *tbuf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_tty_write() called count=%d\n",
			__FILE__,__LINE__,count);
		
	/* Verify pointers */
	if (!n_hdlc)
		return -EIO;

	if (n_hdlc->magic != HDLC_MAGIC)
		return -EIO;

	/* verify frame size */
	if (count > maxframe ) {
		if (debuglevel & DEBUG_LEVEL_INFO)
			printk (KERN_WARNING
				"n_hdlc_tty_write: truncating user packet "
				"from %lu to %d\n", (unsigned long) count,
				maxframe );
		count = maxframe;
	}
	
	add_wait_queue(&n_hdlc->write_wait, &wait);
	set_current_state(TASK_INTERRUPTIBLE);
	
	/* Allocate transmit buffer */
	/* sleep until transmit buffer available */		
	while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) {
		schedule();
			
		n_hdlc = tty2n_hdlc (tty);
		if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || 
		    tty != n_hdlc->tty) {
			printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc);
			error = -EIO;
			break;
		}
			
		if (signal_pending(current)) {
			error = -EINTR;
			break;
		}
	}

	set_current_state(TASK_RUNNING);
	remove_wait_queue(&n_hdlc->write_wait, &wait);

	if (!error) {		
		/* Retrieve the user's buffer */
		COPY_FROM_USER (error, tbuf->buf, data, count);
		if (error) {
			/* return tx buffer to free list */
			n_hdlc_buf_put(&n_hdlc->tx_free_buf_list,tbuf);
		} else {
			/* Send the data */
			tbuf->count = error = count;
			n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
			n_hdlc_send_frames(n_hdlc,tty);
		}
	}

	return error;
	
}	/* end of n_hdlc_tty_write() */
Esempio n. 15
0
static ssize_t vl_sync_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	struct vl_sync_port *port = (struct vl_sync_port *)filp->private_data;
        struct vl_sync_port *paired_port = port->paired_port;
	register struct n_hdlc *n_hdlc = NULL;
        register struct n_hdlc_buf *tbuf;
	int error = 0;
	DECLARE_WAITQUEUE(wait, current);

	/* Verify pointers */
        if (!port)
		return -ENODEV;

        if (!paired_port || !IS_OPEN(port))
                return -EINVAL;

        n_hdlc = paired_port->n_hdlc;
        
	if ((!n_hdlc) || (n_hdlc->magic != HDLC_MAGIC))
		return -EIO;

        	/* verify frame size */
	if (count > MAX_HDLC_FRAME_SIZE ) {
		pr_err("vl_sync_write: truncating user packet "
				"from %lu to %d\n", (unsigned long) count,
				MAX_HDLC_FRAME_SIZE );
		count = MAX_HDLC_FRAME_SIZE;
	}

	add_wait_queue(&port->write_wait, &wait);
	set_current_state(TASK_INTERRUPTIBLE);

//Write the data buffer into the receive buffer for the paired port

	/* Allocate transmit buffer */
	/* sleep until transmit buffer available */
	while (!(tbuf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list))) {
		if (filp->f_flags & O_NONBLOCK) {
			error = -EAGAIN;
			break;
		}
		schedule();

		n_hdlc = paired_port->n_hdlc;
		if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ) {
			pr_err("vl_sync_write: %p invalid after wait!\n", n_hdlc);
			error = -EIO;
			break;
		}

		if (signal_pending(current)) {
			error = -EINTR;
			break;
		}
	}

	set_current_state(TASK_RUNNING);
	remove_wait_queue(&port->write_wait, &wait);

	if (!error) {
		/* Retrieve the user's buffer */
		if (copy_from_user(tbuf->buf, buf, count))
			error = -EFAULT;
		else {
			/* Send the data */
			tbuf->count = error = count;
			n_hdlc_buf_put(&n_hdlc->rx_buf_list,tbuf);
                        /* Wake up any blocked reads on paired port and perform async signalling */
                        wake_up_interruptible (&paired_port->read_wait);
                        if (paired_port->fasync_queue != NULL)
                                kill_fasync (&paired_port->fasync_queue, SIGIO, POLL_IN);
                }
        }
		
	return error;
}
Esempio n. 16
0
static ssize_t vl_sync_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	struct vl_sync_port *port = (struct vl_sync_port *)filp->private_data;
	struct n_hdlc *n_hdlc = port->n_hdlc;
	int ret;
	struct n_hdlc_buf *rbuf;

	pr_debug("%s(%d)vl_sync_read() called\n",__FILE__,__LINE__);

	/* Validate the pointers */
	if (!n_hdlc)
		return -EIO;

	/* verify user access to buffer */
	if (!access_ok(VERIFY_WRITE, buf, count)) {
		pr_err("%s(%d) vl_sync_read() can't verify user buffer\n",
                        __FILE__, __LINE__);
		return -EFAULT;
	}

	/*spin_lock_irqsave(&port->read_ctrl_lock, flags);*/

	for (;;) {
		rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
		if (rbuf)
			break;

		/* no data */
		pr_debug("%s(%d): no data to read\n", __FILE__, __LINE__);
		if (filp->f_flags & O_NONBLOCK) {
			return -EAGAIN;
		}

		interruptible_sleep_on (&port->read_wait);
		if (signal_pending(current)) {
			return -EINTR;
		}
	}

	if (rbuf->count > count)
		/* frame too large for caller's buffer (discard frame) */
		ret = -EOVERFLOW;
	else {
		/* Copy the data to the caller's buffer */
		if (copy_to_user(buf, rbuf->buf, rbuf->count))
			ret = -EFAULT;
		else
			ret = rbuf->count;
	}

	/* return HDLC buffer to free list unless the free list */
	/* count has exceeded the default value, in which case the */
	/* buffer is freed back to the OS to conserve memory */
	if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT)
		kfree(rbuf);
	else
		n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);

	// Wake up paired_port write wait queue
        if (port->paired_port && IS_OPEN(port->paired_port))
                /* wake up sleeping writers */
                wake_up_interruptible(&port->paired_port->write_wait);

	return ret;
}
Esempio n. 17
0
static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
{
	register int actual;
	unsigned long flags;
	struct n_hdlc_buf *tbuf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_send_frames() called\n",__FILE__,__LINE__);
 check_again:
		
 	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
	if (n_hdlc->tbusy) {
		n_hdlc->woke_up = 1;
 		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);
		return;
	}
	n_hdlc->tbusy = 1;
	n_hdlc->woke_up = 0;
	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);

	
	
		
	tbuf = n_hdlc->tbuf;
	if (!tbuf)
		tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
		
	while (tbuf) {
		if (debuglevel >= DEBUG_LEVEL_INFO)	
			printk("%s(%d)sending frame %p, count=%d\n",
				__FILE__,__LINE__,tbuf,tbuf->count);
			
		
		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
		actual = tty->ops->write(tty, tbuf->buf, tbuf->count);

		
		if (actual == -ERESTARTSYS) {
			n_hdlc->tbuf = tbuf;
			break;
		}
		
		
		if (actual < 0)
			actual = tbuf->count;
		
		if (actual == tbuf->count) {
			if (debuglevel >= DEBUG_LEVEL_INFO)	
				printk("%s(%d)frame %p completed\n",
					__FILE__,__LINE__,tbuf);
					
			
			n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf);
			
			
			n_hdlc->tbuf = NULL;
			
			
			wake_up_interruptible(&tty->write_wait);
	
			
			tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);
		} else {
			if (debuglevel >= DEBUG_LEVEL_INFO)	
				printk("%s(%d)frame %p pending\n",
					__FILE__,__LINE__,tbuf);
					
			
			
			n_hdlc->tbuf = tbuf;
			break;
		}
	}
	
	if (!tbuf)
		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
	
	
	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);
	n_hdlc->tbusy = 0;
	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); 
	
        if (n_hdlc->woke_up)
	  goto check_again;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_send_frames() exit\n",__FILE__,__LINE__);
		
}	
Esempio n. 18
0
/**
 * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
 * @tty - pointer to tty instance data
 * @file - pointer to open file object
 * @buf - pointer to returned data buffer
 * @nr - size of returned data buffer
 * 	
 * Returns the number of bytes returned or error code.
 */
static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
			   __u8 __user *buf, size_t nr)
{
	struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
	int ret;
	struct n_hdlc_buf *rbuf;

	if (debuglevel >= DEBUG_LEVEL_INFO)	
		printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__);
		
	/* Validate the pointers */
	if (!n_hdlc)
		return -EIO;

	/* verify user access to buffer */
	if (!access_ok(VERIFY_WRITE, buf, nr)) {
		printk(KERN_WARNING "%s(%d) n_hdlc_tty_read() can't verify user "
		"buffer\n", __FILE__, __LINE__);
		return -EFAULT;
	}

	tty_lock();

	for (;;) {
		if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
			tty_unlock();
			return -EIO;
		}

		n_hdlc = tty2n_hdlc (tty);
		if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
			 tty != n_hdlc->tty) {
			tty_unlock();
			return 0;
		}

		rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
		if (rbuf)
			break;
			
		/* no data */
		if (file->f_flags & O_NONBLOCK) {
			tty_unlock();
			return -EAGAIN;
		}
			
		interruptible_sleep_on (&tty->read_wait);
		if (signal_pending(current)) {
			tty_unlock();
			return -EINTR;
		}
	}
		
	if (rbuf->count > nr)
		/* frame too large for caller's buffer (discard frame) */
		ret = -EOVERFLOW;
	else {
		/* Copy the data to the caller's buffer */
		if (copy_to_user(buf, rbuf->buf, rbuf->count))
			ret = -EFAULT;
		else
			ret = rbuf->count;
	}
	
	/* return HDLC buffer to free list unless the free list */
	/* count has exceeded the default value, in which case the */
	/* buffer is freed back to the OS to conserve memory */
	if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT)
		kfree(rbuf);
	else	
		n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
	tty_unlock();
	return ret;
	
}	/* end of n_hdlc_tty_read() */