!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/drivers/net/irda/   drwxr-xr-x
Free 318.38 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     irtty.c (26.14 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*********************************************************************
 *                
 * Filename:      irtty.c
 * Version:       1.1
 * Description:   IrDA line discipline implementation
 * Status:        Experimental.
 * Author:        Dag Brattli <dagb@cs.uit.no>
 * Created at:    Tue Dec  9 21:18:38 1997
 * Modified at:   Sat Mar 11 07:43:30 2000
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
 * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
 *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
 * 
 *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
 *      
 *     This program is free software; you can redistribute it and/or 
 *     modify it under the terms of the GNU General Public License as 
 *     published by the Free Software Foundation; either version 2 of 
 *     the License, or (at your option) any later version.
 *  
 *     Neither Dag Brattli nor University of Tromsų admit liability nor
 *     provide warranty for any of this software. This material is 
 *     provided "AS-IS" and at no charge.
 *     
 ********************************************************************/    

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>

#include <asm/segment.h>
#include <asm/uaccess.h>

#include <net/irda/irda.h>
#include <net/irda/irtty.h>
#include <net/irda/wrapper.h>
#include <net/irda/timer.h>
#include <net/irda/irda_device.h>

static hashbin_t *irtty = NULL;
static struct tty_ldisc irda_ldisc;

static int qos_mtt_bits = 0x03;      /* 5 ms or more */

/* Network device fuction prototypes */
static int  irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev);
static int  irtty_net_init(struct net_device *dev);
static int  irtty_net_open(struct net_device *dev);
static int  irtty_net_close(struct net_device *dev);
static int  irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static struct net_device_stats *irtty_net_get_stats(struct net_device *dev);

/* Line discipline function prototypes */
static int  irtty_open(struct tty_struct *tty);
static void irtty_close(struct tty_struct *tty);
static int  irtty_ioctl(struct tty_struct *, void *, int, void *);
static int  irtty_receive_room(struct tty_struct *tty);
static void irtty_write_wakeup(struct tty_struct *tty);
static void irtty_receive_buf(struct tty_struct *, const unsigned char *, 
                  char *, int);

/* IrDA specific function protoctypes */
static int  irtty_is_receiving(struct irtty_cb *self);
static int  irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts);
static int  irtty_raw_write(struct net_device *dev, __u8 *buf, int len);
static int  irtty_raw_read(struct net_device *dev, __u8 *buf, int len);
static int  irtty_set_mode(struct net_device *dev, int mode);
static int  irtty_change_speed(struct irda_task *task);

char *driver_name = "irtty";

int __init irtty_init(void)
{
    int status;
    
    irtty = hashbin_new( HB_LOCAL);
    if ( irtty == NULL) {
        printk( KERN_WARNING "IrDA: Can't allocate irtty hashbin!\n");
        return -ENOMEM;
    }

    /* Fill in our line protocol discipline, and register it */
    memset(&irda_ldisc, 0, sizeof( irda_ldisc));

    irda_ldisc.magic = TTY_LDISC_MAGIC;
     irda_ldisc.name  = "irda";
    irda_ldisc.flags = 0;
    irda_ldisc.open  = irtty_open;
    irda_ldisc.close = irtty_close;
    irda_ldisc.read  = NULL;
    irda_ldisc.write = NULL;
    irda_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
                    unsigned int, unsigned long)) irtty_ioctl;
     irda_ldisc.poll  = NULL;
    irda_ldisc.receive_buf  = irtty_receive_buf;
    irda_ldisc.receive_room = irtty_receive_room;
    irda_ldisc.write_wakeup = irtty_write_wakeup;
    
    if ((status = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0) {
        ERROR("IrDA: can't register line discipline (err = %d)\n", 
              status);
    }
    
    return status;
}

/* 
 *  Function irtty_cleanup ( )
 *
 *    Called when the irda module is removed. Here we remove all instances
 *    of the driver, and the master array.
 */
#ifdef MODULE
static void irtty_cleanup(void) 
{
    int ret;
    
    /* Unregister tty line-discipline */
    if ((ret = tty_register_ldisc(N_IRDA, NULL))) {
        ERROR(__FUNCTION__ 
              "(), can't unregister line discipline (err = %d)\n",
              ret);
    }

    /*
     *  The TTY should care of deallocating the instances by using the
     *  callback to irtty_close(), therefore we do give any deallocation
     *  function to hashbin_destroy().
     */
    hashbin_delete(irtty, NULL);
}
#endif /* MODULE */

