Esempio n. 1
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",
        ;

    /* 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) {
            ;
            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. 2
0
static ssize_t thp_read(struct file *filp, char *buf, size_t count, loff_t*ppos)
{
	DECLARE_WAITQUEUE(wait, current);

	struct sk_buff_head *head = &to_sqntool_queue;
	struct sk_buff *curr = NULL;
	ssize_t retval;
	const struct sqn_thp_header *th = 0;

	sqn_pr_enter();
#if THP_DEBUG
	printk(KERN_WARNING "thp_read +\n");
#endif

	add_wait_queue(&to_sqntool_wait, &wait);
	retval = -ERESTARTSYS;

	if(0 == this_device) {
		printk(KERN_WARNING "thp_read() device removed\n");
		retval = -EINVAL;
		goto out;
	}

	while(1)
	{
		if(!skb_queue_empty(head))
			break;
		if(signal_pending(current) || 0 == this_device) {
			printk(KERN_WARNING "thp_read() interrupted by signal\n");
			retval = -EINTR;
			goto out;
		}
		set_current_state(TASK_INTERRUPTIBLE);
		schedule();
	}
	curr = skb_dequeue(head);

	if (count < curr->len) {
		printk(KERN_WARNING "%s: userspace buffer is too small (%u bytes)"
			" to hold THP packet (%u bytes)\n"
			, __func__, count, curr->len);
		retval = -EINVAL;
		goto free_skb;
	} else {
		count =  curr->len;
	}

	if(copy_to_user(buf, curr->data, count))
	{
		printk(KERN_ERR "error copying data to user space\n");
		retval = -EFAULT;
		goto free_skb;
	}

    if (mmc_wimax_get_thp_log()) {
        sqn_pr_info("%s: [to_user]: len = %d\n", __func__, count);
        th = (struct sqn_thp_header *) curr->data;
        sqn_pr_info("%s:  PKTLen: %4u | TVer: 0x0%x | Flags: 0x0%x | Len: %4u"
    		" | SeqNum: %5u | AckNum: %5u | TLen: %5u\n", __func__
    		, count
    		, th->transport_version
    		, th->flags
    		, be16_to_cpu(th->length)
    		, be16_to_cpu(th->seq_number)
    		, be16_to_cpu(th->ack_number)
    		, be32_to_cpu(th->total_length));
        sqn_pr_dbg_dump("THP RX:", curr->data, count);
    }

#if SKB_DEBUG
    sqn_pr_info("%s: free skb [0x%p], users %d\n", __func__, curr, atomic_read(&curr->users));
#endif

    retval = (ssize_t)count;
free_skb:

    dev_kfree_skb_any(curr);

out:
	set_current_state(TASK_RUNNING);
	remove_wait_queue(&to_sqntool_wait, &wait);

#if THP_DEBUG
	printk(KERN_WARNING "thp_read -\n");
#endif
	sqn_pr_leave();

	return retval;
}
Esempio n. 3
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)
        ;

    /* 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 "
        ;
        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() */