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        IRDA_DEBUG(1, "%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        IRDA_DEBUG(2, "%s()\n", __func__);
  81
  82        sirdev_set_dtr_rts(dev, TRUE, TRUE);
  83
  84        qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
  85        qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */      
  86        irda_qos_bits_to_value(qos);
  87
  88        /* irda thread waits 50 msec for power settling */
  89
  90        return 0;
  91}
  92
  93static int tekram_close(struct sir_dev *dev)
  94{
  95        IRDA_DEBUG(2, "%s()\n", __func__);
  96
  97        /* Power off dongle */
  98        sirdev_set_dtr_rts(dev, FALSE, FALSE);
  99
 100        return 0;
 101}
 102
 103/*
 104 * Function tekram_change_speed (dev, state, speed)
 105 *
 106 *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this 
 107 *    function must be called with a process context!
 108 *
 109 *    Algorithm
 110 *    1. clear DTR 
 111 *    2. set RTS, and wait at least 7 us
 112 *    3. send Control Byte to the IR-210 through TXD to set new baud rate
 113 *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
 114 *       it takes about 100 msec)
 115 *
 116 *      [oops, why 100 msec? sending 1 byte (10 bits) takes 1.05 msec
 117 *       - is this probably to compensate for delays in tty layer?]
 118 *
 119 *    5. clear RTS (return to NORMAL Operation)
 120 *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
 121 *       after
 122 */
 123
 124#define TEKRAM_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
 125
 126static int tekram_change_speed(struct sir_dev *dev, unsigned speed)
 127{
 128        unsigned state = dev->fsm.substate;
 129        unsigned delay = 0;
 130        u8 byte;
 131        static int ret = 0;
 132        
 133        IRDA_DEBUG(2, "%s()\n", __func__);
 134
 135        switch(state) {
 136        case SIRDEV_STATE_DONGLE_SPEED:
 137
 138                switch (speed) {
 139                default:
 140                        speed = 9600;
 141                        ret = -EINVAL;
 142                        /* fall thru */
 143                case 9600:
 144                        byte = TEKRAM_PW|TEKRAM_9600;
 145                        break;
 146                case 19200:
 147                        byte = TEKRAM_PW|TEKRAM_19200;
 148                        break;
 149                case 38400:
 150                        byte = TEKRAM_PW|TEKRAM_38400;
 151                        break;
 152                case 57600:
 153                        byte = TEKRAM_PW|TEKRAM_57600;
 154                        break;
 155                case 115200:
 156                        byte = TEKRAM_115200;
 157                        break;
 158                }
 159
 160                /* Set DTR, Clear RTS */
 161                sirdev_set_dtr_rts(dev, TRUE, FALSE);
 162        
 163                /* Wait at least 7us */
 164                udelay(14);
 165
 166                /* Write control byte */
 167                sirdev_raw_write(dev, &byte, 1);
 168                
 169                dev->speed = speed;
 170
 171                state = TEKRAM_STATE_WAIT_SPEED;
 172                delay = tekram_delay;
 173                break;
 174
 175        case TEKRAM_STATE_WAIT_SPEED:
 176                /* Set DTR, Set RTS */
 177                sirdev_set_dtr_rts(dev, TRUE, TRUE);
 178                udelay(50);
 179                break;
 180
 181        default:
 182                IRDA_ERROR("%s - undefined state %d\n", __func__, state);
 183                ret = -EINVAL;
 184                break;
 185        }
 186
 187        dev->fsm.substate = state;
 188        return (delay > 0) ? delay : ret;
 189}
 190
 191/*
 192 * Function tekram_reset (driver)
 193 *
 194 *      This function resets the tekram dongle. Warning, this function 
 195 *      must be called with a process context!! 
 196 *
 197 *      Algorithm:
 198 *        0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 )
 199 *        1. clear RTS 
 200 *        2. set DTR, and wait at least 1 ms 
 201 *        3. clear DTR to SPACE state, wait at least 50 us for further 
 202 *         operation
 203 */
 204
 205static int tekram_reset(struct sir_dev *dev)
 206{
 207        IRDA_DEBUG(2, "%s()\n", __func__);
 208
 209        /* Clear DTR, Set RTS */
 210        sirdev_set_dtr_rts(dev, FALSE, TRUE); 
 211
 212        /* Should sleep 1 ms */
 213        msleep(1);
 214
 215        /* Set DTR, Set RTS */
 216        sirdev_set_dtr_rts(dev, TRUE, TRUE);
 217        
 218        /* Wait at least 50 us */
 219        udelay(75);
 220
 221        dev->speed = 9600;
 222
 223        return 0;
 224}
 225
 226MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 227MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
 228MODULE_LICENSE("GPL");
 229MODULE_ALIAS("irda-dongle-0"); /* IRDA_TEKRAM_DONGLE */
 230                
 231module_init(tekram_sir_init);
 232module_exit(tekram_sir_cleanup);
 233