/* 
 *  Function irtty_open(tty)
 *
 *    This function is called by the TTY module when the IrDA line
 *    discipline is called for.  Because we are sure the tty line exists,
 *    we only have to link it to a free IrDA channel.  
 */
static int irtty_open(struct tty_struct *tty) 
{
    struct net_device *dev;
    struct irtty_cb *self;
    char name[16];
    int err;
    
    ASSERT(tty != NULL, return -EEXIST;);

    /* First make sure we're not already connected. */
    self = (struct irtty_cb *) tty->disc_data;

    if (self != NULL && self->magic == IRTTY_MAGIC)
        return -EEXIST;
    
    /*
     *  Allocate new instance of the driver
     */
    self = kmalloc(sizeof(struct irtty_cb), GFP_KERNEL);
    if (self == NULL) {
        printk(KERN_ERR "IrDA: Can't allocate memory for "
               "IrDA control block!\n");
        return -ENOMEM;
    }
    memset(self, 0, sizeof(struct irtty_cb));
    
    self->tty = tty;
    tty->disc_data = self;

    /* Give self a name */
    sprintf(name, "%s%d", tty->driver.name,
        MINOR(tty->device) - tty->driver.minor_start +
        tty->driver.name_base);

    hashbin_insert(irtty, (irda_queue_t *) self, (int) self, NULL);

    if (tty->driver.flush_buffer)
        tty->driver.flush_buffer(tty);
    
    if (tty->ldisc.flush_buffer)
        tty->ldisc.flush_buffer(tty);
    
    self->magic = IRTTY_MAGIC;
    self->mode = IRDA_IRLAP;

    /* 
     *  Initialize QoS capabilities, we fill in all the stuff that
     *  we support. Be careful not to place any restrictions on values
     *  that are not device dependent (such as link disconnect time) so
     *  this parameter can be set by IrLAP (or the user) instead. DB
     */
    irda_init_max_qos_capabilies(&self->qos);

    /* The only value we must override it the baudrate */
    self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
        IR_115200;
    self->qos.min_turn_time.bits = qos_mtt_bits;
    self->flags = IFF_SIR | IFF_PIO;
    irda_qos_bits_to_value(&self->qos);

    /* Specify how much memory we want */
    self->rx_buff.truesize = 4000; 
    self->tx_buff.truesize = 4000;

    /* Allocate memory if needed */
    if (self->rx_buff.truesize > 0) {
        self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
                              GFP_KERNEL);
        if (self->rx_buff.head == NULL)
            return -ENOMEM;
        memset(self->rx_buff.head, 0, self->rx_buff.truesize);
    }
    if (self->tx_buff.truesize > 0) {
        self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, 
                              GFP_KERNEL);
        if (self->tx_buff.head == NULL) {
            kfree(self->rx_buff.head);
            return -ENOMEM;
        }
        memset(self->tx_buff.head, 0, self->tx_buff.truesize);
    }
    
    self->rx_buff.in_frame = FALSE;
    self->rx_buff.state = OUTSIDE_FRAME;
    self->tx_buff.data = self->tx_buff.head;
    self->rx_buff.data = self->rx_buff.head;
    
    if (!(dev = dev_alloc("irda%d", &err))) {
        ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
        return -ENOMEM;
    }

    dev->priv = (void *) self;
    self->netdev = dev;

    /* Override the network functions we need to use */
    dev->init            = irtty_net_init;
    dev->hard_start_xmit = irtty_hard_xmit;
    dev->open            = irtty_net_open;
    dev->stop            = irtty_net_close;
    dev->get_stats         = irtty_net_get_stats;
    dev->do_ioctl        = irtty_net_ioctl;

    rtnl_lock();
    err = register_netdevice(dev);
    rtnl_unlock();
    if (err) {
        ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
        return -1;
    }

    MESSAGE("IrDA: Registered device %s\n", dev->name);

    MOD_INC_USE_COUNT;

    return 0;
}

