diff options
Diffstat (limited to 'net/irda/ircomm')
-rw-r--r-- | net/irda/ircomm/Kconfig | 12 | ||||
-rw-r--r-- | net/irda/ircomm/Makefile | 8 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_core.c | 563 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_event.c | 246 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_lmp.c | 350 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_param.c | 501 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_ttp.c | 350 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_tty.c | 1329 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_tty_attach.c | 987 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_tty_ioctl.c | 291 |
10 files changed, 0 insertions, 4637 deletions
diff --git a/net/irda/ircomm/Kconfig b/net/irda/ircomm/Kconfig deleted file mode 100644 index 19492c1707b7..000000000000 --- a/net/irda/ircomm/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config IRCOMM - tristate "IrCOMM protocol" - depends on IRDA && TTY - help - Say Y here if you want to build support for the IrCOMM protocol. - To compile it as modules, choose M here: the modules will be - called ircomm and ircomm_tty. - IrCOMM implements serial port emulation, and makes it possible to - use all existing applications that understands TTY's with an - infrared link. Thus you should be able to use application like PPP, - minicom and others. - diff --git a/net/irda/ircomm/Makefile b/net/irda/ircomm/Makefile deleted file mode 100644 index ab23b5ba7e33..000000000000 --- a/net/irda/ircomm/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the Linux IrDA IrCOMM protocol layer. -# - -obj-$(CONFIG_IRCOMM) += ircomm.o ircomm-tty.o - -ircomm-y := ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o -ircomm-tty-y := ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o ircomm_param.o diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c deleted file mode 100644 index 3af219545f6d..000000000000 --- a/net/irda/ircomm/ircomm_core.c +++ /dev/null @@ -1,563 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_core.c - * Version: 1.0 - * Description: IrCOMM service interface - * Status: Experimental. - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Sun Jun 6 20:37:34 1999 - * Modified at: Tue Dec 21 13:26:41 1999 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * - * Copyright (c) 1999 Dag Brattli, All Rights Reserved. - * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/module.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#include <linux/init.h> -#include <linux/slab.h> - -#include <net/irda/irda.h> -#include <net/irda/irmod.h> -#include <net/irda/irlmp.h> -#include <net/irda/iriap.h> -#include <net/irda/irttp.h> -#include <net/irda/irias_object.h> - -#include <net/irda/ircomm_event.h> -#include <net/irda/ircomm_lmp.h> -#include <net/irda/ircomm_ttp.h> -#include <net/irda/ircomm_param.h> -#include <net/irda/ircomm_core.h> - -static int __ircomm_close(struct ircomm_cb *self); -static void ircomm_control_indication(struct ircomm_cb *self, - struct sk_buff *skb, int clen); - -#ifdef CONFIG_PROC_FS -extern struct proc_dir_entry *proc_irda; -static int ircomm_seq_open(struct inode *, struct file *); - -static const struct file_operations ircomm_proc_fops = { - .owner = THIS_MODULE, - .open = ircomm_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; -#endif /* CONFIG_PROC_FS */ - -hashbin_t *ircomm = NULL; - -static int __init ircomm_init(void) -{ - ircomm = hashbin_new(HB_LOCK); - if (ircomm == NULL) { - net_err_ratelimited("%s(), can't allocate hashbin!\n", - __func__); - return -ENOMEM; - } - -#ifdef CONFIG_PROC_FS - { struct proc_dir_entry *ent; - ent = proc_create("ircomm", 0, proc_irda, &ircomm_proc_fops); - if (!ent) { - printk(KERN_ERR "ircomm_init: can't create /proc entry!\n"); - return -ENODEV; - } - } -#endif /* CONFIG_PROC_FS */ - - net_info_ratelimited("IrCOMM protocol (Dag Brattli)\n"); - - return 0; -} - -static void __exit ircomm_cleanup(void) -{ - hashbin_delete(ircomm, (FREE_FUNC) __ircomm_close); - -#ifdef CONFIG_PROC_FS - remove_proc_entry("ircomm", proc_irda); -#endif /* CONFIG_PROC_FS */ -} - -/* - * Function ircomm_open (client_notify) - * - * Start a new IrCOMM instance - * - */ -struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line) -{ - struct ircomm_cb *self = NULL; - int ret; - - pr_debug("%s(), service_type=0x%02x\n", __func__ , - service_type); - - IRDA_ASSERT(ircomm != NULL, return NULL;); - - self = kzalloc(sizeof(struct ircomm_cb), GFP_KERNEL); - if (self == NULL) - return NULL; - - self->notify = *notify; - self->magic = IRCOMM_MAGIC; - - /* Check if we should use IrLMP or IrTTP */ - if (service_type & IRCOMM_3_WIRE_RAW) { - self->flow_status = FLOW_START; - ret = ircomm_open_lsap(self); - } else - ret = ircomm_open_tsap(self); - - if (ret < 0) { - kfree(self); - return NULL; - } - - self->service_type = service_type; - self->line = line; - - hashbin_insert(ircomm, (irda_queue_t *) self, line, NULL); - - ircomm_next_state(self, IRCOMM_IDLE); - - return self; -} - -EXPORT_SYMBOL(ircomm_open); - -/* - * Function ircomm_close_instance (self) - * - * Remove IrCOMM instance - * - */ -static int __ircomm_close(struct ircomm_cb *self) -{ - /* Disconnect link if any */ - ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL, NULL); - - /* Remove TSAP */ - if (self->tsap) { - irttp_close_tsap(self->tsap); - self->tsap = NULL; - } - - /* Remove LSAP */ - if (self->lsap) { - irlmp_close_lsap(self->lsap); - self->lsap = NULL; - } - self->magic = 0; - - kfree(self); - - return 0; -} - -/* - * Function ircomm_close (self) - * - * Closes and removes the specified IrCOMM instance - * - */ -int ircomm_close(struct ircomm_cb *self) -{ - struct ircomm_cb *entry; - - IRDA_ASSERT(self != NULL, return -EIO;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;); - - entry = hashbin_remove(ircomm, self->line, NULL); - - IRDA_ASSERT(entry == self, return -1;); - - return __ircomm_close(self); -} - -EXPORT_SYMBOL(ircomm_close); - -/* - * Function ircomm_connect_request (self, service_type) - * - * Impl. of this function is differ from one of the reference. This - * function does discovery as well as sending connect request - * - */ -int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel, - __u32 saddr, __u32 daddr, struct sk_buff *skb, - __u8 service_type) -{ - struct ircomm_info info; - int ret; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;); - - self->service_type= service_type; - - info.dlsap_sel = dlsap_sel; - info.saddr = saddr; - info.daddr = daddr; - - ret = ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, skb, &info); - - return ret; -} - -EXPORT_SYMBOL(ircomm_connect_request); - -/* - * Function ircomm_connect_indication (self, qos, skb) - * - * Notify user layer about the incoming connection - * - */ -void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb, - struct ircomm_info *info) -{ - /* - * If there are any data hiding in the control channel, we must - * deliver it first. The side effect is that the control channel - * will be removed from the skb - */ - if (self->notify.connect_indication) - self->notify.connect_indication(self->notify.instance, self, - info->qos, info->max_data_size, - info->max_header_size, skb); - else { - pr_debug("%s(), missing handler\n", __func__); - } -} - -/* - * Function ircomm_connect_response (self, userdata, max_sdu_size) - * - * User accepts connection - * - */ -int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata) -{ - int ret; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;); - - ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL); - - return ret; -} - -EXPORT_SYMBOL(ircomm_connect_response); - -/* - * Function connect_confirm (self, skb) - * - * Notify user layer that the link is now connected - * - */ -void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb, - struct ircomm_info *info) -{ - if (self->notify.connect_confirm ) - self->notify.connect_confirm(self->notify.instance, - self, info->qos, - info->max_data_size, - info->max_header_size, skb); - else { - pr_debug("%s(), missing handler\n", __func__); - } -} - -/* - * Function ircomm_data_request (self, userdata) - * - * Send IrCOMM data to peer device - * - */ -int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb) -{ - int ret; - - IRDA_ASSERT(self != NULL, return -EFAULT;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;); - IRDA_ASSERT(skb != NULL, return -EFAULT;); - - ret = ircomm_do_event(self, IRCOMM_DATA_REQUEST, skb, NULL); - - return ret; -} - -EXPORT_SYMBOL(ircomm_data_request); - -/* - * Function ircomm_data_indication (self, skb) - * - * Data arrived, so deliver it to user - * - */ -void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb) -{ - IRDA_ASSERT(skb->len > 0, return;); - - if (self->notify.data_indication) - self->notify.data_indication(self->notify.instance, self, skb); - else { - pr_debug("%s(), missing handler\n", __func__); - } -} - -/* - * Function ircomm_process_data (self, skb) - * - * Data arrived which may contain control channel data - * - */ -void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb) -{ - int clen; - - IRDA_ASSERT(skb->len > 0, return;); - - clen = skb->data[0]; - - /* - * Input validation check: a stir4200/mcp2150 combinations sometimes - * results in frames with clen > remaining packet size. These are - * illegal; if we throw away just this frame then it seems to carry on - * fine - */ - if (unlikely(skb->len < (clen + 1))) { - pr_debug("%s() throwing away illegal frame\n", - __func__); - return; - } - - /* - * If there are any data hiding in the control channel, we must - * deliver it first. The side effect is that the control channel - * will be removed from the skb - */ - if (clen > 0) - ircomm_control_indication(self, skb, clen); - - /* Remove control channel from data channel */ - skb_pull(skb, clen+1); - - if (skb->len) - ircomm_data_indication(self, skb); - else { - pr_debug("%s(), data was control info only!\n", - __func__); - } -} - -/* - * Function ircomm_control_request (self, params) - * - * Send control data to peer device - * - */ -int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb) -{ - int ret; - - IRDA_ASSERT(self != NULL, return -EFAULT;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;); - IRDA_ASSERT(skb != NULL, return -EFAULT;); - - ret = ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb, NULL); - - return ret; -} - -EXPORT_SYMBOL(ircomm_control_request); - -/* - * Function ircomm_control_indication (self, skb) - * - * Data has arrived on the control channel - * - */ -static void ircomm_control_indication(struct ircomm_cb *self, - struct sk_buff *skb, int clen) -{ - /* Use udata for delivering data on the control channel */ - if (self->notify.udata_indication) { - struct sk_buff *ctrl_skb; - - /* We don't own the skb, so clone it */ - ctrl_skb = skb_clone(skb, GFP_ATOMIC); - if (!ctrl_skb) - return; - - /* Remove data channel from control channel */ - skb_trim(ctrl_skb, clen+1); - - self->notify.udata_indication(self->notify.instance, self, - ctrl_skb); - - /* Drop reference count - - * see ircomm_tty_control_indication(). */ - dev_kfree_skb(ctrl_skb); - } else { - pr_debug("%s(), missing handler\n", __func__); - } -} - -/* - * Function ircomm_disconnect_request (self, userdata, priority) - * - * User layer wants to disconnect the IrCOMM connection - * - */ -int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata) -{ - struct ircomm_info info; - int ret; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;); - - ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata, - &info); - return ret; -} - -EXPORT_SYMBOL(ircomm_disconnect_request); - -/* - * Function disconnect_indication (self, skb) - * - * Tell user that the link has been disconnected - * - */ -void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb, - struct ircomm_info *info) -{ - IRDA_ASSERT(info != NULL, return;); - - if (self->notify.disconnect_indication) { - self->notify.disconnect_indication(self->notify.instance, self, - info->reason, skb); - } else { - pr_debug("%s(), missing handler\n", __func__); - } -} - -/* - * Function ircomm_flow_request (self, flow) - * - * - * - */ -void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow) -{ - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - - if (self->service_type == IRCOMM_3_WIRE_RAW) - return; - - irttp_flow_request(self->tsap, flow); -} - -EXPORT_SYMBOL(ircomm_flow_request); - -#ifdef CONFIG_PROC_FS -static void *ircomm_seq_start(struct seq_file *seq, loff_t *pos) -{ - struct ircomm_cb *self; - loff_t off = 0; - - spin_lock_irq(&ircomm->hb_spinlock); - - for (self = (struct ircomm_cb *) hashbin_get_first(ircomm); - self != NULL; - self = (struct ircomm_cb *) hashbin_get_next(ircomm)) { - if (off++ == *pos) - break; - - } - return self; -} - -static void *ircomm_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - ++*pos; - - return (void *) hashbin_get_next(ircomm); -} - -static void ircomm_seq_stop(struct seq_file *seq, void *v) -{ - spin_unlock_irq(&ircomm->hb_spinlock); -} - -static int ircomm_seq_show(struct seq_file *seq, void *v) -{ - const struct ircomm_cb *self = v; - - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EINVAL; ); - - if(self->line < 0x10) - seq_printf(seq, "ircomm%d", self->line); - else - seq_printf(seq, "irlpt%d", self->line - 0x10); - - seq_printf(seq, - " state: %s, slsap_sel: %#02x, dlsap_sel: %#02x, mode:", - ircomm_state[ self->state], - self->slsap_sel, self->dlsap_sel); - - if(self->service_type & IRCOMM_3_WIRE_RAW) - seq_printf(seq, " 3-wire-raw"); - if(self->service_type & IRCOMM_3_WIRE) - seq_printf(seq, " 3-wire"); - if(self->service_type & IRCOMM_9_WIRE) - seq_printf(seq, " 9-wire"); - if(self->service_type & IRCOMM_CENTRONICS) - seq_printf(seq, " Centronics"); - seq_putc(seq, '\n'); - - return 0; -} - -static const struct seq_operations ircomm_seq_ops = { - .start = ircomm_seq_start, - .next = ircomm_seq_next, - .stop = ircomm_seq_stop, - .show = ircomm_seq_show, -}; - -static int ircomm_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &ircomm_seq_ops); -} -#endif /* CONFIG_PROC_FS */ - -MODULE_AUTHOR("Dag Brattli <dag@brattli.net>"); -MODULE_DESCRIPTION("IrCOMM protocol"); -MODULE_LICENSE("GPL"); - -module_init(ircomm_init); -module_exit(ircomm_cleanup); diff --git a/net/irda/ircomm/ircomm_event.c b/net/irda/ircomm/ircomm_event.c deleted file mode 100644 index b0730ac9f388..000000000000 --- a/net/irda/ircomm/ircomm_event.c +++ /dev/null @@ -1,246 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_event.c - * Version: 1.0 - * Description: IrCOMM layer state machine - * Status: Stable - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Sun Jun 6 20:33:11 1999 - * Modified at: Sun Dec 12 13:44:32 1999 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * - * Copyright (c) 1999 Dag Brattli, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/proc_fs.h> -#include <linux/init.h> - -#include <net/irda/irda.h> -#include <net/irda/irlmp.h> -#include <net/irda/iriap.h> -#include <net/irda/irttp.h> -#include <net/irda/irias_object.h> - -#include <net/irda/ircomm_core.h> -#include <net/irda/ircomm_event.h> - -static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info); -static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info); -static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info); -static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info); - -const char *const ircomm_state[] = { - "IRCOMM_IDLE", - "IRCOMM_WAITI", - "IRCOMM_WAITR", - "IRCOMM_CONN", -}; - -static const char *const ircomm_event[] __maybe_unused = { - "IRCOMM_CONNECT_REQUEST", - "IRCOMM_CONNECT_RESPONSE", - "IRCOMM_TTP_CONNECT_INDICATION", - "IRCOMM_LMP_CONNECT_INDICATION", - "IRCOMM_TTP_CONNECT_CONFIRM", - "IRCOMM_LMP_CONNECT_CONFIRM", - - "IRCOMM_LMP_DISCONNECT_INDICATION", - "IRCOMM_TTP_DISCONNECT_INDICATION", - "IRCOMM_DISCONNECT_REQUEST", - - "IRCOMM_TTP_DATA_INDICATION", - "IRCOMM_LMP_DATA_INDICATION", - "IRCOMM_DATA_REQUEST", - "IRCOMM_CONTROL_REQUEST", - "IRCOMM_CONTROL_INDICATION", -}; - -static int (*state[])(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info) = -{ - ircomm_state_idle, - ircomm_state_waiti, - ircomm_state_waitr, - ircomm_state_conn, -}; - -/* - * Function ircomm_state_idle (self, event, skb) - * - * IrCOMM is currently idle - * - */ -static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info) -{ - int ret = 0; - - switch (event) { - case IRCOMM_CONNECT_REQUEST: - ircomm_next_state(self, IRCOMM_WAITI); - ret = self->issue.connect_request(self, skb, info); - break; - case IRCOMM_TTP_CONNECT_INDICATION: - case IRCOMM_LMP_CONNECT_INDICATION: - ircomm_next_state(self, IRCOMM_WAITR); - ircomm_connect_indication(self, skb, info); - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_state_waiti (self, event, skb) - * - * The IrCOMM user has requested an IrCOMM connection to the remote - * device and is awaiting confirmation - */ -static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info) -{ - int ret = 0; - - switch (event) { - case IRCOMM_TTP_CONNECT_CONFIRM: - case IRCOMM_LMP_CONNECT_CONFIRM: - ircomm_next_state(self, IRCOMM_CONN); - ircomm_connect_confirm(self, skb, info); - break; - case IRCOMM_TTP_DISCONNECT_INDICATION: - case IRCOMM_LMP_DISCONNECT_INDICATION: - ircomm_next_state(self, IRCOMM_IDLE); - ircomm_disconnect_indication(self, skb, info); - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_state_waitr (self, event, skb) - * - * IrCOMM has received an incoming connection request and is awaiting - * response from the user - */ -static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info) -{ - int ret = 0; - - switch (event) { - case IRCOMM_CONNECT_RESPONSE: - ircomm_next_state(self, IRCOMM_CONN); - ret = self->issue.connect_response(self, skb); - break; - case IRCOMM_DISCONNECT_REQUEST: - ircomm_next_state(self, IRCOMM_IDLE); - ret = self->issue.disconnect_request(self, skb, info); - break; - case IRCOMM_TTP_DISCONNECT_INDICATION: - case IRCOMM_LMP_DISCONNECT_INDICATION: - ircomm_next_state(self, IRCOMM_IDLE); - ircomm_disconnect_indication(self, skb, info); - break; - default: - pr_debug("%s(), unknown event = %s\n", __func__ , - ircomm_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_state_conn (self, event, skb) - * - * IrCOMM is connected to the peer IrCOMM device - * - */ -static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info) -{ - int ret = 0; - - switch (event) { - case IRCOMM_DATA_REQUEST: - ret = self->issue.data_request(self, skb, 0); - break; - case IRCOMM_TTP_DATA_INDICATION: - ircomm_process_data(self, skb); - break; - case IRCOMM_LMP_DATA_INDICATION: - ircomm_data_indication(self, skb); - break; - case IRCOMM_CONTROL_REQUEST: - /* Just send a separate frame for now */ - ret = self->issue.data_request(self, skb, skb->len); - break; - case IRCOMM_TTP_DISCONNECT_INDICATION: - case IRCOMM_LMP_DISCONNECT_INDICATION: - ircomm_next_state(self, IRCOMM_IDLE); - ircomm_disconnect_indication(self, skb, info); - break; - case IRCOMM_DISCONNECT_REQUEST: - ircomm_next_state(self, IRCOMM_IDLE); - ret = self->issue.disconnect_request(self, skb, info); - break; - default: - pr_debug("%s(), unknown event = %s\n", __func__ , - ircomm_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_do_event (self, event, skb) - * - * Process event - * - */ -int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb, struct ircomm_info *info) -{ - pr_debug("%s: state=%s, event=%s\n", __func__ , - ircomm_state[self->state], ircomm_event[event]); - - return (*state[self->state])(self, event, skb, info); -} - -/* - * Function ircomm_next_state (self, state) - * - * Switch state - * - */ -void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state) -{ - self->state = state; - - pr_debug("%s: next state=%s, service type=%d\n", __func__ , - ircomm_state[self->state], self->service_type); -} diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c deleted file mode 100644 index e4cc847bb933..000000000000 --- a/net/irda/ircomm/ircomm_lmp.c +++ /dev/null @@ -1,350 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_lmp.c - * Version: 1.0 - * Description: Interface between IrCOMM and IrLMP - * Status: Stable - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Sun Jun 6 20:48:27 1999 - * Modified at: Sun Dec 12 13:44:17 1999 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * Sources: Previous IrLPT work by Thomas Davis - * - * Copyright (c) 1999 Dag Brattli, All Rights Reserved. - * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/init.h> -#include <linux/gfp.h> - -#include <net/irda/irda.h> -#include <net/irda/irlmp.h> -#include <net/irda/iriap.h> -#include <net/irda/irda_device.h> /* struct irda_skb_cb */ - -#include <net/irda/ircomm_event.h> -#include <net/irda/ircomm_lmp.h> - - -/* - * Function ircomm_lmp_connect_request (self, userdata) - * - * - * - */ -static int ircomm_lmp_connect_request(struct ircomm_cb *self, - struct sk_buff *userdata, - struct ircomm_info *info) -{ - int ret = 0; - - /* Don't forget to refcount it - should be NULL anyway */ - if(userdata) - skb_get(userdata); - - ret = irlmp_connect_request(self->lsap, info->dlsap_sel, - info->saddr, info->daddr, NULL, userdata); - return ret; -} - -/* - * Function ircomm_lmp_connect_response (self, skb) - * - * - * - */ -static int ircomm_lmp_connect_response(struct ircomm_cb *self, - struct sk_buff *userdata) -{ - struct sk_buff *tx_skb; - - /* Any userdata supplied? */ - if (userdata == NULL) { - tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC); - if (!tx_skb) - return -ENOMEM; - - /* Reserve space for MUX and LAP header */ - skb_reserve(tx_skb, LMP_MAX_HEADER); - } else { - /* - * Check that the client has reserved enough space for - * headers - */ - IRDA_ASSERT(skb_headroom(userdata) >= LMP_MAX_HEADER, - return -1;); - - /* Don't forget to refcount it - should be NULL anyway */ - skb_get(userdata); - tx_skb = userdata; - } - - return irlmp_connect_response(self->lsap, tx_skb); -} - -static int ircomm_lmp_disconnect_request(struct ircomm_cb *self, - struct sk_buff *userdata, - struct ircomm_info *info) -{ - struct sk_buff *tx_skb; - int ret; - - if (!userdata) { - tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC); - if (!tx_skb) - return -ENOMEM; - - /* Reserve space for MUX and LAP header */ - skb_reserve(tx_skb, LMP_MAX_HEADER); - userdata = tx_skb; - } else { - /* Don't forget to refcount it - should be NULL anyway */ - skb_get(userdata); - } - - ret = irlmp_disconnect_request(self->lsap, userdata); - - return ret; -} - -/* - * Function ircomm_lmp_flow_control (skb) - * - * This function is called when a data frame we have sent to IrLAP has - * been deallocated. We do this to make sure we don't flood IrLAP with - * frames, since we are not using the IrTTP flow control mechanism - */ -static void ircomm_lmp_flow_control(struct sk_buff *skb) -{ - struct irda_skb_cb *cb; - struct ircomm_cb *self; - int line; - - IRDA_ASSERT(skb != NULL, return;); - - cb = (struct irda_skb_cb *) skb->cb; - - line = cb->line; - - self = (struct ircomm_cb *) hashbin_lock_find(ircomm, line, NULL); - if (!self) { - pr_debug("%s(), didn't find myself\n", __func__); - return; - } - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - - self->pkt_count--; - - if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) { - pr_debug("%s(), asking TTY to start again!\n", __func__); - self->flow_status = FLOW_START; - if (self->notify.flow_indication) - self->notify.flow_indication(self->notify.instance, - self, FLOW_START); - } -} - -/* - * Function ircomm_lmp_data_request (self, userdata) - * - * Send data frame to peer device - * - */ -static int ircomm_lmp_data_request(struct ircomm_cb *self, - struct sk_buff *skb, - int not_used) -{ - struct irda_skb_cb *cb; - int ret; - - IRDA_ASSERT(skb != NULL, return -1;); - - cb = (struct irda_skb_cb *) skb->cb; - - cb->line = self->line; - - pr_debug("%s(), sending frame\n", __func__); - - /* Don't forget to refcount it - see ircomm_tty_do_softint() */ - skb_get(skb); - - skb_orphan(skb); - skb->destructor = ircomm_lmp_flow_control; - - if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) { - pr_debug("%s(), asking TTY to slow down!\n", __func__); - self->flow_status = FLOW_STOP; - if (self->notify.flow_indication) - self->notify.flow_indication(self->notify.instance, - self, FLOW_STOP); - } - ret = irlmp_data_request(self->lsap, skb); - if (ret) { - net_err_ratelimited("%s(), failed\n", __func__); - /* irlmp_data_request already free the packet */ - } - - return ret; -} - -/* - * Function ircomm_lmp_data_indication (instance, sap, skb) - * - * Incoming data which we must deliver to the state machine, to check - * we are still connected. - */ -static int ircomm_lmp_data_indication(void *instance, void *sap, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;); - IRDA_ASSERT(skb != NULL, return -1;); - - ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL); - - /* Drop reference count - see ircomm_tty_data_indication(). */ - dev_kfree_skb(skb); - - return 0; -} - -/* - * Function ircomm_lmp_connect_confirm (instance, sap, qos, max_sdu_size, - * max_header_size, skb) - * - * Connection has been confirmed by peer device - * - */ -static void ircomm_lmp_connect_confirm(void *instance, void *sap, - struct qos_info *qos, - __u32 max_seg_size, - __u8 max_header_size, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *) instance; - struct ircomm_info info; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - IRDA_ASSERT(skb != NULL, return;); - IRDA_ASSERT(qos != NULL, return;); - - info.max_data_size = max_seg_size; - info.max_header_size = max_header_size; - info.qos = qos; - - ircomm_do_event(self, IRCOMM_LMP_CONNECT_CONFIRM, skb, &info); - - /* Drop reference count - see ircomm_tty_connect_confirm(). */ - dev_kfree_skb(skb); -} - -/* - * Function ircomm_lmp_connect_indication (instance, sap, qos, max_sdu_size, - * max_header_size, skb) - * - * Peer device wants to make a connection with us - * - */ -static void ircomm_lmp_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_seg_size, - __u8 max_header_size, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *)instance; - struct ircomm_info info; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - IRDA_ASSERT(skb != NULL, return;); - IRDA_ASSERT(qos != NULL, return;); - - info.max_data_size = max_seg_size; - info.max_header_size = max_header_size; - info.qos = qos; - - ircomm_do_event(self, IRCOMM_LMP_CONNECT_INDICATION, skb, &info); - - /* Drop reference count - see ircomm_tty_connect_indication(). */ - dev_kfree_skb(skb); -} - -/* - * Function ircomm_lmp_disconnect_indication (instance, sap, reason, skb) - * - * Peer device has closed the connection, or the link went down for some - * other reason - */ -static void ircomm_lmp_disconnect_indication(void *instance, void *sap, - LM_REASON reason, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *) instance; - struct ircomm_info info; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - - info.reason = reason; - - ircomm_do_event(self, IRCOMM_LMP_DISCONNECT_INDICATION, skb, &info); - - /* Drop reference count - see ircomm_tty_disconnect_indication(). */ - if(skb) - dev_kfree_skb(skb); -} -/* - * Function ircomm_open_lsap (self) - * - * Open LSAP. This function will only be used when using "raw" services - * - */ -int ircomm_open_lsap(struct ircomm_cb *self) -{ - notify_t notify; - - /* Register callbacks */ - irda_notify_init(¬ify); - notify.data_indication = ircomm_lmp_data_indication; - notify.connect_confirm = ircomm_lmp_connect_confirm; - notify.connect_indication = ircomm_lmp_connect_indication; - notify.disconnect_indication = ircomm_lmp_disconnect_indication; - notify.instance = self; - strlcpy(notify.name, "IrCOMM", sizeof(notify.name)); - - self->lsap = irlmp_open_lsap(LSAP_ANY, ¬ify, 0); - if (!self->lsap) { - pr_debug("%sfailed to allocate tsap\n", __func__); - return -1; - } - self->slsap_sel = self->lsap->slsap_sel; - - /* - * Initialize the call-table for issuing commands - */ - self->issue.data_request = ircomm_lmp_data_request; - self->issue.connect_request = ircomm_lmp_connect_request; - self->issue.connect_response = ircomm_lmp_connect_response; - self->issue.disconnect_request = ircomm_lmp_disconnect_request; - - return 0; -} diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c deleted file mode 100644 index 5728e76ca6d5..000000000000 --- a/net/irda/ircomm/ircomm_param.c +++ /dev/null @@ -1,501 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_param.c - * Version: 1.0 - * Description: Parameter handling for the IrCOMM protocol - * Status: Experimental. - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Mon Jun 7 10:25:11 1999 - * Modified at: Sun Jan 30 14:32:03 2000 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * - * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/gfp.h> -#include <linux/workqueue.h> -#include <linux/interrupt.h> - -#include <net/irda/irda.h> -#include <net/irda/parameters.h> - -#include <net/irda/ircomm_core.h> -#include <net/irda/ircomm_tty_attach.h> -#include <net/irda/ircomm_tty.h> - -#include <net/irda/ircomm_param.h> - -static int ircomm_param_service_type(void *instance, irda_param_t *param, - int get); -static int ircomm_param_port_type(void *instance, irda_param_t *param, - int get); -static int ircomm_param_port_name(void *instance, irda_param_t *param, - int get); -static int ircomm_param_service_type(void *instance, irda_param_t *param, - int get); -static int ircomm_param_data_rate(void *instance, irda_param_t *param, - int get); -static int ircomm_param_data_format(void *instance, irda_param_t *param, - int get); -static int ircomm_param_flow_control(void *instance, irda_param_t *param, - int get); -static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get); -static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get); -static int ircomm_param_line_status(void *instance, irda_param_t *param, - int get); -static int ircomm_param_dte(void *instance, irda_param_t *param, int get); -static int ircomm_param_dce(void *instance, irda_param_t *param, int get); -static int ircomm_param_poll(void *instance, irda_param_t *param, int get); - -static const pi_minor_info_t pi_minor_call_table_common[] = { - { ircomm_param_service_type, PV_INT_8_BITS }, - { ircomm_param_port_type, PV_INT_8_BITS }, - { ircomm_param_port_name, PV_STRING } -}; -static const pi_minor_info_t pi_minor_call_table_non_raw[] = { - { ircomm_param_data_rate, PV_INT_32_BITS | PV_BIG_ENDIAN }, - { ircomm_param_data_format, PV_INT_8_BITS }, - { ircomm_param_flow_control, PV_INT_8_BITS }, - { ircomm_param_xon_xoff, PV_INT_16_BITS }, - { ircomm_param_enq_ack, PV_INT_16_BITS }, - { ircomm_param_line_status, PV_INT_8_BITS } -}; -static const pi_minor_info_t pi_minor_call_table_9_wire[] = { - { ircomm_param_dte, PV_INT_8_BITS }, - { ircomm_param_dce, PV_INT_8_BITS }, - { ircomm_param_poll, PV_NO_VALUE }, -}; - -static const pi_major_info_t pi_major_call_table[] = { - { pi_minor_call_table_common, 3 }, - { pi_minor_call_table_non_raw, 6 }, - { pi_minor_call_table_9_wire, 3 } -/* { pi_minor_call_table_centronics } */ -}; - -pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 }; - -/* - * Function ircomm_param_request (self, pi, flush) - * - * Queue a parameter for the control channel - * - */ -int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush) -{ - unsigned long flags; - struct sk_buff *skb; - int count; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - /* Make sure we don't send parameters for raw mode */ - if (self->service_type == IRCOMM_3_WIRE_RAW) - return 0; - - spin_lock_irqsave(&self->spinlock, flags); - - skb = self->ctrl_skb; - if (!skb) { - skb = alloc_skb(256, GFP_ATOMIC); - if (!skb) { - spin_unlock_irqrestore(&self->spinlock, flags); - return -ENOMEM; - } - - skb_reserve(skb, self->max_header_size); - self->ctrl_skb = skb; - } - /* - * Inserting is a little bit tricky since we don't know how much - * room we will need. But this should hopefully work OK - */ - count = irda_param_insert(self, pi, skb_tail_pointer(skb), - skb_tailroom(skb), &ircomm_param_info); - if (count < 0) { - net_warn_ratelimited("%s(), no room for parameter!\n", - __func__); - spin_unlock_irqrestore(&self->spinlock, flags); - return -1; - } - skb_put(skb, count); - pr_debug("%s(), skb->len=%d\n", __func__, skb->len); - - spin_unlock_irqrestore(&self->spinlock, flags); - - if (flush) { - /* ircomm_tty_do_softint will take care of the rest */ - schedule_work(&self->tqueue); - } - - return count; -} - -/* - * Function ircomm_param_service_type (self, buf, len) - * - * Handle service type, this function will both be called after the LM-IAS - * query and then the remote device sends its initial parameters - * - */ -static int ircomm_param_service_type(void *instance, irda_param_t *param, - int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - __u8 service_type = (__u8) param->pv.i; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) { - param->pv.i = self->settings.service_type; - return 0; - } - - /* Find all common service types */ - service_type &= self->service_type; - if (!service_type) { - pr_debug("%s(), No common service type to use!\n", __func__); - return -1; - } - pr_debug("%s(), services in common=%02x\n", __func__ , - service_type); - - /* - * Now choose a preferred service type of those available - */ - if (service_type & IRCOMM_CENTRONICS) - self->settings.service_type = IRCOMM_CENTRONICS; - else if (service_type & IRCOMM_9_WIRE) - self->settings.service_type = IRCOMM_9_WIRE; - else if (service_type & IRCOMM_3_WIRE) - self->settings.service_type = IRCOMM_3_WIRE; - else if (service_type & IRCOMM_3_WIRE_RAW) - self->settings.service_type = IRCOMM_3_WIRE_RAW; - - pr_debug("%s(), resulting service type=0x%02x\n", __func__ , - self->settings.service_type); - - /* - * Now the line is ready for some communication. Check if we are a - * server, and send over some initial parameters. - * Client do it in ircomm_tty_state_setup(). - * Note : we may get called from ircomm_tty_getvalue_confirm(), - * therefore before we even have open any socket. And self->client - * is initialised to TRUE only later. So, we check if the link is - * really initialised. - Jean II - */ - if ((self->max_header_size != IRCOMM_TTY_HDR_UNINITIALISED) && - (!self->client) && - (self->settings.service_type != IRCOMM_3_WIRE_RAW)) - { - /* Init connection */ - ircomm_tty_send_initial_parameters(self); - ircomm_tty_link_established(self); - } - - return 0; -} - -/* - * Function ircomm_param_port_type (self, param) - * - * The port type parameter tells if the devices are serial or parallel. - * Since we only advertise serial service, this parameter should only - * be equal to IRCOMM_SERIAL. - */ -static int ircomm_param_port_type(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) - param->pv.i = IRCOMM_SERIAL; - else { - self->settings.port_type = (__u8) param->pv.i; - - pr_debug("%s(), port type=%d\n", __func__ , - self->settings.port_type); - } - return 0; -} - -/* - * Function ircomm_param_port_name (self, param) - * - * Exchange port name - * - */ -static int ircomm_param_port_name(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) { - pr_debug("%s(), not imp!\n", __func__); - } else { - pr_debug("%s(), port-name=%s\n", __func__ , param->pv.c); - strncpy(self->settings.port_name, param->pv.c, 32); - } - - return 0; -} - -/* - * Function ircomm_param_data_rate (self, param) - * - * Exchange data rate to be used in this settings - * - */ -static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) - param->pv.i = self->settings.data_rate; - else - self->settings.data_rate = param->pv.i; - - pr_debug("%s(), data rate = %d\n", __func__ , param->pv.i); - - return 0; -} - -/* - * Function ircomm_param_data_format (self, param) - * - * Exchange data format to be used in this settings - * - */ -static int ircomm_param_data_format(void *instance, irda_param_t *param, - int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) - param->pv.i = self->settings.data_format; - else - self->settings.data_format = (__u8) param->pv.i; - - return 0; -} - -/* - * Function ircomm_param_flow_control (self, param) - * - * Exchange flow control settings to be used in this settings - * - */ -static int ircomm_param_flow_control(void *instance, irda_param_t *param, - int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) - param->pv.i = self->settings.flow_control; - else - self->settings.flow_control = (__u8) param->pv.i; - - pr_debug("%s(), flow control = 0x%02x\n", __func__ , (__u8)param->pv.i); - - return 0; -} - -/* - * Function ircomm_param_xon_xoff (self, param) - * - * Exchange XON/XOFF characters - * - */ -static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) { - param->pv.i = self->settings.xonxoff[0]; - param->pv.i |= self->settings.xonxoff[1] << 8; - } else { - self->settings.xonxoff[0] = (__u16) param->pv.i & 0xff; - self->settings.xonxoff[1] = (__u16) param->pv.i >> 8; - } - - pr_debug("%s(), XON/XOFF = 0x%02x,0x%02x\n", __func__ , - param->pv.i & 0xff, param->pv.i >> 8); - - return 0; -} - -/* - * Function ircomm_param_enq_ack (self, param) - * - * Exchange ENQ/ACK characters - * - */ -static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) { - param->pv.i = self->settings.enqack[0]; - param->pv.i |= self->settings.enqack[1] << 8; - } else { - self->settings.enqack[0] = (__u16) param->pv.i & 0xff; - self->settings.enqack[1] = (__u16) param->pv.i >> 8; - } - - pr_debug("%s(), ENQ/ACK = 0x%02x,0x%02x\n", __func__ , - param->pv.i & 0xff, param->pv.i >> 8); - - return 0; -} - -/* - * Function ircomm_param_line_status (self, param) - * - * - * - */ -static int ircomm_param_line_status(void *instance, irda_param_t *param, - int get) -{ - pr_debug("%s(), not impl.\n", __func__); - - return 0; -} - -/* - * Function ircomm_param_dte (instance, param) - * - * If we get here, there must be some sort of null-modem connection, and - * we are probably working in server mode as well. - */ -static int ircomm_param_dte(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - __u8 dte; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (get) - param->pv.i = self->settings.dte; - else { - dte = (__u8) param->pv.i; - - self->settings.dce = 0; - - if (dte & IRCOMM_DELTA_DTR) - self->settings.dce |= (IRCOMM_DELTA_DSR| - IRCOMM_DELTA_RI | - IRCOMM_DELTA_CD); - if (dte & IRCOMM_DTR) - self->settings.dce |= (IRCOMM_DSR| - IRCOMM_RI | - IRCOMM_CD); - - if (dte & IRCOMM_DELTA_RTS) - self->settings.dce |= IRCOMM_DELTA_CTS; - if (dte & IRCOMM_RTS) - self->settings.dce |= IRCOMM_CTS; - - /* Take appropriate actions */ - ircomm_tty_check_modem_status(self); - - /* Null modem cable emulator */ - self->settings.null_modem = TRUE; - } - - return 0; -} - -/* - * Function ircomm_param_dce (instance, param) - * - * - * - */ -static int ircomm_param_dce(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - __u8 dce; - - pr_debug("%s(), dce = 0x%02x\n", __func__ , (__u8)param->pv.i); - - dce = (__u8) param->pv.i; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - self->settings.dce = dce; - - /* Check if any of the settings have changed */ - if (dce & 0x0f) { - if (dce & IRCOMM_DELTA_CTS) { - pr_debug("%s(), CTS\n", __func__); - } - } - - ircomm_tty_check_modem_status(self); - - return 0; -} - -/* - * Function ircomm_param_poll (instance, param) - * - * Called when the peer device is polling for the line settings - * - */ -static int ircomm_param_poll(void *instance, irda_param_t *param, int get) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - /* Poll parameters are always of length 0 (just a signal) */ - if (!get) { - /* Respond with DTE line settings */ - ircomm_param_request(self, IRCOMM_DTE, TRUE); - } - return 0; -} - - - - - diff --git a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c deleted file mode 100644 index 4b81e0934770..000000000000 --- a/net/irda/ircomm/ircomm_ttp.c +++ /dev/null @@ -1,350 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_ttp.c - * Version: 1.0 - * Description: Interface between IrCOMM and IrTTP - * Status: Stable - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Sun Jun 6 20:48:27 1999 - * Modified at: Mon Dec 13 11:35:13 1999 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * - * Copyright (c) 1999 Dag Brattli, All Rights Reserved. - * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/init.h> - -#include <net/irda/irda.h> -#include <net/irda/irlmp.h> -#include <net/irda/iriap.h> -#include <net/irda/irttp.h> - -#include <net/irda/ircomm_event.h> -#include <net/irda/ircomm_ttp.h> - -static int ircomm_ttp_data_indication(void *instance, void *sap, - struct sk_buff *skb); -static void ircomm_ttp_connect_confirm(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, - __u8 max_header_size, - struct sk_buff *skb); -static void ircomm_ttp_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, - __u8 max_header_size, - struct sk_buff *skb); -static void ircomm_ttp_flow_indication(void *instance, void *sap, - LOCAL_FLOW cmd); -static void ircomm_ttp_disconnect_indication(void *instance, void *sap, - LM_REASON reason, - struct sk_buff *skb); -static int ircomm_ttp_data_request(struct ircomm_cb *self, - struct sk_buff *skb, - int clen); -static int ircomm_ttp_connect_request(struct ircomm_cb *self, - struct sk_buff *userdata, - struct ircomm_info *info); -static int ircomm_ttp_connect_response(struct ircomm_cb *self, - struct sk_buff *userdata); -static int ircomm_ttp_disconnect_request(struct ircomm_cb *self, - struct sk_buff *userdata, - struct ircomm_info *info); - -/* - * Function ircomm_open_tsap (self) - * - * - * - */ -int ircomm_open_tsap(struct ircomm_cb *self) -{ - notify_t notify; - - /* Register callbacks */ - irda_notify_init(¬ify); - notify.data_indication = ircomm_ttp_data_indication; - notify.connect_confirm = ircomm_ttp_connect_confirm; - notify.connect_indication = ircomm_ttp_connect_indication; - notify.flow_indication = ircomm_ttp_flow_indication; - notify.disconnect_indication = ircomm_ttp_disconnect_indication; - notify.instance = self; - strlcpy(notify.name, "IrCOMM", sizeof(notify.name)); - - self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, - ¬ify); - if (!self->tsap) { - pr_debug("%sfailed to allocate tsap\n", __func__); - return -1; - } - self->slsap_sel = self->tsap->stsap_sel; - - /* - * Initialize the call-table for issuing commands - */ - self->issue.data_request = ircomm_ttp_data_request; - self->issue.connect_request = ircomm_ttp_connect_request; - self->issue.connect_response = ircomm_ttp_connect_response; - self->issue.disconnect_request = ircomm_ttp_disconnect_request; - - return 0; -} - -/* - * Function ircomm_ttp_connect_request (self, userdata) - * - * - * - */ -static int ircomm_ttp_connect_request(struct ircomm_cb *self, - struct sk_buff *userdata, - struct ircomm_info *info) -{ - int ret = 0; - - /* Don't forget to refcount it - should be NULL anyway */ - if(userdata) - skb_get(userdata); - - ret = irttp_connect_request(self->tsap, info->dlsap_sel, - info->saddr, info->daddr, NULL, - TTP_SAR_DISABLE, userdata); - - return ret; -} - -/* - * Function ircomm_ttp_connect_response (self, skb) - * - * - * - */ -static int ircomm_ttp_connect_response(struct ircomm_cb *self, - struct sk_buff *userdata) -{ - int ret; - - /* Don't forget to refcount it - should be NULL anyway */ - if(userdata) - skb_get(userdata); - - ret = irttp_connect_response(self->tsap, TTP_SAR_DISABLE, userdata); - - return ret; -} - -/* - * Function ircomm_ttp_data_request (self, userdata) - * - * Send IrCOMM data to IrTTP layer. Currently we do not try to combine - * control data with pure data, so they will be sent as separate frames. - * Should not be a big problem though, since control frames are rare. But - * some of them are sent after connection establishment, so this can - * increase the latency a bit. - */ -static int ircomm_ttp_data_request(struct ircomm_cb *self, - struct sk_buff *skb, - int clen) -{ - int ret; - - IRDA_ASSERT(skb != NULL, return -1;); - - pr_debug("%s(), clen=%d\n", __func__ , clen); - - /* - * Insert clen field, currently we either send data only, or control - * only frames, to make things easier and avoid queueing - */ - IRDA_ASSERT(skb_headroom(skb) >= IRCOMM_HEADER_SIZE, return -1;); - - /* Don't forget to refcount it - see ircomm_tty_do_softint() */ - skb_get(skb); - - skb_push(skb, IRCOMM_HEADER_SIZE); - - skb->data[0] = clen; - - ret = irttp_data_request(self->tsap, skb); - if (ret) { - net_err_ratelimited("%s(), failed\n", __func__); - /* irttp_data_request already free the packet */ - } - - return ret; -} - -/* - * Function ircomm_ttp_data_indication (instance, sap, skb) - * - * Incoming data - * - */ -static int ircomm_ttp_data_indication(void *instance, void *sap, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *) instance; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;); - IRDA_ASSERT(skb != NULL, return -1;); - - ircomm_do_event(self, IRCOMM_TTP_DATA_INDICATION, skb, NULL); - - /* Drop reference count - see ircomm_tty_data_indication(). */ - dev_kfree_skb(skb); - - return 0; -} - -static void ircomm_ttp_connect_confirm(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, - __u8 max_header_size, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *) instance; - struct ircomm_info info; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - IRDA_ASSERT(skb != NULL, return;); - IRDA_ASSERT(qos != NULL, goto out;); - - if (max_sdu_size != TTP_SAR_DISABLE) { - net_err_ratelimited("%s(), SAR not allowed for IrCOMM!\n", - __func__); - goto out; - } - - info.max_data_size = irttp_get_max_seg_size(self->tsap) - - IRCOMM_HEADER_SIZE; - info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE; - info.qos = qos; - - ircomm_do_event(self, IRCOMM_TTP_CONNECT_CONFIRM, skb, &info); - -out: - /* Drop reference count - see ircomm_tty_connect_confirm(). */ - dev_kfree_skb(skb); -} - -/* - * Function ircomm_ttp_connect_indication (instance, sap, qos, max_sdu_size, - * max_header_size, skb) - * - * - * - */ -static void ircomm_ttp_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, - __u8 max_header_size, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *)instance; - struct ircomm_info info; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - IRDA_ASSERT(skb != NULL, return;); - IRDA_ASSERT(qos != NULL, goto out;); - - if (max_sdu_size != TTP_SAR_DISABLE) { - net_err_ratelimited("%s(), SAR not allowed for IrCOMM!\n", - __func__); - goto out; - } - - info.max_data_size = irttp_get_max_seg_size(self->tsap) - - IRCOMM_HEADER_SIZE; - info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE; - info.qos = qos; - - ircomm_do_event(self, IRCOMM_TTP_CONNECT_INDICATION, skb, &info); - -out: - /* Drop reference count - see ircomm_tty_connect_indication(). */ - dev_kfree_skb(skb); -} - -/* - * Function ircomm_ttp_disconnect_request (self, userdata, info) - * - * - * - */ -static int ircomm_ttp_disconnect_request(struct ircomm_cb *self, - struct sk_buff *userdata, - struct ircomm_info *info) -{ - int ret; - - /* Don't forget to refcount it - should be NULL anyway */ - if(userdata) - skb_get(userdata); - - ret = irttp_disconnect_request(self->tsap, userdata, P_NORMAL); - - return ret; -} - -/* - * Function ircomm_ttp_disconnect_indication (instance, sap, reason, skb) - * - * - * - */ -static void ircomm_ttp_disconnect_indication(void *instance, void *sap, - LM_REASON reason, - struct sk_buff *skb) -{ - struct ircomm_cb *self = (struct ircomm_cb *) instance; - struct ircomm_info info; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - - info.reason = reason; - - ircomm_do_event(self, IRCOMM_TTP_DISCONNECT_INDICATION, skb, &info); - - /* Drop reference count - see ircomm_tty_disconnect_indication(). */ - if(skb) - dev_kfree_skb(skb); -} - -/* - * Function ircomm_ttp_flow_indication (instance, sap, cmd) - * - * Layer below is telling us to start or stop the flow of data - * - */ -static void ircomm_ttp_flow_indication(void *instance, void *sap, - LOCAL_FLOW cmd) -{ - struct ircomm_cb *self = (struct ircomm_cb *) instance; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;); - - if (self->notify.flow_indication) - self->notify.flow_indication(self->notify.instance, self, cmd); -} - - diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c deleted file mode 100644 index ec157c3419b5..000000000000 --- a/net/irda/ircomm/ircomm_tty.c +++ /dev/null @@ -1,1329 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_tty.c - * Version: 1.0 - * Description: IrCOMM serial TTY driver - * Status: Experimental. - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Sun Jun 6 21:00:56 1999 - * Modified at: Wed Feb 23 00:09:02 2000 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * Sources: serial.c and previous IrCOMM work by Takahide Higuchi - * - * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved. - * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/slab.h> -#include <linux/sched/signal.h> -#include <linux/seq_file.h> -#include <linux/termios.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/interrupt.h> -#include <linux/device.h> /* for MODULE_ALIAS_CHARDEV_MAJOR */ - -#include <linux/uaccess.h> - -#include <net/irda/irda.h> -#include <net/irda/irmod.h> - -#include <net/irda/ircomm_core.h> -#include <net/irda/ircomm_param.h> -#include <net/irda/ircomm_tty_attach.h> -#include <net/irda/ircomm_tty.h> - -static int ircomm_tty_install(struct tty_driver *driver, - struct tty_struct *tty); -static int ircomm_tty_open(struct tty_struct *tty, struct file *filp); -static void ircomm_tty_close(struct tty_struct * tty, struct file *filp); -static int ircomm_tty_write(struct tty_struct * tty, - const unsigned char *buf, int count); -static int ircomm_tty_write_room(struct tty_struct *tty); -static void ircomm_tty_throttle(struct tty_struct *tty); -static void ircomm_tty_unthrottle(struct tty_struct *tty); -static int ircomm_tty_chars_in_buffer(struct tty_struct *tty); -static void ircomm_tty_flush_buffer(struct tty_struct *tty); -static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch); -static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout); -static void ircomm_tty_hangup(struct tty_struct *tty); -static void ircomm_tty_do_softint(struct work_struct *work); -static void ircomm_tty_shutdown(struct ircomm_tty_cb *self); -static void ircomm_tty_stop(struct tty_struct *tty); - -static int ircomm_tty_data_indication(void *instance, void *sap, - struct sk_buff *skb); -static int ircomm_tty_control_indication(void *instance, void *sap, - struct sk_buff *skb); -static void ircomm_tty_flow_indication(void *instance, void *sap, - LOCAL_FLOW cmd); -#ifdef CONFIG_PROC_FS -static const struct file_operations ircomm_tty_proc_fops; -#endif /* CONFIG_PROC_FS */ -static struct tty_driver *driver; - -static hashbin_t *ircomm_tty = NULL; - -static const struct tty_operations ops = { - .install = ircomm_tty_install, - .open = ircomm_tty_open, - .close = ircomm_tty_close, - .write = ircomm_tty_write, - .write_room = ircomm_tty_write_room, - .chars_in_buffer = ircomm_tty_chars_in_buffer, - .flush_buffer = ircomm_tty_flush_buffer, - .ioctl = ircomm_tty_ioctl, /* ircomm_tty_ioctl.c */ - .tiocmget = ircomm_tty_tiocmget, /* ircomm_tty_ioctl.c */ - .tiocmset = ircomm_tty_tiocmset, /* ircomm_tty_ioctl.c */ - .throttle = ircomm_tty_throttle, - .unthrottle = ircomm_tty_unthrottle, - .send_xchar = ircomm_tty_send_xchar, - .set_termios = ircomm_tty_set_termios, - .stop = ircomm_tty_stop, - .start = ircomm_tty_start, - .hangup = ircomm_tty_hangup, - .wait_until_sent = ircomm_tty_wait_until_sent, -#ifdef CONFIG_PROC_FS - .proc_fops = &ircomm_tty_proc_fops, -#endif /* CONFIG_PROC_FS */ -}; - -static void ircomm_port_raise_dtr_rts(struct tty_port *port, int raise) -{ - struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, - port); - /* - * Here, we use to lock those two guys, but as ircomm_param_request() - * does it itself, I don't see the point (and I see the deadlock). - * Jean II - */ - if (raise) - self->settings.dte |= IRCOMM_RTS | IRCOMM_DTR; - else - self->settings.dte &= ~(IRCOMM_RTS | IRCOMM_DTR); - - ircomm_param_request(self, IRCOMM_DTE, TRUE); -} - -static int ircomm_port_carrier_raised(struct tty_port *port) -{ - struct ircomm_tty_cb *self = container_of(port, struct ircomm_tty_cb, - port); - return self->settings.dce & IRCOMM_CD; -} - -static const struct tty_port_operations ircomm_port_ops = { - .dtr_rts = ircomm_port_raise_dtr_rts, - .carrier_raised = ircomm_port_carrier_raised, -}; - -/* - * Function ircomm_tty_init() - * - * Init IrCOMM TTY layer/driver - * - */ -static int __init ircomm_tty_init(void) -{ - driver = alloc_tty_driver(IRCOMM_TTY_PORTS); - if (!driver) - return -ENOMEM; - ircomm_tty = hashbin_new(HB_LOCK); - if (ircomm_tty == NULL) { - net_err_ratelimited("%s(), can't allocate hashbin!\n", - __func__); - put_tty_driver(driver); - return -ENOMEM; - } - - driver->driver_name = "ircomm"; - driver->name = "ircomm"; - driver->major = IRCOMM_TTY_MAJOR; - driver->minor_start = IRCOMM_TTY_MINOR; - driver->type = TTY_DRIVER_TYPE_SERIAL; - driver->subtype = SERIAL_TYPE_NORMAL; - driver->init_termios = tty_std_termios; - driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(driver, &ops); - if (tty_register_driver(driver)) { - net_err_ratelimited("%s(): Couldn't register serial driver\n", - __func__); - put_tty_driver(driver); - return -1; - } - return 0; -} - -static void __exit __ircomm_tty_cleanup(struct ircomm_tty_cb *self) -{ - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - ircomm_tty_shutdown(self); - - self->magic = 0; - tty_port_destroy(&self->port); - kfree(self); -} - -/* - * Function ircomm_tty_cleanup () - * - * Remove IrCOMM TTY layer/driver - * - */ -static void __exit ircomm_tty_cleanup(void) -{ - int ret; - - ret = tty_unregister_driver(driver); - if (ret) { - net_err_ratelimited("%s(), failed to unregister driver\n", - __func__); - return; - } - - hashbin_delete(ircomm_tty, (FREE_FUNC) __ircomm_tty_cleanup); - put_tty_driver(driver); -} - -/* - * Function ircomm_startup (self) - * - * - * - */ -static int ircomm_tty_startup(struct ircomm_tty_cb *self) -{ - notify_t notify; - int ret = -ENODEV; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - /* Check if already open */ - if (tty_port_initialized(&self->port)) { - pr_debug("%s(), already open so break out!\n", __func__); - return 0; - } - tty_port_set_initialized(&self->port, 1); - - /* Register with IrCOMM */ - irda_notify_init(¬ify); - /* These callbacks we must handle ourselves */ - notify.data_indication = ircomm_tty_data_indication; - notify.udata_indication = ircomm_tty_control_indication; - notify.flow_indication = ircomm_tty_flow_indication; - - /* Use the ircomm_tty interface for these ones */ - notify.disconnect_indication = ircomm_tty_disconnect_indication; - notify.connect_confirm = ircomm_tty_connect_confirm; - notify.connect_indication = ircomm_tty_connect_indication; - strlcpy(notify.name, "ircomm_tty", sizeof(notify.name)); - notify.instance = self; - - if (!self->ircomm) { - self->ircomm = ircomm_open(¬ify, self->service_type, - self->line); - } - if (!self->ircomm) - goto err; - - self->slsap_sel = self->ircomm->slsap_sel; - - /* Connect IrCOMM link with remote device */ - ret = ircomm_tty_attach_cable(self); - if (ret < 0) { - net_err_ratelimited("%s(), error attaching cable!\n", __func__); - goto err; - } - - return 0; -err: - tty_port_set_initialized(&self->port, 0); - return ret; -} - -/* - * Function ircomm_block_til_ready (self, filp) - * - * - * - */ -static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, - struct tty_struct *tty, struct file *filp) -{ - struct tty_port *port = &self->port; - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - unsigned long flags; - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if (tty_io_error(tty)) { - tty_port_set_active(port, 1); - return 0; - } - - if (filp->f_flags & O_NONBLOCK) { - /* nonblock mode is set */ - if (C_BAUD(tty)) - tty_port_raise_dtr_rts(port); - tty_port_set_active(port, 1); - pr_debug("%s(), O_NONBLOCK requested!\n", __func__); - return 0; - } - - if (C_CLOCAL(tty)) { - pr_debug("%s(), doing CLOCAL!\n", __func__); - do_clocal = 1; - } - - /* Wait for carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, port->count is dropped by one, so that - * mgsl_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - - retval = 0; - add_wait_queue(&port->open_wait, &wait); - - pr_debug("%s(%d):block_til_ready before block on %s open_count=%d\n", - __FILE__, __LINE__, tty->driver->name, port->count); - - spin_lock_irqsave(&port->lock, flags); - port->count--; - port->blocked_open++; - spin_unlock_irqrestore(&port->lock, flags); - - while (1) { - if (C_BAUD(tty) && tty_port_initialized(port)) - tty_port_raise_dtr_rts(port); - - set_current_state(TASK_INTERRUPTIBLE); - - if (tty_hung_up_p(filp) || !tty_port_initialized(port)) { - retval = (port->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS; - break; - } - - /* - * Check if link is ready now. Even if CLOCAL is - * specified, we cannot return before the IrCOMM link is - * ready - */ - if ((do_clocal || tty_port_carrier_raised(port)) && - self->state == IRCOMM_TTY_READY) - { - break; - } - - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - - pr_debug("%s(%d):block_til_ready blocking on %s open_count=%d\n", - __FILE__, __LINE__, tty->driver->name, port->count); - - schedule(); - } - - __set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - - spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) - port->count++; - port->blocked_open--; - spin_unlock_irqrestore(&port->lock, flags); - - pr_debug("%s(%d):block_til_ready after blocking on %s open_count=%d\n", - __FILE__, __LINE__, tty->driver->name, port->count); - - if (!retval) - tty_port_set_active(port, 1); - - return retval; -} - - -static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) -{ - struct ircomm_tty_cb *self; - unsigned int line = tty->index; - - /* Check if instance already exists */ - self = hashbin_lock_find(ircomm_tty, line, NULL); - if (!self) { - /* No, so make new instance */ - self = kzalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL); - if (self == NULL) - return -ENOMEM; - - tty_port_init(&self->port); - self->port.ops = &ircomm_port_ops; - self->magic = IRCOMM_TTY_MAGIC; - self->flow = FLOW_STOP; - - self->line = line; - INIT_WORK(&self->tqueue, ircomm_tty_do_softint); - self->max_header_size = IRCOMM_TTY_HDR_UNINITIALISED; - self->max_data_size = IRCOMM_TTY_DATA_UNINITIALISED; - - /* Init some important stuff */ - init_timer(&self->watchdog_timer); - spin_lock_init(&self->spinlock); - - /* - * Force TTY into raw mode by default which is usually what - * we want for IrCOMM and IrLPT. This way applications will - * not have to twiddle with printcap etc. - * - * Note this is completely usafe and doesn't work properly - */ - tty->termios.c_iflag = 0; - tty->termios.c_oflag = 0; - - /* Insert into hash */ - hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); - } - - tty->driver_data = self; - - return tty_port_install(&self->port, driver, tty); -} - -/* - * Function ircomm_tty_open (tty, filp) - * - * This routine is called when a particular tty device is opened. This - * routine is mandatory; if this routine is not filled in, the attempted - * open will fail with ENODEV. - */ -static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) -{ - struct ircomm_tty_cb *self = tty->driver_data; - unsigned long flags; - int ret; - - /* ++ is not atomic, so this should be protected - Jean II */ - spin_lock_irqsave(&self->port.lock, flags); - self->port.count++; - spin_unlock_irqrestore(&self->port.lock, flags); - tty_port_tty_set(&self->port, tty); - - pr_debug("%s(), %s%d, count = %d\n", __func__ , tty->driver->name, - self->line, self->port.count); - - /* Not really used by us, but lets do it anyway */ - self->port.low_latency = (self->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - /* Check if this is a "normal" ircomm device, or an irlpt device */ - if (self->line < 0x10) { - self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE; - self->settings.service_type = IRCOMM_9_WIRE; /* 9 wire as default */ - /* Jan Kiszka -> add DSR/RI -> Conform to IrCOMM spec */ - self->settings.dce = IRCOMM_CTS | IRCOMM_CD | IRCOMM_DSR | IRCOMM_RI; /* Default line settings */ - pr_debug("%s(), IrCOMM device\n", __func__); - } else { - pr_debug("%s(), IrLPT device\n", __func__); - self->service_type = IRCOMM_3_WIRE_RAW; - self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */ - } - - ret = ircomm_tty_startup(self); - if (ret) - return ret; - - ret = ircomm_tty_block_til_ready(self, tty, filp); - if (ret) { - pr_debug("%s(), returning after block_til_ready with %d\n", - __func__, ret); - - return ret; - } - return 0; -} - -/* - * Function ircomm_tty_close (tty, filp) - * - * This routine is called when a particular tty device is closed. - * - */ -static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - struct tty_port *port = &self->port; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - if (tty_port_close_start(port, tty, filp) == 0) - return; - - ircomm_tty_shutdown(self); - - tty_driver_flush_buffer(tty); - - tty_port_close_end(port, tty); - tty_port_tty_set(port, NULL); -} - -/* - * Function ircomm_tty_flush_buffer (tty) - * - * - * - */ -static void ircomm_tty_flush_buffer(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - /* - * Let do_softint() do this to avoid race condition with - * do_softint() ;-) - */ - schedule_work(&self->tqueue); -} - -/* - * Function ircomm_tty_do_softint (work) - * - * We use this routine to give the write wakeup to the user at at a - * safe time (as fast as possible after write have completed). This - * can be compared to the Tx interrupt. - */ -static void ircomm_tty_do_softint(struct work_struct *work) -{ - struct ircomm_tty_cb *self = - container_of(work, struct ircomm_tty_cb, tqueue); - struct tty_struct *tty; - unsigned long flags; - struct sk_buff *skb, *ctrl_skb; - - if (!self || self->magic != IRCOMM_TTY_MAGIC) - return; - - tty = tty_port_tty_get(&self->port); - if (!tty) - return; - - /* Unlink control buffer */ - spin_lock_irqsave(&self->spinlock, flags); - - ctrl_skb = self->ctrl_skb; - self->ctrl_skb = NULL; - - spin_unlock_irqrestore(&self->spinlock, flags); - - /* Flush control buffer if any */ - if(ctrl_skb) { - if(self->flow == FLOW_START) - ircomm_control_request(self->ircomm, ctrl_skb); - /* Drop reference count - see ircomm_ttp_data_request(). */ - dev_kfree_skb(ctrl_skb); - } - - if (tty->hw_stopped) - goto put; - - /* Unlink transmit buffer */ - spin_lock_irqsave(&self->spinlock, flags); - - skb = self->tx_skb; - self->tx_skb = NULL; - - spin_unlock_irqrestore(&self->spinlock, flags); - - /* Flush transmit buffer if any */ - if (skb) { - ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL); - /* Drop reference count - see ircomm_ttp_data_request(). */ - dev_kfree_skb(skb); - } - - /* Check if user (still) wants to be waken up */ - tty_wakeup(tty); -put: - tty_kref_put(tty); -} - -/* - * Function ircomm_tty_write (tty, buf, count) - * - * This routine is called by the kernel to write a series of characters - * to the tty device. The characters may come from user space or kernel - * space. This routine will return the number of characters actually - * accepted for writing. This routine is mandatory. - */ -static int ircomm_tty_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - unsigned long flags; - struct sk_buff *skb; - int tailroom = 0; - int len = 0; - int size; - - pr_debug("%s(), count=%d, hw_stopped=%d\n", __func__ , count, - tty->hw_stopped); - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - /* We may receive packets from the TTY even before we have finished - * our setup. Not cool. - * The problem is that we don't know the final header and data size - * to create the proper skb, so any skb we would create would have - * bogus header and data size, so need care. - * We use a bogus header size to safely detect this condition. - * Another problem is that hw_stopped was set to 0 way before it - * should be, so we would drop this skb. It should now be fixed. - * One option is to not accept data until we are properly setup. - * But, I suspect that when it happens, the ppp line discipline - * just "drops" the data, which might screw up connect scripts. - * The second option is to create a "safe skb", with large header - * and small size (see ircomm_tty_open() for values). - * We just need to make sure that when the real values get filled, - * we don't mess up the original "safe skb" (see tx_data_size). - * Jean II */ - if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED) { - pr_debug("%s() : not initialised\n", __func__); -#ifdef IRCOMM_NO_TX_BEFORE_INIT - /* We didn't consume anything, TTY will retry */ - return 0; -#endif - } - - if (count < 1) - return 0; - - /* Protect our manipulation of self->tx_skb and related */ - spin_lock_irqsave(&self->spinlock, flags); - - /* Fetch current transmit buffer */ - skb = self->tx_skb; - - /* - * Send out all the data we get, possibly as multiple fragmented - * frames, but this will only happen if the data is larger than the - * max data size. The normal case however is just the opposite, and - * this function may be called multiple times, and will then actually - * defragment the data and send it out as one packet as soon as - * possible, but at a safer point in time - */ - while (count) { - size = count; - - /* Adjust data size to the max data size */ - if (size > self->max_data_size) - size = self->max_data_size; - - /* - * Do we already have a buffer ready for transmit, or do - * we need to allocate a new frame - */ - if (skb) { - /* - * Any room for more data at the end of the current - * transmit buffer? Cannot use skb_tailroom, since - * dev_alloc_skb gives us a larger skb than we - * requested - * Note : use tx_data_size, because max_data_size - * may have changed and we don't want to overwrite - * the skb. - Jean II - */ - if ((tailroom = (self->tx_data_size - skb->len)) > 0) { - /* Adjust data to tailroom */ - if (size > tailroom) - size = tailroom; - } else { - /* - * Current transmit frame is full, so break - * out, so we can send it as soon as possible - */ - break; - } - } else { - /* Prepare a full sized frame */ - skb = alloc_skb(self->max_data_size+ - self->max_header_size, - GFP_ATOMIC); - if (!skb) { - spin_unlock_irqrestore(&self->spinlock, flags); - return -ENOBUFS; - } - skb_reserve(skb, self->max_header_size); - self->tx_skb = skb; - /* Remember skb size because max_data_size may - * change later on - Jean II */ - self->tx_data_size = self->max_data_size; - } - - /* Copy data */ - skb_put_data(skb, buf + len, size); - - count -= size; - len += size; - } - - spin_unlock_irqrestore(&self->spinlock, flags); - - /* - * Schedule a new thread which will transmit the frame as soon - * as possible, but at a safe point in time. We do this so the - * "user" can give us data multiple times, as PPP does (because of - * its 256 byte tx buffer). We will then defragment and send out - * all this data as one single packet. - */ - schedule_work(&self->tqueue); - - return len; -} - -/* - * Function ircomm_tty_write_room (tty) - * - * This routine returns the numbers of characters the tty driver will - * accept for queuing to be written. This number is subject to change as - * output buffers get emptied, or if the output flow control is acted. - */ -static int ircomm_tty_write_room(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - unsigned long flags; - int ret; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - -#ifdef IRCOMM_NO_TX_BEFORE_INIT - /* max_header_size tells us if the channel is initialised or not. */ - if (self->max_header_size == IRCOMM_TTY_HDR_UNINITIALISED) - /* Don't bother us yet */ - return 0; -#endif - - /* Check if we are allowed to transmit any data. - * hw_stopped is the regular flow control. - * Jean II */ - if (tty->hw_stopped) - ret = 0; - else { - spin_lock_irqsave(&self->spinlock, flags); - if (self->tx_skb) - ret = self->tx_data_size - self->tx_skb->len; - else - ret = self->max_data_size; - spin_unlock_irqrestore(&self->spinlock, flags); - } - pr_debug("%s(), ret=%d\n", __func__ , ret); - - return ret; -} - -/* - * Function ircomm_tty_wait_until_sent (tty, timeout) - * - * This routine waits until the device has written out all of the - * characters in its transmitter FIFO. - */ -static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - unsigned long orig_jiffies, poll_time; - unsigned long flags; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - orig_jiffies = jiffies; - - /* Set poll time to 200 ms */ - poll_time = msecs_to_jiffies(200); - if (timeout) - poll_time = min_t(unsigned long, timeout, poll_time); - - spin_lock_irqsave(&self->spinlock, flags); - while (self->tx_skb && self->tx_skb->len) { - spin_unlock_irqrestore(&self->spinlock, flags); - schedule_timeout_interruptible(poll_time); - spin_lock_irqsave(&self->spinlock, flags); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - spin_unlock_irqrestore(&self->spinlock, flags); - __set_current_state(TASK_RUNNING); -} - -/* - * Function ircomm_tty_throttle (tty) - * - * This routine notifies the tty driver that input buffers for the line - * discipline are close to full, and it should somehow signal that no - * more characters should be sent to the tty. - */ -static void ircomm_tty_throttle(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - /* Software flow control? */ - if (I_IXOFF(tty)) - ircomm_tty_send_xchar(tty, STOP_CHAR(tty)); - - /* Hardware flow control? */ - if (C_CRTSCTS(tty)) { - self->settings.dte &= ~IRCOMM_RTS; - self->settings.dte |= IRCOMM_DELTA_RTS; - - ircomm_param_request(self, IRCOMM_DTE, TRUE); - } - - ircomm_flow_request(self->ircomm, FLOW_STOP); -} - -/* - * Function ircomm_tty_unthrottle (tty) - * - * This routine notifies the tty drivers that it should signals that - * characters can now be sent to the tty without fear of overrunning the - * input buffers of the line disciplines. - */ -static void ircomm_tty_unthrottle(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - /* Using software flow control? */ - if (I_IXOFF(tty)) - ircomm_tty_send_xchar(tty, START_CHAR(tty)); - - /* Using hardware flow control? */ - if (C_CRTSCTS(tty)) { - self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS); - - ircomm_param_request(self, IRCOMM_DTE, TRUE); - pr_debug("%s(), FLOW_START\n", __func__); - } - ircomm_flow_request(self->ircomm, FLOW_START); -} - -/* - * Function ircomm_tty_chars_in_buffer (tty) - * - * Indicates if there are any data in the buffer - * - */ -static int ircomm_tty_chars_in_buffer(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - unsigned long flags; - int len = 0; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - spin_lock_irqsave(&self->spinlock, flags); - - if (self->tx_skb) - len = self->tx_skb->len; - - spin_unlock_irqrestore(&self->spinlock, flags); - - return len; -} - -static void ircomm_tty_shutdown(struct ircomm_tty_cb *self) -{ - unsigned long flags; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - if (!tty_port_initialized(&self->port)) - return; - tty_port_set_initialized(&self->port, 0); - - ircomm_tty_detach_cable(self); - - spin_lock_irqsave(&self->spinlock, flags); - - del_timer(&self->watchdog_timer); - - /* Free parameter buffer */ - if (self->ctrl_skb) { - dev_kfree_skb(self->ctrl_skb); - self->ctrl_skb = NULL; - } - - /* Free transmit buffer */ - if (self->tx_skb) { - dev_kfree_skb(self->tx_skb); - self->tx_skb = NULL; - } - - if (self->ircomm) { - ircomm_close(self->ircomm); - self->ircomm = NULL; - } - - spin_unlock_irqrestore(&self->spinlock, flags); -} - -/* - * Function ircomm_tty_hangup (tty) - * - * This routine notifies the tty driver that it should hangup the tty - * device. - * - */ -static void ircomm_tty_hangup(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - struct tty_port *port = &self->port; - unsigned long flags; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - /* ircomm_tty_flush_buffer(tty); */ - ircomm_tty_shutdown(self); - - spin_lock_irqsave(&port->lock, flags); - if (port->tty) { - set_bit(TTY_IO_ERROR, &port->tty->flags); - tty_kref_put(port->tty); - } - port->tty = NULL; - port->count = 0; - spin_unlock_irqrestore(&port->lock, flags); - tty_port_set_active(port, 0); - - wake_up_interruptible(&port->open_wait); -} - -/* - * Function ircomm_tty_send_xchar (tty, ch) - * - * This routine is used to send a high-priority XON/XOFF character to - * the device. - */ -static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch) -{ - pr_debug("%s(), not impl\n", __func__); -} - -/* - * Function ircomm_tty_start (tty) - * - * This routine notifies the tty driver that it resume sending - * characters to the tty device. - */ -void ircomm_tty_start(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - - ircomm_flow_request(self->ircomm, FLOW_START); -} - -/* - * Function ircomm_tty_stop (tty) - * - * This routine notifies the tty driver that it should stop outputting - * characters to the tty device. - */ -static void ircomm_tty_stop(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - ircomm_flow_request(self->ircomm, FLOW_STOP); -} - -/* - * Function ircomm_check_modem_status (self) - * - * Check for any changes in the DCE's line settings. This function should - * be called whenever the dce parameter settings changes, to update the - * flow control settings and other things - */ -void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) -{ - struct tty_struct *tty; - int status; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - tty = tty_port_tty_get(&self->port); - - status = self->settings.dce; - - if (status & IRCOMM_DCE_DELTA_ANY) { - /*wake_up_interruptible(&self->delta_msr_wait);*/ - } - if (tty_port_check_carrier(&self->port) && (status & IRCOMM_DELTA_CD)) { - pr_debug("%s(), ircomm%d CD now %s...\n", __func__ , self->line, - (status & IRCOMM_CD) ? "on" : "off"); - - if (status & IRCOMM_CD) { - wake_up_interruptible(&self->port.open_wait); - } else { - pr_debug("%s(), Doing serial hangup..\n", __func__); - if (tty) - tty_hangup(tty); - - /* Hangup will remote the tty, so better break out */ - goto put; - } - } - if (tty && tty_port_cts_enabled(&self->port)) { - if (tty->hw_stopped) { - if (status & IRCOMM_CTS) { - pr_debug("%s(), CTS tx start...\n", __func__); - tty->hw_stopped = 0; - - /* Wake up processes blocked on open */ - wake_up_interruptible(&self->port.open_wait); - - schedule_work(&self->tqueue); - goto put; - } - } else { - if (!(status & IRCOMM_CTS)) { - pr_debug("%s(), CTS tx stop...\n", __func__); - tty->hw_stopped = 1; - } - } - } -put: - tty_kref_put(tty); -} - -/* - * Function ircomm_tty_data_indication (instance, sap, skb) - * - * Handle incoming data, and deliver it to the line discipline - * - */ -static int ircomm_tty_data_indication(void *instance, void *sap, - struct sk_buff *skb) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - struct tty_struct *tty; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - IRDA_ASSERT(skb != NULL, return -1;); - - tty = tty_port_tty_get(&self->port); - if (!tty) { - pr_debug("%s(), no tty!\n", __func__); - return 0; - } - - /* - * If we receive data when hardware is stopped then something is wrong. - * We try to poll the peers line settings to check if we are up todate. - * Devices like WinCE can do this, and since they don't send any - * params, we can just as well declare the hardware for running. - */ - if (tty->hw_stopped && (self->flow == FLOW_START)) { - pr_debug("%s(), polling for line settings!\n", __func__); - ircomm_param_request(self, IRCOMM_POLL, TRUE); - - /* We can just as well declare the hardware for running */ - ircomm_tty_send_initial_parameters(self); - ircomm_tty_link_established(self); - } - tty_kref_put(tty); - - /* - * Use flip buffer functions since the code may be called from interrupt - * context - */ - tty_insert_flip_string(&self->port, skb->data, skb->len); - tty_flip_buffer_push(&self->port); - - /* No need to kfree_skb - see ircomm_ttp_data_indication() */ - - return 0; -} - -/* - * Function ircomm_tty_control_indication (instance, sap, skb) - * - * Parse all incoming parameters (easy!) - * - */ -static int ircomm_tty_control_indication(void *instance, void *sap, - struct sk_buff *skb) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - int clen; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - IRDA_ASSERT(skb != NULL, return -1;); - - clen = skb->data[0]; - - irda_param_extract_all(self, skb->data+1, IRDA_MIN(skb->len-1, clen), - &ircomm_param_info); - - /* No need to kfree_skb - see ircomm_control_indication() */ - - return 0; -} - -/* - * Function ircomm_tty_flow_indication (instance, sap, cmd) - * - * This function is called by IrTTP when it wants us to slow down the - * transmission of data. We just mark the hardware as stopped, and wait - * for IrTTP to notify us that things are OK again. - */ -static void ircomm_tty_flow_indication(void *instance, void *sap, - LOCAL_FLOW cmd) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - struct tty_struct *tty; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - tty = tty_port_tty_get(&self->port); - - switch (cmd) { - case FLOW_START: - pr_debug("%s(), hw start!\n", __func__); - if (tty) - tty->hw_stopped = 0; - - /* ircomm_tty_do_softint will take care of the rest */ - schedule_work(&self->tqueue); - break; - default: /* If we get here, something is very wrong, better stop */ - case FLOW_STOP: - pr_debug("%s(), hw stopped!\n", __func__); - if (tty) - tty->hw_stopped = 1; - break; - } - - tty_kref_put(tty); - self->flow = cmd; -} - -#ifdef CONFIG_PROC_FS -static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) -{ - struct tty_struct *tty; - char sep; - - seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]); - - seq_puts(m, "Service type: "); - if (self->service_type & IRCOMM_9_WIRE) - seq_puts(m, "9_WIRE"); - else if (self->service_type & IRCOMM_3_WIRE) - seq_puts(m, "3_WIRE"); - else if (self->service_type & IRCOMM_3_WIRE_RAW) - seq_puts(m, "3_WIRE_RAW"); - else - seq_puts(m, "No common service type!\n"); - seq_putc(m, '\n'); - - seq_printf(m, "Port name: %s\n", self->settings.port_name); - - seq_printf(m, "DTE status:"); - sep = ' '; - if (self->settings.dte & IRCOMM_RTS) { - seq_printf(m, "%cRTS", sep); - sep = '|'; - } - if (self->settings.dte & IRCOMM_DTR) { - seq_printf(m, "%cDTR", sep); - sep = '|'; - } - seq_putc(m, '\n'); - - seq_puts(m, "DCE status:"); - sep = ' '; - if (self->settings.dce & IRCOMM_CTS) { - seq_printf(m, "%cCTS", sep); - sep = '|'; - } - if (self->settings.dce & IRCOMM_DSR) { - seq_printf(m, "%cDSR", sep); - sep = '|'; - } - if (self->settings.dce & IRCOMM_CD) { - seq_printf(m, "%cCD", sep); - sep = '|'; - } - if (self->settings.dce & IRCOMM_RI) { - seq_printf(m, "%cRI", sep); - sep = '|'; - } - seq_putc(m, '\n'); - - seq_puts(m, "Configuration: "); - if (!self->settings.null_modem) - seq_puts(m, "DTE <-> DCE\n"); - else - seq_puts(m, "DTE <-> DTE (null modem emulation)\n"); - - seq_printf(m, "Data rate: %d\n", self->settings.data_rate); - - seq_puts(m, "Flow control:"); - sep = ' '; - if (self->settings.flow_control & IRCOMM_XON_XOFF_IN) { - seq_printf(m, "%cXON_XOFF_IN", sep); - sep = '|'; - } - if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT) { - seq_printf(m, "%cXON_XOFF_OUT", sep); - sep = '|'; - } - if (self->settings.flow_control & IRCOMM_RTS_CTS_IN) { - seq_printf(m, "%cRTS_CTS_IN", sep); - sep = '|'; - } - if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT) { - seq_printf(m, "%cRTS_CTS_OUT", sep); - sep = '|'; - } - if (self->settings.flow_control & IRCOMM_DSR_DTR_IN) { - seq_printf(m, "%cDSR_DTR_IN", sep); - sep = '|'; - } - if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT) { - seq_printf(m, "%cDSR_DTR_OUT", sep); - sep = '|'; - } - if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN) { - seq_printf(m, "%cENQ_ACK_IN", sep); - sep = '|'; - } - if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT) { - seq_printf(m, "%cENQ_ACK_OUT", sep); - sep = '|'; - } - seq_putc(m, '\n'); - - seq_puts(m, "Flags:"); - sep = ' '; - if (tty_port_cts_enabled(&self->port)) { - seq_printf(m, "%cASYNC_CTS_FLOW", sep); - sep = '|'; - } - if (tty_port_check_carrier(&self->port)) { - seq_printf(m, "%cASYNC_CHECK_CD", sep); - sep = '|'; - } - if (tty_port_initialized(&self->port)) { - seq_printf(m, "%cASYNC_INITIALIZED", sep); - sep = '|'; - } - if (self->port.flags & ASYNC_LOW_LATENCY) { - seq_printf(m, "%cASYNC_LOW_LATENCY", sep); - sep = '|'; - } - if (tty_port_active(&self->port)) { - seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep); - sep = '|'; - } - seq_putc(m, '\n'); - - seq_printf(m, "Role: %s\n", self->client ? "client" : "server"); - seq_printf(m, "Open count: %d\n", self->port.count); - seq_printf(m, "Max data size: %d\n", self->max_data_size); - seq_printf(m, "Max header size: %d\n", self->max_header_size); - - tty = tty_port_tty_get(&self->port); - if (tty) { - seq_printf(m, "Hardware: %s\n", - tty->hw_stopped ? "Stopped" : "Running"); - tty_kref_put(tty); - } -} - -static int ircomm_tty_proc_show(struct seq_file *m, void *v) -{ - struct ircomm_tty_cb *self; - unsigned long flags; - - spin_lock_irqsave(&ircomm_tty->hb_spinlock, flags); - - self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty); - while (self != NULL) { - if (self->magic != IRCOMM_TTY_MAGIC) - break; - - ircomm_tty_line_info(self, m); - self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty); - } - spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags); - return 0; -} - -static int ircomm_tty_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, ircomm_tty_proc_show, NULL); -} - -static const struct file_operations ircomm_tty_proc_fops = { - .owner = THIS_MODULE, - .open = ircomm_tty_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_PROC_FS */ - -MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); -MODULE_DESCRIPTION("IrCOMM serial TTY driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_CHARDEV_MAJOR(IRCOMM_TTY_MAJOR); - -module_init(ircomm_tty_init); -module_exit(ircomm_tty_cleanup); diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c deleted file mode 100644 index 0a411019c098..000000000000 --- a/net/irda/ircomm/ircomm_tty_attach.c +++ /dev/null @@ -1,987 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_tty_attach.c - * Version: - * Description: Code for attaching the serial driver to IrCOMM - * Status: Experimental. - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Sat Jun 5 17:42:00 1999 - * Modified at: Tue Jan 4 14:20:49 2000 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * - * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved. - * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/init.h> -#include <linux/sched.h> - -#include <net/irda/irda.h> -#include <net/irda/irlmp.h> -#include <net/irda/iriap.h> -#include <net/irda/irttp.h> -#include <net/irda/irias_object.h> -#include <net/irda/parameters.h> - -#include <net/irda/ircomm_core.h> -#include <net/irda/ircomm_param.h> -#include <net/irda/ircomm_event.h> - -#include <net/irda/ircomm_tty.h> -#include <net/irda/ircomm_tty_attach.h> - -static void ircomm_tty_ias_register(struct ircomm_tty_cb *self); -static void ircomm_tty_discovery_indication(discinfo_t *discovery, - DISCOVERY_MODE mode, - void *priv); -static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, - struct ias_value *value, void *priv); -static void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, - int timeout); -static void ircomm_tty_watchdog_timer_expired(void *data); - -static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info); -static int ircomm_tty_state_search(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info); -static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info); -static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info); -static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info); -static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info); - -const char *const ircomm_tty_state[] = { - "IRCOMM_TTY_IDLE", - "IRCOMM_TTY_SEARCH", - "IRCOMM_TTY_QUERY_PARAMETERS", - "IRCOMM_TTY_QUERY_LSAP_SEL", - "IRCOMM_TTY_SETUP", - "IRCOMM_TTY_READY", - "*** ERROR *** ", -}; - -static const char *const ircomm_tty_event[] __maybe_unused = { - "IRCOMM_TTY_ATTACH_CABLE", - "IRCOMM_TTY_DETACH_CABLE", - "IRCOMM_TTY_DATA_REQUEST", - "IRCOMM_TTY_DATA_INDICATION", - "IRCOMM_TTY_DISCOVERY_REQUEST", - "IRCOMM_TTY_DISCOVERY_INDICATION", - "IRCOMM_TTY_CONNECT_CONFIRM", - "IRCOMM_TTY_CONNECT_INDICATION", - "IRCOMM_TTY_DISCONNECT_REQUEST", - "IRCOMM_TTY_DISCONNECT_INDICATION", - "IRCOMM_TTY_WD_TIMER_EXPIRED", - "IRCOMM_TTY_GOT_PARAMETERS", - "IRCOMM_TTY_GOT_LSAPSEL", - "*** ERROR ****", -}; - -static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, - struct sk_buff *skb, struct ircomm_tty_info *info) = -{ - ircomm_tty_state_idle, - ircomm_tty_state_search, - ircomm_tty_state_query_parameters, - ircomm_tty_state_query_lsap_sel, - ircomm_tty_state_setup, - ircomm_tty_state_ready, -}; - -/* - * Function ircomm_tty_attach_cable (driver) - * - * Try to attach cable (IrCOMM link). This function will only return - * when the link has been connected, or if an error condition occurs. - * If success, the return value is the resulting service type. - */ -int ircomm_tty_attach_cable(struct ircomm_tty_cb *self) -{ - struct tty_struct *tty; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - /* Check if somebody has already connected to us */ - if (ircomm_is_connected(self->ircomm)) { - pr_debug("%s(), already connected!\n", __func__); - return 0; - } - - /* Make sure nobody tries to write before the link is up */ - tty = tty_port_tty_get(&self->port); - if (tty) { - tty->hw_stopped = 1; - tty_kref_put(tty); - } - - ircomm_tty_ias_register(self); - - ircomm_tty_do_event(self, IRCOMM_TTY_ATTACH_CABLE, NULL, NULL); - - return 0; -} - -/* - * Function ircomm_detach_cable (driver) - * - * Detach cable, or cable has been detached by peer - * - */ -void ircomm_tty_detach_cable(struct ircomm_tty_cb *self) -{ - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - del_timer(&self->watchdog_timer); - - /* Remove discovery handler */ - if (self->ckey) { - irlmp_unregister_client(self->ckey); - self->ckey = NULL; - } - /* Remove IrCOMM hint bits */ - if (self->skey) { - irlmp_unregister_service(self->skey); - self->skey = NULL; - } - - if (self->iriap) { - iriap_close(self->iriap); - self->iriap = NULL; - } - - /* Remove LM-IAS object */ - if (self->obj) { - irias_delete_object(self->obj); - self->obj = NULL; - } - - ircomm_tty_do_event(self, IRCOMM_TTY_DETACH_CABLE, NULL, NULL); - - /* Reset some values */ - self->daddr = self->saddr = 0; - self->dlsap_sel = self->slsap_sel = 0; - - memset(&self->settings, 0, sizeof(struct ircomm_params)); -} - -/* - * Function ircomm_tty_ias_register (self) - * - * Register with LM-IAS depending on which service type we are - * - */ -static void ircomm_tty_ias_register(struct ircomm_tty_cb *self) -{ - __u8 oct_seq[6]; - __u16 hints; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - /* Compute hint bits based on service */ - hints = irlmp_service_to_hint(S_COMM); - if (self->service_type & IRCOMM_3_WIRE_RAW) - hints |= irlmp_service_to_hint(S_PRINTER); - - /* Advertise IrCOMM hint bit in discovery */ - if (!self->skey) - self->skey = irlmp_register_service(hints); - /* Set up a discovery handler */ - if (!self->ckey) - self->ckey = irlmp_register_client(hints, - ircomm_tty_discovery_indication, - NULL, (void *) self); - - /* If already done, no need to do it again */ - if (self->obj) - return; - - if (self->service_type & IRCOMM_3_WIRE_RAW) { - /* Register IrLPT with LM-IAS */ - self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID); - irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel", - self->slsap_sel, IAS_KERNEL_ATTR); - } else { - /* Register IrCOMM with LM-IAS */ - self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID); - irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel", - self->slsap_sel, IAS_KERNEL_ATTR); - - /* Code the parameters into the buffer */ - irda_param_pack(oct_seq, "bbbbbb", - IRCOMM_SERVICE_TYPE, 1, self->service_type, - IRCOMM_PORT_TYPE, 1, IRCOMM_SERIAL); - - /* Register parameters with LM-IAS */ - irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6, - IAS_KERNEL_ATTR); - } - irias_insert_object(self->obj); -} - -/* - * Function ircomm_tty_ias_unregister (self) - * - * Remove our IAS object and client hook while connected. - * - */ -static void ircomm_tty_ias_unregister(struct ircomm_tty_cb *self) -{ - /* Remove LM-IAS object now so it is not reused. - * IrCOMM deals very poorly with multiple incoming connections. - * It should looks a lot more like IrNET, and "dup" a server TSAP - * to the application TSAP (based on various rules). - * This is a cheap workaround allowing multiple clients to - * connect to us. It will not always work. - * Each IrCOMM socket has an IAS entry. Incoming connection will - * pick the first one found. So, when we are fully connected, - * we remove our IAS entries so that the next IAS entry is used. - * We do that for *both* client and server, because a server - * can also create client instances. - * Jean II */ - if (self->obj) { - irias_delete_object(self->obj); - self->obj = NULL; - } - -#if 0 - /* Remove discovery handler. - * While we are connected, we no longer need to receive - * discovery events. This would be the case if there is - * multiple IrLAP interfaces. Jean II */ - if (self->ckey) { - irlmp_unregister_client(self->ckey); - self->ckey = NULL; - } -#endif -} - -/* - * Function ircomm_send_initial_parameters (self) - * - * Send initial parameters to the remote IrCOMM device. These parameters - * must be sent before any data. - */ -int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self) -{ - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (self->service_type & IRCOMM_3_WIRE_RAW) - return 0; - - /* - * Set default values, but only if the application for some reason - * haven't set them already - */ - pr_debug("%s(), data-rate = %d\n", __func__ , - self->settings.data_rate); - if (!self->settings.data_rate) - self->settings.data_rate = 9600; - pr_debug("%s(), data-format = %d\n", __func__ , - self->settings.data_format); - if (!self->settings.data_format) - self->settings.data_format = IRCOMM_WSIZE_8; /* 8N1 */ - - pr_debug("%s(), flow-control = %d\n", __func__ , - self->settings.flow_control); - /*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/ - - /* Do not set delta values for the initial parameters */ - self->settings.dte = IRCOMM_DTR | IRCOMM_RTS; - - /* Only send service type parameter when we are the client */ - if (self->client) - ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE); - ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE); - ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE); - - /* For a 3 wire service, we just flush the last parameter and return */ - if (self->settings.service_type == IRCOMM_3_WIRE) { - ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE); - return 0; - } - - /* Only 9-wire service types continue here */ - ircomm_param_request(self, IRCOMM_FLOW_CONTROL, FALSE); -#if 0 - ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE); - ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE); -#endif - /* Notify peer that we are ready to receive data */ - ircomm_param_request(self, IRCOMM_DTE, TRUE); - - return 0; -} - -/* - * Function ircomm_tty_discovery_indication (discovery) - * - * Remote device is discovered, try query the remote IAS to see which - * device it is, and which services it has. - * - */ -static void ircomm_tty_discovery_indication(discinfo_t *discovery, - DISCOVERY_MODE mode, - void *priv) -{ - struct ircomm_tty_cb *self; - struct ircomm_tty_info info; - - /* Important note : - * We need to drop all passive discoveries. - * The LSAP management of IrComm is deficient and doesn't deal - * with the case of two instance connecting to each other - * simultaneously (it will deadlock in LMP). - * The proper fix would be to use the same technique as in IrNET, - * to have one server socket and separate instances for the - * connecting/connected socket. - * The workaround is to drop passive discovery, which drastically - * reduce the probability of this happening. - * Jean II */ - if(mode == DISCOVERY_PASSIVE) - return; - - info.daddr = discovery->daddr; - info.saddr = discovery->saddr; - - self = priv; - ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION, - NULL, &info); -} - -/* - * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb) - * - * Link disconnected - * - */ -void ircomm_tty_disconnect_indication(void *instance, void *sap, - LM_REASON reason, - struct sk_buff *skb) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - struct tty_struct *tty; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - tty = tty_port_tty_get(&self->port); - if (!tty) - return; - - /* This will stop control data transfers */ - self->flow = FLOW_STOP; - - /* Stop data transfers */ - tty->hw_stopped = 1; - - ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, - NULL); - tty_kref_put(tty); -} - -/* - * Function ircomm_tty_getvalue_confirm (result, obj_id, value, priv) - * - * Got result from the IAS query we make - * - */ -static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, - struct ias_value *value, - void *priv) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - /* We probably don't need to make any more queries */ - iriap_close(self->iriap); - self->iriap = NULL; - - /* Check if request succeeded */ - if (result != IAS_SUCCESS) { - pr_debug("%s(), got NULL value!\n", __func__); - return; - } - - switch (value->type) { - case IAS_OCT_SEQ: - pr_debug("%s(), got octet sequence\n", __func__); - - irda_param_extract_all(self, value->t.oct_seq, value->len, - &ircomm_param_info); - - ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL, - NULL); - break; - case IAS_INTEGER: - /* Got LSAP selector */ - pr_debug("%s(), got lsapsel = %d\n", __func__ , - value->t.integer); - - if (value->t.integer == -1) { - pr_debug("%s(), invalid value!\n", __func__); - } else - self->dlsap_sel = value->t.integer; - - ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL); - break; - case IAS_MISSING: - pr_debug("%s(), got IAS_MISSING\n", __func__); - break; - default: - pr_debug("%s(), got unknown type!\n", __func__); - break; - } - irias_delete_value(value); -} - -/* - * Function ircomm_tty_connect_confirm (instance, sap, qos, max_sdu_size, skb) - * - * Connection confirmed - * - */ -void ircomm_tty_connect_confirm(void *instance, void *sap, - struct qos_info *qos, - __u32 max_data_size, - __u8 max_header_size, - struct sk_buff *skb) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - self->client = TRUE; - self->max_data_size = max_data_size; - self->max_header_size = max_header_size; - self->flow = FLOW_START; - - ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL); - - /* No need to kfree_skb - see ircomm_ttp_connect_confirm() */ -} - -/* - * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size, - * skb) - * - * we are discovered and being requested to connect by remote device ! - * - */ -void ircomm_tty_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_data_size, - __u8 max_header_size, - struct sk_buff *skb) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; - int clen; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - self->client = FALSE; - self->max_data_size = max_data_size; - self->max_header_size = max_header_size; - self->flow = FLOW_START; - - clen = skb->data[0]; - if (clen) - irda_param_extract_all(self, skb->data+1, - IRDA_MIN(skb->len, clen), - &ircomm_param_info); - - ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL); - - /* No need to kfree_skb - see ircomm_ttp_connect_indication() */ -} - -/* - * Function ircomm_tty_link_established (self) - * - * Called when the IrCOMM link is established - * - */ -void ircomm_tty_link_established(struct ircomm_tty_cb *self) -{ - struct tty_struct *tty; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - tty = tty_port_tty_get(&self->port); - if (!tty) - return; - - del_timer(&self->watchdog_timer); - - /* - * IrCOMM link is now up, and if we are not using hardware - * flow-control, then declare the hardware as running. Otherwise we - * will have to wait for the peer device (DCE) to raise the CTS - * line. - */ - if (tty_port_cts_enabled(&self->port) && - ((self->settings.dce & IRCOMM_CTS) == 0)) { - pr_debug("%s(), waiting for CTS ...\n", __func__); - goto put; - } else { - pr_debug("%s(), starting hardware!\n", __func__); - - tty->hw_stopped = 0; - - /* Wake up processes blocked on open */ - wake_up_interruptible(&self->port.open_wait); - } - - schedule_work(&self->tqueue); -put: - tty_kref_put(tty); -} - -/* - * Function ircomm_tty_start_watchdog_timer (self, timeout) - * - * Start the watchdog timer. This timer is used to make sure that any - * connection attempt is successful, and if not, we will retry after - * the timeout - */ -static void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, - int timeout) -{ - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - irda_start_timer(&self->watchdog_timer, timeout, (void *) self, - ircomm_tty_watchdog_timer_expired); -} - -/* - * Function ircomm_tty_watchdog_timer_expired (data) - * - * Called when the connect procedure have taken to much time. - * - */ -static void ircomm_tty_watchdog_timer_expired(void *data) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data; - - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL); -} - - -/* - * Function ircomm_tty_do_event (self, event, skb) - * - * Process event - * - */ -int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event, - struct sk_buff *skb, struct ircomm_tty_info *info) -{ - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - pr_debug("%s: state=%s, event=%s\n", __func__ , - ircomm_tty_state[self->state], ircomm_tty_event[event]); - - return (*state[self->state])(self, event, skb, info); -} - -/* - * Function ircomm_tty_next_state (self, state) - * - * Switch state - * - */ -static inline void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state) -{ - /* - IRDA_ASSERT(self != NULL, return;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - - pr_debug("%s: next state=%s, service type=%d\n", __func__ , - ircomm_tty_state[self->state], self->service_type); - */ - self->state = state; -} - -/* - * Function ircomm_tty_state_idle (self, event, skb, info) - * - * Just hanging around - * - */ -static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info) -{ - int ret = 0; - - pr_debug("%s: state=%s, event=%s\n", __func__ , - ircomm_tty_state[self->state], ircomm_tty_event[event]); - switch (event) { - case IRCOMM_TTY_ATTACH_CABLE: - /* Try to discover any remote devices */ - ircomm_tty_start_watchdog_timer(self, 3*HZ); - ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); - - irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); - break; - case IRCOMM_TTY_DISCOVERY_INDICATION: - self->daddr = info->daddr; - self->saddr = info->saddr; - - if (self->iriap) { - net_warn_ratelimited("%s(), busy with a previous query\n", - __func__); - return -EBUSY; - } - - self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, - ircomm_tty_getvalue_confirm); - - iriap_getvaluebyclass_request(self->iriap, - self->saddr, self->daddr, - "IrDA:IrCOMM", "Parameters"); - - ircomm_tty_start_watchdog_timer(self, 3*HZ); - ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS); - break; - case IRCOMM_TTY_CONNECT_INDICATION: - del_timer(&self->watchdog_timer); - - /* Accept connection */ - ircomm_connect_response(self->ircomm, NULL); - ircomm_tty_next_state(self, IRCOMM_TTY_READY); - break; - case IRCOMM_TTY_WD_TIMER_EXPIRED: - /* Just stay idle */ - break; - case IRCOMM_TTY_DETACH_CABLE: - ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_tty_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_tty_state_search (self, event, skb, info) - * - * Trying to discover an IrCOMM device - * - */ -static int ircomm_tty_state_search(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info) -{ - int ret = 0; - - pr_debug("%s: state=%s, event=%s\n", __func__ , - ircomm_tty_state[self->state], ircomm_tty_event[event]); - - switch (event) { - case IRCOMM_TTY_DISCOVERY_INDICATION: - self->daddr = info->daddr; - self->saddr = info->saddr; - - if (self->iriap) { - net_warn_ratelimited("%s(), busy with a previous query\n", - __func__); - return -EBUSY; - } - - self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, - ircomm_tty_getvalue_confirm); - - if (self->service_type == IRCOMM_3_WIRE_RAW) { - iriap_getvaluebyclass_request(self->iriap, self->saddr, - self->daddr, "IrLPT", - "IrDA:IrLMP:LsapSel"); - ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL); - } else { - iriap_getvaluebyclass_request(self->iriap, self->saddr, - self->daddr, - "IrDA:IrCOMM", - "Parameters"); - - ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS); - } - ircomm_tty_start_watchdog_timer(self, 3*HZ); - break; - case IRCOMM_TTY_CONNECT_INDICATION: - del_timer(&self->watchdog_timer); - ircomm_tty_ias_unregister(self); - - /* Accept connection */ - ircomm_connect_response(self->ircomm, NULL); - ircomm_tty_next_state(self, IRCOMM_TTY_READY); - break; - case IRCOMM_TTY_WD_TIMER_EXPIRED: -#if 1 - /* Give up */ -#else - /* Try to discover any remote devices */ - ircomm_tty_start_watchdog_timer(self, 3*HZ); - irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); -#endif - break; - case IRCOMM_TTY_DETACH_CABLE: - ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_tty_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_tty_state_query (self, event, skb, info) - * - * Querying the remote LM-IAS for IrCOMM parameters - * - */ -static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info) -{ - int ret = 0; - - pr_debug("%s: state=%s, event=%s\n", __func__ , - ircomm_tty_state[self->state], ircomm_tty_event[event]); - - switch (event) { - case IRCOMM_TTY_GOT_PARAMETERS: - if (self->iriap) { - net_warn_ratelimited("%s(), busy with a previous query\n", - __func__); - return -EBUSY; - } - - self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, - ircomm_tty_getvalue_confirm); - - iriap_getvaluebyclass_request(self->iriap, self->saddr, - self->daddr, "IrDA:IrCOMM", - "IrDA:TinyTP:LsapSel"); - - ircomm_tty_start_watchdog_timer(self, 3*HZ); - ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL); - break; - case IRCOMM_TTY_WD_TIMER_EXPIRED: - /* Go back to search mode */ - ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); - ircomm_tty_start_watchdog_timer(self, 3*HZ); - break; - case IRCOMM_TTY_CONNECT_INDICATION: - del_timer(&self->watchdog_timer); - ircomm_tty_ias_unregister(self); - - /* Accept connection */ - ircomm_connect_response(self->ircomm, NULL); - ircomm_tty_next_state(self, IRCOMM_TTY_READY); - break; - case IRCOMM_TTY_DETACH_CABLE: - ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_tty_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_tty_state_query_lsap_sel (self, event, skb, info) - * - * Query remote LM-IAS for the LSAP selector which we can connect to - * - */ -static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info) -{ - int ret = 0; - - pr_debug("%s: state=%s, event=%s\n", __func__ , - ircomm_tty_state[self->state], ircomm_tty_event[event]); - - switch (event) { - case IRCOMM_TTY_GOT_LSAPSEL: - /* Connect to remote device */ - ret = ircomm_connect_request(self->ircomm, self->dlsap_sel, - self->saddr, self->daddr, - NULL, self->service_type); - ircomm_tty_start_watchdog_timer(self, 3*HZ); - ircomm_tty_next_state(self, IRCOMM_TTY_SETUP); - break; - case IRCOMM_TTY_WD_TIMER_EXPIRED: - /* Go back to search mode */ - ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); - ircomm_tty_start_watchdog_timer(self, 3*HZ); - break; - case IRCOMM_TTY_CONNECT_INDICATION: - del_timer(&self->watchdog_timer); - ircomm_tty_ias_unregister(self); - - /* Accept connection */ - ircomm_connect_response(self->ircomm, NULL); - ircomm_tty_next_state(self, IRCOMM_TTY_READY); - break; - case IRCOMM_TTY_DETACH_CABLE: - ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_tty_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_tty_state_setup (self, event, skb, info) - * - * Trying to connect - * - */ -static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info) -{ - int ret = 0; - - pr_debug("%s: state=%s, event=%s\n", __func__ , - ircomm_tty_state[self->state], ircomm_tty_event[event]); - - switch (event) { - case IRCOMM_TTY_CONNECT_CONFIRM: - del_timer(&self->watchdog_timer); - ircomm_tty_ias_unregister(self); - - /* - * Send initial parameters. This will also send out queued - * parameters waiting for the connection to come up - */ - ircomm_tty_send_initial_parameters(self); - ircomm_tty_link_established(self); - ircomm_tty_next_state(self, IRCOMM_TTY_READY); - break; - case IRCOMM_TTY_CONNECT_INDICATION: - del_timer(&self->watchdog_timer); - ircomm_tty_ias_unregister(self); - - /* Accept connection */ - ircomm_connect_response(self->ircomm, NULL); - ircomm_tty_next_state(self, IRCOMM_TTY_READY); - break; - case IRCOMM_TTY_WD_TIMER_EXPIRED: - /* Go back to search mode */ - ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); - ircomm_tty_start_watchdog_timer(self, 3*HZ); - break; - case IRCOMM_TTY_DETACH_CABLE: - /* ircomm_disconnect_request(self->ircomm, NULL); */ - ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_tty_event[event]); - ret = -EINVAL; - } - return ret; -} - -/* - * Function ircomm_tty_state_ready (self, event, skb, info) - * - * IrCOMM is now connected - * - */ -static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, - IRCOMM_TTY_EVENT event, - struct sk_buff *skb, - struct ircomm_tty_info *info) -{ - int ret = 0; - - switch (event) { - case IRCOMM_TTY_DATA_REQUEST: - ret = ircomm_data_request(self->ircomm, skb); - break; - case IRCOMM_TTY_DETACH_CABLE: - ircomm_disconnect_request(self->ircomm, NULL); - ircomm_tty_next_state(self, IRCOMM_TTY_IDLE); - break; - case IRCOMM_TTY_DISCONNECT_INDICATION: - ircomm_tty_ias_register(self); - ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH); - ircomm_tty_start_watchdog_timer(self, 3*HZ); - - if (tty_port_check_carrier(&self->port)) { - /* Drop carrier */ - self->settings.dce = IRCOMM_DELTA_CD; - ircomm_tty_check_modem_status(self); - } else { - pr_debug("%s(), hanging up!\n", __func__); - tty_port_tty_hangup(&self->port, false); - } - break; - default: - pr_debug("%s(), unknown event: %s\n", __func__ , - ircomm_tty_event[event]); - ret = -EINVAL; - } - return ret; -} - diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c deleted file mode 100644 index 171c3dee760e..000000000000 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ /dev/null @@ -1,291 +0,0 @@ -/********************************************************************* - * - * Filename: ircomm_tty_ioctl.c - * Version: - * Description: - * Status: Experimental. - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Thu Jun 10 14:39:09 1999 - * Modified at: Wed Jan 5 14:45:43 2000 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * - * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/termios.h> -#include <linux/tty.h> -#include <linux/serial.h> - -#include <linux/uaccess.h> - -#include <net/irda/irda.h> -#include <net/irda/irmod.h> - -#include <net/irda/ircomm_core.h> -#include <net/irda/ircomm_param.h> -#include <net/irda/ircomm_tty_attach.h> -#include <net/irda/ircomm_tty.h> - -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - -/* - * Function ircomm_tty_change_speed (driver) - * - * Change speed of the driver. If the remote device is a DCE, then this - * should make it change the speed of its serial port - */ -static void ircomm_tty_change_speed(struct ircomm_tty_cb *self, - struct tty_struct *tty) -{ - unsigned int cflag, cval; - int baud; - - if (!self->ircomm) - return; - - cflag = tty->termios.c_cflag; - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: cval = IRCOMM_WSIZE_5; break; - case CS6: cval = IRCOMM_WSIZE_6; break; - case CS7: cval = IRCOMM_WSIZE_7; break; - case CS8: cval = IRCOMM_WSIZE_8; break; - default: cval = IRCOMM_WSIZE_5; break; - } - if (cflag & CSTOPB) - cval |= IRCOMM_2_STOP_BIT; - - if (cflag & PARENB) - cval |= IRCOMM_PARITY_ENABLE; - if (!(cflag & PARODD)) - cval |= IRCOMM_PARITY_EVEN; - - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(tty); - if (!baud) - baud = 9600; /* B0 transition handled in rs_set_termios */ - - self->settings.data_rate = baud; - ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE); - - /* CTS flow control flag and modem status interrupts */ - tty_port_set_cts_flow(&self->port, cflag & CRTSCTS); - if (cflag & CRTSCTS) { - self->settings.flow_control |= IRCOMM_RTS_CTS_IN; - /* This got me. Bummer. Jean II */ - if (self->service_type == IRCOMM_3_WIRE_RAW) - net_warn_ratelimited("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", - __func__); - } else { - self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; - } - tty_port_set_check_carrier(&self->port, ~cflag & CLOCAL); - - self->settings.data_format = cval; - - ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE); - ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE); -} - -/* - * Function ircomm_tty_set_termios (tty, old_termios) - * - * This routine allows the tty driver to be notified when device's - * termios settings have changed. Note that a well-designed tty driver - * should be prepared to accept the case where old == NULL, and try to - * do something rational. - */ -void ircomm_tty_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - unsigned int cflag = tty->termios.c_cflag; - - if ((cflag == old_termios->c_cflag) && - (RELEVANT_IFLAG(tty->termios.c_iflag) == - RELEVANT_IFLAG(old_termios->c_iflag))) - { - return; - } - - ircomm_tty_change_speed(self, tty); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { - self->settings.dte &= ~(IRCOMM_DTR|IRCOMM_RTS); - ircomm_param_request(self, IRCOMM_DTE, TRUE); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { - self->settings.dte |= IRCOMM_DTR; - if (!C_CRTSCTS(tty) || !tty_throttled(tty)) - self->settings.dte |= IRCOMM_RTS; - ircomm_param_request(self, IRCOMM_DTE, TRUE); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) - { - tty->hw_stopped = 0; - ircomm_tty_start(tty); - } -} - -/* - * Function ircomm_tty_tiocmget (tty) - * - * - * - */ -int ircomm_tty_tiocmget(struct tty_struct *tty) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - unsigned int result; - - if (tty_io_error(tty)) - return -EIO; - - result = ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0) - | ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0) - | ((self->settings.dce & IRCOMM_CD) ? TIOCM_CAR : 0) - | ((self->settings.dce & IRCOMM_RI) ? TIOCM_RNG : 0) - | ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0) - | ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0); - return result; -} - -/* - * Function ircomm_tty_tiocmset (tty, set, clear) - * - * - * - */ -int ircomm_tty_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - - if (tty_io_error(tty)) - return -EIO; - - IRDA_ASSERT(self != NULL, return -1;); - IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;); - - if (set & TIOCM_RTS) - self->settings.dte |= IRCOMM_RTS; - if (set & TIOCM_DTR) - self->settings.dte |= IRCOMM_DTR; - - if (clear & TIOCM_RTS) - self->settings.dte &= ~IRCOMM_RTS; - if (clear & TIOCM_DTR) - self->settings.dte &= ~IRCOMM_DTR; - - if ((set|clear) & TIOCM_RTS) - self->settings.dte |= IRCOMM_DELTA_RTS; - if ((set|clear) & TIOCM_DTR) - self->settings.dte |= IRCOMM_DELTA_DTR; - - ircomm_param_request(self, IRCOMM_DTE, TRUE); - - return 0; -} - -/* - * Function get_serial_info (driver, retinfo) - * - * - * - */ -static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self, - struct serial_struct __user *retinfo) -{ - struct serial_struct info; - - memset(&info, 0, sizeof(info)); - info.line = self->line; - info.flags = self->port.flags; - info.baud_base = self->settings.data_rate; - info.close_delay = self->port.close_delay; - info.closing_wait = self->port.closing_wait; - - /* For compatibility */ - info.type = PORT_16550A; - - if (copy_to_user(retinfo, &info, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -/* - * Function set_serial_info (driver, new_info) - * - * - * - */ -static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self, - struct serial_struct __user *new_info) -{ - return 0; -} - -/* - * Function ircomm_tty_ioctl (tty, cmd, arg) - * - * - * - */ -int ircomm_tty_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data; - int ret = 0; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty_io_error(tty)) - return -EIO; - } - - switch (cmd) { - case TIOCGSERIAL: - ret = ircomm_tty_get_serial_info(self, (struct serial_struct __user *) arg); - break; - case TIOCSSERIAL: - ret = ircomm_tty_set_serial_info(self, (struct serial_struct __user *) arg); - break; - case TIOCMIWAIT: - pr_debug("(), TIOCMIWAIT, not impl!\n"); - break; - - case TIOCGICOUNT: - pr_debug("%s(), TIOCGICOUNT not impl!\n", __func__); - return 0; - default: - ret = -ENOIOCTLCMD; /* ioctls which we must ignore */ - } - return ret; -} - - - |