~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/net/irda/tekram.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*********************************************************************
  2  *                
  3  * Filename:      tekram.c
  4  * Version:       1.2
  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:   Fri Dec 17 09:13:09 1999
 10  * Modified by:   Dag Brattli <dagb@cs.uit.no>
 11  * 
 12  *     Copyright (c) 1998-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/tty.h>
 28 #include <linux/sched.h>
 29 #include <linux/init.h>
 30 
 31 #include <net/irda/irda.h>
 32 #include <net/irda/irmod.h>
 33 #include <net/irda/irda_device.h>
 34 #include <net/irda/irtty.h>
 35 
 36 static void tekram_open(dongle_t *self, struct qos_info *qos);
 37 static void tekram_close(dongle_t *self);
 38 static int  tekram_change_speed(struct irda_task *task);
 39 static int  tekram_reset(struct irda_task *task);
 40 
 41 #define TEKRAM_115200 0x00
 42 #define TEKRAM_57600  0x01
 43 #define TEKRAM_38400  0x02
 44 #define TEKRAM_19200  0x03
 45 #define TEKRAM_9600   0x04
 46 
 47 #define TEKRAM_PW     0x10 /* Pulse select bit */
 48 
 49 static struct dongle_reg dongle = {
 50         Q_NULL,
 51         IRDA_TEKRAM_DONGLE,
 52         tekram_open,
 53         tekram_close,
 54         tekram_reset,
 55         tekram_change_speed,
 56 };
 57 
 58 int __init tekram_init(void)
 59 {
 60         return irda_device_register_dongle(&dongle);
 61 }
 62 
 63 void tekram_cleanup(void)
 64 {
 65         irda_device_unregister_dongle(&dongle);
 66 }
 67 
 68 static void tekram_open(dongle_t *self, struct qos_info *qos)
 69 {
 70         IRDA_DEBUG(2, __FUNCTION__ "()\n");
 71 
 72         qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 73         qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */      
 74         irda_qos_bits_to_value(qos);
 75 
 76         MOD_INC_USE_COUNT;
 77 }
 78 
 79 static void tekram_close(dongle_t *self)
 80 {
 81         IRDA_DEBUG(2, __FUNCTION__ "()\n");
 82 
 83         /* Power off dongle */
 84         self->set_dtr_rts(self->dev, FALSE, FALSE);
 85 
 86         if (self->reset_task)
 87                 irda_task_delete(self->reset_task);
 88         if (self->speed_task)
 89                 irda_task_delete(self->speed_task);
 90 
 91         MOD_DEC_USE_COUNT;
 92 }
 93 
 94 /*
 95  * Function tekram_change_speed (dev, state, speed)
 96  *
 97  *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this 
 98  *    function must be called with a process context!
 99  *
100  *    Algorithm
101  *    1. clear DTR 
102  *    2. set RTS, and wait at least 7 us
103  *    3. send Control Byte to the IR-210 through TXD to set new baud rate
104  *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
105  *       it takes about 100 msec)
106  *    5. clear RTS (return to NORMAL Operation)
107  *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
108  *       after
109  */
110 static int tekram_change_speed(struct irda_task *task)
111 {
112         dongle_t *self = (dongle_t *) task->instance;
113         __u32 speed = (__u32) task->param;
114         __u8 byte;
115         int ret = 0;
116         
117         IRDA_DEBUG(2, __FUNCTION__ "()\n");
118 
119         ASSERT(task != NULL, return -1;);
120 
121         if (self->speed_task && self->speed_task != task) {
122                 IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
123                 return MSECS_TO_JIFFIES(10);
124         } else
125                 self->speed_task = task;
126 
127         switch (speed) {
128         default:
129         case 9600:
130                 byte = TEKRAM_PW|TEKRAM_9600;
131                 break;
132         case 19200:
133                 byte = TEKRAM_PW|TEKRAM_19200;
134                 break;
135         case 38400:
136                 byte = TEKRAM_PW|TEKRAM_38400;
137                 break;
138         case 57600:
139                 byte = TEKRAM_PW|TEKRAM_57600;
140                 break;
141         case 115200:
142                 byte = TEKRAM_115200;
143                 break;
144         }
145 
146         switch (task->state) {
147         case IRDA_TASK_INIT:
148         case IRDA_TASK_CHILD_INIT:              
149                 /* 
150                  * Need to reset the dongle and go to 9600 bps before
151                  * programming 
152                  */
153                 if (irda_task_execute(self, tekram_reset, NULL, task, 
154                                       (void *) speed))
155                 {
156                         /* Dongle need more time to reset */
157                         irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
158 
159                         /* Give reset 1 sec to finish */
160                         ret = MSECS_TO_JIFFIES(1000);
161                 } else
162                         irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
163                 break;
164         case IRDA_TASK_CHILD_WAIT:
165                 WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
166                 ret = -1;
167                 break;
168         case IRDA_TASK_CHILD_DONE:
169                 /* Set DTR, Clear RTS */
170                 self->set_dtr_rts(self->dev, TRUE, FALSE);
171         
172                 /* Wait at least 7us */
173                 udelay(14);
174 
175                 /* Write control byte */
176                 self->write(self->dev, &byte, 1);
177                 
178                 irda_task_next_state(task, IRDA_TASK_WAIT);
179 
180                 /* Wait at least 100 ms */
181                 ret = MSECS_TO_JIFFIES(150);
182                 break;
183         case IRDA_TASK_WAIT:
184                 /* Set DTR, Set RTS */
185                 self->set_dtr_rts(self->dev, TRUE, TRUE);
186 
187                 irda_task_next_state(task, IRDA_TASK_DONE);
188                 self->speed_task = NULL;
189                 break;
190         default:
191                 ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
192                 irda_task_next_state(task, IRDA_TASK_DONE);
193                 self->speed_task = NULL;
194                 ret = -1;
195                 break;
196         }
197         return ret;
198 }
199 
200 /*
201  * Function tekram_reset (driver)
202  *
203  *      This function resets the tekram dongle. Warning, this function 
204  *      must be called with a process context!! 
205  *
206  *      Algorithm:
207  *        0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 )
208  *        1. clear RTS 
209  *        2. set DTR, and wait at least 1 ms 
210  *        3. clear DTR to SPACE state, wait at least 50 us for further 
211  *         operation
212  */
213 int tekram_reset(struct irda_task *task)
214 {
215         dongle_t *self = (dongle_t *) task->instance;
216         int ret = 0;
217 
218         IRDA_DEBUG(2, __FUNCTION__ "()\n");
219 
220         ASSERT(task != NULL, return -1;);
221 
222         if (self->reset_task && self->reset_task != task) {
223                 IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
224                 return MSECS_TO_JIFFIES(10);
225         } else
226                 self->reset_task = task;
227         
228         /* Power off dongle */
229         //self->set_dtr_rts(self->dev, FALSE, FALSE);
230         self->set_dtr_rts(self->dev, TRUE, TRUE);
231 
232         switch (task->state) {
233         case IRDA_TASK_INIT:
234                 irda_task_next_state(task, IRDA_TASK_WAIT1);
235 
236                 /* Sleep 50 ms */
237                 ret = MSECS_TO_JIFFIES(50);
238                 break;
239         case IRDA_TASK_WAIT1:
240                 /* Clear DTR, Set RTS */
241                 self->set_dtr_rts(self->dev, FALSE, TRUE); 
242 
243                 irda_task_next_state(task, IRDA_TASK_WAIT2);
244                 
245                 /* Should sleep 1 ms */
246                 ret = MSECS_TO_JIFFIES(1);
247                 break;
248         case IRDA_TASK_WAIT2:
249                 /* Set DTR, Set RTS */
250                 self->set_dtr_rts(self->dev, TRUE, TRUE);
251         
252                 /* Wait at least 50 us */
253                 udelay(75);
254 
255                 irda_task_next_state(task, IRDA_TASK_DONE);
256                 self->reset_task = NULL;
257                 break;
258         default:
259                 ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
260                 irda_task_next_state(task, IRDA_TASK_DONE);             
261                 self->reset_task = NULL;
262                 ret = -1;
263         }
264         return ret;
265 }
266 
267 #ifdef MODULE
268 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
269 MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
270                 
271 /*
272  * Function init_module (void)
273  *
274  *    Initialize Tekram module
275  *
276  */
277 int init_module(void)
278 {
279         return tekram_init();
280 }
281 
282 /*
283  * Function cleanup_module (void)
284  *
285  *    Cleanup Tekram module
286  *
287  */
288 void cleanup_module(void)
289 {
290         tekram_cleanup();
291 }
292 #endif /* MODULE */
293 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.