/* 
 *  Function irtty_close (tty)
 *
 *    Close down a IrDA channel. This means flushing out any pending queues,
 *    and then restoring the TTY line discipline to what it was before it got
 *    hooked to IrDA (which usually is TTY again).  
 */
static void irtty_close(struct tty_struct *tty) 
{
    struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
    
    /* First make sure we're connected. */
    ASSERT(self != NULL, return;);
    ASSERT(self->magic == IRTTY_MAGIC, return;);
    
    /* Stop tty */
    tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
    tty->disc_data = 0;
    
    /* We are not using any dongle anymore! */
    if (self->dongle)
        irda_device_dongle_cleanup(self->dongle);
    self->dongle = NULL;

    /* Remove netdevice */
    if (self->netdev) {
        rtnl_lock();
        unregister_netdevice(self->netdev);
        rtnl_unlock();
    }
    
    /* Remove speed changing task if any */
    if (self->task)
        irda_task_delete(self->task);

    self->tty = NULL;
    self->magic = 0;
    
    self = hashbin_remove(irtty, (int) self, NULL);

    if (self->tx_buff.head)
        kfree(self->tx_buff.head);
    
    if (self->rx_buff.head)
        kfree(self->rx_buff.head);
    
    kfree(self);
    
     MOD_DEC_USE_COUNT;
}

/*
 * Function irtty_stop_receiver (self, stop)
 *
 *    
 *
 */
static void irtty_stop_receiver(struct irtty_cb *self, int stop)
{
    struct termios old_termios;
    int cflag;

    old_termios = *(self->tty->termios);
    cflag = self->tty->termios->c_cflag;
    
    if (stop)
        cflag &= ~CREAD;
    else
        cflag |= CREAD;

    self->tty->termios->c_cflag = cflag;
    self->tty->driver.set_termios(self->tty, &old_termios);
}

/* 
 *  Function irtty_do_change_speed (self, speed)
 *
 *    Change the speed of the serial port.
 */
static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
{
        struct termios old_termios;
    int cflag;

    ASSERT(self != NULL, return;);
    ASSERT(self->magic == IRTTY_MAGIC, return;);

    old_termios = *(self->tty->termios);
    cflag = self->tty->termios->c_cflag;

    cflag &= ~CBAUD;

    IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to %d\n", speed);

    switch (speed) {
    case 1200:
        cflag |= B1200;
        break;
    case 2400:
        cflag |= B2400;
        break;
    case 4800:
        cflag |= B4800;
        break;
    case 19200:
        cflag |= B19200;
        break;
    case 38400:
        cflag |= B38400;
        break;
    case 57600:
        cflag |= B57600;
        break;
    case 115200:
        cflag |= B115200;
        break;
    case 9600:
    default:
        cflag |= B9600;
        break;
    }    

    self->tty->termios->c_cflag = cflag;
    self->tty->driver.set_termios(self->tty, &old_termios);

    self->io.speed = speed;
}

/*
 * Function irtty_change_speed (instance, state, param)
 *
 *    State machine for changing speed of the device. We do it this way since
 *    we cannot use schedule_timeout() when we are in interrupt context
 */
static int irtty_change_speed(struct irda_task *task)
{
    struct irtty_cb *self;
    __u32 speed = (__u32) task->param;
    int ret = 0;

    IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); 

    self = (struct irtty_cb *) task->instance;
    ASSERT(self != NULL, return -1;);

    /* Check if busy */
    if (self->task && self->task != task) {
        IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
        return MSECS_TO_JIFFIES(10);
    } else
        self->task = task;

    switch (task->state) {
    case IRDA_TASK_INIT:
        /* 
         * Make sure all data is sent before changing the speed of the
         * serial port.
         */
        if (self->tty->driver.chars_in_buffer(self->tty)) {
            /* Keep state, and try again later */
            ret = MSECS_TO_JIFFIES(10);
            break;
        } else {
            /* Transmit buffer is now empty, but it may still
             * take over 13 ms for the FIFO to become empty, so
             * wait some more to be sure all data is sent
             */
            irda_task_next_state(task, IRDA_TASK_WAIT);
            ret = MSECS_TO_JIFFIES(13);
        }
    case IRDA_TASK_WAIT:
        if (self->dongle)
            irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
        else
            irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
        break;
    case IRDA_TASK_CHILD_INIT:
        /* Go to default speed */
        __irtty_change_speed(self, 9600);

        /* Change speed of dongle */
        if (irda_task_execute(self->dongle,
                      self->dongle->issue->change_speed, 
                      NULL, task, (void *) speed))
        {
            /* Dongle need more time to change its speed */
            irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);

            /* Give dongle 1 sec to finish */
            ret = MSECS_TO_JIFFIES(1000);
        } else
            /* Child finished immediately */
            irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
        break;
    case IRDA_TASK_CHILD_WAIT:
        WARNING(__FUNCTION__ 
            "(), changing speed of dongle timed out!\n");
        ret = -1;        
        break;
    case IRDA_TASK_CHILD_DONE:
        /* Finally we are ready to change the speed */
        __irtty_change_speed(self, speed);
        
        irda_task_next_state(task, IRDA_TASK_DONE);
        self->task = NULL;
        break;
    default:
        ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
        irda_task_next_state(task, IRDA_TASK_DONE);
        self->task = NULL;
        ret = -1;
        break;
    }    
    return ret;
}

