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