1 /*********************************************************************
3 * Filename: ircomm_tty_attach.c
5 * Description: Code for attaching the serial driver to IrCOMM
6 * Status: Experimental.
7 * Author: Dag Brattli <dagb@cs.uit.no>
8 * Created at: Sat Jun 5 17:42:00 1999
9 * Modified at: Tue Jan 4 14:20:49 2000
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
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.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 ********************************************************************/
31 #include <linux/sched.h>
32 #include <linux/init.h>
34 #include <net/irda/irda.h>
35 #include <net/irda/irlmp.h>
36 #include <net/irda/iriap.h>
37 #include <net/irda/irttp.h>
38 #include <net/irda/irias_object.h>
39 #include <net/irda/parameters.h>
41 #include <net/irda/ircomm_core.h>
42 #include <net/irda/ircomm_param.h>
43 #include <net/irda/ircomm_event.h>
45 #include <net/irda/ircomm_tty.h>
46 #include <net/irda/ircomm_tty_attach.h>
48 static void ircomm_tty_ias_register(struct ircomm_tty_cb
*self
);
49 static void ircomm_tty_discovery_indication(discovery_t
*discovery
,
51 static void ircomm_tty_getvalue_confirm(int result
, __u16 obj_id
,
52 struct ias_value
*value
, void *priv
);
53 void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb
*self
, int timeout
);
54 void ircomm_tty_watchdog_timer_expired(void *data
);
56 static int ircomm_tty_state_idle(struct ircomm_tty_cb
*self
,
57 IRCOMM_TTY_EVENT event
,
59 struct ircomm_tty_info
*info
);
60 static int ircomm_tty_state_search(struct ircomm_tty_cb
*self
,
61 IRCOMM_TTY_EVENT event
,
63 struct ircomm_tty_info
*info
);
64 static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb
*self
,
65 IRCOMM_TTY_EVENT event
,
67 struct ircomm_tty_info
*info
);
68 static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb
*self
,
69 IRCOMM_TTY_EVENT event
,
71 struct ircomm_tty_info
*info
);
72 static int ircomm_tty_state_setup(struct ircomm_tty_cb
*self
,
73 IRCOMM_TTY_EVENT event
,
75 struct ircomm_tty_info
*info
);
76 static int ircomm_tty_state_ready(struct ircomm_tty_cb
*self
,
77 IRCOMM_TTY_EVENT event
,
79 struct ircomm_tty_info
*info
);
81 char *ircomm_tty_state
[] = {
84 "IRCOMM_TTY_QUERY_PARAMETERS",
85 "IRCOMM_TTY_QUERY_LSAP_SEL",
91 char *ircomm_tty_event
[] = {
92 "IRCOMM_TTY_ATTACH_CABLE",
93 "IRCOMM_TTY_DETACH_CABLE",
94 "IRCOMM_TTY_DATA_REQUEST",
95 "IRCOMM_TTY_DATA_INDICATION",
96 "IRCOMM_TTY_DISCOVERY_REQUEST",
97 "IRCOMM_TTY_DISCOVERY_INDICATION",
98 "IRCOMM_TTY_CONNECT_CONFIRM",
99 "IRCOMM_TTY_CONNECT_INDICATION",
100 "IRCOMM_TTY_DISCONNECT_REQUEST",
101 "IRCOMM_TTY_DISCONNECT_INDICATION",
102 "IRCOMM_TTY_WD_TIMER_EXPIRED",
103 "IRCOMM_TTY_GOT_PARAMETERS",
104 "IRCOMM_TTY_GOT_LSAPSEL",
108 static int (*state
[])(struct ircomm_tty_cb
*self
, IRCOMM_TTY_EVENT event
,
109 struct sk_buff
*skb
, struct ircomm_tty_info
*info
) =
111 ircomm_tty_state_idle
,
112 ircomm_tty_state_search
,
113 ircomm_tty_state_query_parameters
,
114 ircomm_tty_state_query_lsap_sel
,
115 ircomm_tty_state_setup
,
116 ircomm_tty_state_ready
,
120 * Function ircomm_tty_attach_cable (driver)
122 * Try to attach cable (IrCOMM link). This function will only return
123 * when the link has been connected, or if an error condition occurs.
124 * If success, the return value is the resulting service type.
126 int ircomm_tty_attach_cable(struct ircomm_tty_cb
*self
)
128 IRDA_DEBUG(0, __FUNCTION__
"()\n");
130 ASSERT(self
!= NULL
, return -1;);
131 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return -1;);
133 /* Check if somebody has already connected to us */
134 if (ircomm_is_connected(self
->ircomm
)) {
135 IRDA_DEBUG(0, __FUNCTION__
"(), already connected!\n");
139 /* Make sure nobody tries to write before the link is up */
140 self
->tty
->hw_stopped
= 1;
142 ircomm_tty_ias_register(self
);
144 /* Check if somebody has already connected to us */
145 if (ircomm_is_connected(self
->ircomm
)) {
146 IRDA_DEBUG(0, __FUNCTION__
"(), already connected!\n");
150 ircomm_tty_do_event(self
, IRCOMM_TTY_ATTACH_CABLE
, NULL
, NULL
);
156 * Function ircomm_detach_cable (driver)
158 * Detach cable, or cable has been detached by peer
161 void ircomm_tty_detach_cable(struct ircomm_tty_cb
*self
)
163 IRDA_DEBUG(0, __FUNCTION__
"()\n");
165 ASSERT(self
!= NULL
, return;);
166 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
168 del_timer(&self
->watchdog_timer
);
170 /* Remove IrCOMM hint bits */
171 irlmp_unregister_client(self
->ckey
);
172 irlmp_unregister_service(self
->skey
);
175 iriap_close(self
->iriap
);
179 /* Remove LM-IAS object */
181 irias_delete_object(self
->obj
);
185 ircomm_tty_do_event(self
, IRCOMM_TTY_DETACH_CABLE
, NULL
, NULL
);
187 /* Reset some values */
188 self
->daddr
= self
->saddr
= 0;
189 self
->dlsap_sel
= self
->slsap_sel
= 0;
191 memset(&self
->settings
, 0, sizeof(struct ircomm_params
));
195 * Function ircomm_tty_ias_register (self)
197 * Register with LM-IAS depending on which service type we are
200 static void ircomm_tty_ias_register(struct ircomm_tty_cb
*self
)
205 IRDA_DEBUG(0, __FUNCTION__
"()\n");
207 ASSERT(self
!= NULL
, return;);
208 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
210 if (self
->service_type
& IRCOMM_3_WIRE_RAW
) {
211 hints
= irlmp_service_to_hint(S_PRINTER
);
212 hints
|= irlmp_service_to_hint(S_COMM
);
214 /* Register IrLPT with LM-IAS */
215 self
->obj
= irias_new_object("IrLPT", IAS_IRLPT_ID
);
216 irias_add_integer_attrib(self
->obj
, "IrDA:IrLMP:LsapSel",
217 self
->slsap_sel
, IAS_KERNEL_ATTR
);
218 irias_insert_object(self
->obj
);
220 hints
= irlmp_service_to_hint(S_COMM
);
222 /* Register IrCOMM with LM-IAS */
223 self
->obj
= irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID
);
224 irias_add_integer_attrib(self
->obj
, "IrDA:TinyTP:LsapSel",
225 self
->slsap_sel
, IAS_KERNEL_ATTR
);
227 /* Code the parameters into the buffer */
228 irda_param_pack(oct_seq
, "bbbbbb",
229 IRCOMM_SERVICE_TYPE
, 1, self
->service_type
,
230 IRCOMM_PORT_TYPE
, 1, IRCOMM_SERIAL
);
232 /* Register parameters with LM-IAS */
233 irias_add_octseq_attrib(self
->obj
, "Parameters", oct_seq
, 6,
235 irias_insert_object(self
->obj
);
237 self
->skey
= irlmp_register_service(hints
);
238 self
->ckey
= irlmp_register_client(
239 hints
, ircomm_tty_discovery_indication
, NULL
, (void *) self
);
243 * Function ircomm_send_initial_parameters (self)
245 * Send initial parameters to the remote IrCOMM device. These parameters
246 * must be sent before any data.
248 int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb
*self
)
250 ASSERT(self
!= NULL
, return -1;);
251 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return -1;);
253 if (self
->service_type
& IRCOMM_3_WIRE_RAW
)
257 * Set default values, but only if the application for some reason
258 * haven't set them already
260 IRDA_DEBUG(2, __FUNCTION__
"(), data-rate = %d\n",
261 self
->settings
.data_rate
);
262 if (!self
->settings
.data_rate
)
263 self
->settings
.data_rate
= 9600;
264 IRDA_DEBUG(2, __FUNCTION__
"(), data-format = %d\n",
265 self
->settings
.data_format
);
266 if (!self
->settings
.data_format
)
267 self
->settings
.data_format
= IRCOMM_WSIZE_8
; /* 8N1 */
269 IRDA_DEBUG(2, __FUNCTION__
"(), flow-control = %d\n",
270 self
->settings
.flow_control
);
271 /*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
273 /* Do not set delta values for the initial parameters */
274 self
->settings
.dte
= IRCOMM_DTR
| IRCOMM_RTS
;
276 /* Only send service type parameter when we are the client */
278 ircomm_param_request(self
, IRCOMM_SERVICE_TYPE
, FALSE
);
279 ircomm_param_request(self
, IRCOMM_DATA_RATE
, FALSE
);
280 ircomm_param_request(self
, IRCOMM_DATA_FORMAT
, FALSE
);
282 /* For a 3 wire service, we just flush the last parameter and return */
283 if (self
->settings
.service_type
== IRCOMM_3_WIRE
) {
284 ircomm_param_request(self
, IRCOMM_FLOW_CONTROL
, TRUE
);
288 /* Only 9-wire service types continue here */
289 ircomm_param_request(self
, IRCOMM_FLOW_CONTROL
, FALSE
);
291 ircomm_param_request(self
, IRCOMM_XON_XOFF
, FALSE
);
292 ircomm_param_request(self
, IRCOMM_ENQ_ACK
, FALSE
);
294 /* Notify peer that we are ready to receive data */
295 ircomm_param_request(self
, IRCOMM_DTE
, TRUE
);
301 * Function ircomm_tty_discovery_indication (discovery)
303 * Remote device is discovered, try query the remote IAS to see which
304 * device it is, and which services it has.
307 static void ircomm_tty_discovery_indication(discovery_t
*discovery
,
310 struct ircomm_tty_cb
*self
;
311 struct ircomm_tty_info info
;
313 IRDA_DEBUG(2, __FUNCTION__
"()\n");
315 info
.daddr
= discovery
->daddr
;
316 info
.saddr
= discovery
->saddr
;
318 self
= (struct ircomm_tty_cb
*) hashbin_get_first(ircomm_tty
);
319 while (self
!= NULL
) {
320 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
322 ircomm_tty_do_event(self
, IRCOMM_TTY_DISCOVERY_INDICATION
,
325 self
= (struct ircomm_tty_cb
*) hashbin_get_next(ircomm_tty
);
330 * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb)
335 void ircomm_tty_disconnect_indication(void *instance
, void *sap
,
339 struct ircomm_tty_cb
*self
= (struct ircomm_tty_cb
*) instance
;
341 IRDA_DEBUG(2, __FUNCTION__
"()\n");
343 ASSERT(self
!= NULL
, return;);
344 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
349 /* This will stop control data transfers */
350 self
->flow
= FLOW_STOP
;
352 /* Stop data transfers */
353 self
->tty
->hw_stopped
= 1;
355 ircomm_tty_do_event(self
, IRCOMM_TTY_DISCONNECT_INDICATION
, NULL
,
360 * Function ircomm_tty_getvalue_confirm (result, obj_id, value, priv)
362 * Got result from the IAS query we make
365 static void ircomm_tty_getvalue_confirm(int result
, __u16 obj_id
,
366 struct ias_value
*value
,
369 struct ircomm_tty_cb
*self
= (struct ircomm_tty_cb
*) priv
;
371 IRDA_DEBUG(2, __FUNCTION__
"()\n");
373 ASSERT(self
!= NULL
, return;);
374 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
376 /* We probably don't need to make any more queries */
377 iriap_close(self
->iriap
);
380 /* Check if request succeeded */
381 if (result
!= IAS_SUCCESS
) {
382 IRDA_DEBUG(4, __FUNCTION__
"(), got NULL value!\n");
386 switch (value
->type
) {
388 IRDA_DEBUG(2, __FUNCTION__
"(), got octet sequence\n");
390 irda_param_extract_all(self
, value
->t
.oct_seq
, value
->len
,
393 ircomm_tty_do_event(self
, IRCOMM_TTY_GOT_PARAMETERS
, NULL
,
397 /* Got LSAP selector */
398 IRDA_DEBUG(2, __FUNCTION__
"(), got lsapsel = %d\n",
401 if (value
->t
.integer
== -1) {
402 IRDA_DEBUG(0, __FUNCTION__
"(), invalid value!\n");
404 self
->dlsap_sel
= value
->t
.integer
;
406 ircomm_tty_do_event(self
, IRCOMM_TTY_GOT_LSAPSEL
, NULL
, NULL
);
409 IRDA_DEBUG(0, __FUNCTION__
"(), got IAS_MISSING\n");
412 IRDA_DEBUG(0, __FUNCTION__
"(), got unknown type!\n");
415 irias_delete_value(value
);
419 * Function ircomm_tty_connect_confirm (instance, sap, qos, max_sdu_size, skb)
421 * Connection confirmed
424 void ircomm_tty_connect_confirm(void *instance
, void *sap
,
425 struct qos_info
*qos
,
427 __u8 max_header_size
,
430 struct ircomm_tty_cb
*self
= (struct ircomm_tty_cb
*) instance
;
432 IRDA_DEBUG(2, __FUNCTION__
"()\n");
434 ASSERT(self
!= NULL
, return;);
435 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
438 self
->max_data_size
= max_data_size
;
439 self
->max_header_size
= max_header_size
;
440 self
->flow
= FLOW_START
;
442 ircomm_tty_do_event(self
, IRCOMM_TTY_CONNECT_CONFIRM
, NULL
, NULL
);
448 * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size,
451 * we are discovered and being requested to connect by remote device !
454 void ircomm_tty_connect_indication(void *instance
, void *sap
,
455 struct qos_info
*qos
,
457 __u8 max_header_size
,
460 struct ircomm_tty_cb
*self
= (struct ircomm_tty_cb
*) instance
;
463 IRDA_DEBUG(2, __FUNCTION__
"()\n");
465 ASSERT(self
!= NULL
, return;);
466 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
468 self
->client
= FALSE
;
469 self
->max_data_size
= max_data_size
;
470 self
->max_header_size
= max_header_size
;
471 self
->flow
= FLOW_START
;
475 irda_param_extract_all(self
, skb
->data
+1,
476 IRDA_MIN(skb
->len
, clen
),
479 ircomm_tty_do_event(self
, IRCOMM_TTY_CONNECT_INDICATION
, NULL
, NULL
);
485 * Function ircomm_tty_link_established (self)
487 * Called when the IrCOMM link is established
490 void ircomm_tty_link_established(struct ircomm_tty_cb
*self
)
492 IRDA_DEBUG(2, __FUNCTION__
"()\n");
494 ASSERT(self
!= NULL
, return;);
495 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
500 del_timer(&self
->watchdog_timer
);
503 * IrCOMM link is now up, and if we are not using hardware
504 * flow-control, then declare the hardware as running. Otherwise we
505 * will have to wait for the peer device (DCE) to raise the CTS
508 if (self
->flags
& ASYNC_CTS_FLOW
) {
509 IRDA_DEBUG(0, __FUNCTION__
"(), waiting for CTS ...\n");
512 IRDA_DEBUG(2, __FUNCTION__
"(), starting hardware!\n");
514 self
->tty
->hw_stopped
= 0;
516 /* Wake up processes blocked on open */
517 wake_up_interruptible(&self
->open_wait
);
520 queue_task(&self
->tqueue
, &tq_immediate
);
521 mark_bh(IMMEDIATE_BH
);
525 * Function irlan_start_watchdog_timer (self, timeout)
527 * Start the watchdog timer. This timer is used to make sure that any
528 * connection attempt is successful, and if not, we will retry after
531 void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb
*self
, int timeout
)
533 ASSERT(self
!= NULL
, return;);
534 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
536 irda_start_timer(&self
->watchdog_timer
, timeout
, (void *) self
,
537 ircomm_tty_watchdog_timer_expired
);
541 * Function ircomm_tty_watchdog_timer_expired (data)
543 * Called when the connect procedure have taken to much time.
546 void ircomm_tty_watchdog_timer_expired(void *data
)
548 struct ircomm_tty_cb
*self
= (struct ircomm_tty_cb
*) data
;
550 IRDA_DEBUG(2, __FUNCTION__
"()\n");
552 ASSERT(self
!= NULL
, return;);
553 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
555 ircomm_tty_do_event(self
, IRCOMM_TTY_WD_TIMER_EXPIRED
, NULL
, NULL
);
559 * Function ircomm_tty_state_idle (self, event, skb, info)
561 * Just hanging around
564 static int ircomm_tty_state_idle(struct ircomm_tty_cb
*self
,
565 IRCOMM_TTY_EVENT event
,
567 struct ircomm_tty_info
*info
)
571 IRDA_DEBUG(2, __FUNCTION__
": state=%s, event=%s\n",
572 ircomm_tty_state
[self
->state
], ircomm_tty_event
[event
]);
574 case IRCOMM_TTY_ATTACH_CABLE
:
575 /* Try to discover any remote devices */
576 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
577 ircomm_tty_next_state(self
, IRCOMM_TTY_SEARCH
);
579 irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS
);
581 case IRCOMM_TTY_DISCOVERY_INDICATION
:
582 self
->daddr
= info
->daddr
;
583 self
->saddr
= info
->saddr
;
587 "(), busy with a previous query\n");
591 self
->iriap
= iriap_open(LSAP_ANY
, IAS_CLIENT
, self
,
592 ircomm_tty_getvalue_confirm
);
594 iriap_getvaluebyclass_request(self
->iriap
,
595 self
->saddr
, self
->daddr
,
596 "IrDA:IrCOMM", "Parameters");
598 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
599 ircomm_tty_next_state(self
, IRCOMM_TTY_QUERY_PARAMETERS
);
601 case IRCOMM_TTY_CONNECT_INDICATION
:
602 del_timer(&self
->watchdog_timer
);
604 /* Accept connection */
605 ircomm_connect_response(self
->ircomm
, NULL
);
606 ircomm_tty_next_state(self
, IRCOMM_TTY_READY
);
608 case IRCOMM_TTY_WD_TIMER_EXPIRED
:
611 case IRCOMM_TTY_DETACH_CABLE
:
612 ircomm_tty_next_state(self
, IRCOMM_TTY_IDLE
);
615 IRDA_DEBUG(2, __FUNCTION__
"(), unknown event: %s\n",
616 ircomm_tty_event
[event
]);
623 * Function ircomm_tty_state_search (self, event, skb, info)
625 * Trying to discover an IrCOMM device
628 static int ircomm_tty_state_search(struct ircomm_tty_cb
*self
,
629 IRCOMM_TTY_EVENT event
,
631 struct ircomm_tty_info
*info
)
635 IRDA_DEBUG(2, __FUNCTION__
": state=%s, event=%s\n",
636 ircomm_tty_state
[self
->state
], ircomm_tty_event
[event
]);
639 case IRCOMM_TTY_DISCOVERY_INDICATION
:
640 self
->daddr
= info
->daddr
;
641 self
->saddr
= info
->saddr
;
645 "(), busy with a previous query\n");
649 self
->iriap
= iriap_open(LSAP_ANY
, IAS_CLIENT
, self
,
650 ircomm_tty_getvalue_confirm
);
652 if (self
->service_type
== IRCOMM_3_WIRE_RAW
) {
653 iriap_getvaluebyclass_request(self
->iriap
, self
->saddr
,
654 self
->daddr
, "IrLPT",
655 "IrDA:IrLMP:LsapSel");
656 ircomm_tty_next_state(self
, IRCOMM_TTY_QUERY_LSAP_SEL
);
658 iriap_getvaluebyclass_request(self
->iriap
, self
->saddr
,
663 ircomm_tty_next_state(self
, IRCOMM_TTY_QUERY_PARAMETERS
);
665 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
667 case IRCOMM_TTY_CONNECT_INDICATION
:
668 del_timer(&self
->watchdog_timer
);
670 /* Accept connection */
671 ircomm_connect_response(self
->ircomm
, NULL
);
672 ircomm_tty_next_state(self
, IRCOMM_TTY_READY
);
674 case IRCOMM_TTY_WD_TIMER_EXPIRED
:
678 /* Try to discover any remote devices */
679 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
680 irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS
);
683 case IRCOMM_TTY_DETACH_CABLE
:
684 ircomm_tty_next_state(self
, IRCOMM_TTY_IDLE
);
687 IRDA_DEBUG(2, __FUNCTION__
"(), unknown event: %s\n",
688 ircomm_tty_event
[event
]);
695 * Function ircomm_tty_state_query (self, event, skb, info)
697 * Querying the remote LM-IAS for IrCOMM parameters
700 static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb
*self
,
701 IRCOMM_TTY_EVENT event
,
703 struct ircomm_tty_info
*info
)
707 IRDA_DEBUG(2, __FUNCTION__
": state=%s, event=%s\n",
708 ircomm_tty_state
[self
->state
], ircomm_tty_event
[event
]);
711 case IRCOMM_TTY_GOT_PARAMETERS
:
714 "(), busy with a previous query\n");
718 self
->iriap
= iriap_open(LSAP_ANY
, IAS_CLIENT
, self
,
719 ircomm_tty_getvalue_confirm
);
721 iriap_getvaluebyclass_request(self
->iriap
, self
->saddr
,
722 self
->daddr
, "IrDA:IrCOMM",
723 "IrDA:TinyTP:LsapSel");
725 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
726 ircomm_tty_next_state(self
, IRCOMM_TTY_QUERY_LSAP_SEL
);
728 case IRCOMM_TTY_WD_TIMER_EXPIRED
:
729 /* Go back to search mode */
730 ircomm_tty_next_state(self
, IRCOMM_TTY_SEARCH
);
731 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
733 case IRCOMM_TTY_CONNECT_INDICATION
:
734 del_timer(&self
->watchdog_timer
);
736 /* Accept connection */
737 ircomm_connect_response(self
->ircomm
, NULL
);
738 ircomm_tty_next_state(self
, IRCOMM_TTY_READY
);
740 case IRCOMM_TTY_DETACH_CABLE
:
741 ircomm_tty_next_state(self
, IRCOMM_TTY_IDLE
);
744 IRDA_DEBUG(2, __FUNCTION__
"(), unknown event: %s\n",
745 ircomm_tty_event
[event
]);
752 * Function ircomm_tty_state_query_lsap_sel (self, event, skb, info)
754 * Query remote LM-IAS for the LSAP selector which we can connect to
757 static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb
*self
,
758 IRCOMM_TTY_EVENT event
,
760 struct ircomm_tty_info
*info
)
764 IRDA_DEBUG(2, __FUNCTION__
": state=%s, event=%s\n",
765 ircomm_tty_state
[self
->state
], ircomm_tty_event
[event
]);
768 case IRCOMM_TTY_GOT_LSAPSEL
:
769 /* Connect to remote device */
770 ret
= ircomm_connect_request(self
->ircomm
, self
->dlsap_sel
,
771 self
->saddr
, self
->daddr
,
772 NULL
, self
->service_type
);
773 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
774 ircomm_tty_next_state(self
, IRCOMM_TTY_SETUP
);
776 case IRCOMM_TTY_WD_TIMER_EXPIRED
:
777 /* Go back to search mode */
778 ircomm_tty_next_state(self
, IRCOMM_TTY_SEARCH
);
779 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
781 case IRCOMM_TTY_CONNECT_INDICATION
:
782 del_timer(&self
->watchdog_timer
);
784 /* Accept connection */
785 ircomm_connect_response(self
->ircomm
, NULL
);
786 ircomm_tty_next_state(self
, IRCOMM_TTY_READY
);
788 case IRCOMM_TTY_DETACH_CABLE
:
789 ircomm_tty_next_state(self
, IRCOMM_TTY_IDLE
);
792 IRDA_DEBUG(2, __FUNCTION__
"(), unknown event: %s\n",
793 ircomm_tty_event
[event
]);
800 * Function ircomm_tty_state_setup (self, event, skb, info)
805 static int ircomm_tty_state_setup(struct ircomm_tty_cb
*self
,
806 IRCOMM_TTY_EVENT event
,
808 struct ircomm_tty_info
*info
)
812 IRDA_DEBUG(2, __FUNCTION__
": state=%s, event=%s\n",
813 ircomm_tty_state
[self
->state
], ircomm_tty_event
[event
]);
816 case IRCOMM_TTY_CONNECT_CONFIRM
:
817 del_timer(&self
->watchdog_timer
);
818 ircomm_tty_next_state(self
, IRCOMM_TTY_READY
);
821 * Send initial parameters. This will also send out queued
822 * parameters waiting for the connection to come up
824 ircomm_tty_send_initial_parameters(self
);
825 ircomm_tty_link_established(self
);
827 case IRCOMM_TTY_CONNECT_INDICATION
:
828 del_timer(&self
->watchdog_timer
);
830 /* Accept connection */
831 ircomm_connect_response(self
->ircomm
, NULL
);
832 ircomm_tty_next_state(self
, IRCOMM_TTY_READY
);
834 case IRCOMM_TTY_WD_TIMER_EXPIRED
:
835 /* Go back to search mode */
836 ircomm_tty_next_state(self
, IRCOMM_TTY_SEARCH
);
837 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
839 case IRCOMM_TTY_DETACH_CABLE
:
840 /* ircomm_disconnect_request(self->ircomm, NULL); */
841 ircomm_tty_next_state(self
, IRCOMM_TTY_IDLE
);
844 IRDA_DEBUG(2, __FUNCTION__
"(), unknown event: %s\n",
845 ircomm_tty_event
[event
]);
852 * Function ircomm_tty_state_ready (self, event, skb, info)
854 * IrCOMM is now connected
857 static int ircomm_tty_state_ready(struct ircomm_tty_cb
*self
,
858 IRCOMM_TTY_EVENT event
,
860 struct ircomm_tty_info
*info
)
865 case IRCOMM_TTY_DATA_REQUEST
:
866 ret
= ircomm_data_request(self
->ircomm
, skb
);
868 case IRCOMM_TTY_DETACH_CABLE
:
869 ircomm_disconnect_request(self
->ircomm
, NULL
);
870 ircomm_tty_next_state(self
, IRCOMM_TTY_IDLE
);
872 case IRCOMM_TTY_DISCONNECT_INDICATION
:
873 ircomm_tty_next_state(self
, IRCOMM_TTY_SEARCH
);
874 ircomm_tty_start_watchdog_timer(self
, 3*HZ
);
876 if (self
->flags
& ASYNC_CHECK_CD
) {
878 self
->settings
.dce
= IRCOMM_DELTA_CD
;
879 ircomm_tty_check_modem_status(self
);
881 IRDA_DEBUG(0, __FUNCTION__
"(), hanging up!\n");
883 tty_hangup(self
->tty
);
887 IRDA_DEBUG(2, __FUNCTION__
"(), unknown event: %s\n",
888 ircomm_tty_event
[event
]);
895 * Function ircomm_tty_do_event (self, event, skb)
900 int ircomm_tty_do_event(struct ircomm_tty_cb
*self
, IRCOMM_TTY_EVENT event
,
901 struct sk_buff
*skb
, struct ircomm_tty_info
*info
)
903 ASSERT(self
!= NULL
, return -1;);
904 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return -1;);
906 IRDA_DEBUG(2, __FUNCTION__
": state=%s, event=%s\n",
907 ircomm_tty_state
[self
->state
], ircomm_tty_event
[event
]);
909 return (*state
[self
->state
])(self
, event
, skb
, info
);
913 * Function ircomm_tty_next_state (self, state)
918 void ircomm_tty_next_state(struct ircomm_tty_cb
*self
, IRCOMM_TTY_STATE state
)
920 ASSERT(self
!= NULL
, return;);
921 ASSERT(self
->magic
== IRCOMM_TTY_MAGIC
, return;);
925 IRDA_DEBUG(2, __FUNCTION__
": next state=%s, service type=%d\n",
926 ircomm_tty_state
[self
->state
], self
->service_type
);