/*
 * Function irtty_ioctl (tty, file, cmd, arg)
 *
 *     The Swiss army knife of system calls :-)
 *
 */
static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
{
    dongle_t *dongle;
    struct irtty_info info;
    struct irtty_cb *self;
    int size = _IOC_SIZE(cmd);
    int err = 0;

    self = (struct irtty_cb *) tty->disc_data;

    ASSERT(self != NULL, return -ENODEV;);
    ASSERT(self->magic == IRTTY_MAGIC, return -EBADR;);

    if (_IOC_DIR(cmd) & _IOC_READ)
        err = verify_area(VERIFY_WRITE, (void *) arg, size);
    else if (_IOC_DIR(cmd) & _IOC_WRITE)
        err = verify_area(VERIFY_READ, (void *) arg, size);
    if (err)
        return err;
    
    switch (cmd) {
    case TCGETS:
    case TCGETA:
        return n_tty_ioctl(tty, (struct file *) file, cmd, 
                   (unsigned long) arg);
        break;
    case IRTTY_IOCTDONGLE:
        /* Initialize dongle */
        dongle = irda_device_dongle_init(self->netdev, (int) arg);
        if (!dongle)
            break;
        
        /* Initialize callbacks */
        dongle->set_mode    = irtty_set_mode;
        dongle->read        = irtty_raw_read;
        dongle->write       = irtty_raw_write;
        dongle->set_dtr_rts = irtty_set_dtr_rts;
        
        /* Bind dongle */
        self->dongle = dongle;
        
        /* Now initialize the dongle!  */
        dongle->issue->open(dongle, &self->qos);
        
        /* Reset dongle */
        irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
                  NULL);        
        break;
    case IRTTY_IOCGET:
        ASSERT(self->netdev != NULL, return -1;);

        memset(&info, 0, sizeof(struct irtty_info)); 
        strncpy(info.name, self->netdev->name, 5);

        if (copy_to_user(arg, &info, sizeof(struct irtty_info)))
            return -EFAULT;
        break;
    default:
        return -ENOIOCTLCMD;
    }
    return 0;
}

/* 
 *  Function irtty_receive_buf( tty, cp, count)
 *
 *    Handle the 'receiver data ready' interrupt.  This function is called
 *    by the 'tty_io' module in the kernel when a block of IrDA data has
 *    been received, which can now be decapsulated and delivered for
 *    further processing 
 */
static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                  char *fp, int count) 
{
    struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;

    if (!self || !self->netdev) {
        IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n");
        return;
    }

    /* Read the characters out of the buffer */
     while (count--) {
        /* 
         *  Characters received with a parity error, etc?
         */
         if (fp && *fp++) { 
            IRDA_DEBUG(0, "Framing or parity error!\n");
            irda_device_set_media_busy(self->netdev, TRUE);
            
             cp++;
             continue;
         }
        
        switch (self->mode) {
        case IRDA_IRLAP:
            /* Unwrap and destuff one byte */
            async_unwrap_char(self->netdev, &self->stats, 
                      &self->rx_buff, *cp++);
            break;
        case IRDA_RAW:
            /* What should we do when the buffer is full? */
            if (self->rx_buff.len == self->rx_buff.truesize)
                self->rx_buff.len = 0;
            
            self->rx_buff.data[self->rx_buff.len++] = *cp++;
            break;
        default:
            break;
        }
    }
}

