Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
329c2084
Commit
329c2084
authored
Aug 19, 2003
by
Stephen Hemminger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IRDA]: Kill old irtty driver, as suggested by Jean and Jeff.
parent
71c2e86e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1 addition
and
1093 deletions
+1
-1093
drivers/net/irda/Kconfig
drivers/net/irda/Kconfig
+0
-14
drivers/net/irda/Makefile
drivers/net/irda/Makefile
+1
-2
drivers/net/irda/irtty.c
drivers/net/irda/irtty.c
+0
-1077
No files found.
drivers/net/irda/Kconfig
View file @
329c2084
...
@@ -68,20 +68,6 @@ config TEKRAM_DONGLE
...
@@ -68,20 +68,6 @@ config TEKRAM_DONGLE
comment "Old SIR device drivers"
comment "Old SIR device drivers"
config IRTTY_OLD
tristate "Old IrTTY (broken)"
depends on IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the IrTTY line
discipline. If you want to compile it as a module (irtty), say M
here and read <file:Documentation/modules.txt>. IrTTY makes it
possible to use Linux's own serial driver for all IrDA ports that
are 16550 compatible. Most IrDA chips are 16550 compatible so you
should probably say Y to this option. Using IrTTY will however
limit the speed of the connection to 115200 bps (IrDA SIR mode).
If unsure, say N.
config IRPORT_SIR
config IRPORT_SIR
tristate "IrPORT (IrDA serial driver)"
tristate "IrPORT (IrDA serial driver)"
depends on IRDA
depends on IRDA
...
...
drivers/net/irda/Makefile
View file @
329c2084
...
@@ -5,8 +5,7 @@
...
@@ -5,8 +5,7 @@
# Rewritten to use lists instead of if-statements.
# Rewritten to use lists instead of if-statements.
#
#
# Old SIR drivers (irtty is broken)
# Old SIR drivers
obj-$(CONFIG_IRTTY_OLD)
+=
irtty.o
obj-$(CONFIG_IRPORT_SIR)
+=
irport.o
obj-$(CONFIG_IRPORT_SIR)
+=
irport.o
# FIR drivers
# FIR drivers
obj-$(CONFIG_USB_IRDA)
+=
irda-usb.o
obj-$(CONFIG_USB_IRDA)
+=
irda-usb.o
...
...
drivers/net/irda/irtty.c
deleted
100644 → 0
View file @
71c2e86e
/*********************************************************************
*
* Filename: irtty.c
* Version: 1.1
* Description: IrDA line discipline implementation
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
* Modified at: Sat Mar 11 07:43:30 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
* Copyright (c) 1998-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.
*
* Neither Dag Brattli nor University of Troms admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <asm/uaccess.h>
#include <net/irda/irda.h>
#include <net/irda/irtty.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
static
int
qos_mtt_bits
=
0x03
;
/* 5 ms or more */
/* Network device fuction prototypes */
static
int
irtty_hard_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
int
irtty_net_init
(
struct
net_device
*
dev
);
static
int
irtty_net_open
(
struct
net_device
*
dev
);
static
int
irtty_net_close
(
struct
net_device
*
dev
);
static
int
irtty_net_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
static
struct
net_device_stats
*
irtty_net_get_stats
(
struct
net_device
*
dev
);
/* Line discipline function prototypes */
static
int
irtty_open
(
struct
tty_struct
*
tty
);
static
void
irtty_close
(
struct
tty_struct
*
tty
);
static
int
irtty_ioctl
(
struct
tty_struct
*
,
struct
file
*
,
unsigned
int
,
unsigned
long
);
static
int
irtty_receive_room
(
struct
tty_struct
*
tty
);
static
void
irtty_write_wakeup
(
struct
tty_struct
*
tty
);
static
void
irtty_receive_buf
(
struct
tty_struct
*
,
const
unsigned
char
*
,
char
*
,
int
);
/* IrDA specific function protoctypes */
static
int
irtty_is_receiving
(
struct
irtty_cb
*
self
);
static
int
irtty_set_dtr_rts
(
struct
net_device
*
dev
,
int
dtr
,
int
rts
);
static
int
irtty_raw_write
(
struct
net_device
*
dev
,
__u8
*
buf
,
int
len
);
static
int
irtty_raw_read
(
struct
net_device
*
dev
,
__u8
*
buf
,
int
len
);
static
int
irtty_set_mode
(
struct
net_device
*
dev
,
int
mode
);
static
int
irtty_change_speed
(
struct
irda_task
*
task
);
static
struct
tty_ldisc
irda_ldisc
=
{
.
owner
=
THIS_MODULE
,
.
magic
=
TTY_LDISC_MAGIC
,
.
name
=
"irda"
,
.
open
=
irtty_open
,
.
close
=
irtty_close
,
.
ioctl
=
irtty_ioctl
,
.
receive_buf
=
irtty_receive_buf
,
.
receive_room
=
irtty_receive_room
,
.
write_wakeup
=
irtty_write_wakeup
,
};
int
__init
irtty_init
(
void
)
{
int
status
;
if
((
status
=
tty_register_ldisc
(
N_IRDA
,
&
irda_ldisc
))
!=
0
)
{
ERROR
(
"IrDA: can't register line discipline (err = %d)
\n
"
,
status
);
}
return
status
;
}
/*
* Function irtty_cleanup ( )
*
* Called when the irda module is removed. Here we remove all instances
* of the driver, and the master array.
*/
static
void
__exit
irtty_cleanup
(
void
)
{
int
ret
;
/* Unregister tty line-discipline */
if
((
ret
=
tty_register_ldisc
(
N_IRDA
,
NULL
)))
{
ERROR
(
"%s(), can't unregister line discipline (err = %d)
\n
"
,
__FUNCTION__
,
ret
);
}
}
/*
* Function irtty_open(tty)
*
* This function is called by the TTY module when the IrDA line
* discipline is called for. Because we are sure the tty line exists,
* we only have to link it to a free IrDA channel.
*/
static
int
irtty_open
(
struct
tty_struct
*
tty
)
{
struct
net_device
*
dev
;
struct
irtty_cb
*
self
;
char
name
[
16
];
int
err
;
ASSERT
(
tty
!=
NULL
,
return
-
EEXIST
;);
/* First make sure we're not already connected. */
self
=
(
struct
irtty_cb
*
)
tty
->
disc_data
;
if
(
self
!=
NULL
&&
self
->
magic
==
IRTTY_MAGIC
)
return
-
EEXIST
;
/*
* Allocate new instance of the driver
*/
self
=
kmalloc
(
sizeof
(
struct
irtty_cb
),
GFP_KERNEL
);
if
(
self
==
NULL
)
{
printk
(
KERN_ERR
"IrDA: Can't allocate memory for "
"IrDA control block!
\n
"
);
return
-
ENOMEM
;
}
memset
(
self
,
0
,
sizeof
(
struct
irtty_cb
));
spin_lock_init
(
&
self
->
lock
);
self
->
tty
=
tty
;
tty
->
disc_data
=
self
;
/* Give self a name */
strcpy
(
name
,
tty
->
name
);
if
(
tty
->
driver
->
flush_buffer
)
tty
->
driver
->
flush_buffer
(
tty
);
if
(
tty
->
ldisc
.
flush_buffer
)
tty
->
ldisc
.
flush_buffer
(
tty
);
self
->
magic
=
IRTTY_MAGIC
;
self
->
mode
=
IRDA_IRLAP
;
/*
* Initialize QoS capabilities, we fill in all the stuff that
* we support. Be careful not to place any restrictions on values
* that are not device dependent (such as link disconnect time) so
* this parameter can be set by IrLAP (or the user) instead. DB
*/
irda_init_max_qos_capabilies
(
&
self
->
qos
);
/* The only value we must override it the baudrate */
self
->
qos
.
baud_rate
.
bits
=
IR_9600
|
IR_19200
|
IR_38400
|
IR_57600
|
IR_115200
;
self
->
qos
.
min_turn_time
.
bits
=
qos_mtt_bits
;
self
->
flags
=
IFF_SIR
|
IFF_PIO
;
irda_qos_bits_to_value
(
&
self
->
qos
);
/* Specify how much memory we want */
self
->
rx_buff
.
truesize
=
4000
;
self
->
tx_buff
.
truesize
=
4000
;
/* Allocate memory if needed */
if
(
self
->
rx_buff
.
truesize
>
0
)
{
self
->
rx_buff
.
head
=
(
__u8
*
)
kmalloc
(
self
->
rx_buff
.
truesize
,
GFP_KERNEL
);
if
(
self
->
rx_buff
.
head
==
NULL
)
return
-
ENOMEM
;
memset
(
self
->
rx_buff
.
head
,
0
,
self
->
rx_buff
.
truesize
);
}
if
(
self
->
tx_buff
.
truesize
>
0
)
{
self
->
tx_buff
.
head
=
(
__u8
*
)
kmalloc
(
self
->
tx_buff
.
truesize
,
GFP_KERNEL
);
if
(
self
->
tx_buff
.
head
==
NULL
)
{
kfree
(
self
->
rx_buff
.
head
);
return
-
ENOMEM
;
}
memset
(
self
->
tx_buff
.
head
,
0
,
self
->
tx_buff
.
truesize
);
}
self
->
rx_buff
.
in_frame
=
FALSE
;
self
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
self
->
tx_buff
.
data
=
self
->
tx_buff
.
head
;
self
->
rx_buff
.
data
=
self
->
rx_buff
.
head
;
if
(
!
(
dev
=
dev_alloc
(
"irda%d"
,
&
err
)))
{
ERROR
(
"%s(), dev_alloc() failed!
\n
"
,
__FUNCTION__
);
return
-
ENOMEM
;
}
dev
->
priv
=
(
void
*
)
self
;
self
->
netdev
=
dev
;
/* Override the network functions we need to use */
dev
->
init
=
irtty_net_init
;
dev
->
hard_start_xmit
=
irtty_hard_xmit
;
dev
->
open
=
irtty_net_open
;
dev
->
stop
=
irtty_net_close
;
dev
->
get_stats
=
irtty_net_get_stats
;
dev
->
do_ioctl
=
irtty_net_ioctl
;
rtnl_lock
();
err
=
register_netdevice
(
dev
);
rtnl_unlock
();
if
(
err
)
{
ERROR
(
"%s(), register_netdev() failed!
\n
"
,
__FUNCTION__
);
return
-
1
;
}
MESSAGE
(
"IrDA: Registered device %s
\n
"
,
dev
->
name
);
return
0
;
}
/*
* Function irtty_close (tty)
*
* Close down a IrDA channel. This means flushing out any pending queues,
* and then restoring the TTY line discipline to what it was before it got
* hooked to IrDA (which usually is TTY again).
*/
static
void
irtty_close
(
struct
tty_struct
*
tty
)
{
struct
irtty_cb
*
self
=
(
struct
irtty_cb
*
)
tty
->
disc_data
;
unsigned
long
flags
;
/* First make sure we're connected. */
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
;);
/* Stop tty */
tty
->
flags
&=
~
(
1
<<
TTY_DO_WRITE_WAKEUP
);
tty
->
disc_data
=
0
;
/* We are not using any dongle anymore! */
if
(
self
->
dongle
)
irda_device_dongle_cleanup
(
self
->
dongle
);
self
->
dongle
=
NULL
;
/* Remove netdevice */
if
(
self
->
netdev
)
unregister_netdev
(
self
->
netdev
);
/* Protect access to self->task and self->?x_buff - Jean II */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Remove speed changing task if any */
if
(
self
->
task
)
irda_task_delete
(
self
->
task
);
self
->
tty
=
NULL
;
self
->
magic
=
0
;
if
(
self
->
tx_buff
.
head
)
kfree
(
self
->
tx_buff
.
head
);
if
(
self
->
rx_buff
.
head
)
kfree
(
self
->
rx_buff
.
head
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
kfree
(
self
);
}
/*
* Function irtty_stop_receiver (self, stop)
*
*
*
*/
static
void
irtty_stop_receiver
(
struct
irtty_cb
*
self
,
int
stop
)
{
struct
termios
old_termios
;
int
cflag
;
old_termios
=
*
(
self
->
tty
->
termios
);
cflag
=
self
->
tty
->
termios
->
c_cflag
;
if
(
stop
)
cflag
&=
~
CREAD
;
else
cflag
|=
CREAD
;
/* This is unsafe, but currently under discussion - Jean II */
self
->
tty
->
termios
->
c_cflag
=
cflag
;
self
->
tty
->
driver
->
set_termios
(
self
->
tty
,
&
old_termios
);
}
/*
* Function irtty_do_change_speed (self, speed)
*
* Change the speed of the serial port.
*/
static
void
__irtty_change_speed
(
struct
irtty_cb
*
self
,
__u32
speed
)
{
struct
termios
old_termios
;
int
cflag
;
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
;);
old_termios
=
*
(
self
->
tty
->
termios
);
cflag
=
self
->
tty
->
termios
->
c_cflag
;
cflag
&=
~
CBAUD
;
IRDA_DEBUG
(
2
,
"%s(), Setting speed to %d
\n
"
,
__FUNCTION__
,
speed
);
switch
(
speed
)
{
case
1200
:
cflag
|=
B1200
;
break
;
case
2400
:
cflag
|=
B2400
;
break
;
case
4800
:
cflag
|=
B4800
;
break
;
case
19200
:
cflag
|=
B19200
;
break
;
case
38400
:
cflag
|=
B38400
;
break
;
case
57600
:
cflag
|=
B57600
;
break
;
case
115200
:
cflag
|=
B115200
;
break
;
case
9600
:
default:
cflag
|=
B9600
;
break
;
}
/* This is unsafe, but currently under discussion - Jean II */
self
->
tty
->
termios
->
c_cflag
=
cflag
;
self
->
tty
->
driver
->
set_termios
(
self
->
tty
,
&
old_termios
);
self
->
io
.
speed
=
speed
;
}
/*
* Function irtty_change_speed (instance, state, param)
*
* State machine for changing speed of the device. We do it this way since
* we cannot use schedule_timeout() when we are in interrupt context
*/
static
int
irtty_change_speed
(
struct
irda_task
*
task
)
{
struct
irtty_cb
*
self
;
unsigned
long
flags
;
__u32
speed
=
(
__u32
)
task
->
param
;
int
ret
=
0
;
IRDA_DEBUG
(
2
,
"%s(), <%ld>
\n
"
,
__FUNCTION__
,
jiffies
);
self
=
(
struct
irtty_cb
*
)
task
->
instance
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
/* Protect access to self->task - Jean II */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Check if busy */
if
(
self
->
task
&&
self
->
task
!=
task
)
{
IRDA_DEBUG
(
0
,
"%s(), busy!
\n
"
,
__FUNCTION__
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
return
MSECS_TO_JIFFIES
(
10
);
}
else
self
->
task
=
task
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
switch
(
task
->
state
)
{
case
IRDA_TASK_INIT
:
/*
* Make sure all data is sent before changing the speed of the
* serial port.
*/
if
(
self
->
tty
->
driver
->
chars_in_buffer
(
self
->
tty
))
{
/* Keep state, and try again later */
ret
=
MSECS_TO_JIFFIES
(
10
);
break
;
}
else
{
/* Transmit buffer is now empty, but it may still
* take over 13 ms for the FIFO to become empty, so
* wait some more to be sure all data is sent
*/
irda_task_next_state
(
task
,
IRDA_TASK_WAIT
);
ret
=
MSECS_TO_JIFFIES
(
13
);
}
case
IRDA_TASK_WAIT
:
if
(
self
->
dongle
)
irda_task_next_state
(
task
,
IRDA_TASK_CHILD_INIT
);
else
irda_task_next_state
(
task
,
IRDA_TASK_CHILD_DONE
);
break
;
case
IRDA_TASK_CHILD_INIT
:
/* Go to default speed */
__irtty_change_speed
(
self
,
9600
);
/* Change speed of dongle */
if
(
irda_task_execute
(
self
->
dongle
,
self
->
dongle
->
issue
->
change_speed
,
NULL
,
task
,
(
void
*
)
speed
))
{
/* Dongle need more time to change its speed */
irda_task_next_state
(
task
,
IRDA_TASK_CHILD_WAIT
);
/* Give dongle 1 sec to finish */
ret
=
MSECS_TO_JIFFIES
(
1000
);
}
else
/* Child finished immediately */
irda_task_next_state
(
task
,
IRDA_TASK_CHILD_DONE
);
break
;
case
IRDA_TASK_CHILD_WAIT
:
WARNING
(
"%s(), changing speed of dongle timed out!
\n
"
,
__FUNCTION__
);
ret
=
-
1
;
break
;
case
IRDA_TASK_CHILD_DONE
:
/* Finally we are ready to change the speed */
__irtty_change_speed
(
self
,
speed
);
irda_task_next_state
(
task
,
IRDA_TASK_DONE
);
self
->
task
=
NULL
;
break
;
default:
ERROR
(
"%s(), unknown state %d
\n
"
,
__FUNCTION__
,
task
->
state
);
irda_task_next_state
(
task
,
IRDA_TASK_DONE
);
self
->
task
=
NULL
;
ret
=
-
1
;
break
;
}
return
ret
;
}
/*
* Function irtty_ioctl (tty, file, cmd, arg)
*
* The Swiss army knife of system calls :-)
*
*/
static
int
irtty_ioctl
(
struct
tty_struct
*
tty
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
dongle_t
*
dongle
;
struct
irtty_info
info
;
struct
irtty_cb
*
self
;
int
size
=
_IOC_SIZE
(
cmd
);
int
err
=
0
;
self
=
(
struct
irtty_cb
*
)
tty
->
disc_data
;
ASSERT
(
self
!=
NULL
,
return
-
ENODEV
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
-
EBADR
;);
if
(
_IOC_DIR
(
cmd
)
&
_IOC_READ
)
err
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
size
);
else
if
(
_IOC_DIR
(
cmd
)
&
_IOC_WRITE
)
err
=
verify_area
(
VERIFY_READ
,
(
void
*
)
arg
,
size
);
if
(
err
)
return
err
;
switch
(
cmd
)
{
case
TCGETS
:
case
TCGETA
:
/* Unsure about locking here, to check - Jean II */
return
n_tty_ioctl
(
tty
,
(
struct
file
*
)
file
,
cmd
,
arg
);
break
;
case
IRTTY_IOCTDONGLE
:
/* Initialize dongle */
dongle
=
irda_device_dongle_init
(
self
->
netdev
,
(
int
)
arg
);
if
(
!
dongle
)
break
;
/* Initialize callbacks */
dongle
->
set_mode
=
irtty_set_mode
;
dongle
->
read
=
irtty_raw_read
;
dongle
->
write
=
irtty_raw_write
;
dongle
->
set_dtr_rts
=
irtty_set_dtr_rts
;
/* Now initialize the dongle! */
dongle
->
issue
->
open
(
dongle
,
&
self
->
qos
);
/* Reset dongle */
irda_task_execute
(
dongle
,
dongle
->
issue
->
reset
,
NULL
,
NULL
,
NULL
);
/* Make dongle available to driver only now to avoid
* race conditions - Jean II */
self
->
dongle
=
dongle
;
break
;
case
IRTTY_IOCGET
:
ASSERT
(
self
->
netdev
!=
NULL
,
return
-
1
;);
memset
(
&
info
,
0
,
sizeof
(
struct
irtty_info
));
strncpy
(
info
.
name
,
self
->
netdev
->
name
,
5
);
if
(
copy_to_user
((
void
*
)
arg
,
&
info
,
sizeof
(
struct
irtty_info
)))
return
-
EFAULT
;
break
;
default:
return
-
ENOIOCTLCMD
;
}
return
0
;
}
/*
* Function irtty_receive_buf( tty, cp, count)
*
* Handle the 'receiver data ready' interrupt. This function is called
* by the 'tty_io' module in the kernel when a block of IrDA data has
* been received, which can now be decapsulated and delivered for
* further processing
*/
static
void
irtty_receive_buf
(
struct
tty_struct
*
tty
,
const
unsigned
char
*
cp
,
char
*
fp
,
int
count
)
{
struct
irtty_cb
*
self
=
(
struct
irtty_cb
*
)
tty
->
disc_data
;
if
(
!
self
||
!
self
->
netdev
)
{
IRDA_DEBUG
(
0
,
"%s(), not ready yet!
\n
"
,
__FUNCTION__
);
return
;
}
// Are we in interrupt context ? What locking is done ? - Jean II
//spin_lock_irqsave(&self->lock, flags);
/* Read the characters out of the buffer */
while
(
count
--
)
{
/*
* Characters received with a parity error, etc?
*/
if
(
fp
&&
*
fp
++
)
{
IRDA_DEBUG
(
0
,
"Framing or parity error!
\n
"
);
irda_device_set_media_busy
(
self
->
netdev
,
TRUE
);
cp
++
;
continue
;
}
switch
(
self
->
mode
)
{
case
IRDA_IRLAP
:
/* Unwrap and destuff one byte */
async_unwrap_char
(
self
->
netdev
,
&
self
->
stats
,
&
self
->
rx_buff
,
*
cp
++
);
break
;
case
IRDA_RAW
:
/* What should we do when the buffer is full? */
if
(
self
->
rx_buff
.
len
==
self
->
rx_buff
.
truesize
)
self
->
rx_buff
.
len
=
0
;
self
->
rx_buff
.
data
[
self
->
rx_buff
.
len
++
]
=
*
cp
++
;
break
;
default:
break
;
}
}
//spin_unlock_irqrestore(&self->lock, flags);
}
/*
* Function irtty_change_speed_complete (task)
*
* Called when the change speed operation completes
*
*/
static
int
irtty_change_speed_complete
(
struct
irda_task
*
task
)
{
struct
irtty_cb
*
self
;
IRDA_DEBUG
(
2
,
"%s()
\n
"
,
__FUNCTION__
);
self
=
(
struct
irtty_cb
*
)
task
->
instance
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
ASSERT
(
self
->
netdev
!=
NULL
,
return
-
1
;);
/* Finished changing speed, so we are not busy any longer */
/* Signal network layer so it can try to send the frame */
netif_wake_queue
(
self
->
netdev
);
return
0
;
}
/*
* Function irtty_hard_xmit (skb, dev)
*
* Transmit frame
*
*/
static
int
irtty_hard_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
irtty_cb
*
self
;
int
actual
=
0
;
__s32
speed
;
unsigned
long
flags
;
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
0
;);
/* Lock transmit buffer
* this serialise operations, no need to spinlock - Jean II */
netif_stop_queue
(
dev
);
/* Check if we need to change the speed */
speed
=
irda_get_next_speed
(
skb
);
if
((
speed
!=
self
->
io
.
speed
)
&&
(
speed
!=
-
1
))
{
/* Check for empty frame */
if
(
!
skb
->
len
)
{
irda_task_execute
(
self
,
irtty_change_speed
,
irtty_change_speed_complete
,
NULL
,
(
void
*
)
speed
);
dev_kfree_skb
(
skb
);
return
0
;
}
else
self
->
new_speed
=
speed
;
}
/* Protect access to self->tx_buff - Jean II */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Init tx buffer*/
self
->
tx_buff
.
data
=
self
->
tx_buff
.
head
;
/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
self
->
tx_buff
.
len
=
async_wrap_skb
(
skb
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
truesize
);
self
->
tty
->
flags
|=
(
1
<<
TTY_DO_WRITE_WAKEUP
);
dev
->
trans_start
=
jiffies
;
self
->
stats
.
tx_bytes
+=
self
->
tx_buff
.
len
;
if
(
self
->
tty
->
driver
->
write
)
actual
=
self
->
tty
->
driver
->
write
(
self
->
tty
,
0
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
len
);
/* Hide the part we just transmitted */
self
->
tx_buff
.
data
+=
actual
;
self
->
tx_buff
.
len
-=
actual
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
}
/*
* Function irtty_receive_room (tty)
*
* Used by the TTY to find out how much data we can receive at a time
*
*/
static
int
irtty_receive_room
(
struct
tty_struct
*
tty
)
{
IRDA_DEBUG
(
0
,
"%s()
\n
"
,
__FUNCTION__
);
return
65536
;
/* We can handle an infinite amount of data. :-) */
}
/*
* Function irtty_write_wakeup (tty)
*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
*
*/
static
void
irtty_write_wakeup
(
struct
tty_struct
*
tty
)
{
struct
irtty_cb
*
self
=
(
struct
irtty_cb
*
)
tty
->
disc_data
;
int
actual
=
0
;
unsigned
long
flags
;
/*
* First make sure we're connected.
*/
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
;);
/* Protected via netif_stop_queue(dev); - Jean II */
/* Protect access to self->tx_buff - Jean II */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Finished with frame? */
if
(
self
->
tx_buff
.
len
>
0
)
{
/* Write data left in transmit buffer */
actual
=
tty
->
driver
->
write
(
tty
,
0
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
len
);
self
->
tx_buff
.
data
+=
actual
;
self
->
tx_buff
.
len
-=
actual
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
}
else
{
/*
* Now serial buffer is almost free & we can start
* transmission of another packet
*/
IRDA_DEBUG
(
5
,
"%s(), finished with frame!
\n
"
,
__FUNCTION__
);
self
->
stats
.
tx_packets
++
;
tty
->
flags
&=
~
(
1
<<
TTY_DO_WRITE_WAKEUP
);
/* Don't change speed with irq off */
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
if
(
self
->
new_speed
)
{
IRDA_DEBUG
(
5
,
"%s(), Changing speed!
\n
"
,
__FUNCTION__
);
irda_task_execute
(
self
,
irtty_change_speed
,
irtty_change_speed_complete
,
NULL
,
(
void
*
)
self
->
new_speed
);
self
->
new_speed
=
0
;
}
else
{
/* Tell network layer that we want more frames */
netif_wake_queue
(
self
->
netdev
);
}
}
}
/*
* Function irtty_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
*
*/
static
int
irtty_is_receiving
(
struct
irtty_cb
*
self
)
{
return
(
self
->
rx_buff
.
state
!=
OUTSIDE_FRAME
);
}
/*
* Function irtty_set_dtr_rts (tty, dtr, rts)
*
* This function can be used by dongles etc. to set or reset the status
* of the dtr and rts lines
*/
static
int
irtty_set_dtr_rts
(
struct
net_device
*
dev
,
int
dtr
,
int
rts
)
{
struct
irtty_cb
*
self
;
struct
tty_struct
*
tty
;
//unsigned long flags;
mm_segment_t
fs
;
int
arg
=
0
;
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
tty
=
self
->
tty
;
/* Was protected in ioctl handler, but the serial driver doesn't
* like it. This may need to change. - Jean II */
//spin_lock_irqsave(&self->lock, flags);
#ifdef TIOCM_OUT2
/* Not defined for ARM */
arg
=
TIOCM_OUT2
;
#endif
if
(
rts
)
arg
|=
TIOCM_RTS
;
if
(
dtr
)
arg
|=
TIOCM_DTR
;
/*
* The ioctl() function, or actually set_modem_info() in serial.c
* expects a pointer to the argument in user space. To hack us
* around this, we use the set_fs() function to fool the routines
* that check if they are called from user space. We also need
* to send a pointer to the argument so get_user() gets happy. DB.
*/
fs
=
get_fs
();
set_fs
(
get_ds
());
/* This is probably unsafe, but currently under discussion - Jean II */
if
(
tty
->
driver
->
ioctl
(
tty
,
NULL
,
TIOCMSET
,
(
unsigned
long
)
&
arg
))
{
IRDA_DEBUG
(
2
,
"%s(), error doing ioctl!
\n
"
,
__FUNCTION__
);
}
set_fs
(
fs
);
//spin_unlock_irqrestore(&self->lock, flags);
return
0
;
}
/*
* Function irtty_set_mode (self, status)
*
* For the airport dongle, we need support for reading raw characters
* from the IrDA device. This function switches between those modes.
* FALSE is the default mode, and will then treat incoming data as IrDA
* packets.
*/
int
irtty_set_mode
(
struct
net_device
*
dev
,
int
mode
)
{
struct
irtty_cb
*
self
;
unsigned
long
flags
;
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
IRDA_DEBUG
(
2
,
"%s(), mode=%s
\n
"
,
__FUNCTION__
,
infrared_mode
[
mode
]);
/* Protect access to self->rx_buff - Jean II */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* save status for driver */
self
->
mode
=
mode
;
/* reset the buffer state */
self
->
rx_buff
.
data
=
self
->
rx_buff
.
head
;
self
->
rx_buff
.
len
=
0
;
self
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
return
0
;
}
/*
* Function irtty_raw_read (self, buf, len)
*
* Receive incoming data. This function sleeps, so it must only be
* called with a process context. Timeout is currently defined to be
* a multiple of 10 ms.
*/
static
int
irtty_raw_read
(
struct
net_device
*
dev
,
__u8
*
buf
,
int
len
)
{
struct
irtty_cb
*
self
;
int
count
;
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
0
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
0
;);
return
0
;
#if 0
buf = self->rx_buff.data;
/* Wait for the requested amount of data to arrive */
while (len < self->rx_buff.len) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(10));
if (!timeout--)
break;
}
count = self->rx_buff.len < len ? self->rx_buff.len : len;
/*
* Reset the state, this mean that a raw read is sort of a
* datagram read, and _not_ a stream style read. Be aware of the
* difference. Implementing it the other way will just be painful ;-)
*/
self->rx_buff.data = self->rx_buff.head;
self->rx_buff.len = 0;
self->rx_buff.state = OUTSIDE_FRAME;
#endif
/* Return the amount we were able to get */
return
count
;
}
static
int
irtty_raw_write
(
struct
net_device
*
dev
,
__u8
*
buf
,
int
len
)
{
struct
irtty_cb
*
self
;
int
actual
=
0
;
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
0
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
0
;);
if
(
self
->
tty
->
driver
->
write
)
actual
=
self
->
tty
->
driver
->
write
(
self
->
tty
,
0
,
buf
,
len
);
return
actual
;
}
static
int
irtty_net_init
(
struct
net_device
*
dev
)
{
/* Set up to be a normal IrDA network device driver */
irda_device_setup
(
dev
);
/* Insert overrides below this line! */
return
0
;
}
static
int
irtty_net_open
(
struct
net_device
*
dev
)
{
struct
irtty_cb
*
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
struct
tty_struct
*
tty
=
self
->
tty
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
-
1
;);
IRDA_DEBUG
(
0
,
"%s()
\n
"
,
__FUNCTION__
);
/* Ready to play! */
netif_start_queue
(
dev
);
/* Make sure we can receive more data */
irtty_stop_receiver
(
self
,
FALSE
);
/*
* Open new IrLAP layer instance, now that everything should be
* initialized properly
*/
self
->
irlap
=
irlap_open
(
dev
,
&
self
->
qos
,
tty
->
name
);
return
0
;
}
static
int
irtty_net_close
(
struct
net_device
*
dev
)
{
struct
irtty_cb
*
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
-
1
;);
/* Make sure we don't receive more data */
irtty_stop_receiver
(
self
,
TRUE
);
/* Stop device */
netif_stop_queue
(
dev
);
/* Stop and remove instance of IrLAP */
if
(
self
->
irlap
)
irlap_close
(
self
->
irlap
);
self
->
irlap
=
NULL
;
return
0
;
}
/*
* Function irtty_net_ioctl (dev, rq, cmd)
*
* Process IOCTL commands for this device
*
*/
static
int
irtty_net_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
struct
if_irda_req
*
irq
=
(
struct
if_irda_req
*
)
rq
;
struct
irtty_cb
*
self
;
dongle_t
*
dongle
;
int
ret
=
0
;
ASSERT
(
dev
!=
NULL
,
return
-
1
;);
self
=
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
ASSERT
(
self
->
magic
==
IRTTY_MAGIC
,
return
-
1
;);
IRDA_DEBUG
(
3
,
"%s(), %s, (cmd=0x%X)
\n
"
,
__FUNCTION__
,
dev
->
name
,
cmd
);
/* Locking :
* irda_device_dongle_init() can't be locked.
* irda_task_execute() doesn't need to be locked (but
* irtty_change_speed() should protect itself).
* Other calls protect themselves.
* Jean II
*/
switch
(
cmd
)
{
case
SIOCSBANDWIDTH
:
/* Set bandwidth */
if
(
!
capable
(
CAP_NET_ADMIN
))
ret
=
-
EPERM
;
else
irda_task_execute
(
self
,
irtty_change_speed
,
NULL
,
NULL
,
(
void
*
)
irq
->
ifr_baudrate
);
break
;
case
SIOCSDONGLE
:
/* Set dongle */
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret
=
-
EPERM
;
break
;
}
/* Initialize dongle */
dongle
=
irda_device_dongle_init
(
dev
,
irq
->
ifr_dongle
);
if
(
!
dongle
)
break
;
dongle
->
set_mode
=
irtty_set_mode
;
dongle
->
read
=
irtty_raw_read
;
dongle
->
write
=
irtty_raw_write
;
dongle
->
set_dtr_rts
=
irtty_set_dtr_rts
;
/* Now initialize the dongle!
* Safe to do unlocked : self->dongle is still NULL. */
dongle
->
issue
->
open
(
dongle
,
&
self
->
qos
);
/* Reset dongle */
irda_task_execute
(
dongle
,
dongle
->
issue
->
reset
,
NULL
,
NULL
,
NULL
);
/* Make dongle available to driver only now to avoid
* race conditions - Jean II */
self
->
dongle
=
dongle
;
break
;
case
SIOCSMEDIABUSY
:
/* Set media busy */
if
(
!
capable
(
CAP_NET_ADMIN
))
ret
=
-
EPERM
;
else
irda_device_set_media_busy
(
self
->
netdev
,
TRUE
);
break
;
case
SIOCGRECEIVING
:
/* Check if we are receiving right now */
irq
->
ifr_receiving
=
irtty_is_receiving
(
self
);
break
;
case
SIOCSDTRRTS
:
if
(
!
capable
(
CAP_NET_ADMIN
))
ret
=
-
EPERM
;
else
{
irtty_set_dtr_rts
(
dev
,
irq
->
ifr_dtr
,
irq
->
ifr_rts
);
}
break
;
case
SIOCSMODE
:
if
(
!
capable
(
CAP_NET_ADMIN
))
ret
=
-
EPERM
;
else
{
irtty_set_mode
(
dev
,
irq
->
ifr_mode
);
}
break
;
default:
ret
=
-
EOPNOTSUPP
;
}
return
ret
;
}
static
struct
net_device_stats
*
irtty_net_get_stats
(
struct
net_device
*
dev
)
{
struct
irtty_cb
*
self
=
(
struct
irtty_cb
*
)
dev
->
priv
;
return
&
self
->
stats
;
}
MODULE_AUTHOR
(
"Dag Brattli <dagb@cs.uit.no>"
);
MODULE_DESCRIPTION
(
"IrDA TTY device driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
qos_mtt_bits
,
"i"
);
MODULE_PARM_DESC
(
qos_mtt_bits
,
"Minimum Turn Time"
);
/*
* Function init_module (void)
*
* Initialize IrTTY module
*
*/
module_init
(
irtty_init
);
/*
* Function cleanup_module (void)
*
* Cleanup IrTTY module
*
*/
module_exit
(
irtty_cleanup
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment