1 /*********************************************************************
5 * Description: Implementation for the Adaptec Airport 1000 and 2000
7 * Status: Experimental.
8 * Author: Fons Botman <budely@tref.nl>
9 * Created at: Wed May 19 23:14:34 CEST 1999
11 * By: Dag Brattli <dagb@cs.uit.no>
13 * Copyright (c) 1998-1999 Fons Botman, All Rights Reserved.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * Neither Fons Botman nor anyone else admit liability nor
21 * provide warranty for any of this software. This material is
22 * provided "AS-IS" and at no charge.
24 ********************************************************************/
26 #include <linux/module.h>
27 #include <linux/delay.h>
28 #include <linux/tty.h>
29 #include <linux/sched.h>
30 #include <linux/init.h>
32 #include <net/irda/irda.h>
33 #include <net/irda/irmod.h>
34 #include <net/irda/irda_device.h>
35 #include <net/irda/dongle.h>
38 static void airport_reset(struct irda_device
*dev
);
39 static void airport_open(struct irda_device
*idev
, int type
);
40 static void airport_close(struct irda_device
*dev
);
41 static void airport_change_speed( struct irda_device
*dev
, __u32 speed
);
42 static void airport_init_qos(struct irda_device
*idev
, struct qos_info
*qos
);
45 static struct dongle dongle
= {
55 int __init
airport_init(void)
59 DEBUG(2, __FUNCTION__
"()\n");
60 ret
= irda_device_register_dongle(&dongle
);
66 void airport_cleanup(void)
68 DEBUG(2, __FUNCTION__
"()\n");
69 irda_device_unregister_dongle(&dongle
);
72 static void airport_open(struct irda_device
*idev
, int type
)
74 DEBUG(2, __FUNCTION__
"(,%d)\n", type
);
75 if (strlen(idev
->description
) < sizeof(idev
->description
) - 13)
76 strcat(idev
->description
, " <-> airport");
78 DEBUG(0, __FUNCTION__
" description too long: %s\n",
81 idev
->io
.dongle_id
= type
;
82 idev
->flags
|= IFF_DONGLE
;
87 static void airport_close(struct irda_device
*idev
)
89 DEBUG(2, __FUNCTION__
"()\n");
90 /* Power off dongle */
91 irda_device_set_dtr_rts(idev
, FALSE
, FALSE
);
96 static void airport_set_command_mode(struct irda_device
*idev
)
98 DEBUG(2, __FUNCTION__
"()\n");
99 irda_device_set_dtr_rts(idev
, FALSE
, TRUE
);
102 static void airport_set_normal_mode(struct irda_device
*idev
)
104 DEBUG(2, __FUNCTION__
"()\n");
105 irda_device_set_dtr_rts(idev
, TRUE
, TRUE
);
109 void airport_write_char(struct irda_device
*idev
, unsigned char c
)
112 DEBUG(2, __FUNCTION__
"(,0x%x)\n", c
& 0xff);
113 actual
= idev
->raw_write(idev
, &c
, 1);
114 ASSERT(actual
== 1, return;);
117 #define JIFFIES_TO_MSECS(j) ((j)*1000/HZ)
119 static int airport_waitfor_char(struct irda_device
*idev
, unsigned char c
)
121 int i
, found
= FALSE
;
123 DEBUG(2, __FUNCTION__
"(,0x%x)\n", c
);
125 /* Sleep approx. 10 ms */
127 current
->state
= TASK_INTERRUPTIBLE
;
128 schedule_timeout(MSECS_TO_JIFFIES(20));
129 DEBUG(4, __FUNCTION__
" waited %ldms\n",
130 JIFFIES_TO_MSECS(jiffies
- before
));
132 for ( i
= 0 ; !found
&& i
< idev
->rx_buff
.len
; i
++ ) {
133 /* DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
134 found
= c
== idev
->rx_buff
.data
[i
];
136 idev
->rx_buff
.len
= 0;
138 DEBUG(2, __FUNCTION__
" returns %s\n", (found
? "true" : "false"));
142 static int airport_check_command_mode(struct irda_device
*idev
)
147 DEBUG(2, __FUNCTION__
"()\n");
148 current
->state
= TASK_INTERRUPTIBLE
;
149 schedule_timeout(MSECS_TO_JIFFIES(20));
150 airport_set_command_mode(idev
);
152 /* Loop until the time expires (200ms) or we get the magic char. */
154 for ( i
= 0 ; i
< 25 ; i
++ ) {
155 airport_write_char(idev
, 0xff);
156 if (airport_waitfor_char(idev
, 0xc3)) {
163 DEBUG(2, __FUNCTION__
" OK. (%d)\n", i
);
165 DEBUG(0, __FUNCTION__
" FAILED!\n");
171 static int airport_write_register(struct irda_device
*idev
, unsigned char reg
)
176 DEBUG(4, __FUNCTION__
"(,0x%x)\n", reg
);
177 airport_check_command_mode(idev
);
179 for ( i
= 0 ; i
< 6 ; i
++ ) {
180 airport_write_char(idev
, reg
);
181 if (!airport_waitfor_char(idev
, reg
))
184 /* Now read it back */
185 airport_write_char(idev
, (reg
<< 4) | 0x0f);
186 if (airport_waitfor_char(idev
, reg
)) {
192 airport_set_normal_mode(idev
);
194 DEBUG(4, __FUNCTION__
"(,0x%x) returns OK\n", reg
);
196 DEBUG(0, __FUNCTION__
"(,0x%x) returns False!\n", reg
);
203 * Function airport_change_speed (tty, baud)
205 * Change speed of the Airport type IrDA dongles.
207 static void airport_change_speed(struct irda_device
*idev
, __u32 speed
)
209 __u32 current_baudrate
;
212 DEBUG(4, __FUNCTION__
"(,%d)\n", speed
);
214 ASSERT(idev
!= NULL
, return;);
215 ASSERT(idev
->magic
== IRDA_DEVICE_MAGIC
, return;);
217 /* Find the correct baudrate code for the required baudrate */
219 case 2400: baudcode
= 0x10; break;
220 case 4800: baudcode
= 0x20; break;
221 case 9600: baudcode
= 0x30; break;
222 case 19200: baudcode
= 0x40; break;
223 case 38400: baudcode
= 0x50; break;
224 case 57600: baudcode
= 0x60; break;
225 case 115200: baudcode
= 0x70; break;
227 DEBUG(0, __FUNCTION__
" bad baud rate: %d\n", speed
);
231 current_baudrate
= idev
->qos
.baud_rate
.value
;
232 DEBUG(4, __FUNCTION__
" current baudrate: %d\n", current_baudrate
);
234 /* The dongle falls back to 9600 baud */
235 if (current_baudrate
!= 9600) {
236 DEBUG(4, __FUNCTION__
" resetting speed to 9600 baud\n");
237 ASSERT(idev
->change_speed
, return;);
238 idev
->change_speed(idev
, 9600);
239 idev
->qos
.baud_rate
.value
= 9600;
242 if (idev
->set_raw_mode
)
243 idev
->set_raw_mode(idev
, TRUE
);
245 /* Set the new speed in both registers */
246 if (airport_write_register(idev
, baudcode
)) {
247 if (airport_write_register(idev
, baudcode
|0x01)) {
250 DEBUG(0, __FUNCTION__
251 " Cannot set new speed in second register\n");
254 DEBUG(0, __FUNCTION__
255 " Cannot set new speed in first register\n");
258 if (idev
->set_raw_mode
)
259 idev
->set_raw_mode(idev
, FALSE
);
261 /* How do I signal an error in these functions? */
263 DEBUG(4, __FUNCTION__
" returning\n");
268 * Function airport_reset (idev)
270 * Reset the Airport type dongle. Warning, this function must only be
271 * called with a process context!
274 static void airport_reset(struct irda_device
*idev
)
278 DEBUG(2, __FUNCTION__
"()\n");
279 ASSERT(idev
!= NULL
, return;);
280 ASSERT(idev
->magic
== IRDA_DEVICE_MAGIC
, return;);
281 ASSERT(idev
->set_raw_mode
/* The airport needs this */, return;);
283 if (idev
->set_raw_mode
)
284 idev
->set_raw_mode(idev
, TRUE
);
286 airport_set_normal_mode(idev
);
289 DEBUG(2, __FUNCTION__
" waiting for powerup\n");
290 current
->state
= TASK_INTERRUPTIBLE
;
291 schedule_timeout(MSECS_TO_JIFFIES(2000));
292 DEBUG(2, __FUNCTION__
" finished waiting for powerup\n");
294 /* set dongle speed to 9600 */
298 ok
= airport_write_register(idev
, 0x30);
300 MESSAGE(__FUNCTION__
"() dongle not connected?\n");
302 ok
= airport_write_register(idev
, 0x31);
305 ok
= airport_write_register(idev
, 0x02);
307 ok
= airport_write_register(idev
, 0x03);
310 ok
= airport_check_command_mode(idev
);
313 airport_write_char(idev
, 0x04);
314 ok
= airport_waitfor_char(idev
, 0x04);
316 airport_set_normal_mode(idev
);
319 if (idev
->set_raw_mode
)
320 idev
->set_raw_mode(idev
, FALSE
);
323 current
->state
= TASK_INTERRUPTIBLE
;
324 schedule_timeout(MSECS_TO_JIFFIES(20));
325 DEBUG(4, __FUNCTION__
" waited 20ms\n");
327 idev
->qos
.baud_rate
.value
= 9600;
329 MESSAGE(__FUNCTION__
"() failed.\n");
330 DEBUG(2, __FUNCTION__
" returning.\n");
334 * Function airport_init_qos (qos)
336 * Initialize QoS capabilities
339 static void airport_init_qos(struct irda_device
*idev
, struct qos_info
*qos
)
341 qos
->baud_rate
.bits
&=
342 IR_2400
|IR_9600
|IR_19200
|IR_38400
|IR_57600
|IR_115200
;
344 qos
->min_turn_time
.bits
&= 0x07;
349 MODULE_AUTHOR("Fons Botman <budely@tref.nl>");
350 MODULE_DESCRIPTION("Adaptec Airport 1000 and 2000 dongle driver");
353 * Function init_module (void)
355 * Initialize Airport module
358 int init_module(void)
360 return airport_init();
364 * Function cleanup_module (void)
366 * Cleanup Airport module
369 void cleanup_module(void)