linux/drivers/net/irda/tekram-sir.c
<<
>>
Prefs
   1/*********************************************************************
   2 *                
   3 * Filename:      tekram.c
   4 * Version:       1.3
   5 * Description:   Implementation of the Tekram IrMate IR-210B dongle
   6 * Status:        Experimental.
   7 * Author:        Dag Brattli <dagb@cs.uit.no>
   8 * Created at:    Wed Oct 21 20:02:35 1998
   9 * Modified at:   Sun Oct 27 22:02:38 2002
  10 * Modified by:   Martin Diehl <mad@mdiehl.de>
  11 * 
  12 *     Copyright (c) 1998-1999 Dag Brattli,
  13 *     Copyright (c) 2002 Martin Diehl,
  14 *     All Rights Reserved.
  15 *      
  16 *     This program is free software; you can redistribute it and/or 
  17 *     modify it under the terms of the GNU General Public License as 
  18 *     published by the Free Software Foundation; either version 2 of 
  19 *     the License, or (at your option) any later version.
  20 *  
  21 *     Neither Dag Brattli nor University of Tromsø admit liability nor
  22 *     provide warranty for any of this software. This material is 
  23 *     provided "AS-IS" and at no charge.
  24 *     
  25 ********************************************************************/
  26
  27#include <linux/module.h>
  28#include <linux/delay.h>
  29#include <linux/init.h>
  30
  31#include <net/irda/irda.h>
  32
  33#include "sir-dev.h"
  34
  35static int tekram_delay = 150;          /* default is 150 ms */
  36module_param(tekram_delay, int, 0);
  37MODULE_PARM_DESC(tekram_delay, "tekram dongle write complete delay");
  38
  39static int tekram_open(struct sir_dev *);
  40static int tekram_close(struct sir_dev *);
  41static int tekram_change_speed(struct sir_dev *, unsigned);
  42static int tekram_reset(struct sir_dev *);
  43
  44#define TEKRAM_115200 0x00
  45#define TEKRAM_57600  0x01
  46#define TEKRAM_38400  0x02
  47#define TEKRAM_19200  0x03
  48#define TEKRAM_9600   0x04
  49
  50#define TEKRAM_PW     0x10 /* Pulse select bit */
  51
  52static struct dongle_driver tekram = {
  53        .owner          = THIS_MODULE,
  54        .driver_name    = "Tekram IR-210B",
  55        .type           = IRDA_TEKRAM_DONGLE,
  56        .open           = tekram_open,
  57        .close          = tekram_close,
  58        .reset          = tekram_reset,
  59        .set_speed      = tekram_change_speed,
  60};
  61
  62static int __init tekram_sir_init(void)
  63{
  64        if (tekram_delay < 1  ||  tekram_delay > 500)
  65                tekram_delay = 200;
  66        pr_debug("%s - using %d ms delay\n",
  67                 tekram.driver_name, tekram_delay);
  68        return irda_register_dongle(&tekram);
  69}
  70
  71static void __exit tekram_sir_cleanup(void)
  72{
  73        irda_unregister_dongle(&tekram);
  74}
  75
  76static int tekram_open(struct sir_dev *dev)
  77{
  78        struct qos_info *qos = &dev->qos;
  79
  80        sirdev_set_dtr_rts(dev, TRUE, TRUE);
  81
  82        qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
  83        qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */      
  84        irda_qos_bits_to_value(qos);
  85
  86        /* irda thread waits 50 msec for power settling */
  87
  88        return 0;
  89}
  90
  91static int tekram_close(struct sir_dev *dev)
  92{
  93        /* Power off dongle */
  94        sirdev_set_dtr_rts(dev, FALSE, FALSE);
  95
  96        return 0;
  97}
  98
  99/*
 100 * Function tekram_change_speed (dev, state, speed)
 101 *
 102 *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this 
 103 *    function must be called with a process context!
 104 *
 105 *    Algorithm
 106 *    1. clear DTR 
 107 *    2. set RTS, and wait at least 7 us
 108 *    3. send Control Byte to the IR-210 through TXD to set new baud rate
 109 *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
 110 *       it takes about 100 msec)
 111 *
 112 *      [oops, why 100 msec? sending 1 byte (10 bits) takes 1.05 msec
 113 *       - is this probably to compensate for delays in tty layer?]
 114 *
 115 *    5. clear RTS (return to NORMAL Operation)
 116 *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
 117 *       after
 118 */
 119
 120#define TEKRAM_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
 121
 122static int tekram_change_speed(struct sir_dev *dev, unsigned speed)
 123{
 124        unsigned state = dev->fsm.substate;
 125        unsigned delay = 0;
 126        u8 byte;
 127        static int ret = 0;
 128        
 129        switch(state) {
 130        case SIRDEV_STATE_DONGLE_SPEED:
 131
 132                switch (speed) {
 133                default:
 134                        speed = 9600;
 135                        ret = -EINVAL;
 136                        /* fall thru */
 137                case 9600:
 138                        byte = TEKRAM_PW|TEKRAM_9600;
 139                        break;
 140                case 19200:
 141                        byte = TEKRAM_PW|TEKRAM_19200;
 142                        break;
 143                case 38400:
 144                        byte = TEKRAM_PW|TEKRAM_38400;
 145                        break;
 146                case 57600:
 147                        byte = TEKRAM_PW|TEKRAM_57600;
 148                        break;
 149                case 115200:
 150                        byte = TEKRAM_115200;
 151                        break;
 152                }
 153
 154                /* Set DTR, Clear RTS */
 155                sirdev_set_dtr_rts(dev, TRUE, FALSE);
 156        
 157                /* Wait at least 7us */
 158                udelay(14);
 159
 160                /* Write control byte */
 161                sirdev_raw_write(dev, &byte, 1);
 162                
 163                dev->speed = speed;
 164
 165                state = TEKRAM_STATE_WAIT_SPEED;
 166                delay = tekram_delay;
 167                break;
 168
 169        case TEKRAM_STATE_WAIT_SPEED:
 170                /* Set DTR, Set RTS */
 171                sirdev_set_dtr_rts(dev, TRUE, TRUE);
 172                udelay(50);
 173                break;
 174
 175        default:
 176                net_err_ratelimited("%s - undefined state %d\n",
 177                                    __func__, state);
 178                ret = -EINVAL;
 179                break;
 180        }
 181
 182        dev->fsm.substate = state;
 183        return (delay > 0) ? delay : ret;
 184}
 185
 186/*
 187 * Function tekram_reset (driver)
 188 *
 189 *      This function resets the tekram dongle. Warning, this function 
 190 *      must be called with a process context!! 
 191 *
 192 *      Algorithm:
 193 *        0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 )
 194 *        1. clear RTS 
 195 *        2. set DTR, and wait at least 1 ms 
 196 *        3. clear DTR to SPACE state, wait at least 50 us for further 
 197 *         operation
 198 */
 199
 200static int tekram_reset(struct sir_dev *dev)
 201{
 202        /* Clear DTR, Set RTS */
 203        sirdev_set_dtr_rts(dev, FALSE, TRUE); 
 204
 205        /* Should sleep 1 ms */
 206        msleep(1);
 207
 208        /* Set DTR, Set RTS */
 209        sirdev_set_dtr_rts(dev, TRUE, TRUE);
 210        
 211        /* Wait at least 50 us */
 212        udelay(75);
 213
 214        dev->speed = 9600;
 215
 216        return 0;
 217}
 218
 219MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 220MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
 221MODULE_LICENSE("GPL");
 222MODULE_ALIAS("irda-dongle-0"); /* IRDA_TEKRAM_DONGLE */
 223                
 224module_init(tekram_sir_init);
 225module_exit(tekram_sir_cleanup);
 226