linux/drivers/net/irda/girbil-sir.c
<<
>>
Prefs
   1/*********************************************************************
   2 *
   3 * Filename:      girbil.c
   4 * Version:       1.2
   5 * Description:   Implementation for the Greenwich GIrBIL dongle
   6 * Status:        Experimental.
   7 * Author:        Dag Brattli <dagb@cs.uit.no>
   8 * Created at:    Sat Feb  6 21:02:33 1999
   9 * Modified at:   Fri Dec 17 09:13:20 1999
  10 * Modified by:   Dag Brattli <dagb@cs.uit.no>
  11 *
  12 *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  13 *     
  14 *     This program is free software; you can redistribute it and/or
  15 *     modify it under the terms of the GNU General Public License as
  16 *     published by the Free Software Foundation; either version 2 of
  17 *     the License, or (at your option) any later version.
  18 * 
  19 *     Neither Dag Brattli nor University of Tromsø admit liability nor
  20 *     provide warranty for any of this software. This material is
  21 *     provided "AS-IS" and at no charge.
  22 *
  23 ********************************************************************/
  24
  25#include <linux/module.h>
  26#include <linux/delay.h>
  27#include <linux/init.h>
  28
  29#include <net/irda/irda.h>
  30
  31#include "sir-dev.h"
  32
  33static int girbil_reset(struct sir_dev *dev);
  34static int girbil_open(struct sir_dev *dev);
  35static int girbil_close(struct sir_dev *dev);
  36static int girbil_change_speed(struct sir_dev *dev, unsigned speed);
  37
  38/* Control register 1 */
  39#define GIRBIL_TXEN    0x01 /* Enable transmitter */
  40#define GIRBIL_RXEN    0x02 /* Enable receiver */
  41#define GIRBIL_ECAN    0x04 /* Cancel self emitted data */
  42#define GIRBIL_ECHO    0x08 /* Echo control characters */
  43
  44/* LED Current Register (0x2) */
  45#define GIRBIL_HIGH    0x20
  46#define GIRBIL_MEDIUM  0x21
  47#define GIRBIL_LOW     0x22
  48
  49/* Baud register (0x3) */
  50#define GIRBIL_2400    0x30
  51#define GIRBIL_4800    0x31
  52#define GIRBIL_9600    0x32
  53#define GIRBIL_19200   0x33
  54#define GIRBIL_38400   0x34
  55#define GIRBIL_57600   0x35
  56#define GIRBIL_115200  0x36
  57
  58/* Mode register (0x4) */
  59#define GIRBIL_IRDA    0x40
  60#define GIRBIL_ASK     0x41
  61
  62/* Control register 2 (0x5) */
  63#define GIRBIL_LOAD    0x51 /* Load the new baud rate value */
  64
  65static struct dongle_driver girbil = {
  66        .owner          = THIS_MODULE,
  67        .driver_name    = "Greenwich GIrBIL",
  68        .type           = IRDA_GIRBIL_DONGLE,
  69        .open           = girbil_open,
  70        .close          = girbil_close,
  71        .reset          = girbil_reset,
  72        .set_speed      = girbil_change_speed,
  73};
  74
  75static int __init girbil_sir_init(void)
  76{
  77        return irda_register_dongle(&girbil);
  78}
  79
  80static void __exit girbil_sir_cleanup(void)
  81{
  82        irda_unregister_dongle(&girbil);
  83}
  84
  85static int girbil_open(struct sir_dev *dev)
  86{
  87        struct qos_info *qos = &dev->qos;
  88
  89        /* Power on dongle */
  90        sirdev_set_dtr_rts(dev, TRUE, TRUE);
  91
  92        qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
  93        qos->min_turn_time.bits = 0x03;
  94        irda_qos_bits_to_value(qos);
  95
  96        /* irda thread waits 50 msec for power settling */
  97
  98        return 0;
  99}
 100
 101static int girbil_close(struct sir_dev *dev)
 102{
 103        /* Power off dongle */
 104        sirdev_set_dtr_rts(dev, FALSE, FALSE);
 105
 106        return 0;
 107}
 108
 109/*
 110 * Function girbil_change_speed (dev, speed)
 111 *
 112 *    Set the speed for the Girbil type dongle.
 113 *
 114 */
 115
 116#define GIRBIL_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
 117
 118static int girbil_change_speed(struct sir_dev *dev, unsigned speed)
 119{
 120        unsigned state = dev->fsm.substate;
 121        unsigned delay = 0;
 122        u8 control[2];
 123        static int ret = 0;
 124
 125        /* dongle alread reset - port and dongle at default speed */
 126
 127        switch(state) {
 128
 129        case SIRDEV_STATE_DONGLE_SPEED:
 130
 131                /* Set DTR and Clear RTS to enter command mode */
 132                sirdev_set_dtr_rts(dev, FALSE, TRUE);
 133
 134                udelay(25);             /* better wait a little while */
 135
 136                ret = 0;
 137                switch (speed) {
 138                default:
 139                        ret = -EINVAL;
 140                        /* fall through */
 141                case 9600:
 142                        control[0] = GIRBIL_9600;
 143                        break;
 144                case 19200:
 145                        control[0] = GIRBIL_19200;
 146                        break;
 147                case 34800:
 148                        control[0] = GIRBIL_38400;
 149                        break;
 150                case 57600:
 151                        control[0] = GIRBIL_57600;
 152                        break;
 153                case 115200:
 154                        control[0] = GIRBIL_115200;
 155                        break;
 156                }
 157                control[1] = GIRBIL_LOAD;
 158        
 159                /* Write control bytes */
 160                sirdev_raw_write(dev, control, 2);
 161
 162                dev->speed = speed;
 163
 164                state = GIRBIL_STATE_WAIT_SPEED;
 165                delay = 100;
 166                break;
 167
 168        case GIRBIL_STATE_WAIT_SPEED:
 169                /* Go back to normal mode */
 170                sirdev_set_dtr_rts(dev, TRUE, TRUE);
 171
 172                udelay(25);             /* better wait a little while */
 173                break;
 174
 175        default:
 176                net_err_ratelimited("%s - undefined state %d\n",
 177                                    __func__, state);
 178                ret = -EINVAL;
 179                break;
 180        }
 181        dev->fsm.substate = state;
 182        return (delay > 0) ? delay : ret;
 183}
 184
 185/*
 186 * Function girbil_reset (driver)
 187 *
 188 *      This function resets the girbil dongle.
 189 *
 190 *      Algorithm:
 191 *        0. set RTS, and wait at least 5 ms
 192 *        1. clear RTS
 193 */
 194
 195
 196#define GIRBIL_STATE_WAIT1_RESET        (SIRDEV_STATE_DONGLE_RESET + 1)
 197#define GIRBIL_STATE_WAIT2_RESET        (SIRDEV_STATE_DONGLE_RESET + 2)
 198#define GIRBIL_STATE_WAIT3_RESET        (SIRDEV_STATE_DONGLE_RESET + 3)
 199
 200static int girbil_reset(struct sir_dev *dev)
 201{
 202        unsigned state = dev->fsm.substate;
 203        unsigned delay = 0;
 204        u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
 205        int ret = 0;
 206
 207        switch (state) {
 208        case SIRDEV_STATE_DONGLE_RESET:
 209                /* Reset dongle */
 210                sirdev_set_dtr_rts(dev, TRUE, FALSE);
 211                /* Sleep at least 5 ms */
 212                delay = 20;
 213                state = GIRBIL_STATE_WAIT1_RESET;
 214                break;
 215
 216        case GIRBIL_STATE_WAIT1_RESET:
 217                /* Set DTR and clear RTS to enter command mode */
 218                sirdev_set_dtr_rts(dev, FALSE, TRUE);
 219                delay = 20;
 220                state = GIRBIL_STATE_WAIT2_RESET;
 221                break;
 222
 223        case GIRBIL_STATE_WAIT2_RESET:
 224                /* Write control byte */
 225                sirdev_raw_write(dev, &control, 1);
 226                delay = 20;
 227                state = GIRBIL_STATE_WAIT3_RESET;
 228                break;
 229
 230        case GIRBIL_STATE_WAIT3_RESET:
 231                /* Go back to normal mode */
 232                sirdev_set_dtr_rts(dev, TRUE, TRUE);
 233                dev->speed = 9600;
 234                break;
 235
 236        default:
 237                net_err_ratelimited("%s(), undefined state %d\n",
 238                                    __func__, state);
 239                ret = -1;
 240                break;
 241        }
 242        dev->fsm.substate = state;
 243        return (delay > 0) ? delay : ret;
 244}
 245
 246MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 247MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
 248MODULE_LICENSE("GPL");
 249MODULE_ALIAS("irda-dongle-4"); /* IRDA_GIRBIL_DONGLE */
 250
 251module_init(girbil_sir_init);
 252module_exit(girbil_sir_cleanup);
 253