/*
 * Function irtty_change_speed_complete (task)
 *
 *    Called when the change speed operation completes
 *
 */
static int irtty_change_speed_complete(struct irda_task *task)
{
    struct irtty_cb *self;

    IRDA_DEBUG(2, __FUNCTION__ "()\n");

    self = (struct irtty_cb *) task->instance;

    ASSERT(self != NULL, return -1;);
    ASSERT(self->netdev != NULL, return -1;);

    /* Finished changing speed, so we are not busy any longer */
    /* Signal network layer so it can try to send the frame */
    netif_wake_queue(self->netdev);
    
    return 0;
}

/*
 * Function irtty_hard_xmit (skb, dev)
 *
 *    Transmit frame
 *
 */
static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
    struct irtty_cb *self;
    int actual = 0;
    __s32 speed;

    self = (struct irtty_cb *) dev->priv;
    ASSERT(self != NULL, return 0;);

    /* Lock transmit buffer */
    netif_stop_queue(dev);
    
    /* Check if we need to change the speed */
    speed = irda_get_next_speed(skb);
    if ((speed != self->io.speed) && (speed != -1)) {
        /* Check for empty frame */
        if (!skb->len) {
            irda_task_execute(self, irtty_change_speed, 
                      irtty_change_speed_complete, 
                      NULL, (void *) speed);
            dev_kfree_skb(skb);
            return 0;
        } else
            self->new_speed = speed;
    }

    /* Init tx buffer*/
    self->tx_buff.data = self->tx_buff.head;
    
        /* Copy skb to tx_buff while wrapping, stuffing and making CRC */
        self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
                       self->tx_buff.truesize); 

    self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);

    dev->trans_start = jiffies;
    self->stats.tx_bytes += self->tx_buff.len;

    if (self->tty->driver.write)
        actual = self->tty->driver.write(self->tty, 0, 
                         self->tx_buff.data, 
                         self->tx_buff.len);
    /* Hide the part we just transmitted */
    self->tx_buff.data += actual;
    self->tx_buff.len -= actual;

    dev_kfree_skb(skb);

    return 0;
}

/*
 * Function irtty_receive_room (tty)
 *
 *    Used by the TTY to find out how much data we can receive at a time
 * 
*/
static int irtty_receive_room(struct tty_struct *tty) 
{
    IRDA_DEBUG(0, __FUNCTION__ "()\n");
    return 65536;  /* We can handle an infinite amount of data. :-) */
}

/*
 * Function irtty_write_wakeup (tty)
 *
 *    Called by the driver when there's room for more data.  If we have
 *    more packets to send, we send them here.
 *
 */
static void irtty_write_wakeup(struct tty_struct *tty) 
{
    struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
    int actual = 0;
    
    /* 
     *  First make sure we're connected. 
     */
    ASSERT(self != NULL, return;);
    ASSERT(self->magic == IRTTY_MAGIC, return;);

    /* Finished with frame?  */
    if (self->tx_buff.len > 0)  {
        /* Write data left in transmit buffer */
        actual = tty->driver.write(tty, 0, self->tx_buff.data, 
                       self->tx_buff.len);

        self->tx_buff.data += actual;
        self->tx_buff.len  -= actual;

        self->stats.tx_packets++;              
    } else {        
        /* 
         *  Now serial buffer is almost free & we can start 
         *  transmission of another packet 
         */
        IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
        
        tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);

        if (self->new_speed) {
            IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
            irda_task_execute(self, irtty_change_speed, 
                      irtty_change_speed_complete, 
                      NULL, (void *) self->new_speed);
            self->new_speed = 0;
        } else {
            /* Tell network layer that we want more frames */
            netif_wake_queue(self->netdev);
        }
    }
}

/*
 * Function irtty_is_receiving (self)
 *
 *    Return TRUE is we are currently receiving a frame
 *
 */
static int irtty_is_receiving(struct irtty_cb *self)
{
    return (self->rx_buff.state != OUTSIDE_FRAME);
}

