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
nexedi
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
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
tristate "IrPORT (IrDA serial driver)"
depends on IRDA
...
...
drivers/net/irda/Makefile
View file @
329c2084
...
...
@@ -5,8 +5,7 @@
# Rewritten to use lists instead of if-statements.
#
# Old SIR drivers (irtty is broken)
obj-$(CONFIG_IRTTY_OLD)
+=
irtty.o
# Old SIR drivers
obj-$(CONFIG_IRPORT_SIR)
+=
irport.o
# FIR drivers
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