patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / net / irda / ma600.c
1 /*********************************************************************
2  *                
3  * Filename:      ma600.c
4  * Version:       0.1
5  * Description:   Implementation of the MA600 dongle
6  * Status:        Experimental.
7  * Author:        Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95
8  * Created at:    Sat Jun 10 20:02:35 2000
9  * Modified at:   
10  * Modified by:   
11  *
12  * Note: very thanks to Mr. Maru Wang <maru@mobileaction.com.tw> for providing 
13  *       information on the MA600 dongle
14  * 
15  *     Copyright (c) 2000 Leung, All Rights Reserved.
16  *      
17  *     This program is free software; you can redistribute it and/or 
18  *     modify it under the terms of the GNU General Public License as 
19  *     published by the Free Software Foundation; either version 2 of 
20  *     the License, or (at your option) any later version.
21  *  
22  *     This program is distributed in the hope that it will be useful,
23  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
24  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  *     GNU General Public License for more details.
26  * 
27  *     You should have received a copy of the GNU General Public License 
28  *     along with this program; if not, write to the Free Software 
29  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
30  *     MA 02111-1307 USA
31  *     
32  ********************************************************************/
33
34 /* define this macro for release version */
35 //#define NDEBUG
36
37 #include <linux/module.h>
38 #include <linux/delay.h>
39 #include <linux/tty.h>
40 #include <linux/init.h>
41
42 #include <net/irda/irda.h>
43 #include <net/irda/irda_device.h>
44
45 #ifndef NDEBUG
46         #undef IRDA_DEBUG
47         #define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args))
48
49         #undef ASSERT
50         #define ASSERT(expr, func) \
51         if(!(expr)) { \
52                 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
53                 #expr,__FILE__,__FUNCTION__,__LINE__); \
54                 func}
55 #endif
56
57 /* convert hex value to ascii hex */
58 static const char hexTbl[] = "0123456789ABCDEF";
59
60
61 static void ma600_open(dongle_t *self, struct qos_info *qos);
62 static void ma600_close(dongle_t *self);
63 static int  ma600_change_speed(struct irda_task *task);
64 static int  ma600_reset(struct irda_task *task);
65
66 /* control byte for MA600 */
67 #define MA600_9600      0x00
68 #define MA600_19200     0x01
69 #define MA600_38400     0x02
70 #define MA600_57600     0x03
71 #define MA600_115200    0x04
72 #define MA600_DEV_ID1   0x05
73 #define MA600_DEV_ID2   0x06
74 #define MA600_2400      0x08
75
76 static struct dongle_reg dongle = {
77         .type = IRDA_MA600_DONGLE,
78         .open = ma600_open,
79         .close = ma600_close,
80         .reset = ma600_reset,
81         .change_speed = ma600_change_speed,
82         .owner = THIS_MODULE,
83 };
84
85 static int __init ma600_init(void)
86 {
87         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
88         return irda_device_register_dongle(&dongle);
89 }
90
91 static void __exit ma600_cleanup(void)
92 {
93         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
94         irda_device_unregister_dongle(&dongle);
95 }
96
97 /*
98         Power on:
99                 (0) Clear RTS and DTR for 1 second
100                 (1) Set RTS and DTR for 1 second
101                 (2) 9600 bps now
102         Note: assume RTS, DTR are clear before
103 */
104 static void ma600_open(dongle_t *self, struct qos_info *qos)
105 {
106         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
107
108         qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
109                                 |IR_57600|IR_115200;
110         qos->min_turn_time.bits = 0x01;         /* Needs at least 1 ms */       
111         irda_qos_bits_to_value(qos);
112
113         //self->set_dtr_rts(self->dev, FALSE, FALSE);
114         // should wait 1 second
115
116         self->set_dtr_rts(self->dev, TRUE, TRUE);
117         // should wait 1 second
118 }
119
120 static void ma600_close(dongle_t *self)
121 {
122         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
123
124         /* Power off dongle */
125         self->set_dtr_rts(self->dev, FALSE, FALSE);
126 }
127
128 static __u8 get_control_byte(__u32 speed)
129 {
130         __u8 byte;
131
132         switch (speed) {
133         default:
134         case 115200:
135                 byte = MA600_115200;
136                 break;
137         case 57600:
138                 byte = MA600_57600;
139                 break;
140         case 38400:
141                 byte = MA600_38400;
142                 break;
143         case 19200:
144                 byte = MA600_19200;
145                 break;
146         case 9600:
147                 byte = MA600_9600;
148                 break;
149         case 2400:
150                 byte = MA600_2400;
151                 break;
152         }
153
154         return byte;
155 }
156
157 /*
158  * Function ma600_change_speed (dev, state, speed)
159  *
160  *    Set the speed for the MA600 type dongle. Warning, this 
161  *    function must be called with a process context!
162  *
163  *    Algorithm
164  *    1. Reset
165  *    2. clear RTS, set DTR and wait for 1ms
166  *    3. send Control Byte to the MA600 through TXD to set new baud rate
167  *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
168  *       it takes about 10 msec)
169  *    4. set RTS, set DTR (return to NORMAL Operation)
170  *    5. wait at least 10 ms, new setting (baud rate, etc) takes effect here 
171  *       after
172  */
173 static int ma600_change_speed(struct irda_task *task)
174 {
175         dongle_t *self = (dongle_t *) task->instance;
176         __u32 speed = (__u32) task->param;
177         static __u8 byte;
178         __u8 byte_echo;
179         int ret = 0;
180         
181         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
182
183         ASSERT(task != NULL, return -1;);
184
185         if (self->speed_task && self->speed_task != task) {
186                 IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
187                 return msecs_to_jiffies(10);
188         } else {
189                 self->speed_task = task;
190         }
191
192         switch (task->state) {
193         case IRDA_TASK_INIT:
194         case IRDA_TASK_CHILD_INIT:
195                 /* 
196                  * Need to reset the dongle and go to 9600 bps before
197                  * programming 
198                  */
199                 if (irda_task_execute(self, ma600_reset, NULL, task, 
200                                       (void *) speed)) {
201                         /* Dongle need more time to reset */
202                         irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
203         
204                         /* give 1 second to finish */
205                         ret = msecs_to_jiffies(1000);
206                 } else {
207                         irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
208                 }
209                 break;
210
211         case IRDA_TASK_CHILD_WAIT:
212                 WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
213                 ret = -1;
214                 break;
215
216         case IRDA_TASK_CHILD_DONE:
217                 /* Set DTR, Clear RTS */
218                 self->set_dtr_rts(self->dev, TRUE, FALSE);
219         
220                 ret = msecs_to_jiffies(1);              /* Sleep 1 ms */
221                 irda_task_next_state(task, IRDA_TASK_WAIT);
222                 break;
223
224         case IRDA_TASK_WAIT:
225                 speed = (__u32) task->param;
226                 byte = get_control_byte(speed);
227
228                 /* Write control byte */
229                 self->write(self->dev, &byte, sizeof(byte));
230                 
231                 irda_task_next_state(task, IRDA_TASK_WAIT1);
232
233                 /* Wait at least 10 ms */
234                 ret = msecs_to_jiffies(15);
235                 break;
236
237         case IRDA_TASK_WAIT1:
238                 /* Read control byte echo */
239                 self->read(self->dev, &byte_echo, sizeof(byte_echo));
240
241                 if(byte != byte_echo) {
242                         /* if control byte != echo, I don't know what to do */
243                         printk(KERN_WARNING "%s() control byte written != read!\n", __FUNCTION__);
244                         printk(KERN_WARNING "control byte = 0x%c%c\n", 
245                                hexTbl[(byte>>4)&0x0f], hexTbl[byte&0x0f]);
246                         printk(KERN_WARNING "byte echo = 0x%c%c\n", 
247                                hexTbl[(byte_echo>>4) & 0x0f], 
248                                hexTbl[byte_echo & 0x0f]);
249                 #ifndef NDEBUG
250                 } else {
251                         IRDA_DEBUG(2, "%s() control byte write read OK\n", __FUNCTION__);
252                 #endif
253                 }
254
255                 /* Set DTR, Set RTS */
256                 self->set_dtr_rts(self->dev, TRUE, TRUE);
257
258                 irda_task_next_state(task, IRDA_TASK_WAIT2);
259
260                 /* Wait at least 10 ms */
261                 ret = msecs_to_jiffies(10);
262                 break;
263
264         case IRDA_TASK_WAIT2:
265                 irda_task_next_state(task, IRDA_TASK_DONE);
266                 self->speed_task = NULL;
267                 break;
268
269         default:
270                 ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
271                 irda_task_next_state(task, IRDA_TASK_DONE);
272                 self->speed_task = NULL;
273                 ret = -1;
274                 break;
275         }
276         return ret;
277 }
278
279 /*
280  * Function ma600_reset (driver)
281  *
282  *      This function resets the ma600 dongle. Warning, this function 
283  *      must be called with a process context!! 
284  *
285  *      Algorithm:
286  *        0. DTR=0, RTS=1 and wait 10 ms
287  *        1. DTR=1, RTS=1 and wait 10 ms
288  *        2. 9600 bps now
289  */
290 int ma600_reset(struct irda_task *task)
291 {
292         dongle_t *self = (dongle_t *) task->instance;
293         int ret = 0;
294
295         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
296
297         ASSERT(task != NULL, return -1;);
298
299         if (self->reset_task && self->reset_task != task) {
300                 IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
301                 return msecs_to_jiffies(10);
302         } else
303                 self->reset_task = task;
304         
305         switch (task->state) {
306         case IRDA_TASK_INIT:
307                 /* Clear DTR and Set RTS */
308                 self->set_dtr_rts(self->dev, FALSE, TRUE);
309                 irda_task_next_state(task, IRDA_TASK_WAIT1);
310                 ret = msecs_to_jiffies(10);             /* Sleep 10 ms */
311                 break;
312         case IRDA_TASK_WAIT1:
313                 /* Set DTR and RTS */
314                 self->set_dtr_rts(self->dev, TRUE, TRUE);
315                 irda_task_next_state(task, IRDA_TASK_WAIT2);
316                 ret = msecs_to_jiffies(10);             /* Sleep 10 ms */
317                 break;
318         case IRDA_TASK_WAIT2:
319                 irda_task_next_state(task, IRDA_TASK_DONE);
320                 self->reset_task = NULL;
321                 break;
322         default:
323                 ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
324                 irda_task_next_state(task, IRDA_TASK_DONE);             
325                 self->reset_task = NULL;
326                 ret = -1;
327         }
328         return ret;
329 }
330
331 MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95");
332 MODULE_DESCRIPTION("MA600 dongle driver version 0.1");
333 MODULE_LICENSE("GPL");
334 MODULE_ALIAS("irda-dongle-11"); /* IRDA_MA600_DONGLE */
335                 
336 /*
337  * Function init_module (void)
338  *
339  *    Initialize MA600 module
340  *
341  */
342 module_init(ma600_init);
343
344 /*
345  * Function cleanup_module (void)
346  *
347  *    Cleanup MA600 module
348  *
349  */
350 module_exit(ma600_cleanup);
351