/*
 * Function irtty_set_dtr_rts (tty, dtr, rts)
 *
 *    This function can be used by dongles etc. to set or reset the status
 *    of the dtr and rts lines
 */
static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
{
    struct irtty_cb *self;
    struct tty_struct *tty;
    mm_segment_t fs;
    int arg = 0;

    self = (struct irtty_cb *) dev->priv;
    tty = self->tty;

#ifdef TIOCM_OUT2 /* Not defined for ARM */
    arg = TIOCM_OUT2;
#endif
    if (rts)
        arg |= TIOCM_RTS;
    if (dtr)
        arg |= TIOCM_DTR;

    /*
     *  The ioctl() function, or actually set_modem_info() in serial.c
     *  expects a pointer to the argument in user space. To hack us
     *  around this, we use the set_fs() function to fool the routines 
     *  that check if they are called from user space. We also need 
     *  to send a pointer to the argument so get_user() gets happy. DB.
     */

    fs = get_fs();
    set_fs(get_ds());
    
    if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
        IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n");
    }
    set_fs(fs);

    return 0;
}

/*
 * Function irtty_set_mode (self, status)
 *
 *    For the airport dongle, we need support for reading raw characters
 *    from the IrDA device. This function switches between those modes. 
 *    FALSE is the default mode, and will then treat incoming data as IrDA 
 *    packets.
 */
int irtty_set_mode(struct net_device *dev, int mode)
{
    struct irtty_cb *self;

    self = (struct irtty_cb *) dev->priv;

    ASSERT(self != NULL, return -1;);

    IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]);
    
    /* save status for driver */
    self->mode = mode;
    
    /* reset the buffer state */
    self->rx_buff.data = self->rx_buff.head;
    self->rx_buff.len = 0;
    self->rx_buff.state = OUTSIDE_FRAME;

    return 0;
}

/*
 * Function irtty_raw_read (self, buf, len)
 *
 *    Receive incoming data. This function sleeps, so it must only be
 *    called with a process context. Timeout is currently defined to be
 *    a multiple of 10 ms.
 */
static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len)
{
    struct irtty_cb *self;
    int count;

    self = (struct irtty_cb *) dev->priv;

    ASSERT(self != NULL, return 0;);
    ASSERT(self->magic == IRTTY_MAGIC, return 0;);

    return 0;
#if 0
    buf = self->rx_buff.data;

    /* Wait for the requested amount of data to arrive */
    while (len < self->rx_buff.len) {
        current->state = TASK_INTERRUPTIBLE;
        schedule_timeout(MSECS_TO_JIFFIES(10));

        if (!timeout--)
            break;
    }
    
    count = self->rx_buff.len < len ? self->rx_buff.len : len;

    /* 
     * Reset the state, this mean that a raw read is sort of a 
     * datagram read, and _not_ a stream style read. Be aware of the
     * difference. Implementing it the other way will just be painful ;-)
     */
    self->rx_buff.data = self->rx_buff.head;
    self->rx_buff.len = 0;
    self->rx_buff.state = OUTSIDE_FRAME;
#endif
    /* Return the amount we were able to get */
    return count;
}

static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len)
{
    struct irtty_cb *self;
    int actual = 0;

    self = (struct irtty_cb *) dev->priv;

    ASSERT(self != NULL, return 0;);
    ASSERT(self->magic == IRTTY_MAGIC, return 0;);

    if (self->tty->driver.write)
        actual = self->tty->driver.write(self->tty, 0, buf, len);

    return actual;
}

static int irtty_net_init(struct net_device *dev)
{
    /* Set up to be a normal IrDA network device driver */
    irda_device_setup(dev);

    /* Insert overrides below this line! */

    return 0;
}

static int irtty_net_open(struct net_device *dev)
{
    struct irtty_cb *self = (struct irtty_cb *) dev->priv;
    struct tty_struct *tty = self->tty;
    char hwname[16];

    ASSERT(self != NULL, return -1;);
    ASSERT(self->magic == IRTTY_MAGIC, return -1;);

    IRDA_DEBUG(0, __FUNCTION__ "()\n");
    
    /* Ready to play! */
    netif_start_queue(dev);
    
    /* Make sure we can receive more data */
    irtty_stop_receiver(self, FALSE);

    /* Give self a hardware name */
    sprintf(hwname, "%s%d", tty->driver.name,
        MINOR(tty->device) - tty->driver.minor_start +
        tty->driver.name_base);

    /* 
     * Open new IrLAP layer instance, now that everything should be
     * initialized properly 
     */
    self->irlap = irlap_open(dev, &self->qos, hwname);

    MOD_INC_USE_COUNT;

    return 0;
}

