ircomm_tty_attach.c revision ea110733874d5176cb56dcf612a629ffac09dbf0
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 266819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * along with this program; if not, write to the Free Software 276819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MA 02111-1307 USA 296819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************/ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 33d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/sched.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irda.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irlmp.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/iriap.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irttp.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/irias_object.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/parameters.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_core.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_param.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_event.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_tty.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/irda/ircomm_tty_attach.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_ias_register(struct ircomm_tty_cb *self); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_discovery_indication(discinfo_t *discovery, 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DISCOVERY_MODE mode, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *priv); 536819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ias_value *value, void *priv); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int timeout); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_watchdog_timer_expired(void *data); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 596819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 606819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 616819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info); 636819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_search(struct ircomm_tty_cb *self, 646819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 656819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info); 676819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 686819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 696819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info); 716819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 726819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 736819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info); 756819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 766819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 776819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info); 796819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 806819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 816819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8436cbd3dcc10384f813ec0814255f576c84f2bcd4Jan Engelhardtconst char *const ircomm_tty_state[] = { 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_IDLE", 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_SEARCH", 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_QUERY_PARAMETERS", 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_QUERY_LSAP_SEL", 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_SETUP", 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_READY", 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "*** ERROR *** ", 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IRDA_DEBUG 9536cbd3dcc10384f813ec0814255f576c84f2bcd4Jan Engelhardtstatic const char *const ircomm_tty_event[] = { 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_ATTACH_CABLE", 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_DETACH_CABLE", 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_DATA_REQUEST", 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_DATA_INDICATION", 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_DISCOVERY_REQUEST", 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_DISCOVERY_INDICATION", 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_CONNECT_CONFIRM", 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_CONNECT_INDICATION", 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_DISCONNECT_REQUEST", 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_DISCONNECT_INDICATION", 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_WD_TIMER_EXPIRED", 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_GOT_PARAMETERS", 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IRCOMM_TTY_GOT_LSAPSEL", 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "*** ERROR ****", 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_IRDA_DEBUG */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, 1146819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, struct ircomm_tty_info *info) = 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state_idle, 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state_search, 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state_query_parameters, 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state_query_lsap_sel, 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state_setup, 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state_ready, 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_attach_cable (driver) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Try to attach cable (IrCOMM link). This function will only return 1286819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * when the link has been connected, or if an error condition occurs. 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If success, the return value is the resulting service type. 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ircomm_tty_attach_cable(struct ircomm_tty_cb *self) 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 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 */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->tty->hw_stopped = 1; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_ias_register(self); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_do_event(self, IRCOMM_TTY_ATTACH_CABLE, NULL, NULL); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_detach_cable (driver) 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Detach cable, or cable has been detached by peer 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ircomm_tty_detach_cable(struct ircomm_tty_cb *self) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1620dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(0, "%s()\n", __func__ ); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove discovery handler */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->ckey) { 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irlmp_unregister_client(self->ckey); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->ckey = NULL; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove IrCOMM hint bits */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->skey) { 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irlmp_unregister_service(self->skey); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->skey = NULL; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1806819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki if (self->iriap) { 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iriap_close(self->iriap); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->iriap = NULL; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove LM-IAS object */ 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->obj) { 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irias_delete_object(self->obj); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->obj = NULL; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_do_event(self, IRCOMM_TTY_DETACH_CABLE, NULL, NULL); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset some values */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->daddr = self->saddr = 0; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->dlsap_sel = self->slsap_sel = 0; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&self->settings, 0, sizeof(struct ircomm_params)); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_ias_register (self) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Register with LM-IAS depending on which service type we are 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_ias_register(struct ircomm_tty_cb *self) 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 oct_seq[6]; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u16 hints; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2110dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(0, "%s()\n", __func__ ); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 2156819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Compute hint bits based on service */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hints = irlmp_service_to_hint(S_COMM); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->service_type & IRCOMM_3_WIRE_RAW) 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hints |= irlmp_service_to_hint(S_PRINTER); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Advertise IrCOMM hint bit in discovery */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!self->skey) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->skey = irlmp_register_service(hints); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up a discovery handler */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!self->ckey) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->ckey = irlmp_register_client(hints, 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_discovery_indication, 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, (void *) self); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If already done, no need to do it again */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->obj) 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->service_type & IRCOMM_3_WIRE_RAW) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register IrLPT with LM-IAS */ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID); 2376819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel", 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->slsap_sel, IAS_KERNEL_ATTR); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register IrCOMM with LM-IAS */ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID); 2426819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel", 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->slsap_sel, IAS_KERNEL_ATTR); 2446819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Code the parameters into the buffer */ 2466819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki irda_param_pack(oct_seq, "bbbbbb", 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRCOMM_SERVICE_TYPE, 1, self->service_type, 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRCOMM_PORT_TYPE, 1, IRCOMM_SERIAL); 2496819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Register parameters with LM-IAS */ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6, 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IAS_KERNEL_ATTR); 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irias_insert_object(self->obj); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_ias_unregister (self) 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Remove our IAS object and client hook while connected. 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_ias_unregister(struct ircomm_tty_cb *self) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove LM-IAS object now so it is not reused. 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IrCOMM deals very poorly with multiple incoming connections. 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It should looks a lot more like IrNET, and "dup" a server TSAP 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the application TSAP (based on various rules). 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a cheap workaround allowing multiple clients to 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connect to us. It will not always work. 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Each IrCOMM socket has an IAS entry. Incoming connection will 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pick the first one found. So, when we are fully connected, 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we remove our IAS entries so that the next IAS entry is used. 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We do that for *both* client and server, because a server 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can also create client instances. 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Jean II */ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->obj) { 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irias_delete_object(self->obj); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->obj = NULL; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove discovery handler. 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * While we are connected, we no longer need to receive 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * discovery events. This would be the case if there is 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * multiple IrLAP interfaces. Jean II */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->ckey) { 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irlmp_unregister_client(self->ckey); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->ckey = NULL; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_send_initial_parameters (self) 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send initial parameters to the remote IrCOMM device. These parameters 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * must be sent before any data. 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self) 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return -1;); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3056819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki if (self->service_type & IRCOMM_3_WIRE_RAW) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3086819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki /* 3096819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * Set default values, but only if the application for some reason 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * haven't set them already 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3120dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), data-rate = %d\n", __func__ , 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->settings.data_rate); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!self->settings.data_rate) 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->settings.data_rate = 9600; 3160dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), data-format = %d\n", __func__ , 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->settings.data_format); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!self->settings.data_format) 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->settings.data_format = IRCOMM_WSIZE_8; /* 8N1 */ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3210dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), flow-control = %d\n", __func__ , 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->settings.flow_control); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/ 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Do not set delta values for the initial parameters */ 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->settings.dte = IRCOMM_DTR | IRCOMM_RTS; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only send service type parameter when we are the client */ 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->client) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE); 3336819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For a 3 wire service, we just flush the last parameter and return */ 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->settings.service_type == IRCOMM_3_WIRE) { 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only 9-wire service types continue here */ 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_FLOW_CONTROL, FALSE); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE); 3456819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki#endif 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Notify peer that we are ready to receive data */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_param_request(self, IRCOMM_DTE, TRUE); 3486819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_discovery_indication (discovery) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Remote device is discovered, try query the remote IAS to see which 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device it is, and which services it has. 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_discovery_indication(discinfo_t *discovery, 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DISCOVERY_MODE mode, 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *priv) 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_cb *self; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info info; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3660dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s()\n", __func__ ); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Important note : 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We need to drop all passive discoveries. 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The LSAP management of IrComm is deficient and doesn't deal 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with the case of two instance connecting to each other 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * simultaneously (it will deadlock in LMP). 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The proper fix would be to use the same technique as in IrNET, 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to have one server socket and separate instances for the 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * connecting/connected socket. 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The workaround is to drop passive discovery, which drastically 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reduce the probability of this happening. 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Jean II */ 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(mode == DISCOVERY_PASSIVE) 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.daddr = discovery->daddr; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info.saddr = discovery->saddr; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 385ea110733874d5176cb56dcf612a629ffac09dbf0Joe Perches self = priv; 386c310f099be953a20b5fabed341ad085f444cf2bdRyan Reading ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION, 387c310f099be953a20b5fabed341ad085f444cf2bdRyan Reading NULL, &info); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb) 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Link disconnected 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3966819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakivoid ircomm_tty_disconnect_indication(void *instance, void *sap, 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LM_REASON reason, 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4020dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s()\n", __func__ ); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!self->tty) 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This will stop control data transfers */ 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->flow = FLOW_STOP; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Stop data transfers */ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->tty->hw_stopped = 1; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4166819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_getvalue_confirm (result, obj_id, value, priv) 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Got result from the IAS query we make 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4266819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 4276819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct ias_value *value, 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *priv) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv; 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4320dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s()\n", __func__ ); 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We probably don't need to make any more queries */ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iriap_close(self->iriap); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->iriap = NULL; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check if request succeeded */ 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result != IAS_SUCCESS) { 4430dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(4, "%s(), got NULL value!\n", __func__ ); 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (value->type) { 4486819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki case IAS_OCT_SEQ: 4490dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), got octet sequence\n", __func__ ); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irda_param_extract_all(self, value->t.oct_seq, value->len, 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ircomm_param_info); 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4546819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL, 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IAS_INTEGER: 4586819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki /* Got LSAP selector */ 4590dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), got lsapsel = %d\n", __func__ , 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value->t.integer); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (value->t.integer == -1) { 4630dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(0, "%s(), invalid value!\n", __func__ ); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->dlsap_sel = value->t.integer; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL); 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IAS_MISSING: 4700dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(0, "%s(), got IAS_MISSING\n", __func__ ); 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4730dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(0, "%s(), got unknown type!\n", __func__ ); 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irias_delete_value(value); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_connect_confirm (instance, sap, qos, max_sdu_size, skb) 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Connection confirmed 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4856819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakivoid ircomm_tty_connect_confirm(void *instance, void *sap, 4866819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct qos_info *qos, 4876819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki __u32 max_data_size, 4886819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki __u8 max_header_size, 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb) 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4930dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s()\n", __func__ ); 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->client = TRUE; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->max_data_size = max_data_size; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->max_header_size = max_header_size; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->flow = FLOW_START; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* No need to kfree_skb - see ircomm_ttp_connect_confirm() */ 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5096819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size, 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * skb) 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we are discovered and being requested to connect by remote device ! 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5156819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakivoid ircomm_tty_connect_indication(void *instance, void *sap, 5166819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct qos_info *qos, 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u32 max_data_size, 5186819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki __u8 max_header_size, 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb) 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int clen; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5240dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s()\n", __func__ ); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->client = FALSE; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->max_data_size = max_data_size; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->max_header_size = max_header_size; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->flow = FLOW_START; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clen = skb->data[0]; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clen) 5366819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki irda_param_extract_all(self, skb->data+1, 5376819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRDA_MIN(skb->len, clen), 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &ircomm_param_info); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* No need to kfree_skb - see ircomm_ttp_connect_indication() */ 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_link_established (self) 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called when the IrCOMM link is established 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid ircomm_tty_link_established(struct ircomm_tty_cb *self) 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5530dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s()\n", __func__ ); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!self->tty) 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5606819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5636819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki /* 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IrCOMM link is now up, and if we are not using hardware 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * flow-control, then declare the hardware as running. Otherwise we 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will have to wait for the peer device (DCE) to raise the CTS 5676819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * line. 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((self->flags & ASYNC_CTS_FLOW) && ((self->settings.dce & IRCOMM_CTS) == 0)) { 5700dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(0, "%s(), waiting for CTS ...\n", __func__ ); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5730dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(1, "%s(), starting hardware!\n", __func__ ); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->tty->hw_stopped = 0; 5766819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wake up processes blocked on open */ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&self->open_wait); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_work(&self->tqueue); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_start_watchdog_timer (self, timeout) 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5876819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * Start the watchdog timer. This timer is used to make sure that any 5886819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * connection attempt is successful, and if not, we will retry after 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the timeout 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int timeout) 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irda_start_timer(&self->watchdog_timer, timeout, (void *) self, 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_watchdog_timer_expired); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_watchdog_timer_expired (data) 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Called when the connect procedure have taken to much time. 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ircomm_tty_watchdog_timer_expired(void *data) 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data; 6106819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 6110dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s()\n", __func__ ); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_do_event (self, event, skb) 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Process event 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, 6276819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, struct ircomm_tty_info *info) 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return -1;); 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6320dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ , 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state[self->state], ircomm_tty_event[event]); 6346819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (*state[self->state])(self, event, skb, info); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_next_state (self, state) 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch state 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state) 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self != NULL, return;); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6500dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __func__ , 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state[self->state], self->service_type); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->state = state; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_idle (self, event, skb, info) 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Just hanging around 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6626819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 6636819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 6646819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info) 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6690dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ , 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state[self->state], ircomm_tty_event[event]); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_ATTACH_CABLE: 6736819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki /* Try to discover any remote devices */ 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); 6766819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DISCOVERY_INDICATION: 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->daddr = info->daddr; 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->saddr = info->saddr; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->iriap) { 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_WARNING("%s(), busy with a previous query\n", 6850dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison __func__); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_getvalue_confirm); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iriap_getvaluebyclass_request(self->iriap, 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->saddr, self->daddr, 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IrDA:IrCOMM", "Parameters"); 6956819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS); 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_CONNECT_INDICATION: 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Accept connection */ 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_connect_response(self->ircomm, NULL); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_READY); 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_WD_TIMER_EXPIRED: 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Just stay idle */ 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DETACH_CABLE: 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7130dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ , 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_event[event]); 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_search (self, event, skb, info) 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Trying to discover an IrCOMM device 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7266819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_search(struct ircomm_tty_cb *self, 7276819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 7286819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info) 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7330dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ , 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state[self->state], ircomm_tty_event[event]); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DISCOVERY_INDICATION: 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->daddr = info->daddr; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->saddr = info->saddr; 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->iriap) { 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_WARNING("%s(), busy with a previous query\n", 7430dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison __func__); 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7466819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_getvalue_confirm); 7496819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->service_type == IRCOMM_3_WIRE_RAW) { 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iriap_getvaluebyclass_request(self->iriap, self->saddr, 7526819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki self->daddr, "IrLPT", 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IrDA:IrLMP:LsapSel"); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iriap_getvaluebyclass_request(self->iriap, self->saddr, 7576819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki self->daddr, 7586819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki "IrDA:IrCOMM", 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Parameters"); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS); 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_CONNECT_INDICATION: 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_ias_unregister(self); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Accept connection */ 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_connect_response(self->ircomm, NULL); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_READY); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_WD_TIMER_EXPIRED: 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 1 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Give up */ 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 7776819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki /* Try to discover any remote devices */ 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DETACH_CABLE: 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7860dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ , 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_event[event]); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_query (self, event, skb, info) 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Querying the remote LM-IAS for IrCOMM parameters 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7996819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 8006819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 8016819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info) 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8060dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ , 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state[self->state], ircomm_tty_event[event]); 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_GOT_PARAMETERS: 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->iriap) { 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IRDA_WARNING("%s(), busy with a previous query\n", 8130dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison __func__); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8166819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_getvalue_confirm); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8206819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki iriap_getvaluebyclass_request(self->iriap, self->saddr, 8216819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki self->daddr, "IrDA:IrCOMM", 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IrDA:TinyTP:LsapSel"); 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL); 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_WD_TIMER_EXPIRED: 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Go back to search mode */ 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); 8306819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki ircomm_tty_start_watchdog_timer(self, 3*HZ); 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_CONNECT_INDICATION: 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_ias_unregister(self); 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Accept connection */ 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_connect_response(self->ircomm, NULL); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_READY); 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DETACH_CABLE: 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8440dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ , 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_event[event]); 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_query_lsap_sel (self, event, skb, info) 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Query remote LM-IAS for the LSAP selector which we can connect to 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8576819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 8586819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 8596819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info) 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8640dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ , 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state[self->state], ircomm_tty_event[event]); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_GOT_LSAPSEL: 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Connect to remote device */ 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ircomm_connect_request(self->ircomm, self->dlsap_sel, 8716819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki self->saddr, self->daddr, 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NULL, self->service_type); 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_SETUP); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_WD_TIMER_EXPIRED: 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Go back to search mode */ 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_CONNECT_INDICATION: 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_ias_unregister(self); 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Accept connection */ 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_connect_response(self->ircomm, NULL); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_READY); 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DETACH_CABLE: 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8930dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ , 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_event[event]); 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_setup (self, event, skb, info) 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Trying to connect 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9066819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 9076819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 9086819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info) 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9130dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __func__ , 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_state[self->state], ircomm_tty_event[event]); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_CONNECT_CONFIRM: 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_ias_unregister(self); 9206819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 9216819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki /* 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send initial parameters. This will also send out queued 9236819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki * parameters waiting for the connection to come up 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_send_initial_parameters(self); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_link_established(self); 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_READY); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_CONNECT_INDICATION: 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer(&self->watchdog_timer); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_ias_unregister(self); 9326819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Accept connection */ 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_connect_response(self->ircomm, NULL); 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_READY); 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_WD_TIMER_EXPIRED: 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Go back to search mode */ 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DETACH_CABLE: 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ircomm_disconnect_request(self->ircomm, NULL); */ 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9470dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ , 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_event[event]); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function ircomm_tty_state_ready (self, event, skb, info) 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IrCOMM is now connected 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9606819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideakistatic int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 9616819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki IRCOMM_TTY_EVENT event, 9626819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki struct sk_buff *skb, 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ircomm_tty_info *info) 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DATA_REQUEST: 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = ircomm_data_request(self->ircomm, skb); 9706819bc2e1e46c71711a8dddf4040e706b02973c0YOSHIFUJI Hideaki break; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DETACH_CABLE: 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_disconnect_request(self->ircomm, NULL); 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case IRCOMM_TTY_DISCONNECT_INDICATION: 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_ias_register(self); 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_start_watchdog_timer(self, 3*HZ); 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->flags & ASYNC_CHECK_CD) { 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Drop carrier */ 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds self->settings.dce = IRCOMM_DELTA_CD; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_check_modem_status(self); 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9850dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(0, "%s(), hanging up!\n", __func__ ); 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (self->tty) 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_hangup(self->tty); 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9910dc47877a3de00ceadea0005189656ae8dc52669Harvey Harrison IRDA_DEBUG(2, "%s(), unknown event: %s\n", __func__ , 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ircomm_tty_event[event]); 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EINVAL; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 998