11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************************************************
26819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Filename:      ircomm_tty_attach.c
46819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * Version:
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Description:   Code for attaching the serial driver to IrCOMM
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Status:        Experimental.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author:        Dag Brattli <dagb@cs.uit.no>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Created at:    Sat Jun  5 17:42:00 1999
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified at:   Tue Jan  4 14:20:49 2000
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Modified by:   Dag Brattli <dagb@cs.uit.no>
116819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
146819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *
156819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *     This program is free software; you can redistribute it and/or
166819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *     modify it under the terms of the GNU General Public License as
176819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *     published by the Free Software Foundation; either version 2 of
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     the License, or (at your option) any later version.
196819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     This program is distributed in the hope that it will be useful,
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     but WITHOUT ANY WARRANTY; without even the implied warranty of
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     GNU General Public License for more details.
246819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *
256819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *     You should have received a copy of the GNU General Public License
26d37705092fb1bad8dade186451f3cca754a5d1d1Jeff Kirsher *     along with this program; if not, see <http://www.gnu.org/licenses/>.
276819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************/
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
31d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/sched.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irda.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irlmp.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/iriap.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irttp.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irias_object.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/parameters.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_core.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_param.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_event.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_tty.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_tty_attach.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_ias_register(struct ircomm_tty_cb *self);
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_discovery_indication(discinfo_t *discovery,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    DISCOVERY_MODE mode,
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    void *priv);
516819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					struct ias_value *value, void *priv);
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self,
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    int timeout);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_watchdog_timer_expired(void *data);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
576819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
586819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				 IRCOMM_TTY_EVENT event,
596819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				 struct sk_buff *skb,
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 struct ircomm_tty_info *info);
616819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_search(struct ircomm_tty_cb *self,
626819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				   IRCOMM_TTY_EVENT event,
636819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				   struct sk_buff *skb,
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   struct ircomm_tty_info *info);
656819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
666819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					     IRCOMM_TTY_EVENT event,
676819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					     struct sk_buff *skb,
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     struct ircomm_tty_info *info);
696819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
706819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					   IRCOMM_TTY_EVENT event,
716819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					   struct sk_buff *skb,
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   struct ircomm_tty_info *info);
736819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
746819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  IRCOMM_TTY_EVENT event,
756819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  struct sk_buff *skb,
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  struct ircomm_tty_info *info);
776819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
786819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  IRCOMM_TTY_EVENT event,
796819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  struct sk_buff *skb,
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  struct ircomm_tty_info *info);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8236cbd3dcc10384f813ec0814255f576c84f2bcd4Jan Engelhardtconst char *const ircomm_tty_state[] = {
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_IDLE",
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_SEARCH",
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_QUERY_PARAMETERS",
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_QUERY_LSAP_SEL",
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_SETUP",
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_READY",
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"*** ERROR *** ",
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IRDA_DEBUG
9336cbd3dcc10384f813ec0814255f576c84f2bcd4Jan Engelhardtstatic const char *const ircomm_tty_event[] = {
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_ATTACH_CABLE",
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_DETACH_CABLE",
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_DATA_REQUEST",
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_DATA_INDICATION",
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_DISCOVERY_REQUEST",
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_DISCOVERY_INDICATION",
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_CONNECT_CONFIRM",
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_CONNECT_INDICATION",
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_DISCONNECT_REQUEST",
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_DISCONNECT_INDICATION",
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_WD_TIMER_EXPIRED",
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_GOT_PARAMETERS",
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"IRCOMM_TTY_GOT_LSAPSEL",
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"*** ERROR ****",
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_IRDA_DEBUG */
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
1126819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		      struct sk_buff *skb, struct ircomm_tty_info *info) =
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_state_idle,
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_state_search,
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_state_query_parameters,
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_state_query_lsap_sel,
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_state_setup,
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_state_ready,
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_attach_cable (driver)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Try to attach cable (IrCOMM link). This function will only return
1266819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *    when the link has been connected, or if an error condition occurs.
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    If success, the return value is the resulting service type.
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13162f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	struct tty_struct *tty;
13262f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby
1330dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(0, "%s()\n", __func__ );
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return -1;);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1386819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	/* Check if somebody has already connected to us */
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ircomm_is_connected(self->ircomm)) {
1400dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(0, "%s(), already connected!\n", __func__ );
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure nobody tries to write before the link is up */
14562f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	tty = tty_port_tty_get(&self->port);
14662f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	if (tty) {
14762f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby		tty->hw_stopped = 1;
14862f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby		tty_kref_put(tty);
14962f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	}
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_ias_register(self);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_do_event(self, IRCOMM_TTY_ATTACH_CABLE, NULL, NULL);
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_detach_cable (driver)
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Detach cable, or cable has been detached by peer
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1660dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(0, "%s()\n", __func__ );
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer(&self->watchdog_timer);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Remove discovery handler */
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->ckey) {
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irlmp_unregister_client(self->ckey);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->ckey = NULL;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Remove IrCOMM hint bits */
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->skey) {
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irlmp_unregister_service(self->skey);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->skey = NULL;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1846819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	if (self->iriap) {
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iriap_close(self->iriap);
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->iriap = NULL;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Remove LM-IAS object */
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->obj) {
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irias_delete_object(self->obj);
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->obj = NULL;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_do_event(self, IRCOMM_TTY_DETACH_CABLE, NULL, NULL);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reset some values */
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->daddr = self->saddr = 0;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->dlsap_sel = self->slsap_sel = 0;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(&self->settings, 0, sizeof(struct ircomm_params));
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_ias_register (self)
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Register with LM-IAS depending on which service type we are
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8 oct_seq[6];
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u16 hints;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2150dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(0, "%s()\n", __func__ );
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
2196819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Compute hint bits based on service */
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hints = irlmp_service_to_hint(S_COMM);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->service_type & IRCOMM_3_WIRE_RAW)
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hints |= irlmp_service_to_hint(S_PRINTER);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Advertise IrCOMM hint bit in discovery */
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!self->skey)
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->skey = irlmp_register_service(hints);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up a discovery handler */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!self->ckey)
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->ckey = irlmp_register_client(hints,
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   ircomm_tty_discovery_indication,
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						   NULL, (void *) self);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If already done, no need to do it again */
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->obj)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->service_type & IRCOMM_3_WIRE_RAW) {
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Register IrLPT with LM-IAS */
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
2416819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel",
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 self->slsap_sel, IAS_KERNEL_ATTR);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Register IrCOMM with LM-IAS */
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID);
2466819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel",
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 self->slsap_sel, IAS_KERNEL_ATTR);
2486819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Code the parameters into the buffer */
2506819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		irda_param_pack(oct_seq, "bbbbbb",
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IRCOMM_SERVICE_TYPE, 1, self->service_type,
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				IRCOMM_PORT_TYPE,    1, IRCOMM_SERIAL);
2536819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Register parameters with LM-IAS */
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6,
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					IAS_KERNEL_ATTR);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	irias_insert_object(self->obj);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_ias_unregister (self)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Remove our IAS object and client hook while connected.
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_ias_unregister(struct ircomm_tty_cb *self)
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Remove LM-IAS object now so it is not reused.
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * IrCOMM deals very poorly with multiple incoming connections.
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * It should looks a lot more like IrNET, and "dup" a server TSAP
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to the application TSAP (based on various rules).
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This is a cheap workaround allowing multiple clients to
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * connect to us. It will not always work.
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Each IrCOMM socket has an IAS entry. Incoming connection will
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * pick the first one found. So, when we are fully connected,
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we remove our IAS entries so that the next IAS entry is used.
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We do that for *both* client and server, because a server
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * can also create client instances.
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Jean II */
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->obj) {
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irias_delete_object(self->obj);
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->obj = NULL;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Remove discovery handler.
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * While we are connected, we no longer need to receive
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * discovery events. This would be the case if there is
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * multiple IrLAP interfaces. Jean II */
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->ckey) {
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irlmp_unregister_client(self->ckey);
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->ckey = NULL;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_send_initial_parameters (self)
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Send initial parameters to the remote IrCOMM device. These parameters
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    must be sent before any data.
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return -1;);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3096819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	if (self->service_type & IRCOMM_3_WIRE_RAW)
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3126819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	/*
3136819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	 * Set default values, but only if the application for some reason
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * haven't set them already
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3160dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s(), data-rate = %d\n", __func__ ,
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   self->settings.data_rate);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!self->settings.data_rate)
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->settings.data_rate = 9600;
3200dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s(), data-format = %d\n", __func__ ,
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   self->settings.data_format);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!self->settings.data_format)
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->settings.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3250dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s(), flow-control = %d\n", __func__ ,
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   self->settings.flow_control);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Do not set delta values for the initial parameters */
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->settings.dte = IRCOMM_DTR | IRCOMM_RTS;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Only send service type parameter when we are the client */
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->client)
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
3376819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* For a 3 wire service, we just flush the last parameter and return */
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (self->settings.service_type == IRCOMM_3_WIRE) {
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Only 9-wire service types continue here */
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, FALSE);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE);
3496819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki#endif
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Notify peer that we are ready to receive data */
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_param_request(self, IRCOMM_DTE, TRUE);
3526819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_discovery_indication (discovery)
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Remote device is discovered, try query the remote IAS to see which
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    device it is, and which services it has.
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_discovery_indication(discinfo_t *discovery,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    DISCOVERY_MODE mode,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    void *priv)
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ircomm_tty_cb *self;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ircomm_tty_info info;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3700dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s()\n", __func__ );
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Important note :
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We need to drop all passive discoveries.
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The LSAP management of IrComm is deficient and doesn't deal
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * with the case of two instance connecting to each other
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * simultaneously (it will deadlock in LMP).
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The proper fix would be to use the same technique as in IrNET,
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to have one server socket and separate instances for the
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * connecting/connected socket.
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The workaround is to drop passive discovery, which drastically
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reduce the probability of this happening.
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Jean II */
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(mode == DISCOVERY_PASSIVE)
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.daddr = discovery->daddr;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.saddr = discovery->saddr;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
389ea110733874d5176cb56dcf612a629ffac09dbf0Joe Perches	self = priv;
390c310f099be953a20b5fabed341ad085f444cf2bdRyan Reading	ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
391c310f099be953a20b5fabed341ad085f444cf2bdRyan Reading			    NULL, &info);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb)
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Link disconnected
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4006819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakivoid ircomm_tty_disconnect_indication(void *instance, void *sap,
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      LM_REASON reason,
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      struct sk_buff *skb)
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
40562f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	struct tty_struct *tty;
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4070dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s()\n", __func__ );
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41262f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	tty = tty_port_tty_get(&self->port);
41362f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	if (!tty)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* This will stop control data transfers */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->flow = FLOW_STOP;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Stop data transfers */
42062f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	tty->hw_stopped = 1;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4226819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL,
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    NULL);
42462f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	tty_kref_put(tty);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_getvalue_confirm (result, obj_id, value, priv)
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Got result from the IAS query we make
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4336819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
4346819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					struct ias_value *value,
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					void *priv)
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4390dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s()\n", __func__ );
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We probably don't need to make any more queries */
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iriap_close(self->iriap);
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->iriap = NULL;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check if request succeeded */
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (result != IAS_SUCCESS) {
4500dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(4, "%s(), got NULL value!\n", __func__ );
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (value->type) {
4556819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	case IAS_OCT_SEQ:
4560dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), got octet sequence\n", __func__ );
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irda_param_extract_all(self, value->t.oct_seq, value->len,
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       &ircomm_param_info);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4616819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL,
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    NULL);
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IAS_INTEGER:
4656819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		/* Got LSAP selector */
4660dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __func__ ,
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   value->t.integer);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (value->t.integer == -1) {
4700dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison			IRDA_DEBUG(0, "%s(), invalid value!\n", __func__ );
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			self->dlsap_sel = value->t.integer;
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL);
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IAS_MISSING:
4770dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(0, "%s(), got IAS_MISSING\n", __func__ );
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
4800dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(0, "%s(), got unknown type!\n", __func__ );
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	irias_delete_value(value);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_connect_confirm (instance, sap, qos, max_sdu_size, skb)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Connection confirmed
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4926819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakivoid ircomm_tty_connect_confirm(void *instance, void *sap,
4936819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				struct qos_info *qos,
4946819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				__u32 max_data_size,
4956819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				__u8 max_header_size,
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				struct sk_buff *skb)
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5000dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s()\n", __func__ );
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->client = TRUE;
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->max_data_size = max_data_size;
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->max_header_size = max_header_size;
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->flow = FLOW_START;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL);
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No need to kfree_skb - see ircomm_ttp_connect_confirm() */
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5166819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size,
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                         skb)
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    we are discovered and being requested to connect by remote device !
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5226819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakivoid ircomm_tty_connect_indication(void *instance, void *sap,
5236819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				   struct qos_info *qos,
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   __u32 max_data_size,
5256819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				   __u8 max_header_size,
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   struct sk_buff *skb)
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int clen;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5310dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s()\n", __func__ );
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->client = FALSE;
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->max_data_size = max_data_size;
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->max_header_size = max_header_size;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->flow = FLOW_START;
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clen = skb->data[0];
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (clen)
5436819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		irda_param_extract_all(self, skb->data+1,
5446819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				       IRDA_MIN(skb->len, clen),
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       &ircomm_param_info);
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No need to kfree_skb - see ircomm_ttp_connect_indication() */
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_link_established (self)
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Called when the IrCOMM link is established
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ircomm_tty_link_established(struct ircomm_tty_cb *self)
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
56062f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	struct tty_struct *tty;
56162f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby
5620dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s()\n", __func__ );
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56762f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	tty = tty_port_tty_get(&self->port);
56862f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	if (!tty)
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5706819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer(&self->watchdog_timer);
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5736819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	/*
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * IrCOMM link is now up, and if we are not using hardware
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * flow-control, then declare the hardware as running. Otherwise we
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * will have to wait for the peer device (DCE) to raise the CTS
5776819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki	 * line.
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
579f21ec3d2d46e5f2ffc06f31fe2704fdcea7a58f3Huang Shijie	if (tty_port_cts_enabled(&self->port) &&
580849d5a997fe6a9e44401daed62a98121390ec0d3Jiri Slaby			((self->settings.dce & IRCOMM_CTS) == 0)) {
5810dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ );
58262f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby		goto put;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
5840dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ );
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
58662f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby		tty->hw_stopped = 0;
5876819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Wake up processes blocked on open */
589a3cc9fcff84c4c8aaecda2420acd89a1418d57e9Jiri Slaby		wake_up_interruptible(&self->port.open_wait);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	schedule_work(&self->tqueue);
59362f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slabyput:
59462f228acb807c370c3b1583bf0f1aa4ab8e19acaJiri Slaby	tty_kref_put(tty);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_start_watchdog_timer (self, timeout)
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6006819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *    Start the watchdog timer. This timer is used to make sure that any
6016819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki *    connection attempt is successful, and if not, we will retry after
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    the timeout
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self,
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    int timeout)
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 ircomm_tty_watchdog_timer_expired);
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_watchdog_timer_expired (data)
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Called when the connect procedure have taken to much time.
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_watchdog_timer_expired(void *data)
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
6236819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
6240dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s()\n", __func__ );
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL);
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_do_event (self, event, skb)
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Process event
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
6406819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki			struct sk_buff *skb, struct ircomm_tty_info *info)
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return -1;);
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6450dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
6476819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (*state[self->state])(self, event, skb, info);
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_next_state (self, state)
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Switch state
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state)
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self != NULL, return;);
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6630dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __func__ ,
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   ircomm_tty_state[self->state], self->service_type);
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	self->state = state;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_idle (self, event, skb, info)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Just hanging around
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6756819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
6766819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				 IRCOMM_TTY_EVENT event,
6776819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				 struct sk_buff *skb,
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 struct ircomm_tty_info *info)
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6820dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_ATTACH_CABLE:
6866819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		/* Try to discover any remote devices */
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
6896819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DISCOVERY_INDICATION:
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->daddr = info->daddr;
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->saddr = info->saddr;
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (self->iriap) {
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			IRDA_WARNING("%s(), busy with a previous query\n",
6980dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison				     __func__);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EBUSY;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 ircomm_tty_getvalue_confirm);
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iriap_getvaluebyclass_request(self->iriap,
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					      self->saddr, self->daddr,
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					      "IrDA:IrCOMM", "Parameters");
7086819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_CONNECT_INDICATION:
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&self->watchdog_timer);
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Accept connection */
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_connect_response(self->ircomm, NULL);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_WD_TIMER_EXPIRED:
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Just stay idle */
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DETACH_CABLE:
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
7260dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ircomm_tty_event[event]);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_search (self, event, skb, info)
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Trying to discover an IrCOMM device
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7396819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_search(struct ircomm_tty_cb *self,
7406819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				   IRCOMM_TTY_EVENT event,
7416819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				   struct sk_buff *skb,
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   struct ircomm_tty_info *info)
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7460dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DISCOVERY_INDICATION:
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->daddr = info->daddr;
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->saddr = info->saddr;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (self->iriap) {
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			IRDA_WARNING("%s(), busy with a previous query\n",
7560dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison				     __func__);
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EBUSY;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7596819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 ircomm_tty_getvalue_confirm);
7626819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (self->service_type == IRCOMM_3_WIRE_RAW) {
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iriap_getvaluebyclass_request(self->iriap, self->saddr,
7656819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki						      self->daddr, "IrLPT",
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						      "IrDA:IrLMP:LsapSel");
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			iriap_getvaluebyclass_request(self->iriap, self->saddr,
7706819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki						      self->daddr,
7716819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki						      "IrDA:IrCOMM",
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						      "Parameters");
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_CONNECT_INDICATION:
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&self->watchdog_timer);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_ias_unregister(self);
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Accept connection */
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_connect_response(self->ircomm, NULL);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_WD_TIMER_EXPIRED:
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 1
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Give up */
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
7906819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		/* Try to discover any remote devices */
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DETACH_CABLE:
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
7990dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ircomm_tty_event[event]);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_query (self, event, skb, info)
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Querying the remote LM-IAS for IrCOMM parameters
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8126819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
8136819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					     IRCOMM_TTY_EVENT event,
8146819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					     struct sk_buff *skb,
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     struct ircomm_tty_info *info)
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8190dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_GOT_PARAMETERS:
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (self->iriap) {
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			IRDA_WARNING("%s(), busy with a previous query\n",
8260dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison				     __func__);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EBUSY;
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8296819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 ircomm_tty_getvalue_confirm);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8336819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		iriap_getvaluebyclass_request(self->iriap, self->saddr,
8346819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					      self->daddr, "IrDA:IrCOMM",
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					      "IrDA:TinyTP:LsapSel");
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_WD_TIMER_EXPIRED:
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Go back to search mode */
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
8436819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		ircomm_tty_start_watchdog_timer(self, 3*HZ);
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_CONNECT_INDICATION:
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&self->watchdog_timer);
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_ias_unregister(self);
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Accept connection */
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_connect_response(self->ircomm, NULL);
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DETACH_CABLE:
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
8570dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ircomm_tty_event[event]);
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_query_lsap_sel (self, event, skb, info)
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Query remote LM-IAS for the LSAP selector which we can connect to
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8706819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
8716819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					   IRCOMM_TTY_EVENT event,
8726819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					   struct sk_buff *skb,
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					   struct ircomm_tty_info *info)
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8770dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_GOT_LSAPSEL:
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Connect to remote device */
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = ircomm_connect_request(self->ircomm, self->dlsap_sel,
8846819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki					     self->saddr, self->daddr,
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     NULL, self->service_type);
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_SETUP);
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_WD_TIMER_EXPIRED:
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Go back to search mode */
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_CONNECT_INDICATION:
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&self->watchdog_timer);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_ias_unregister(self);
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Accept connection */
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_connect_response(self->ircomm, NULL);
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DETACH_CABLE:
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
9060dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ircomm_tty_event[event]);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_setup (self, event, skb, info)
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Trying to connect
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9196819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
9206819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  IRCOMM_TTY_EVENT event,
9216819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  struct sk_buff *skb,
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  struct ircomm_tty_info *info)
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9260dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison	IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ ,
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   ircomm_tty_state[self->state], ircomm_tty_event[event]);
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_CONNECT_CONFIRM:
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&self->watchdog_timer);
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_ias_unregister(self);
9336819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
9346819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		/*
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Send initial parameters. This will also send out queued
9366819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		 * parameters waiting for the connection to come up
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_send_initial_parameters(self);
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_link_established(self);
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_CONNECT_INDICATION:
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		del_timer(&self->watchdog_timer);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_ias_unregister(self);
9456819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Accept connection */
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_connect_response(self->ircomm, NULL);
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_WD_TIMER_EXPIRED:
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Go back to search mode */
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DETACH_CABLE:
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* ircomm_disconnect_request(self->ircomm, NULL); */
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
9600dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ircomm_tty_event[event]);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_ready (self, event, skb, info)
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    IrCOMM is now connected
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9736819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
9746819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  IRCOMM_TTY_EVENT event,
9756819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki				  struct sk_buff *skb,
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  struct ircomm_tty_info *info)
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (event) {
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DATA_REQUEST:
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = ircomm_data_request(self->ircomm, skb);
9836819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki		break;
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DETACH_CABLE:
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_disconnect_request(self->ircomm, NULL);
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IRCOMM_TTY_DISCONNECT_INDICATION:
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_ias_register(self);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ircomm_tty_start_watchdog_timer(self, 3*HZ);
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
993849d5a997fe6a9e44401daed62a98121390ec0d3Jiri Slaby		if (self->port.flags & ASYNC_CHECK_CD) {
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Drop carrier */
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			self->settings.dce = IRCOMM_DELTA_CD;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ircomm_tty_check_modem_status(self);
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
9980dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison			IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ );
999aa27a094e2c2e0cc59914e56113b860f524f4479Jiri Slaby			tty_port_tty_hangup(&self->port, false);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
10030dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison		IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ ,
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   ircomm_tty_event[event]);
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1010