static int irtty_net_close(struct net_device *dev)
{
    struct irtty_cb *self = (struct irtty_cb *) dev->priv;

    ASSERT(self != NULL, return -1;);
    ASSERT(self->magic == IRTTY_MAGIC, return -1;);

    /* Make sure we don't receive more data */
    irtty_stop_receiver(self, TRUE);

    /* Stop device */
    netif_stop_queue(dev);
    
    /* Stop and remove instance of IrLAP */
    if (self->irlap)
        irlap_close(self->irlap);
    self->irlap = NULL;

    MOD_DEC_USE_COUNT;

    return 0;
}

/*
 * Function irtty_net_ioctl (dev, rq, cmd)
 *
 *    Process IOCTL commands for this device
 *
 */
static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
    struct if_irda_req *irq = (struct if_irda_req *) rq;
    struct irtty_cb *self;
    dongle_t *dongle;
    unsigned long flags;
    int ret = 0;

    ASSERT(dev != NULL, return -1;);

    self = dev->priv;

    ASSERT(self != NULL, return -1;);
    ASSERT(self->magic == IRTTY_MAGIC, return -1;);

    IRDA_DEBUG(3, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
    
    /* Disable interrupts & save flags */
    save_flags(flags);
    cli();
    
    switch (cmd) {
    case SIOCSBANDWIDTH: /* Set bandwidth */
        if (!capable(CAP_NET_ADMIN))
            ret = -EPERM;
        else
            irda_task_execute(self, irtty_change_speed, NULL, NULL, 
                      (void *) irq->ifr_baudrate);
        break;
    case SIOCSDONGLE: /* Set dongle */
        if (!capable(CAP_NET_ADMIN)) {
            ret = -EPERM;
            break;
        }

        /* Initialize dongle */
        dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
        if (!dongle)
            break;
        
        dongle->set_mode    = irtty_set_mode;
        dongle->read        = irtty_raw_read;
        dongle->write       = irtty_raw_write;
        dongle->set_dtr_rts = irtty_set_dtr_rts;
        
        self->dongle = dongle;

        /* Now initialize the dongle!  */
        dongle->issue->open(dongle, &self->qos);
        
        /* Reset dongle */
        irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
                  NULL);    
        break;
    case SIOCSMEDIABUSY: /* Set media busy */
        if (!capable(CAP_NET_ADMIN))
            ret = -EPERM;
        else
            irda_device_set_media_busy(self->netdev, TRUE);
        break;
    case SIOCGRECEIVING: /* Check if we are receiving right now */
        irq->ifr_receiving = irtty_is_receiving(self);
        break;
    case SIOCSDTRRTS:
        if (!capable(CAP_NET_ADMIN))
            ret = -EPERM;
        else
            irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
        break;
    case SIOCSMODE:
        if (!capable(CAP_NET_ADMIN))
            ret = -EPERM;
        else
            irtty_set_mode(dev, irq->ifr_mode);
        break;
    default:
        ret = -EOPNOTSUPP;
    }
    
    restore_flags(flags);
    
    return ret;
}

static struct net_device_stats *irtty_net_get_stats(struct net_device *dev)
{
    struct irtty_cb *self = (struct irtty_cb *) dev->priv;

    return &self->stats;
}

#ifdef MODULE

MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("IrDA TTY device driver");
MODULE_LICENSE("GPL");


MODULE_PARM(qos_mtt_bits, "i");
MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");

/*
 * Function init_module (void)
 *
 *    Initialize IrTTY module
 *
 */
int init_module(void)
{
    return irtty_init();
}

/*
 * Function cleanup_module (void)
 *
 *    Cleanup IrTTY module
 *
 */
void cleanup_module(void)
{
    irtty_cleanup();
}

#endif /* MODULE */

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0318 ]--