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        IRDA_DEBUG(2, "%s()\n", __func__);
  90
  91        /* Power on dongle */
  92        sirdev_set_dtr_rts(dev, TRUE, TRUE);
  93
  94        qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
  95        qos->min_turn_time.bits = 0x03;
  96        irda_qos_bits_to_value(qos);
  97
  98        /* irda thread waits 50 msec for power settling */
  99
 100        return 0;
 101}
 102
 103static int girbil_close(struct sir_dev *dev)
 104{
 105        IRDA_DEBUG(2, "%s()\n", __func__);
 106
 107        /* Power off dongle */
 108        sirdev_set_dtr_rts(dev, FALSE, FALSE);
 109
 110        return 0;
 111}
 112
 113/*
 114 * Function girbil_change_speed (dev, speed)
 115 *
 116 *    Set the speed for the Girbil type dongle.
 117 *
 118 */
 119
 120#define GIRBIL_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
 121
 122static int girbil_change_speed(struct sir_dev *dev, unsigned speed)
 123{
 124        unsigned state = dev->fsm.substate;
 125        unsigned delay = 0;
 126        u8 control[2];
 127        static int ret = 0;
 128
 129        IRDA_DEBUG(2, "%s()\n", __func__);
 130
 131        /* dongle alread reset - port and dongle at default speed */
 132
 133        switch(state) {
 134
 135        case SIRDEV_STATE_DONGLE_SPEED:
 136
 137                /* Set DTR and Clear RTS to enter command mode */
 138                sirdev_set_dtr_rts(dev, FALSE, TRUE);
 139
 140                udelay(25);             /* better wait a little while */
 141
 142                ret = 0;
 143                switch (speed) {
 144                default:
 145                        ret = -EINVAL;
 146                        /* fall through */
 147                case 9600:
 148                        control[0] = GIRBIL_9600;
 149                        break;
 150                case 19200:
 151                        control[0] = GIRBIL_19200;
 152                        break;
 153                case 34800:
 154                        control[0] = GIRBIL_38400;
 155                        break;
 156                case 57600:
 157                        control[0] = GIRBIL_57600;
 158                        break;
 159                case 115200:
 160                        control[0] = GIRBIL_115200;
 161                        break;
 162                }
 163                control[1] = GIRBIL_LOAD;
 164        
 165                /* Write control bytes */
 166                sirdev_raw_write(dev, control, 2);
 167
 168                dev->speed = speed;
 169
 170                state = GIRBIL_STATE_WAIT_SPEED;
 171                delay = 100;
 172                break;
 173
 174        case GIRBIL_STATE_WAIT_SPEED:
 175                /* Go back to normal mode */
 176                sirdev_set_dtr_rts(dev, TRUE, TRUE);
 177
 178                udelay(25);             /* better wait a little while */
 179                break;
 180
 181        default:
 182                IRDA_ERROR("%s - undefined state %d\n", __func__, state);
 183                ret = -EINVAL;
 184                break;
 185        }
 186        dev->fsm.substate = state;
 187        return (delay > 0) ? delay : ret;
 188}
 189
 190/*
 191 * Function girbil_reset (driver)
 192 *
 193 *      This function resets the girbil dongle.
 194 *
 195 *      Algorithm:
 196 *        0. set RTS, and wait at least 5 ms
 197 *        1. clear RTS
 198 */
 199
 200
 201#define GIRBIL_STATE_WAIT1_RESET        (SIRDEV_STATE_DONGLE_RESET + 1)
 202#define GIRBIL_STATE_WAIT2_RESET        (SIRDEV_STATE_DONGLE_RESET + 2)
 203#define GIRBIL_STATE_WAIT3_RESET        (SIRDEV_STATE_DONGLE_RESET + 3)
 204
 205static int girbil_reset(struct sir_dev *dev)
 206{
 207        unsigned state = dev->fsm.substate;
 208        unsigned delay = 0;
 209        u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
 210        int ret = 0;
 211
 212        IRDA_DEBUG(2, "%s()\n", __func__);
 213
 214        switch (state) {
 215        case SIRDEV_STATE_DONGLE_RESET:
 216                /* Reset dongle */
 217                sirdev_set_dtr_rts(dev, TRUE, FALSE);
 218                /* Sleep at least 5 ms */
 219                delay = 20;
 220                state = GIRBIL_STATE_WAIT1_RESET;
 221                break;
 222
 223        case GIRBIL_STATE_WAIT1_RESET:
 224                /* Set DTR and clear RTS to enter command mode */
 225                sirdev_set_dtr_rts(dev, FALSE, TRUE);
 226                delay = 20;
 227                state = GIRBIL_STATE_WAIT2_RESET;
 228                break;
 229
 230        case GIRBIL_STATE_WAIT2_RESET:
 231                /* Write control byte */
 232                sirdev_raw_write(dev, &control, 1);
 233                delay = 20;
 234                state = GIRBIL_STATE_WAIT3_RESET;
 235                break;
 236
 237        case GIRBIL_STATE_WAIT3_RESET:
 238                /* Go back to normal mode */
 239                sirdev_set_dtr_rts(dev, TRUE, TRUE);
 240                dev->speed = 9600;
 241                break;
 242
 243        default:
 244                IRDA_ERROR("%s(), undefined state %d\n", __func__, state);
 245                ret = -1;
 246                break;
 247        }
 248        dev->fsm.substate = state;
 249        return (delay > 0) ? delay : ret;
 250}
 251
 252MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 253MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
 254MODULE_LICENSE("GPL");
 255MODULE_ALIAS("irda-dongle-4"); /* IRDA_GIRBIL_DONGLE */
 256
 257module_init(girbil_sir_init);
 258module_exit(girbil_sir_cleanup);
 259