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
8f7155ad
Commit
8f7155ad
authored
Mar 03, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/davem/net-2.6
into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents
dbbffa7b
dd2514fe
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
536 additions
and
364 deletions
+536
-364
Documentation/crypto/api-intro.txt
Documentation/crypto/api-intro.txt
+1
-0
crypto/Kconfig
crypto/Kconfig
+10
-0
crypto/Makefile
crypto/Makefile
+1
-0
crypto/arc4.c
crypto/arc4.c
+106
-0
crypto/tcrypt.c
crypto/tcrypt.c
+10
-1
crypto/tcrypt.h
crypto/tcrypt.h
+141
-0
drivers/net/irda/stir4200.c
drivers/net/irda/stir4200.c
+267
-363
No files found.
Documentation/crypto/api-intro.txt
View file @
8f7155ad
...
...
@@ -186,6 +186,7 @@ Original developers of the crypto algorithms:
Dag Arne Osvik (Serpent)
Brian Gladman (AES)
Kartikey Mahendra Bhatt (CAST6)
Jon Oberheide (ARC4)
SHA1 algorithm contributors:
Jean-Francois Dive
...
...
crypto/Kconfig
View file @
8f7155ad
...
...
@@ -140,6 +140,16 @@ config CRYPTO_CAST6
The CAST6 encryption algorithm (synonymous with CAST-256) is
described in RFC2612.
config CRYPTO_ARC4
tristate "ARC4 cipher algorithm"
depends on CRYPTO
help
ARC4 cipher algorithm.
This is a stream cipher using keys ranging from 8 bits to 2048
bits in length. ARC4 is commonly used in protocols such as WEP
and SSL.
config CRYPTO_DEFLATE
tristate "Deflate compression algorithm"
depends on CRYPTO
...
...
crypto/Makefile
View file @
8f7155ad
...
...
@@ -21,6 +21,7 @@ obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
obj-$(CONFIG_CRYPTO_AES)
+=
aes.o
obj-$(CONFIG_CRYPTO_CAST5)
+=
cast5.o
obj-$(CONFIG_CRYPTO_CAST6)
+=
cast6.o
obj-$(CONFIG_CRYPTO_ARC4)
+=
arc4.o
obj-$(CONFIG_CRYPTO_DEFLATE)
+=
deflate.o
obj-$(CONFIG_CRYPTO_TEST)
+=
tcrypt.o
crypto/arc4.c
0 → 100644
View file @
8f7155ad
/*
* Cryptographic API
*
* ARC4 Cipher Algorithm
*
* Jon Oberheide <jon@focalhost.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.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/crypto.h>
#define ARC4_MIN_KEY_SIZE 1
#define ARC4_MAX_KEY_SIZE 256
#define ARC4_BLOCK_SIZE 1
struct
arc4_ctx
{
u8
S
[
256
];
u8
x
,
y
;
};
static
int
arc4_set_key
(
void
*
ctx_arg
,
const
u8
*
in_key
,
unsigned
int
key_len
,
u32
*
flags
)
{
struct
arc4_ctx
*
ctx
=
ctx_arg
;
int
i
,
j
=
0
,
k
=
0
;
ctx
->
x
=
1
;
ctx
->
y
=
0
;
for
(
i
=
0
;
i
<
256
;
i
++
)
ctx
->
S
[
i
]
=
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
u8
a
=
ctx
->
S
[
i
];
j
=
(
j
+
in_key
[
k
]
+
a
)
&
0xff
;
ctx
->
S
[
i
]
=
ctx
->
S
[
j
];
ctx
->
S
[
j
]
=
a
;
if
(
++
k
>=
key_len
)
k
=
0
;
}
/* TODO: dump the first 768 bytes generated as recommended
by Ilya Mironov (http://eprint.iacr.org/2002/067/) to
increase the statistical strength of the state table */
return
0
;
}
static
void
arc4_crypt
(
void
*
ctx_arg
,
u8
*
out
,
const
u8
*
in
)
{
struct
arc4_ctx
*
ctx
=
ctx_arg
;
u8
*
const
S
=
ctx
->
S
;
u8
x
=
ctx
->
x
;
u8
y
=
ctx
->
y
;
u8
a
=
S
[
x
];
y
=
(
y
+
a
)
&
0xff
;
u8
b
=
S
[
y
];
S
[
x
]
=
b
;
S
[
y
]
=
a
;
x
=
(
x
+
1
)
&
0xff
;
*
out
++
=
*
in
^
S
[(
a
+
b
)
&
0xff
];
ctx
->
x
=
x
;
ctx
->
y
=
y
;
}
static
struct
crypto_alg
arc4_alg
=
{
.
cra_name
=
"arc4"
,
.
cra_flags
=
CRYPTO_ALG_TYPE_CIPHER
,
.
cra_blocksize
=
ARC4_BLOCK_SIZE
,
.
cra_ctxsize
=
sizeof
(
struct
arc4_ctx
),
.
cra_module
=
THIS_MODULE
,
.
cra_list
=
LIST_HEAD_INIT
(
arc4_alg
.
cra_list
),
.
cra_u
=
{
.
cipher
=
{
.
cia_min_keysize
=
ARC4_MIN_KEY_SIZE
,
.
cia_max_keysize
=
ARC4_MAX_KEY_SIZE
,
.
cia_setkey
=
arc4_set_key
,
.
cia_encrypt
=
arc4_crypt
,
.
cia_decrypt
=
arc4_crypt
}
}
};
static
int
__init
arc4_init
(
void
)
{
return
crypto_register_alg
(
&
arc4_alg
);
}
static
void
__exit
arc4_exit
(
void
)
{
crypto_unregister_alg
(
&
arc4_alg
);
}
module_init
(
arc4_init
);
module_exit
(
arc4_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"ARC4 Cipher Algorithm"
);
MODULE_AUTHOR
(
"Jon Oberheide <jon@focalhost.com>"
);
crypto/tcrypt.c
View file @
8f7155ad
...
...
@@ -61,7 +61,7 @@ static char *tvmem;
static
char
*
check
[]
=
{
"des"
,
"md5"
,
"des3_ede"
,
"rot13"
,
"sha1"
,
"sha256"
,
"blowfish"
,
"twofish"
,
"serpent"
,
"sha384"
,
"sha512"
,
"md4"
,
"aes"
,
"cast6"
,
"deflate"
,
NULL
"
arc4"
,
"
deflate"
,
NULL
};
static
void
...
...
@@ -556,6 +556,10 @@ do_test(void)
test_cipher
(
"cast6"
,
MODE_ECB
,
ENCRYPT
,
cast6_enc_tv_template
,
CAST6_ENC_TEST_VECTORS
);
test_cipher
(
"cast6"
,
MODE_ECB
,
DECRYPT
,
cast6_dec_tv_template
,
CAST6_DEC_TEST_VECTORS
);
//ARC4
test_cipher
(
"arc4"
,
MODE_ECB
,
ENCRYPT
,
arc4_enc_tv_template
,
ARC4_ENC_TEST_VECTORS
);
test_cipher
(
"arc4x"
,
MODE_ECB
,
DECRYPT
,
arc4_dec_tv_template
,
ARC4_DEC_TEST_VECTORS
);
test_hash
(
"sha384"
,
sha384_tv_template
,
SHA384_TEST_VECTORS
);
test_hash
(
"sha512"
,
sha512_tv_template
,
SHA512_TEST_VECTORS
);
test_deflate
();
...
...
@@ -638,6 +642,11 @@ do_test(void)
test_cipher
(
"cast6"
,
MODE_ECB
,
DECRYPT
,
cast6_dec_tv_template
,
CAST6_DEC_TEST_VECTORS
);
break
;
case
16
:
test_cipher
(
"arc4"
,
MODE_ECB
,
ENCRYPT
,
arc4_enc_tv_template
,
ARC4_ENC_TEST_VECTORS
);
test_cipher
(
"arc4"
,
MODE_ECB
,
DECRYPT
,
arc4_dec_tv_template
,
ARC4_DEC_TEST_VECTORS
);
break
;
#ifdef CONFIG_CRYPTO_HMAC
case
100
:
test_hmac
(
"md5"
,
hmac_md5_tv_template
,
HMAC_MD5_TEST_VECTORS
);
...
...
crypto/tcrypt.h
View file @
8f7155ad
...
...
@@ -1488,6 +1488,147 @@ struct cipher_testvec cast5_dec_tv_template[] =
},
};
/*
* ARC4 test vectors from OpenSSL
*/
#define ARC4_ENC_TEST_VECTORS 7
#define ARC4_DEC_TEST_VECTORS 7
struct
cipher_testvec
arc4_enc_tv_template
[]
=
{
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
klen
=
8
,
.
input
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
ilen
=
8
,
.
result
=
{
0x75
,
0xb7
,
0x87
,
0x80
,
0x99
,
0xe0
,
0xc5
,
0x96
},
.
rlen
=
8
,
},
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
klen
=
8
,
.
input
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
ilen
=
8
,
.
result
=
{
0x74
,
0x94
,
0xc2
,
0xe7
,
0x10
,
0x4b
,
0x08
,
0x79
},
.
rlen
=
8
,
},
{
.
key
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
klen
=
8
,
.
input
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
ilen
=
8
,
.
result
=
{
0xde
,
0x18
,
0x89
,
0x41
,
0xa3
,
0x37
,
0x5d
,
0x3a
},
.
rlen
=
8
,
},
{
.
key
=
{
0xef
,
0x01
,
0x23
,
0x45
},
.
klen
=
4
,
.
input
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
ilen
=
20
,
.
result
=
{
0xd6
,
0xa1
,
0x41
,
0xa7
,
0xec
,
0x3c
,
0x38
,
0xdf
,
0xbd
,
0x61
,
0x5a
,
0x11
,
0x62
,
0xe1
,
0xc7
,
0xba
,
0x36
,
0xb6
,
0x78
,
0x58
},
.
rlen
=
20
,
},
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
klen
=
8
,
.
input
=
{
0x12
,
0x34
,
0x56
,
0x78
,
0x9A
,
0xBC
,
0xDE
,
0xF0
,
0x12
,
0x34
,
0x56
,
0x78
,
0x9A
,
0xBC
,
0xDE
,
0xF0
,
0x12
,
0x34
,
0x56
,
0x78
,
0x9A
,
0xBC
,
0xDE
,
0xF0
,
0x12
,
0x34
,
0x56
,
0x78
},
.
ilen
=
28
,
.
result
=
{
0x66
,
0xa0
,
0x94
,
0x9f
,
0x8a
,
0xf7
,
0xd6
,
0x89
,
0x1f
,
0x7f
,
0x83
,
0x2b
,
0xa8
,
0x33
,
0xc0
,
0x0c
,
0x89
,
0x2e
,
0xbe
,
0x30
,
0x14
,
0x3c
,
0xe2
,
0x87
,
0x40
,
0x01
,
0x1e
,
0xcf
},
.
rlen
=
28
,
},
{
.
key
=
{
0xef
,
0x01
,
0x23
,
0x45
},
.
klen
=
4
,
.
input
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
ilen
=
10
,
.
result
=
{
0xd6
,
0xa1
,
0x41
,
0xa7
,
0xec
,
0x3c
,
0x38
,
0xdf
,
0xbd
,
0x61
},
.
rlen
=
10
,
},
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xAB
,
0xCD
,
0xEF
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
klen
=
16
,
.
input
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xAB
,
0xCD
,
0xEF
},
.
ilen
=
8
,
.
result
=
{
0x69
,
0x72
,
0x36
,
0x59
,
0x1B
,
0x52
,
0x42
,
0xB1
},
.
rlen
=
8
,
},
};
struct
cipher_testvec
arc4_dec_tv_template
[]
=
{
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
klen
=
8
,
.
input
=
{
0x75
,
0xb7
,
0x87
,
0x80
,
0x99
,
0xe0
,
0xc5
,
0x96
},
.
ilen
=
8
,
.
result
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
rlen
=
8
,
},
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
klen
=
8
,
.
input
=
{
0x74
,
0x94
,
0xc2
,
0xe7
,
0x10
,
0x4b
,
0x08
,
0x79
},
.
ilen
=
8
,
.
result
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
rlen
=
8
,
},
{
.
key
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
klen
=
8
,
.
input
=
{
0xde
,
0x18
,
0x89
,
0x41
,
0xa3
,
0x37
,
0x5d
,
0x3a
},
.
ilen
=
8
,
.
result
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
rlen
=
8
,
},
{
.
key
=
{
0xef
,
0x01
,
0x23
,
0x45
},
.
klen
=
4
,
.
input
=
{
0xd6
,
0xa1
,
0x41
,
0xa7
,
0xec
,
0x3c
,
0x38
,
0xdf
,
0xbd
,
0x61
,
0x5a
,
0x11
,
0x62
,
0xe1
,
0xc7
,
0xba
,
0x36
,
0xb6
,
0x78
,
0x58
},
.
ilen
=
20
,
.
result
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
rlen
=
20
,
},
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xab
,
0xcd
,
0xef
},
.
klen
=
8
,
.
input
=
{
0x66
,
0xa0
,
0x94
,
0x9f
,
0x8a
,
0xf7
,
0xd6
,
0x89
,
0x1f
,
0x7f
,
0x83
,
0x2b
,
0xa8
,
0x33
,
0xc0
,
0x0c
,
0x89
,
0x2e
,
0xbe
,
0x30
,
0x14
,
0x3c
,
0xe2
,
0x87
,
0x40
,
0x01
,
0x1e
,
0xcf
},
.
ilen
=
28
,
.
result
=
{
0x12
,
0x34
,
0x56
,
0x78
,
0x9A
,
0xBC
,
0xDE
,
0xF0
,
0x12
,
0x34
,
0x56
,
0x78
,
0x9A
,
0xBC
,
0xDE
,
0xF0
,
0x12
,
0x34
,
0x56
,
0x78
,
0x9A
,
0xBC
,
0xDE
,
0xF0
,
0x12
,
0x34
,
0x56
,
0x78
},
.
rlen
=
28
,
},
{
.
key
=
{
0xef
,
0x01
,
0x23
,
0x45
},
.
klen
=
4
,
.
input
=
{
0xd6
,
0xa1
,
0x41
,
0xa7
,
0xec
,
0x3c
,
0x38
,
0xdf
,
0xbd
,
0x61
},
.
ilen
=
10
,
.
result
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
rlen
=
10
,
},
{
.
key
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xAB
,
0xCD
,
0xEF
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
},
.
klen
=
16
,
.
input
=
{
0x69
,
0x72
,
0x36
,
0x59
,
0x1B
,
0x52
,
0x42
,
0xB1
},
.
ilen
=
8
,
.
result
=
{
0x01
,
0x23
,
0x45
,
0x67
,
0x89
,
0xAB
,
0xCD
,
0xEF
},
.
rlen
=
8
,
},
};
/*
* Compression stuff.
*/
...
...
drivers/net/irda/stir4200.c
View file @
8f7155ad
...
...
@@ -49,12 +49,14 @@
#include <linux/suspend.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/crc32.h>
#include <net/irda/irda.h>
#include <net/irda/irlap.h>
#include <net/irda/irda_device.h>
#include <net/irda/wrapper.h>
#include <net/irda/crc.h>
#include <linux/crc32.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
MODULE_AUTHOR
(
"Stephen Hemminger <shemminger@osdl.org>"
);
MODULE_DESCRIPTION
(
"IrDA-USB Dongle Driver for SigmaTel STIr4200"
);
...
...
@@ -72,15 +74,11 @@ static int tx_power = 0; /* 0 = highest ... 3 = lowest */
module_param
(
tx_power
,
int
,
0
);
MODULE_PARM_DESC
(
tx_power
,
"Set Transmitter power (0-3, 0 is highest power)"
);
static
int
rx_interval
=
5
;
/* milliseconds */
module_param
(
rx_interval
,
int
,
0
);
MODULE_PARM_DESC
(
rx_interval
,
"Receive polling interval (ms)"
);
#define STIR_IRDA_HEADER 4
#define CTRL_TIMEOUT 100
/* milliseconds */
#define TRANSMIT_TIMEOUT 200
/* milliseconds */
#define STIR_FIFO_SIZE 4096
#define
NUM_RX_URBS 2
#define
FIFO_REGS_SIZE 3
enum
FirChars
{
FIR_CE
=
0x7d
,
...
...
@@ -167,36 +165,26 @@ enum StirTestMask {
TEST_TSTOSC
=
0x0F
,
};
enum
StirState
{
STIR_STATE_RECEIVING
=
0
,
STIR_STATE_TXREADY
,
};
struct
stir_cb
{
struct
usb_device
*
usbdev
;
/* init: probe_irda */
struct
net_device
*
netdev
;
/* network layer */
struct
irlap_cb
*
irlap
;
/* The link layer we are binded to */
struct
net_device_stats
stats
;
/* network statistics */
struct
qos_info
qos
;
unsigned
long
state
;
unsigned
speed
;
/* Current speed */
wait_queue_head_t
thr_wait
;
/* transmit thread wakeup */
struct
completion
thr_exited
;
pid_t
thr_pid
;
unsigned
int
tx_bulkpipe
;
void
*
tx_data
;
/* wrapped data out */
unsigned
tx_len
;
unsigned
tx_newspeed
;
unsigned
tx_mtt
;
struct
sk_buff
*
tx_pending
;
void
*
io_buf
;
/* transmit/receive buffer */
__u8
*
fifo_status
;
unsigned
int
rx_intpipe
;
iobuff_t
rx_buff
;
/* receive unwrap state machine */
struct
timespec
rx_time
;
struct
urb
*
rx_urbs
[
NUM_RX_URBS
];
void
*
rx_data
[
NUM_RX_URBS
];
struct
timeval
rx_time
;
int
receiving
;
struct
urb
*
rx_urb
;
};
...
...
@@ -209,9 +197,6 @@ static struct usb_device_id dongles[] = {
MODULE_DEVICE_TABLE
(
usb
,
dongles
);
static
int
fifo_txwait
(
struct
stir_cb
*
stir
,
unsigned
space
);
static
void
stir_usb_receive
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
);
/* Send control message to set dongle register */
static
int
write_reg
(
struct
stir_cb
*
stir
,
__u16
reg
,
__u8
value
)
{
...
...
@@ -239,6 +224,11 @@ static inline int read_reg(struct stir_cb *stir, __u16 reg,
MSECS_TO_JIFFIES
(
CTRL_TIMEOUT
));
}
static
inline
int
isfir
(
u32
speed
)
{
return
(
speed
==
4000000
);
}
/*
* Prepare a FIR IrDA frame for transmission to the USB dongle. The
* FIR transmit frame is documented in the datasheet. It consists of
...
...
@@ -333,8 +323,8 @@ static void fir_eof(struct stir_cb *stir)
{
iobuff_t
*
rx_buff
=
&
stir
->
rx_buff
;
int
len
=
rx_buff
->
len
-
4
;
struct
sk_buff
*
skb
,
*
nskb
;
__u32
fcs
;
struct
sk_buff
*
nskb
;
if
(
unlikely
(
len
<=
0
))
{
pr_debug
(
"%s: short frame len %d
\n
"
,
...
...
@@ -345,41 +335,46 @@ static void fir_eof(struct stir_cb *stir)
return
;
}
fcs
=
rx_buff
->
data
[
len
]
|
rx_buff
->
data
[
len
+
1
]
<<
8
|
rx_buff
->
data
[
len
+
2
]
<<
16
|
rx_buff
->
data
[
len
+
3
]
<<
24
;
if
(
unlikely
(
fcs
!=
~
(
crc32_le
(
~
0
,
rx_buff
->
data
,
len
))))
{
pr_debug
(
"%s: crc error
\n
"
,
stir
->
netdev
->
name
);
irda_device_set_media_busy
(
stir
->
netdev
,
TRUE
);
fcs
=
~
(
crc32_le
(
~
0
,
rx_buff
->
data
,
len
));
if
(
fcs
!=
le32_to_cpu
(
get_unaligned
((
u32
*
)(
rx_buff
->
data
+
len
))))
{
pr_debug
(
"crc error calc 0x%x len %d
\n
"
,
fcs
,
len
);
stir
->
stats
.
rx_errors
++
;
stir
->
stats
.
rx_crc_errors
++
;
return
;
}
/* If can't get new buffer, just drop and reuse */
nskb
=
dev_alloc_skb
(
IRDA_SKB_MAX_MTU
);
if
(
unlikely
(
!
nskb
))
/* if frame is short then just copy it */
if
(
len
<
IRDA_RX_COPY_THRESHOLD
)
{
nskb
=
dev_alloc_skb
(
len
+
1
);
if
(
unlikely
(
!
nskb
))
{
++
stir
->
stats
.
rx_dropped
;
else
{
struct
sk_buff
*
oskb
=
rx_buff
->
skb
;
return
;
}
skb_reserve
(
nskb
,
1
);
skb
=
nskb
;
memcpy
(
nskb
->
data
,
rx_buff
->
data
,
len
);
}
else
{
nskb
=
dev_alloc_skb
(
rx_buff
->
truesize
);
if
(
unlikely
(
!
nskb
))
{
++
stir
->
stats
.
rx_dropped
;
return
;
}
skb_reserve
(
nskb
,
1
);
skb
=
rx_buff
->
skb
;
rx_buff
->
skb
=
nskb
;
rx_buff
->
head
=
nskb
->
data
;
}
/* Set correct length in socket buffer */
skb_put
(
oskb
,
len
);
skb_put
(
skb
,
len
);
oskb
->
mac
.
raw
=
o
skb
->
data
;
o
skb
->
protocol
=
htons
(
ETH_P_IRDA
);
o
skb
->
dev
=
stir
->
netdev
;
skb
->
mac
.
raw
=
skb
->
data
;
skb
->
protocol
=
htons
(
ETH_P_IRDA
);
skb
->
dev
=
stir
->
netdev
;
netif_rx
(
o
skb
);
netif_rx
(
skb
);
stir
->
stats
.
rx_packets
++
;
stir
->
stats
.
rx_bytes
+=
len
;
rx_buff
->
skb
=
nskb
;
rx_buff
->
head
=
nskb
->
data
;
}
rx_buff
->
data
=
rx_buff
->
head
;
rx_buff
->
len
=
0
;
...
...
@@ -402,7 +397,6 @@ static void stir_fir_chars(struct stir_cb *stir,
continue
;
/* Now receiving frame */
rx_buff
->
state
=
BEGIN_FRAME
;
rx_buff
->
in_frame
=
TRUE
;
/* Time to initialize receive buffer */
rx_buff
->
data
=
rx_buff
->
head
;
...
...
@@ -424,6 +418,7 @@ static void stir_fir_chars(struct stir_cb *stir,
if
(
byte
==
FIR_EOF
)
continue
;
rx_buff
->
state
=
INSIDE_FRAME
;
rx_buff
->
in_frame
=
TRUE
;
/* fall through */
case
INSIDE_FRAME
:
...
...
@@ -461,7 +456,6 @@ static void stir_fir_chars(struct stir_cb *stir,
error_recovery:
++
stir
->
stats
.
rx_errors
;
irda_device_set_media_busy
(
stir
->
netdev
,
TRUE
);
rx_buff
->
state
=
OUTSIDE_FRAME
;
rx_buff
->
in_frame
=
FALSE
;
}
...
...
@@ -478,11 +472,6 @@ static void stir_sir_chars(struct stir_cb *stir,
&
stir
->
rx_buff
,
bytes
[
i
]);
}
static
inline
int
isfir
(
u32
speed
)
{
return
(
speed
==
4000000
);
}
static
inline
void
unwrap_chars
(
struct
stir_cb
*
stir
,
const
__u8
*
bytes
,
int
length
)
{
...
...
@@ -519,25 +508,31 @@ static int change_speed(struct stir_cb *stir, unsigned speed)
int
i
,
err
;
__u8
mode
;
pr_debug
(
"%s: change speed %d
\n
"
,
stir
->
netdev
->
name
,
speed
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
stir_modes
);
++
i
)
{
if
(
speed
==
stir_modes
[
i
].
speed
)
goto
found
;
}
ERROR
(
"%s: invalid speed %d
\n
"
,
stir
->
netdev
->
name
,
speed
);
warn
(
"%s: invalid speed %d
"
,
stir
->
netdev
->
name
,
speed
);
return
-
EINVAL
;
found:
pr_debug
(
"%s: speed change from %d to %d
\n
"
,
stir
->
netdev
->
name
,
stir
->
speed
,
speed
);
pr_debug
(
"speed change from %d to %d
\n
"
,
stir
->
speed
,
speed
);
/* sometimes needed to get chip out of stuck state */
err
=
usb_reset_device
(
stir
->
usbdev
);
if
(
err
)
goto
out
;
/* Reset modulator */
err
=
write_reg
(
stir
,
REG_CTRL1
,
CTRL1_SRESET
);
if
(
err
)
goto
out
;
/* Make sure any previous Tx is really finished. This happens
* when we answer an incomming request ; the ua:rsp and the
* speed change are bundled together, so we need to wait until
* the packet we just submitted has been sent. Jean II */
if
(
fifo_txwait
(
stir
,
0
))
return
-
EIO
;
/* Undocumented magic to tweak the DPLL */
err
=
write_reg
(
stir
,
REG_DPLL
,
0x15
);
if
(
err
)
goto
out
;
/* Set clock */
err
=
write_reg
(
stir
,
REG_PDCLK
,
stir_modes
[
i
].
pdclk
);
...
...
@@ -564,33 +559,13 @@ static int change_speed(struct stir_cb *stir, unsigned speed)
goto
out
;
err
=
write_reg
(
stir
,
REG_CTRL1
,
(
tx_power
&
3
)
<<
1
);
out:
stir
->
speed
=
speed
;
return
err
;
}
static
int
stir_reset
(
struct
stir_cb
*
stir
)
{
int
err
;
/* reset state */
stir
->
rx_buff
.
in_frame
=
FALSE
;
stir
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
stir
->
speed
=
-
1
;
/* Undocumented magic to tweak the DPLL */
err
=
write_reg
(
stir
,
REG_DPLL
,
0x15
);
if
(
err
)
goto
out
;
/* Reset sensitivity */
err
=
write_reg
(
stir
,
REG_CTRL2
,
(
rx_sensitivity
&
7
)
<<
5
);
if
(
err
)
goto
out
;
err
=
change_speed
(
stir
,
9600
);
out:
stir
->
speed
=
speed
;
return
err
;
}
...
...
@@ -606,48 +581,62 @@ static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/* the IRDA wrapping routines don't deal with non linear skb */
SKB_LINEAR_ASSERT
(
skb
);
if
(
unlikely
(
skb
->
len
)
==
0
)
/* speed change only */
stir
->
tx_len
=
0
;
else
if
(
isfir
(
stir
->
speed
))
stir
->
tx_len
=
wrap_fir_skb
(
skb
,
stir
->
tx_data
);
else
stir
->
tx_len
=
wrap_sir_skb
(
skb
,
stir
->
tx_data
);
stir
->
stats
.
tx_packets
++
;
stir
->
stats
.
tx_bytes
+=
skb
->
len
;
stir
->
tx_mtt
=
irda_get_mtt
(
skb
);
stir
->
tx_newspeed
=
irda_get_next_speed
(
skb
);
if
(
!
test_and_set_bit
(
STIR_STATE_TXREADY
,
&
stir
->
state
))
skb
=
xchg
(
&
stir
->
tx_pending
,
skb
);
wake_up
(
&
stir
->
thr_wait
);
/* this should never happen unless stop/wakeup problem */
if
(
unlikely
(
skb
))
{
WARN_ON
(
1
);
dev_kfree_skb
(
skb
);
}
return
0
;
}
/*
* Wait for the transmit FIFO to have space for next data
*
* If space < 0 then wait till FIFO completely drains.
* FYI: can take up to 13 seconds at 2400baud.
*/
static
int
fifo_txwait
(
struct
stir_cb
*
stir
,
unsigned
space
)
static
int
fifo_txwait
(
struct
stir_cb
*
stir
,
int
space
)
{
int
err
;
unsigned
count
;
__u8
regs
[
3
];
unsigned
long
timeout
=
jiffies
+
HZ
/
10
;
unsigned
long
count
,
status
;
for
(;;)
{
/* Read FIFO status and count */
err
=
read_reg
(
stir
,
REG_FIFOCTL
,
regs
,
3
);
if
(
unlikely
(
err
!=
3
))
{
WARNING
(
"%s: FIFO register read error: %d
\n
"
,
for
(;;)
{
err
=
read_reg
(
stir
,
REG_FIFOCTL
,
stir
->
fifo_status
,
FIFO_REGS_SIZE
);
if
(
unlikely
(
err
!=
FIFO_REGS_SIZE
))
{
warn
(
"%s: FIFO register read error: %d"
,
stir
->
netdev
->
name
,
err
);
return
err
;
}
status
=
stir
->
fifo_status
[
0
];
count
=
(
unsigned
)(
stir
->
fifo_status
[
2
]
&
0x1f
)
<<
8
|
stir
->
fifo_status
[
1
];
pr_debug
(
"fifo status 0x%lx count %lu
\n
"
,
status
,
count
);
/* error when receive/transmit fifo gets confused */
if
(
status
&
FIFOCTL_RXERR
)
{
stir
->
stats
.
rx_fifo_errors
++
;
stir
->
stats
.
rx_errors
++
;
break
;
}
if
(
status
&
FIFOCTL_TXERR
)
{
stir
->
stats
.
tx_fifo_errors
++
;
stir
->
stats
.
tx_errors
++
;
break
;
}
/* is fifo receiving already, or empty */
if
(
!
(
regs
[
0
]
&
FIFOCTL_DIR
)
||
(
regs
[
0
]
&
FIFOCTL_EMPTY
))
if
(
!
(
status
&
FIFOCTL_DIR
)
||
(
status
&
FIFOCTL_EMPTY
))
return
0
;
if
(
signal_pending
(
current
))
...
...
@@ -658,40 +647,37 @@ static int fifo_txwait(struct stir_cb *stir, unsigned space)
||
!
netif_device_present
(
stir
->
netdev
))
return
-
ESHUTDOWN
;
count
=
(
unsigned
)(
regs
[
2
]
&
0x1f
)
<<
8
|
regs
[
1
];
pr_debug
(
"%s: fifo status 0x%x count %u
\n
"
,
stir
->
netdev
->
name
,
regs
[
0
],
count
);
/* only waiting for some space */
if
(
space
&&
STIR_FIFO_SIZE
-
4
>
space
+
count
)
if
(
space
>=
0
&&
STIR_FIFO_SIZE
-
4
>
space
+
count
)
return
0
;
if
(
time_after
(
jiffies
,
timeout
))
{
WARNING
(
"%s: transmit fifo timeout status=0x%x count=%d
\n
"
,
stir
->
netdev
->
name
,
regs
[
0
],
count
);
++
stir
->
stats
.
tx_errors
;
irda_device_set_media_busy
(
stir
->
netdev
,
TRUE
);
return
-
ETIMEDOUT
;
}
/* estimate transfer time for remaining chars */
wait_ms
((
count
*
8000
)
/
stir
->
speed
);
}
err
=
write_reg
(
stir
,
REG_FIFOCTL
,
FIFOCTL_CLR
);
if
(
err
)
return
err
;
err
=
write_reg
(
stir
,
REG_FIFOCTL
,
0
);
if
(
err
)
return
err
;
return
0
;
}
/* Wait for turnaround delay before starting transmit. */
static
void
turnaround_delay
(
long
us
,
const
struct
timespec
*
last
)
static
void
turnaround_delay
(
const
struct
stir_cb
*
stir
,
long
us
)
{
long
ticks
;
struct
time
spec
now
=
CURRENT_TIME
;
struct
time
val
now
;
if
(
us
<=
0
)
return
;
us
-=
(
now
.
tv_sec
-
last
->
tv_sec
)
*
USEC_PER_SEC
;
us
-=
(
now
.
tv_nsec
-
last
->
tv_nsec
)
/
NSEC_PER_USEC
;
do_gettimeofday
(
&
now
);
us
-=
(
now
.
tv_sec
-
stir
->
rx_time
.
tv_sec
)
*
USEC_PER_SEC
;
us
-=
now
.
tv_usec
-
stir
->
rx_time
.
tv_usec
;
if
(
us
<
10
)
return
;
...
...
@@ -707,77 +693,60 @@ static void turnaround_delay(long us, const struct timespec *last)
* Start receiver by submitting a request to the receive pipe.
* If nothing is available it will return after rx_interval.
*/
static
void
receive_start
(
struct
stir_cb
*
stir
)
static
int
receive_start
(
struct
stir_cb
*
stir
)
{
int
i
;
if
(
test_and_set_bit
(
STIR_STATE_RECEIVING
,
&
stir
->
state
))
return
;
if
(
fifo_txwait
(
stir
,
0
))
return
;
for
(
i
=
0
;
i
<
NUM_RX_URBS
;
i
++
)
{
struct
urb
*
urb
=
stir
->
rx_urbs
[
i
];
usb_fill_int_urb
(
urb
,
stir
->
usbdev
,
stir
->
rx_intpipe
,
stir
->
rx_data
[
i
],
STIR_FIFO_SIZE
,
stir_usb_receive
,
stir
,
rx_interval
);
if
(
usb_submit_urb
(
urb
,
GFP_KERNEL
))
urb
->
status
=
-
EINVAL
;
}
/* reset state */
stir
->
receiving
=
1
;
if
(
i
==
0
)
{
/* if nothing got queued, then just retry next time */
if
(
net_ratelimit
())
WARNING
(
"%s: no receive buffers avaiable
\n
"
,
stir
->
netdev
->
name
);
stir
->
rx_buff
.
in_frame
=
FALSE
;
stir
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
clear_bit
(
STIR_STATE_RECEIVING
,
&
stir
->
state
)
;
}
stir
->
rx_urb
->
status
=
0
;
return
usb_submit_urb
(
stir
->
rx_urb
,
GFP_KERNEL
);
}
/* Stop all pending receive Urb's */
static
void
receive_stop
(
struct
stir_cb
*
stir
)
{
int
i
;
stir
->
receiving
=
0
;
usb_unlink_urb
(
stir
->
rx_urb
);
for
(
i
=
0
;
i
<
NUM_RX_URBS
;
i
++
)
{
struct
urb
*
urb
=
stir
->
rx_urbs
[
i
];
usb_unlink_urb
(
urb
);
}
if
(
stir
->
rx_buff
.
in_frame
)
stir
->
stats
.
collisions
++
;
}
/* Send wrapped data (in tx_data) to device */
static
void
stir_send
(
struct
stir_cb
*
stir
)
/*
* Wrap data in socket buffer and send it.
*/
static
void
stir_send
(
struct
stir_cb
*
stir
,
struct
sk_buff
*
skb
)
{
int
rc
;
unsigned
wraplen
;
int
first_frame
=
0
;
if
(
test_and_clear_bit
(
STIR_STATE_RECEIVING
,
&
stir
->
state
))
{
/* if receiving, need to turnaround */
if
(
stir
->
receiving
)
{
receive_stop
(
stir
);
turnaround_delay
(
stir
,
irda_get_mtt
(
skb
));
first_frame
=
1
;
}
turnaround_delay
(
stir
->
tx_mtt
,
&
stir
->
rx_time
);
if
(
isfir
(
stir
->
speed
))
wraplen
=
wrap_fir_skb
(
skb
,
stir
->
io_buf
);
else
wraplen
=
wrap_sir_skb
(
skb
,
stir
->
io_buf
);
if
(
stir
->
rx_buff
.
in_frame
)
++
stir
->
stats
.
collisions
;
}
else
if
(
fifo_txwait
(
stir
,
stir
->
tx_len
))
return
;
/* shutdown or major errors */
/* check for space available in fifo */
if
(
!
first_frame
)
fifo_txwait
(
stir
,
wraplen
);
stir
->
stats
.
tx_packets
++
;
stir
->
stats
.
tx_bytes
+=
skb
->
len
;
stir
->
netdev
->
trans_start
=
jiffies
;
pr_debug
(
"send %d (%d)
\n
"
,
skb
->
len
,
wraplen
);
pr_debug
(
"%s: send %d
\n
"
,
stir
->
netdev
->
name
,
stir
->
tx_len
);
rc
=
usb_bulk_msg
(
stir
->
usbdev
,
stir
->
tx_bulkpipe
,
stir
->
tx_data
,
stir
->
tx_len
,
NULL
,
MSECS_TO_JIFFIES
(
TRANSMIT_TIMEOUT
));
if
(
unlikely
(
rc
))
{
WARNING
(
"%s: usb bulk message failed %d
\n
"
,
stir
->
netdev
->
name
,
rc
);
if
(
usb_bulk_msg
(
stir
->
usbdev
,
usb_sndbulkpipe
(
stir
->
usbdev
,
1
),
stir
->
io_buf
,
wraplen
,
NULL
,
MSECS_TO_JIFFIES
(
TRANSMIT_TIMEOUT
)))
stir
->
stats
.
tx_errors
++
;
}
}
/*
...
...
@@ -787,7 +756,7 @@ static int stir_transmit_thread(void *arg)
{
struct
stir_cb
*
stir
=
arg
;
struct
net_device
*
dev
=
stir
->
netdev
;
DECLARE_WAITQUEUE
(
wait
,
current
)
;
struct
sk_buff
*
skb
;
daemonize
(
"%s"
,
dev
->
name
);
allow_signal
(
SIGTERM
);
...
...
@@ -796,44 +765,58 @@ static int stir_transmit_thread(void *arg)
&&
netif_device_present
(
dev
)
&&
!
signal_pending
(
current
))
{
/*
make swsusp happy with our thread
*/
/*
if suspending, then power off and wait
*/
if
(
current
->
flags
&
PF_FREEZE
)
{
if
(
stir
->
receiving
)
receive_stop
(
stir
);
else
fifo_txwait
(
stir
,
-
1
);
write_reg
(
stir
,
REG_CTRL1
,
CTRL1_TXPWD
|
CTRL1_RXPWD
);
refrigerator
(
PF_IOTHREAD
);
stir_reset
(
stir
);
if
(
change_speed
(
stir
,
stir
->
speed
))
break
;
}
/* if something to send? */
if
(
test_and_clear_bit
(
STIR_STATE_TXREADY
,
&
stir
->
state
))
{
unsigned
new_speed
=
stir
->
tx_newspeed
;
skb
=
xchg
(
&
stir
->
tx_pending
,
NULL
);
if
(
skb
)
{
unsigned
new_speed
=
irda_get_next_speed
(
skb
);
netif_wake_queue
(
dev
);
/* Note that we may both send a packet and
* change speed in some cases. Jean II */
if
(
skb
->
len
>
0
)
stir_send
(
stir
,
skb
);
dev_kfree_skb
(
skb
);
if
(
stir
->
tx_len
!=
0
)
stir_send
(
stir
);
if
(
stir
->
speed
!=
new_speed
)
{
if
(
fifo_txwait
(
stir
,
-
1
)
||
change_speed
(
stir
,
new_speed
))
break
;
}
continue
;
}
if
(
stir
->
speed
!=
new_speed
)
change_speed
(
stir
,
new_speed
);
/* nothing to send? start receiving */
if
(
!
stir
->
receiving
&&
irda_device_txqueue_empty
(
dev
))
{
/* Wait otherwise chip gets confused. */
if
(
fifo_txwait
(
stir
,
-
1
))
break
;
netif_wake_queue
(
stir
->
netdev
);
if
(
unlikely
(
receive_start
(
stir
)))
{
if
(
net_ratelimit
())
info
(
"%s: receive usb submit failed"
,
stir
->
netdev
->
name
);
stir
->
receiving
=
0
;
wait_ms
(
10
);
continue
;
}
}
if
(
irda_device_txqueue_empty
(
dev
))
receive_start
(
stir
);
set_task_state
(
current
,
TASK_INTERRUPTIBLE
);
add_wait_queue
(
&
stir
->
thr_wait
,
&
wait
);
if
(
test_bit
(
STIR_STATE_TXREADY
,
&
stir
->
state
))
__set_task_state
(
current
,
TASK_RUNNING
);
else
schedule_timeout
(
HZ
/
10
);
remove_wait_queue
(
&
stir
->
thr_wait
,
&
wait
);
/* sleep if nothing to send */
wait_event_interruptible
(
stir
->
thr_wait
,
stir
->
tx_pending
);
}
complete_and_exit
(
&
stir
->
thr_exited
,
0
);
...
...
@@ -841,48 +824,34 @@ static int stir_transmit_thread(void *arg)
/*
*
Receive wrapped data into rx_data buffer
.
*
This chip doesn't block until data is available, we just have
*
to read the FIFO perodically (ugh)
.
*
USB bulk receive completion callback
.
*
Wakes up every ms (usb round trip) with wrapped
*
data
.
*/
static
void
stir_
usb_receive
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
static
void
stir_
rcv_irq
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
stir_cb
*
stir
=
urb
->
context
;
int
err
;
/* in process of stopping, just drop data */
if
(
!
netif_running
(
stir
->
netdev
))
return
;
switch
(
urb
->
status
)
{
case
0
:
if
(
urb
->
actual_length
>
0
)
{
pr_debug
(
"%s: receive %d
\n
"
,
stir
->
netdev
->
name
,
urb
->
actual_length
);
/* unlink, shutdown, unplug, other nasties */
if
(
urb
->
status
!=
0
)
return
;
if
(
urb
->
actual_length
>
0
)
{
pr_debug
(
"receive %d
\n
"
,
urb
->
actual_length
);
unwrap_chars
(
stir
,
urb
->
transfer_buffer
,
urb
->
actual_length
);
stir
->
netdev
->
last_rx
=
jiffies
;
stir
->
rx_time
=
CURRENT_TIME
;
}
break
;
case
-
ECONNRESET
:
/* killed but pending */
case
-
ENOENT
:
/* killed but not in use */
case
-
ESHUTDOWN
:
/* These are normal errors when URB is cancelled */
stir
->
rx_buff
.
in_frame
=
FALSE
;
stir
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
return
;
default:
WARNING
(
"%s: received status %d
\n
"
,
stir
->
netdev
->
name
,
urb
->
status
);
stir
->
stats
.
rx_errors
++
;
urb
->
status
=
0
;
do_gettimeofday
(
&
stir
->
rx_time
);
}
/* kernel thread is stopping receiver don't resubmit */
if
(
!
test_bit
(
STIR_STATE_RECEIVING
,
&
stir
->
state
)
)
if
(
!
stir
->
receiving
)
return
;
/* resubmit existing urb */
...
...
@@ -890,14 +859,13 @@ static void stir_usb_receive(struct urb *urb, struct pt_regs *regs)
/* in case of error, the kernel thread will restart us */
if
(
err
)
{
WARNING
(
"%s: usb receive submit error: %d
\n
"
,
warn
(
"%s: usb receive submit error: %d
"
,
stir
->
netdev
->
name
,
err
);
urb
->
status
=
-
ENOENT
;
stir
->
receiving
=
0
;
wake_up
(
&
stir
->
thr_wait
);
}
}
/*
* Function stir_net_open (dev)
*
...
...
@@ -906,49 +874,49 @@ static void stir_usb_receive(struct urb *urb, struct pt_regs *regs)
static
int
stir_net_open
(
struct
net_device
*
netdev
)
{
struct
stir_cb
*
stir
=
netdev
->
priv
;
int
i
,
err
;
int
err
;
char
hwname
[
16
];
err
=
stir_reset
(
stir
);
err
=
usb_clear_halt
(
stir
->
usbdev
,
usb_sndbulkpipe
(
stir
->
usbdev
,
1
));
if
(
err
)
goto
err_out1
;
err
=
usb_clear_halt
(
stir
->
usbdev
,
usb_rcvbulkpipe
(
stir
->
usbdev
,
2
));
if
(
err
)
goto
err_out1
;
err
=
-
ENOMEM
;
/* Note: Max SIR frame possible is 4273 */
stir
->
tx_data
=
kmalloc
(
STIR_FIFO_SIZE
,
GFP_KERNEL
);
if
(
!
stir
->
tx_data
)
{
ERROR
(
"%s(), alloc failed for rxbuf!
\n
"
,
__FUNCTION__
);
err
=
change_speed
(
stir
,
9600
);
if
(
err
)
goto
err_out1
;
}
err
=
-
ENOMEM
;
/* Initialize for SIR/FIR to copy data directly into skb. */
stir
->
receiving
=
0
;
stir
->
rx_buff
.
truesize
=
IRDA_SKB_MAX_MTU
;
stir
->
rx_buff
.
skb
=
dev_alloc_skb
(
IRDA_SKB_MAX_MTU
);
if
(
!
stir
->
rx_buff
.
skb
)
{
ERROR
(
"%s(), dev_alloc_skb() failed for rxbuf!
\n
"
,
__FUNCTION__
);
goto
err_out2
;
}
if
(
!
stir
->
rx_buff
.
skb
)
goto
err_out1
;
skb_reserve
(
stir
->
rx_buff
.
skb
,
1
);
stir
->
rx_buff
.
head
=
stir
->
rx_buff
.
skb
->
data
;
stir
->
rx_time
=
CURRENT_TIME
;
do_gettimeofday
(
&
stir
->
rx_time
)
;
/* Allocate N receive buffer's and urbs */
for
(
i
=
0
;
i
<
NUM_RX_URBS
;
i
++
)
{
stir
->
rx_urbs
[
i
]
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
stir
->
rx_urbs
[
i
]){
ERROR
(
"%s(), usb_alloc_urb failed
\n
"
,
__FUNCTION__
);
goto
err_out3
;
}
stir
->
rx_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
stir
->
rx_urb
)
goto
err_out2
;
stir
->
rx_data
[
i
]
=
kmalloc
(
STIR_FIFO_SIZE
,
GFP_KERNEL
);
if
(
!
stir
->
rx_data
)
{
usb_free_urb
(
stir
->
rx_urbs
[
i
]);
ERROR
(
"%s(), alloc failed for rxbuf!
\n
"
,
__FUNCTION__
);
stir
->
io_buf
=
kmalloc
(
STIR_FIFO_SIZE
,
GFP_KERNEL
);
if
(
!
stir
->
io_buf
)
goto
err_out3
;
}
}
usb_fill_bulk_urb
(
stir
->
rx_urb
,
stir
->
usbdev
,
usb_rcvbulkpipe
(
stir
->
usbdev
,
2
),
stir
->
io_buf
,
STIR_FIFO_SIZE
,
stir_rcv_irq
,
stir
);
stir
->
fifo_status
=
kmalloc
(
FIFO_REGS_SIZE
,
GFP_KERNEL
);
if
(
!
stir
->
fifo_status
)
goto
err_out4
;
/*
* Now that everything should be initialized properly,
...
...
@@ -958,8 +926,8 @@ static int stir_net_open(struct net_device *netdev)
sprintf
(
hwname
,
"usb#%d"
,
stir
->
usbdev
->
devnum
);
stir
->
irlap
=
irlap_open
(
netdev
,
&
stir
->
qos
,
hwname
);
if
(
!
stir
->
irlap
)
{
ERROR
(
"%s(): irlap_open failed
\n
"
,
__FUNCTION__
);
goto
err_out
3
;
err
(
"irlap_open failed"
);
goto
err_out
5
;
}
/** Start kernel thread for transmit. */
...
...
@@ -967,25 +935,24 @@ static int stir_net_open(struct net_device *netdev)
CLONE_FS
|
CLONE_FILES
);
if
(
stir
->
thr_pid
<
0
)
{
err
=
stir
->
thr_pid
;
WARNING
(
"%s: unable to start kernel thread
\n
"
,
stir
->
netdev
->
name
);
goto
err_out4
;
err
(
"unable to start kernel thread"
);
goto
err_out6
;
}
netif_start_queue
(
netdev
);
return
0
;
err_out
4
:
err_out
6
:
irlap_close
(
stir
->
irlap
);
err_out5:
kfree
(
stir
->
fifo_status
);
err_out4:
kfree
(
stir
->
io_buf
);
err_out3:
while
(
--
i
>=
0
)
{
usb_free_urb
(
stir
->
rx_urbs
[
i
]);
kfree
(
stir
->
rx_data
[
i
]);
}
kfree_skb
(
stir
->
rx_buff
.
skb
);
usb_free_urb
(
stir
->
rx_urb
);
err_out2:
kfree
(
stir
->
tx_data
);
kfree
_skb
(
stir
->
rx_buff
.
skb
);
err_out1:
return
err
;
}
...
...
@@ -999,7 +966,6 @@ static int stir_net_open(struct net_device *netdev)
static
int
stir_net_close
(
struct
net_device
*
netdev
)
{
struct
stir_cb
*
stir
=
netdev
->
priv
;
int
i
;
/* Stop transmit processing */
netif_stop_queue
(
netdev
);
...
...
@@ -1007,15 +973,13 @@ static int stir_net_close(struct net_device *netdev)
/* Kill transmit thread */
kill_proc
(
stir
->
thr_pid
,
SIGTERM
,
1
);
wait_for_completion
(
&
stir
->
thr_exited
);
kfree
(
stir
->
tx_data
);
kfree
(
stir
->
fifo_status
);
clear_bit
(
STIR_STATE_RECEIVING
,
&
stir
->
state
);
receive_stop
(
stir
);
/* Mop up receive urb's */
usb_unlink_urb
(
stir
->
rx_urb
);
for
(
i
=
0
;
i
<
NUM_RX_URBS
;
i
++
)
{
usb_free_urb
(
stir
->
rx_urbs
[
i
]);
kfree
(
stir
->
rx_data
[
i
]);
}
kfree
(
stir
->
io_buf
);
usb_free_urb
(
stir
->
rx_urb
);
kfree_skb
(
stir
->
rx_buff
.
skb
);
/* Stop and remove instance of IrLAP */
...
...
@@ -1057,7 +1021,7 @@ static int stir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case
SIOCGRECEIVING
:
/* Only approximately true */
irq
->
ifr_receiving
=
test_bit
(
STIR_STATE_RECEIVING
,
&
stir
->
state
)
;
irq
->
ifr_receiving
=
stir
->
receiving
;
break
;
default:
...
...
@@ -1076,53 +1040,6 @@ static struct net_device_stats *stir_net_get_stats(struct net_device *dev)
return
&
stir
->
stats
;
}
/*
* Parse the various endpoints and find the one we need.
*
* The endpoint are the pipes used to communicate with the USB device.
* The spec defines 2 endpoints of type bulk transfer, one in, and one out.
* These are used to pass frames back and forth with the dongle.
*/
static
int
stir_setup_usb
(
struct
stir_cb
*
stir
,
struct
usb_interface
*
intf
)
{
struct
usb_device
*
usbdev
=
interface_to_usbdev
(
intf
);
const
struct
usb_host_interface
*
interface
=
&
intf
->
altsetting
[
intf
->
act_altsetting
];
const
struct
usb_endpoint_descriptor
*
ep_in
=
NULL
;
const
struct
usb_endpoint_descriptor
*
ep_out
=
NULL
;
int
i
;
if
(
interface
->
desc
.
bNumEndpoints
!=
2
)
{
WARNING
(
"%s: expected two endpoints
\n
"
,
__FUNCTION__
);
return
-
ENODEV
;
}
for
(
i
=
0
;
i
<
interface
->
desc
.
bNumEndpoints
;
i
++
)
{
const
struct
usb_endpoint_descriptor
*
ep
=
&
interface
->
endpoint
[
i
].
desc
;
if
((
ep
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_BULK
)
{
/* We need to find an IN and an OUT */
if
((
ep
->
bEndpointAddress
&
USB_ENDPOINT_DIR_MASK
)
==
USB_DIR_IN
)
ep_in
=
ep
;
else
ep_out
=
ep
;
}
else
WARNING
(
"%s: unknown endpoint type 0x%x
\n
"
,
__FUNCTION__
,
ep
->
bmAttributes
);
}
if
(
!
ep_in
||
!
ep_out
)
return
-
EIO
;
stir
->
tx_bulkpipe
=
usb_sndbulkpipe
(
usbdev
,
ep_out
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
stir
->
rx_intpipe
=
usb_rcvintpipe
(
usbdev
,
ep_in
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
return
0
;
}
/*
* This routine is called by the USB subsystem for each new device
* in the system. We need to check if the device is ours, and in
...
...
@@ -1149,9 +1066,9 @@ static int stir_probe(struct usb_interface *intf,
stir
->
netdev
=
net
;
stir
->
usbdev
=
dev
;
ret
=
stir_setup_usb
(
stir
,
intf
);
ret
=
usb_reset_configuration
(
dev
);
if
(
ret
!=
0
)
{
ERROR
(
"%s(), Bogus endpoints...
\n
"
,
__FUNCTION__
);
err
(
"usb reset configuration failed"
);
goto
err_out2
;
}
...
...
@@ -1180,10 +1097,6 @@ static int stir_probe(struct usb_interface *intf,
net
->
get_stats
=
stir_net_get_stats
;
net
->
do_ioctl
=
stir_net_ioctl
;
ret
=
stir_reset
(
stir
);
if
(
ret
)
goto
err_out2
;
ret
=
register_netdev
(
net
);
if
(
ret
!=
0
)
goto
err_out2
;
...
...
@@ -1206,23 +1119,14 @@ static int stir_probe(struct usb_interface *intf,
static
void
stir_disconnect
(
struct
usb_interface
*
intf
)
{
struct
stir_cb
*
stir
=
usb_get_intfdata
(
intf
);
struct
net_device
*
net
;
usb_set_intfdata
(
intf
,
NULL
);
if
(
!
stir
)
return
;
/* Stop transmitter */
net
=
stir
->
netdev
;
netif_device_detach
(
net
);
/* Remove netdevice */
unregister_netdev
(
net
);
unregister_netdev
(
stir
->
netdev
);
free_netdev
(
stir
->
netdev
);
/* No longer attached to USB bus */
stir
->
usbdev
=
NULL
;
free_netdev
(
net
);
usb_set_intfdata
(
intf
,
NULL
);
}
...
...
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