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
10795980
Commit
10795980
authored
Apr 07, 2003
by
Alan Cox
Committed by
Linus Torvalds
Apr 07, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] first pass at fixing strip for 2.5
parent
2f5b7e8c
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1973 additions
and
1983 deletions
+1973
-1983
drivers/net/wireless/strip.c
drivers/net/wireless/strip.c
+1973
-1983
No files found.
drivers/net/wireless/strip.c
View file @
10795980
...
...
@@ -69,9 +69,9 @@
*/
#ifdef MODULE
static
const
char
StripVersion
[]
=
"1.3-STUART.CHESHIRE-MODULAR"
;
static
const
char
StripVersion
[]
=
"1.3
A
-STUART.CHESHIRE-MODULAR"
;
#else
static
const
char
StripVersion
[]
=
"1.3-STUART.CHESHIRE"
;
static
const
char
StripVersion
[]
=
"1.3
A
-STUART.CHESHIRE"
;
#endif
#define TICKLE_TIMERS 0
...
...
@@ -89,18 +89,7 @@ static const char StripVersion[] = "1.3-STUART.CHESHIRE";
#include <asm/uaccess.h>
#include <asm/bitops.h>
/*
* isdigit() and isspace() use the ctype[] array, which is not available
* to kernel modules. If compiling as a module, use a local definition
* of isdigit() and isspace() until _ctype is added to ksyms.
*/
#ifdef MODULE
# define isdigit(c) ('0' <= (c) && (c) <= '9')
# define isspace(c) ((c) == ' ' || (c) == '\t')
#else
# include <linux/ctype.h>
#endif
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
...
...
@@ -131,8 +120,7 @@ static const char StripVersion[] = "1.3-STUART.CHESHIRE";
* Starmode packet.
*/
typedef
union
{
typedef
union
{
__u8
c
[
4
];
__u32
l
;
}
MetricomKey
;
...
...
@@ -142,8 +130,7 @@ typedef union
* a single 32-bit long (which is convenient for assignment, equality testing etc.)
*/
typedef
union
{
typedef
union
{
__u8
b
[
4
];
__u32
l
;
}
IPaddr
;
...
...
@@ -153,8 +140,7 @@ typedef union
* a Metricom address.
*/
typedef
struct
{
typedef
struct
{
__u8
c
[
24
];
}
MetricomAddressString
;
...
...
@@ -173,21 +159,18 @@ typedef struct
* already understands Ethernet headers.
*/
typedef
struct
{
typedef
struct
{
MetricomAddress
dst_addr
;
/* Destination address, e.g. "0000-1234" */
MetricomAddress
src_addr
;
/* Source address, e.g. "0000-5678" */
unsigned
short
protocol
;
/* The protocol type, using Ethernet codes */
}
STRIP_Header
;
typedef
struct
{
typedef
struct
{
char
c
[
60
];
}
MetricomNode
;
#define NODE_TABLE_SIZE 32
typedef
struct
{
typedef
struct
{
struct
timeval
timestamp
;
int
num_nodes
;
MetricomNode
node
[
NODE_TABLE_SIZE
];
...
...
@@ -198,48 +181,42 @@ enum { FALSE = 0, TRUE = 1 };
/*
* Holds the radio's firmware version.
*/
typedef
struct
{
typedef
struct
{
char
c
[
50
];
}
FirmwareVersion
;
/*
* Holds the radio's serial number.
*/
typedef
struct
{
typedef
struct
{
char
c
[
18
];
}
SerialNumber
;
/*
* Holds the radio's battery voltage.
*/
typedef
struct
{
typedef
struct
{
char
c
[
11
];
}
BatteryVoltage
;
typedef
struct
{
typedef
struct
{
char
c
[
8
];
}
char8
;
enum
{
enum
{
NoStructure
=
0
,
/* Really old firmware */
StructuredMessages
=
1
,
/* Parsable AT response msgs */
ChecksummedMessages
=
2
/* Parsable AT response msgs with checksums */
}
FirmwareLevel
;
struct
strip
{
struct
strip
{
int
magic
;
/*
* These are pointers to the malloc()ed frame buffers.
*/
unsigned
char
*
rx_buff
;
/* buffer for received IP packet
*/
unsigned
char
*
sx_buff
;
/* buffer for received serial data
*/
unsigned
char
*
rx_buff
;
/* buffer for received IP packet
*/
unsigned
char
*
sx_buff
;
/* buffer for received serial data
*/
int
sx_count
;
/* received serial data counter */
int
sx_size
;
/* Serial buffer size */
unsigned
char
*
tx_buff
;
/* transmitter buffer */
...
...
@@ -283,7 +260,7 @@ struct strip
*/
struct
strip
*
next
;
/* The next struct in the list */
struct
strip
**
referrer
;
/* The pointer that points to us
*/
struct
strip
**
referrer
;
/* The pointer that points to us
*/
int
discard
;
/* Set if serial error */
int
working
;
/* Is radio working correctly? */
int
firmware_level
;
/* Message structuring level */
...
...
@@ -292,7 +269,7 @@ struct strip
int
mtu
;
/* Our mtu (to spot changes!) */
long
watchdog_doprobe
;
/* Next time to test the radio */
long
watchdog_doreset
;
/* Time to do next reset */
long
gratuitous_arp
;
/* Time to send next ARP refresh
*/
long
gratuitous_arp
;
/* Time to send next ARP refresh
*/
long
arp_interval
;
/* Next ARP interval */
struct
timer_list
idle_timer
;
/* For periodic wakeup calls */
MetricomAddress
true_dev_addr
;
/* True address of radio */
...
...
@@ -406,17 +383,19 @@ static const char CommandString2[] = "*&COMMAND*ATS325?"; /* Query battery volta
static
const
char
CommandString3
[]
=
"*&COMMAND*ATS300?"
;
/* Query version information */
static
const
char
CommandString4
[]
=
"*&COMMAND*ATS311?"
;
/* Query poletop list */
static
const
char
CommandString5
[]
=
"*&COMMAND*AT~LA"
;
/* Query portables list */
typedef
struct
{
const
char
*
string
;
long
length
;
}
StringDescriptor
;
static
const
StringDescriptor
CommandString
[]
=
{
{
CommandString0
,
sizeof
(
CommandString0
)
-
1
},
{
CommandString1
,
sizeof
(
CommandString1
)
-
1
},
{
CommandString2
,
sizeof
(
CommandString2
)
-
1
},
{
CommandString3
,
sizeof
(
CommandString3
)
-
1
},
{
CommandString4
,
sizeof
(
CommandString4
)
-
1
},
{
CommandString5
,
sizeof
(
CommandString5
)
-
1
}
};
typedef
struct
{
const
char
*
string
;
long
length
;
}
StringDescriptor
;
static
const
StringDescriptor
CommandString
[]
=
{
{
CommandString0
,
sizeof
(
CommandString0
)
-
1
},
{
CommandString1
,
sizeof
(
CommandString1
)
-
1
},
{
CommandString2
,
sizeof
(
CommandString2
)
-
1
},
{
CommandString3
,
sizeof
(
CommandString3
)
-
1
},
{
CommandString4
,
sizeof
(
CommandString4
)
-
1
},
{
CommandString5
,
sizeof
(
CommandString5
)
-
1
}
};
#define GOT_ALL_RADIO_INFO(S) \
((S)->firmware_version.c[0] && \
...
...
@@ -426,14 +405,15 @@ static const StringDescriptor CommandString[] =
static
const
char
hextable
[
16
]
=
"0123456789ABCDEF"
;
static
const
MetricomAddress
zero_address
;
static
const
MetricomAddress
broadcast_address
=
{
{
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
}
};
static
const
MetricomAddress
broadcast_address
=
{
{
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
}
};
static
const
MetricomKey
SIP0Key
=
{
{
"SIP0"
}
};
static
const
MetricomKey
ARP0Key
=
{
{
"ARP0"
}
};
static
const
MetricomKey
ATR_Key
=
{
{
"ATR "
}
};
static
const
MetricomKey
ACK_Key
=
{
{
"ACK_"
}
};
static
const
MetricomKey
INF_Key
=
{
{
"INF_"
}
};
static
const
MetricomKey
ERR_Key
=
{
{
"ERR_"
}
};
static
const
MetricomKey
SIP0Key
=
{
{
"SIP0"
}
};
static
const
MetricomKey
ARP0Key
=
{
{
"ARP0"
}
};
static
const
MetricomKey
ATR_Key
=
{
{
"ATR "
}
};
static
const
MetricomKey
ACK_Key
=
{
{
"ACK_"
}
};
static
const
MetricomKey
INF_Key
=
{
{
"INF_"
}
};
static
const
MetricomKey
ERR_Key
=
{
{
"ERR_"
}
};
static
const
long
MaxARPInterval
=
60
*
HZ
;
/* One minute */
...
...
@@ -451,12 +431,11 @@ static const unsigned short DEFAULT_STRIP_MTU = 1152;
static
const
int
STRIP_MAGIC
=
0x5303
;
static
const
long
LongTime
=
0x7FFFFFFF
;
/************************************************************************/
/* Global variables */
static
struct
strip
*
struct_strip_list
;
static
spinlock_t
strip_lock
;
/************************************************************************/
/* Macros */
...
...
@@ -486,32 +465,16 @@ static struct strip *struct_strip_list;
/************************************************************************/
/* Utility routines */
typedef
unsigned
long
InterruptStatus
;
static
inline
InterruptStatus
DisableInterrupts
(
void
)
{
InterruptStatus
x
;
save_flags
(
x
);
cli
();
return
(
x
);
}
static
inline
void
RestoreInterrupts
(
InterruptStatus
x
)
{
restore_flags
(
x
);
}
static
int
arp_query
(
unsigned
char
*
haddr
,
u32
paddr
,
struct
net_device
*
dev
)
static
int
arp_query
(
unsigned
char
*
haddr
,
u32
paddr
,
struct
net_device
*
dev
)
{
struct
neighbour
*
neighbor_entry
;
neighbor_entry
=
neigh_lookup
(
&
arp_tbl
,
&
paddr
,
dev
);
if
(
neighbor_entry
!=
NULL
)
{
if
(
neighbor_entry
!=
NULL
)
{
neighbor_entry
->
used
=
jiffies
;
if
(
neighbor_entry
->
nud_state
&
NUD_VALID
)
{
if
(
neighbor_entry
->
nud_state
&
NUD_VALID
)
{
memcpy
(
haddr
,
neighbor_entry
->
ha
,
dev
->
addr_len
);
return
1
;
}
...
...
@@ -519,67 +482,36 @@ static int arp_query(unsigned char *haddr, u32 paddr, struct net_device * dev)
return
0
;
}
static
void
DumpData
(
char
*
msg
,
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
static
void
DumpData
(
char
*
msg
,
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
{
static
const
int
MAX_DumpData
=
80
;
__u8
pkt_text
[
MAX_DumpData
],
*
p
=
pkt_text
;
*
p
++
=
'\"'
;
while
(
ptr
<
end
&&
p
<
&
pkt_text
[
MAX_DumpData
-
4
])
{
if
(
*
ptr
==
'\\'
)
{
while
(
ptr
<
end
&&
p
<
&
pkt_text
[
MAX_DumpData
-
4
])
{
if
(
*
ptr
==
'\\'
)
{
*
p
++
=
'\\'
;
*
p
++
=
'\\'
;
}
else
{
if
(
*
ptr
>=
32
&&
*
ptr
<=
126
)
{
}
else
{
if
(
*
ptr
>=
32
&&
*
ptr
<=
126
)
{
*
p
++
=
*
ptr
;
}
else
{
}
else
{
sprintf
(
p
,
"
\\
%02X"
,
*
ptr
);
p
+=
3
;
p
+=
3
;
}
}
ptr
++
;
}
if
(
ptr
==
end
)
{
*
p
++
=
'\"'
;
}
*
p
++
=
0
;
printk
(
KERN_INFO
"%s: %-13s%s
\n
"
,
strip_info
->
dev
.
name
,
msg
,
pkt_text
);
}
#if 0
static void HexDump(char *msg, struct strip *strip_info, __u8 *start, __u8 *end)
{
__u8 *ptr = start;
printk(KERN_INFO "%s: %s: %d bytes\n", strip_info->dev.name, msg, end-ptr);
while (ptr < end)
{
long offset = ptr - start;
__u8 text[80], *p = text;
while (ptr < end && p < &text[16*3])
{
*p++ = hextable[*ptr >> 4];
*p++ = hextable[*ptr++ & 0xF];
*p++ = ' ';
}
p[-1] = 0;
printk(KERN_INFO "%s: %4lX %s\n", strip_info->dev.name, offset, text);
}
}
#endif
/************************************************************************/
/* Byte stuffing/unstuffing routines */
...
...
@@ -592,8 +524,7 @@ static void HexDump(char *msg, struct strip *strip_info, __u8 *start, __u8 *end)
* C0-FF Run of 1-64 zeroes (ASCII 0)
*/
typedef
enum
{
typedef
enum
{
Stuff_Diff
=
0x00
,
Stuff_DiffZero
=
0x40
,
Stuff_Same
=
0x80
,
...
...
@@ -622,17 +553,17 @@ typedef enum
#define StuffData_FinishBlock(X) \
(*code_ptr = (X) ^ Stuff_Magic, code = Stuff_NoCode)
static
__u8
*
StuffData
(
__u8
*
src
,
__u32
length
,
__u8
*
dst
,
__u8
**
code_ptr_ptr
)
static
__u8
*
StuffData
(
__u8
*
src
,
__u32
length
,
__u8
*
dst
,
__u8
**
code_ptr_ptr
)
{
__u8
*
end
=
src
+
length
;
__u8
*
code_ptr
=
*
code_ptr_ptr
;
__u8
code
=
Stuff_NoCode
,
count
=
0
;
if
(
!
length
)
return
(
dst
);
return
(
dst
);
if
(
code_ptr
)
{
if
(
code_ptr
)
{
/*
* Recover state from last call, if applicable
*/
...
...
@@ -640,23 +571,18 @@ static __u8 *StuffData(__u8 *src, __u32 length, __u8 *dst, __u8 **code_ptr_ptr)
count
=
(
*
code_ptr
^
Stuff_Magic
)
&
Stuff_CountMask
;
}
while
(
src
<
end
)
{
switch
(
code
)
{
while
(
src
<
end
)
{
switch
(
code
)
{
/* Stuff_NoCode: If no current code, select one */
case
Stuff_NoCode
:
/* Record where we're going to put this code */
code_ptr
=
dst
++
;
count
=
0
;
/* Reset the count (zero means one instance) */
/* Tentatively start a new block */
if
(
*
src
==
0
)
{
if
(
*
src
==
0
)
{
code
=
Stuff_Zero
;
src
++
;
}
else
{
}
else
{
code
=
Stuff_Same
;
*
dst
++
=
*
src
++
^
Stuff_Magic
;
}
...
...
@@ -668,13 +594,10 @@ static __u8 *StuffData(__u8 *src, __u32 length, __u8 *dst, __u8 **code_ptr_ptr)
/* Stuff_Zero: We already have at least one zero encoded */
case
Stuff_Zero
:
/* If another zero, count it, else finish this code block */
if
(
*
src
==
0
)
{
if
(
*
src
==
0
)
{
count
++
;
src
++
;
}
else
{
}
else
{
StuffData_FinishBlock
(
Stuff_Zero
+
count
);
}
break
;
...
...
@@ -682,16 +605,14 @@ static __u8 *StuffData(__u8 *src, __u32 length, __u8 *dst, __u8 **code_ptr_ptr)
/* Stuff_Same: We already have at least one byte encoded */
case
Stuff_Same
:
/* If another one the same, count it */
if
((
*
src
^
Stuff_Magic
)
==
code_ptr
[
1
])
{
if
((
*
src
^
Stuff_Magic
)
==
code_ptr
[
1
])
{
count
++
;
src
++
;
break
;
}
/* else, this byte does not match this block. */
/* If we already have two or more bytes encoded, finish this code block */
if
(
count
)
{
if
(
count
)
{
StuffData_FinishBlock
(
Stuff_Same
+
count
);
break
;
}
...
...
@@ -710,50 +631,44 @@ static __u8 *StuffData(__u8 *src, __u32 length, __u8 *dst, __u8 **code_ptr_ptr)
/* Stuff_Diff: We have at least two *different* bytes encoded */
case
Stuff_Diff
:
/* If this is a zero, must encode a Stuff_DiffZero, and begin a new block */
if
(
*
src
==
0
)
{
StuffData_FinishBlock
(
Stuff_DiffZero
+
count
);
if
(
*
src
==
0
)
{
StuffData_FinishBlock
(
Stuff_DiffZero
+
count
);
}
/* else, if we have three in a row, it is worth starting a Stuff_Same block */
else
if
((
*
src
^
Stuff_Magic
)
==
dst
[
-
1
]
&&
dst
[
-
1
]
==
dst
[
-
2
])
{
else
if
((
*
src
^
Stuff_Magic
)
==
dst
[
-
1
]
&&
dst
[
-
1
]
==
dst
[
-
2
])
{
/* Back off the last two characters we encoded */
code
+=
count
-
2
;
code
+=
count
-
2
;
/* Note: "Stuff_Diff + 0" is an illegal code */
if
(
code
==
Stuff_Diff
+
0
)
{
if
(
code
==
Stuff_Diff
+
0
)
{
code
=
Stuff_Same
+
0
;
}
StuffData_FinishBlock
(
code
);
code_ptr
=
dst
-
2
;
code_ptr
=
dst
-
2
;
/* dst[-1] already holds the correct value */
count
=
2
;
/* 2 means three bytes encoded */
code
=
Stuff_Same
;
}
/* else, another different byte, so add it to the block */
else
{
else
{
*
dst
++
=
*
src
^
Stuff_Magic
;
count
++
;
}
src
++
;
/* Consume the byte */
break
;
}
if
(
count
==
Stuff_MaxCount
)
{
if
(
count
==
Stuff_MaxCount
)
{
StuffData_FinishBlock
(
code
+
count
);
}
}
if
(
code
==
Stuff_NoCode
)
{
if
(
code
==
Stuff_NoCode
)
{
*
code_ptr_ptr
=
NULL
;
}
else
{
}
else
{
*
code_ptr_ptr
=
code_ptr
;
StuffData_FinishBlock
(
code
+
count
);
}
return
(
dst
);
return
(
dst
);
}
/*
...
...
@@ -776,67 +691,64 @@ static __u8 *StuffData(__u8 *src, __u32 length, __u8 *dst, __u8 **code_ptr_ptr)
* call to resume correctly).
*/
static
__u8
*
UnStuffData
(
__u8
*
src
,
__u8
*
end
,
__u8
*
dst
,
__u32
dst_length
)
static
__u8
*
UnStuffData
(
__u8
*
src
,
__u8
*
end
,
__u8
*
dst
,
__u32
dst_length
)
{
__u8
*
dst_end
=
dst
+
dst_length
;
/* Sanity check */
if
(
!
src
||
!
end
||
!
dst
||
!
dst_length
)
return
(
NULL
);
while
(
src
<
end
&&
dst
<
dst_end
)
{
return
(
NULL
);
while
(
src
<
end
&&
dst
<
dst_end
)
{
int
count
=
(
*
src
^
Stuff_Magic
)
&
Stuff_CountMask
;
switch
((
*
src
^
Stuff_Magic
)
&
Stuff_CodeMask
)
{
switch
((
*
src
^
Stuff_Magic
)
&
Stuff_CodeMask
)
{
case
Stuff_Diff
:
if
(
src
+
1
+
count
>=
end
)
return
(
NULL
);
do
{
if
(
src
+
1
+
count
>=
end
)
return
(
NULL
);
do
{
*
dst
++
=
*++
src
^
Stuff_Magic
;
}
while
(
--
count
>=
0
&&
dst
<
dst_end
);
while
(
--
count
>=
0
&&
dst
<
dst_end
);
if
(
count
<
0
)
src
+=
1
;
else
{
else
{
if
(
count
==
0
)
*
src
=
Stuff_Same
^
Stuff_Magic
;
else
*
src
=
(
Stuff_Diff
+
count
)
^
Stuff_Magic
;
*
src
=
(
Stuff_Diff
+
count
)
^
Stuff_Magic
;
}
break
;
case
Stuff_DiffZero
:
if
(
src
+
1
+
count
>=
end
)
return
(
NULL
);
do
{
if
(
src
+
1
+
count
>=
end
)
return
(
NULL
);
do
{
*
dst
++
=
*++
src
^
Stuff_Magic
;
}
while
(
--
count
>=
0
&&
dst
<
dst_end
);
while
(
--
count
>=
0
&&
dst
<
dst_end
);
if
(
count
<
0
)
*
src
=
Stuff_Zero
^
Stuff_Magic
;
else
*
src
=
(
Stuff_DiffZero
+
count
)
^
Stuff_Magic
;
*
src
=
(
Stuff_DiffZero
+
count
)
^
Stuff_Magic
;
break
;
case
Stuff_Same
:
if
(
src
+
1
>=
end
)
return
(
NULL
);
do
{
if
(
src
+
1
>=
end
)
return
(
NULL
);
do
{
*
dst
++
=
src
[
1
]
^
Stuff_Magic
;
}
while
(
--
count
>=
0
&&
dst
<
dst_end
);
while
(
--
count
>=
0
&&
dst
<
dst_end
);
if
(
count
<
0
)
src
+=
2
;
else
*
src
=
(
Stuff_Same
+
count
)
^
Stuff_Magic
;
break
;
case
Stuff_Zero
:
do
{
do
{
*
dst
++
=
0
;
}
while
(
--
count
>=
0
&&
dst
<
dst_end
);
while
(
--
count
>=
0
&&
dst
<
dst_end
);
if
(
count
<
0
)
src
+=
1
;
else
...
...
@@ -845,9 +757,9 @@ static __u8 *UnStuffData(__u8 *src, __u8 *end, __u8 *dst, __u32 dst_length)
}
}
if
(
dst
<
dst_end
)
return
(
NULL
);
return
(
NULL
);
else
return
(
src
);
return
(
src
);
}
...
...
@@ -862,16 +774,19 @@ static __u8 *UnStuffData(__u8 *src, __u8 *end, __u8 *dst, __u32 dst_length)
* currently in effect (57.6 or 115.2) is returned.
*/
static
unsigned
int
get_baud
(
struct
tty_struct
*
tty
)
{
if
(
!
tty
||
!
tty
->
termios
)
return
(
0
);
if
((
tty
->
termios
->
c_cflag
&
CBAUD
)
==
B38400
&&
tty
->
driver_data
)
{
struct
async_struct
*
info
=
(
struct
async_struct
*
)
tty
->
driver_data
;
if
((
info
->
flags
&
ASYNC_SPD_MASK
)
==
ASYNC_SPD_HI
)
return
(
B57600
);
if
((
info
->
flags
&
ASYNC_SPD_MASK
)
==
ASYNC_SPD_VHI
)
return
(
B115200
);
}
return
(
tty
->
termios
->
c_cflag
&
CBAUD
);
}
{
if
(
!
tty
||
!
tty
->
termios
)
return
(
0
);
if
((
tty
->
termios
->
c_cflag
&
CBAUD
)
==
B38400
&&
tty
->
driver_data
)
{
struct
async_struct
*
info
=
(
struct
async_struct
*
)
tty
->
driver_data
;
if
((
info
->
flags
&
ASYNC_SPD_MASK
)
==
ASYNC_SPD_HI
)
return
(
B57600
);
if
((
info
->
flags
&
ASYNC_SPD_MASK
)
==
ASYNC_SPD_VHI
)
return
(
B115200
);
}
return
(
tty
->
termios
->
c_cflag
&
CBAUD
);
}
/*
* set_baud sets the baud rate to the rate defined by baudcode
...
...
@@ -882,12 +797,12 @@ static unsigned int get_baud(struct tty_struct *tty)
* user, so it is simplest to just avoid using 38400.
*/
static
void
set_baud
(
struct
tty_struct
*
tty
,
unsigned
int
baudcode
)
{
{
struct
termios
old_termios
=
*
(
tty
->
termios
);
tty
->
termios
->
c_cflag
&=
~
CBAUD
;
/* Clear the old baud setting */
tty
->
termios
->
c_cflag
|=
baudcode
;
/* Set the new baud setting */
tty
->
driver
.
set_termios
(
tty
,
&
old_termios
);
}
}
/*
* Convert a string to a Metricom Address.
...
...
@@ -898,26 +813,29 @@ static void set_baud(struct tty_struct *tty, unsigned int baudcode)
(p)[4] == '-' && \
isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && isdigit((p)[8]) )
static
int
string_to_radio_address
(
MetricomAddress
*
addr
,
__u8
*
p
)
static
int
string_to_radio_address
(
MetricomAddress
*
addr
,
__u8
*
p
)
{
if
(
!
IS_RADIO_ADDRESS
(
p
))
return
(
1
);
if
(
!
IS_RADIO_ADDRESS
(
p
))
return
(
1
);
addr
->
c
[
0
]
=
0
;
addr
->
c
[
1
]
=
0
;
addr
->
c
[
2
]
=
READHEX
(
p
[
0
])
<<
4
|
READHEX
(
p
[
1
]);
addr
->
c
[
3
]
=
READHEX
(
p
[
2
])
<<
4
|
READHEX
(
p
[
3
]);
addr
->
c
[
4
]
=
READHEX
(
p
[
5
])
<<
4
|
READHEX
(
p
[
6
]);
addr
->
c
[
5
]
=
READHEX
(
p
[
7
])
<<
4
|
READHEX
(
p
[
8
]);
return
(
0
);
return
(
0
);
}
/*
* Convert a Metricom Address to a string.
*/
static
__u8
*
radio_address_to_string
(
const
MetricomAddress
*
addr
,
MetricomAddressString
*
p
)
static
__u8
*
radio_address_to_string
(
const
MetricomAddress
*
addr
,
MetricomAddressString
*
p
)
{
sprintf
(
p
->
c
,
"%02X%02X-%02X%02X"
,
addr
->
c
[
2
],
addr
->
c
[
3
],
addr
->
c
[
4
],
addr
->
c
[
5
]);
return
(
p
->
c
);
sprintf
(
p
->
c
,
"%02X%02X-%02X%02X"
,
addr
->
c
[
2
],
addr
->
c
[
3
],
addr
->
c
[
4
],
addr
->
c
[
5
]);
return
(
p
->
c
);
}
/*
...
...
@@ -934,26 +852,30 @@ static int allocate_buffers(struct strip *strip_info)
__u8
*
r
=
kmalloc
(
MAX_RECV_MTU
,
GFP_ATOMIC
);
__u8
*
s
=
kmalloc
(
sx_size
,
GFP_ATOMIC
);
__u8
*
t
=
kmalloc
(
tx_size
,
GFP_ATOMIC
);
if
(
r
&&
s
&&
t
)
{
if
(
r
&&
s
&&
t
)
{
strip_info
->
rx_buff
=
r
;
strip_info
->
sx_buff
=
s
;
strip_info
->
tx_buff
=
t
;
strip_info
->
sx_size
=
sx_size
;
strip_info
->
tx_size
=
tx_size
;
strip_info
->
mtu
=
dev
->
mtu
;
return
(
1
);
}
if
(
r
)
kfree
(
r
);
if
(
s
)
kfree
(
s
);
if
(
t
)
kfree
(
t
);
return
(
0
);
return
(
1
);
}
if
(
r
)
kfree
(
r
);
if
(
s
)
kfree
(
s
);
if
(
t
)
kfree
(
t
);
return
(
0
);
}
/*
* MTU has been changed by the IP layer. Unfortunately we are not told
* about this, but we spot it ourselves and fix things up. We could be in
* an upcall from the tty driver, or in an ip packet queue.
*
* Caller must hold the strip_lock
*/
static
void
strip_changedmtu
(
struct
strip
*
strip_info
)
...
...
@@ -963,65 +885,52 @@ static void strip_changedmtu(struct strip *strip_info)
unsigned
char
*
orbuff
=
strip_info
->
rx_buff
;
unsigned
char
*
osbuff
=
strip_info
->
sx_buff
;
unsigned
char
*
otbuff
=
strip_info
->
tx_buff
;
InterruptStatus
intstat
;
if
(
dev
->
mtu
>
MAX_SEND_MTU
)
{
printk
(
KERN_ERR
"%s: MTU exceeds maximum allowable (%d), MTU change cancelled.
\n
"
,
if
(
dev
->
mtu
>
MAX_SEND_MTU
)
{
printk
(
KERN_ERR
"%s: MTU exceeds maximum allowable (%d), MTU change cancelled.
\n
"
,
strip_info
->
dev
.
name
,
MAX_SEND_MTU
);
dev
->
mtu
=
old_mtu
;
return
;
}
/*
* Have to disable interrupts here because we're reallocating and resizing
* the serial buffers, and we can't have data arriving in them while we're
* moving them around in memory. This may cause data to be lost on the serial
* port, but hopefully people won't change MTU that often.
* Also note, this may not work on a symmetric multi-processor system.
*/
intstat
=
DisableInterrupts
();
if
(
!
allocate_buffers
(
strip_info
))
{
RestoreInterrupts
(
intstat
);
if
(
!
allocate_buffers
(
strip_info
))
{
printk
(
KERN_ERR
"%s: unable to grow strip buffers, MTU change cancelled.
\n
"
,
strip_info
->
dev
.
name
);
dev
->
mtu
=
old_mtu
;
return
;
}
if
(
strip_info
->
sx_count
)
{
if
(
strip_info
->
sx_count
)
{
if
(
strip_info
->
sx_count
<=
strip_info
->
sx_size
)
memcpy
(
strip_info
->
sx_buff
,
osbuff
,
strip_info
->
sx_count
);
else
{
memcpy
(
strip_info
->
sx_buff
,
osbuff
,
strip_info
->
sx_count
);
else
{
strip_info
->
discard
=
strip_info
->
sx_count
;
strip_info
->
rx_over_errors
++
;
}
}
if
(
strip_info
->
tx_left
)
{
if
(
strip_info
->
tx_left
)
{
if
(
strip_info
->
tx_left
<=
strip_info
->
tx_size
)
memcpy
(
strip_info
->
tx_buff
,
strip_info
->
tx_head
,
strip_info
->
tx_left
);
else
{
memcpy
(
strip_info
->
tx_buff
,
strip_info
->
tx_head
,
strip_info
->
tx_left
);
else
{
strip_info
->
tx_left
=
0
;
strip_info
->
tx_dropped
++
;
}
}
strip_info
->
tx_head
=
strip_info
->
tx_buff
;
RestoreInterrupts
(
intstat
);
printk
(
KERN_NOTICE
"%s: strip MTU changed fom %d to %d.
\n
"
,
strip_info
->
dev
.
name
,
old_mtu
,
strip_info
->
mtu
);
if
(
orbuff
)
kfree
(
orbuff
);
if
(
osbuff
)
kfree
(
osbuff
);
if
(
otbuff
)
kfree
(
otbuff
);
if
(
orbuff
)
kfree
(
orbuff
);
if
(
osbuff
)
kfree
(
osbuff
);
if
(
otbuff
)
kfree
(
otbuff
);
}
static
void
strip_unlock
(
struct
strip
*
strip_info
)
...
...
@@ -1029,7 +938,7 @@ static void strip_unlock(struct strip *strip_info)
/*
* Set the timer to go off in one second.
*/
strip_info
->
idle_timer
.
expires
=
jiffies
+
1
*
HZ
;
strip_info
->
idle_timer
.
expires
=
jiffies
+
1
*
HZ
;
add_timer
(
&
strip_info
->
idle_timer
);
netif_wake_queue
(
&
strip_info
->
dev
);
}
...
...
@@ -1059,8 +968,7 @@ shift_buffer(char *buffer, int requested_offset, int requested_len,
if
(
*
total
+
printed
<=
requested_offset
)
{
*
total
+=
printed
;
*
buf
=
buffer
;
}
else
{
}
else
{
if
(
*
total
<
requested_offset
)
{
*
slop
=
requested_offset
-
*
total
;
}
...
...
@@ -1068,8 +976,7 @@ shift_buffer(char *buffer, int requested_offset, int requested_len,
}
if
(
*
total
>
requested_offset
+
requested_len
)
{
return
1
;
}
else
{
}
else
{
return
0
;
}
}
...
...
@@ -1117,32 +1024,37 @@ calc_start_len(char *buffer, char **start, int requested_offset,
static
char
*
time_delta
(
char
buffer
[],
long
time
)
{
time
-=
jiffies
;
if
(
time
>
LongTime
/
2
)
return
(
"Not scheduled"
);
if
(
time
<
0
)
time
=
0
;
/* Don't print negative times */
if
(
time
>
LongTime
/
2
)
return
(
"Not scheduled"
);
if
(
time
<
0
)
time
=
0
;
/* Don't print negative times */
sprintf
(
buffer
,
"%ld seconds"
,
time
/
HZ
);
return
(
buffer
);
return
(
buffer
);
}
static
int
sprintf_neighbours
(
char
*
buffer
,
MetricomNodeTable
*
table
,
char
*
title
)
static
int
sprintf_neighbours
(
char
*
buffer
,
MetricomNodeTable
*
table
,
char
*
title
)
{
/* We wrap this in a do/while loop, so if the table changes */
/* while we're reading it, we just go around and try again. */
struct
timeval
t
;
char
*
ptr
;
do
{
unsigned
long
flags
;
do
{
int
i
;
t
=
table
->
timestamp
;
ptr
=
buffer
;
if
(
table
->
num_nodes
)
ptr
+=
sprintf
(
ptr
,
"
\n
%s
\n
"
,
title
);
for
(
i
=
0
;
i
<
table
->
num_nodes
;
i
++
)
{
InterruptStatus
intstat
=
DisableInterrupts
(
);
if
(
table
->
num_nodes
)
ptr
+=
sprintf
(
ptr
,
"
\n
%s
\n
"
,
title
);
for
(
i
=
0
;
i
<
table
->
num_nodes
;
i
++
)
{
spin_lock_irqsave
(
&
strip_lock
,
flags
);
MetricomNode
node
=
table
->
node
[
i
];
RestoreInterrupts
(
intstat
);
spin_unlock_irqrestore
(
&
strip_lock
,
flags
);
ptr
+=
sprintf
(
ptr
,
" %s
\n
"
,
node
.
c
);
}
}
while
(
table
->
timestamp
.
tv_sec
!=
t
.
tv_sec
||
table
->
timestamp
.
tv_usec
!=
t
.
tv_usec
);
}
while
(
table
->
timestamp
.
tv_sec
!=
t
.
tv_sec
||
table
->
timestamp
.
tv_usec
!=
t
.
tv_usec
);
return
ptr
-
buffer
;
}
...
...
@@ -1152,8 +1064,7 @@ static int sprintf_neighbours(char *buffer, MetricomNodeTable *table, char *titl
* than 4K of data into it. With the maximum of 32 portables and 32 poletops
* reported, the routine outputs 3107 bytes into the buffer.
*/
static
int
sprintf_status_info
(
char
*
buffer
,
struct
strip
*
strip_info
)
static
int
sprintf_status_info
(
char
*
buffer
,
struct
strip
*
strip_info
)
{
char
temp
[
32
];
char
*
p
=
buffer
;
...
...
@@ -1161,7 +1072,6 @@ sprintf_status_info(char *buffer, struct strip *strip_info)
/* First, we must copy all of our data to a safe place, */
/* in case a serial interrupt comes in and changes it. */
InterruptStatus
intstat
=
DisableInterrupts
();
int
tx_left
=
strip_info
->
tx_left
;
unsigned
long
rx_average_pps
=
strip_info
->
rx_average_pps
;
unsigned
long
tx_average_pps
=
strip_info
->
tx_average_pps
;
...
...
@@ -1175,9 +1085,10 @@ sprintf_status_info(char *buffer, struct strip *strip_info)
FirmwareVersion
firmware_version
=
strip_info
->
firmware_version
;
SerialNumber
serial_number
=
strip_info
->
serial_number
;
BatteryVoltage
battery_voltage
=
strip_info
->
battery_voltage
;
char
*
if_name
=
strip_info
->
dev
.
name
;
char
*
if_name
=
strip_info
->
dev
.
name
;
MetricomAddress
true_dev_addr
=
strip_info
->
true_dev_addr
;
MetricomAddress
dev_dev_addr
=
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
;
MetricomAddress
dev_dev_addr
=
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
;
int
manual_dev_addr
=
strip_info
->
manual_dev_addr
;
#ifdef EXT_COUNTERS
unsigned
long
rx_bytes
=
strip_info
->
rx_bytes
;
...
...
@@ -1189,51 +1100,66 @@ sprintf_status_info(char *buffer, struct strip *strip_info)
unsigned
long
rx_ebytes
=
strip_info
->
rx_ebytes
;
unsigned
long
tx_ebytes
=
strip_info
->
tx_ebytes
;
#endif
RestoreInterrupts
(
intstat
);
p
+=
sprintf
(
p
,
"
\n
Interface name
\t\t
%s
\n
"
,
if_name
);
p
+=
sprintf
(
p
,
" Radio working:
\t\t
%s
\n
"
,
working
?
"Yes"
:
"No"
);
radio_address_to_string
(
&
true_dev_addr
,
&
addr_string
);
p
+=
sprintf
(
p
,
" Radio address:
\t\t
%s
\n
"
,
addr_string
.
c
);
if
(
manual_dev_addr
)
{
if
(
manual_dev_addr
)
{
radio_address_to_string
(
&
dev_dev_addr
,
&
addr_string
);
p
+=
sprintf
(
p
,
" Device address:
\t
%s
\n
"
,
addr_string
.
c
);
}
p
+=
sprintf
(
p
,
" Firmware version:
\t
%s"
,
!
working
?
"Unknown"
:
!
firmware_level
?
"Should be upgraded"
:
firmware_version
.
c
);
if
(
firmware_level
>=
ChecksummedMessages
)
p
+=
sprintf
(
p
,
" (Checksums Enabled)"
);
if
(
firmware_level
>=
ChecksummedMessages
)
p
+=
sprintf
(
p
,
" (Checksums Enabled)"
);
p
+=
sprintf
(
p
,
"
\n
"
);
p
+=
sprintf
(
p
,
" Serial number:
\t\t
%s
\n
"
,
serial_number
.
c
);
p
+=
sprintf
(
p
,
" Battery voltage:
\t
%s
\n
"
,
battery_voltage
.
c
);
p
+=
sprintf
(
p
,
" Transmit queue (bytes):%d
\n
"
,
tx_left
);
p
+=
sprintf
(
p
,
" Receive packet rate: %ld packets per second
\n
"
,
rx_average_pps
/
8
);
p
+=
sprintf
(
p
,
" Transmit packet rate: %ld packets per second
\n
"
,
tx_average_pps
/
8
);
p
+=
sprintf
(
p
,
" Sent packet rate: %ld packets per second
\n
"
,
sx_average_pps
/
8
);
p
+=
sprintf
(
p
,
" Next watchdog probe:
\t
%s
\n
"
,
time_delta
(
temp
,
watchdog_doprobe
));
p
+=
sprintf
(
p
,
" Next watchdog reset:
\t
%s
\n
"
,
time_delta
(
temp
,
watchdog_doreset
));
p
+=
sprintf
(
p
,
" Receive packet rate: %ld packets per second
\n
"
,
rx_average_pps
/
8
);
p
+=
sprintf
(
p
,
" Transmit packet rate: %ld packets per second
\n
"
,
tx_average_pps
/
8
);
p
+=
sprintf
(
p
,
" Sent packet rate: %ld packets per second
\n
"
,
sx_average_pps
/
8
);
p
+=
sprintf
(
p
,
" Next watchdog probe:
\t
%s
\n
"
,
time_delta
(
temp
,
watchdog_doprobe
));
p
+=
sprintf
(
p
,
" Next watchdog reset:
\t
%s
\n
"
,
time_delta
(
temp
,
watchdog_doreset
));
p
+=
sprintf
(
p
,
" Next gratuitous ARP:
\t
"
);
if
(
!
memcmp
(
strip_info
->
dev
.
dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
)))
if
(
!
memcmp
(
strip_info
->
dev
.
dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
)))
p
+=
sprintf
(
p
,
"Disabled
\n
"
);
else
{
else
{
p
+=
sprintf
(
p
,
"%s
\n
"
,
time_delta
(
temp
,
gratuitous_arp
));
p
+=
sprintf
(
p
,
" Next ARP interval:
\t
%ld seconds
\n
"
,
JIFFIE_TO_SEC
(
arp_interval
));
p
+=
sprintf
(
p
,
" Next ARP interval:
\t
%ld seconds
\n
"
,
JIFFIE_TO_SEC
(
arp_interval
));
}
if
(
working
)
{
if
(
working
)
{
#ifdef EXT_COUNTERS
p
+=
sprintf
(
p
,
"
\n
"
);
p
+=
sprintf
(
p
,
" Total bytes:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_bytes
,
tx_bytes
);
p
+=
sprintf
(
p
,
" thru radio:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_rbytes
,
tx_rbytes
);
p
+=
sprintf
(
p
,
" thru serial port:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_sbytes
,
tx_sbytes
);
p
+=
sprintf
(
p
,
" Total stat/err bytes:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_ebytes
,
tx_ebytes
);
p
+=
sprintf
(
p
,
" Total bytes:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_bytes
,
tx_bytes
);
p
+=
sprintf
(
p
,
" thru radio:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_rbytes
,
tx_rbytes
);
p
+=
sprintf
(
p
,
" thru serial port:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_sbytes
,
tx_sbytes
);
p
+=
sprintf
(
p
,
" Total stat/err bytes:
\t
rx:
\t
%lu
\t
tx:
\t
%lu
\n
"
,
rx_ebytes
,
tx_ebytes
);
#endif
p
+=
sprintf_neighbours
(
p
,
&
strip_info
->
poletops
,
"Poletops:"
);
p
+=
sprintf_neighbours
(
p
,
&
strip_info
->
portables
,
"Portables:"
);
p
+=
sprintf_neighbours
(
p
,
&
strip_info
->
poletops
,
"Poletops:"
);
p
+=
sprintf_neighbours
(
p
,
&
strip_info
->
portables
,
"Portables:"
);
}
return
p
-
buffer
;
...
...
@@ -1244,23 +1170,27 @@ sprintf_status_info(char *buffer, struct strip *strip_info)
* the /proc file system.
*/
static
int
get_status_info
(
char
*
buffer
,
char
**
start
,
off_t
req_offset
,
int
req_len
)
static
int
get_status_info
(
char
*
buffer
,
char
**
start
,
off_t
req_offset
,
int
req_len
)
{
int
total
=
0
,
slop
=
0
;
struct
strip
*
strip_info
=
struct_strip_list
;
char
*
buf
=
buffer
;
buf
+=
sprintf
(
buf
,
"strip_version: %s
\n
"
,
StripVersion
);
if
(
shift_buffer
(
buffer
,
req_offset
,
req_len
,
&
total
,
&
slop
,
&
buf
))
goto
exit
;
if
(
shift_buffer
(
buffer
,
req_offset
,
req_len
,
&
total
,
&
slop
,
&
buf
))
goto
exit
;
while
(
strip_info
!=
NULL
)
{
while
(
strip_info
!=
NULL
)
{
buf
+=
sprintf_status_info
(
buf
,
strip_info
);
if
(
shift_buffer
(
buffer
,
req_offset
,
req_len
,
&
total
,
&
slop
,
&
buf
))
break
;
if
(
shift_buffer
(
buffer
,
req_offset
,
req_len
,
&
total
,
&
slop
,
&
buf
))
break
;
strip_info
=
strip_info
->
next
;
}
exit:
return
(
calc_start_len
(
buffer
,
start
,
req_offset
,
req_len
,
total
,
buf
));
return
(
calc_start_len
(
buffer
,
start
,
req_offset
,
req_len
,
total
,
buf
));
}
/************************************************************************/
...
...
@@ -1270,15 +1200,15 @@ static void ResetRadio(struct strip *strip_info)
{
struct
tty_struct
*
tty
=
strip_info
->
tty
;
static
const
char
init
[]
=
"ate0q1dt**starmode
\r
**"
;
StringDescriptor
s
=
{
init
,
sizeof
(
init
)
-
1
};
StringDescriptor
s
=
{
init
,
sizeof
(
init
)
-
1
};
/*
* If the radio isn't working anymore,
* we should clear the old status information.
*/
if
(
strip_info
->
working
)
{
printk
(
KERN_INFO
"%s: No response: Resetting radio.
\n
"
,
strip_info
->
dev
.
name
);
if
(
strip_info
->
working
)
{
printk
(
KERN_INFO
"%s: No response: Resetting radio.
\n
"
,
strip_info
->
dev
.
name
);
strip_info
->
firmware_version
.
c
[
0
]
=
'\0'
;
strip_info
->
serial_number
.
c
[
0
]
=
'\0'
;
strip_info
->
battery_voltage
.
c
[
0
]
=
'\0'
;
...
...
@@ -1297,9 +1227,10 @@ static void ResetRadio(struct strip *strip_info)
strip_info
->
sx_average_pps
=
0
;
/* Mark radio address as unknown */
*
(
MetricomAddress
*
)
&
strip_info
->
true_dev_addr
=
zero_address
;
*
(
MetricomAddress
*
)
&
strip_info
->
true_dev_addr
=
zero_address
;
if
(
!
strip_info
->
manual_dev_addr
)
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
zero_address
;
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
zero_address
;
strip_info
->
working
=
FALSE
;
strip_info
->
firmware_level
=
NoStructure
;
strip_info
->
next_command
=
CompatibilityCommand
;
...
...
@@ -1307,8 +1238,7 @@ static void ResetRadio(struct strip *strip_info)
strip_info
->
watchdog_doreset
=
jiffies
+
1
*
HZ
;
/* If the user has selected a baud rate above 38.4 see what magic we have to do */
if
(
strip_info
->
user_baud
>
B38400
)
{
if
(
strip_info
->
user_baud
>
B38400
)
{
/*
* Subtle stuff: Pay attention :-)
* If the serial port is currently at the user's selected (>38.4) rate,
...
...
@@ -1318,18 +1248,22 @@ static void ResetRadio(struct strip *strip_info)
* issued the ATS304 command last time through, so this time we restore
* the user's selected rate and issue the normal starmode reset string.
*/
if
(
strip_info
->
user_baud
==
get_baud
(
tty
))
{
if
(
strip_info
->
user_baud
==
get_baud
(
tty
))
{
static
const
char
b0
[]
=
"ate0q1s304=57600
\r
"
;
static
const
char
b1
[]
=
"ate0q1s304=115200
\r
"
;
static
const
StringDescriptor
baudstring
[
2
]
=
{
{
b0
,
sizeof
(
b0
)
-
1
},
{
b1
,
sizeof
(
b1
)
-
1
}
};
{
{
b0
,
sizeof
(
b0
)
-
1
}
,
{
b1
,
sizeof
(
b1
)
-
1
}
};
set_baud
(
tty
,
B19200
);
if
(
strip_info
->
user_baud
==
B57600
)
s
=
baudstring
[
0
];
else
if
(
strip_info
->
user_baud
==
B115200
)
s
=
baudstring
[
1
];
else
s
=
baudstring
[
1
];
/* For now */
}
else
set_baud
(
tty
,
strip_info
->
user_baud
);
if
(
strip_info
->
user_baud
==
B57600
)
s
=
baudstring
[
0
];
else
if
(
strip_info
->
user_baud
==
B115200
)
s
=
baudstring
[
1
];
else
s
=
baudstring
[
1
];
/* For now */
}
else
set_baud
(
tty
,
strip_info
->
user_baud
);
}
tty
->
driver
.
write
(
tty
,
0
,
s
.
string
,
s
.
length
);
...
...
@@ -1352,93 +1286,84 @@ static void strip_write_some_more(struct tty_struct *tty)
!
netif_running
(
&
strip_info
->
dev
))
return
;
if
(
strip_info
->
tx_left
>
0
)
{
/*
* If some data left, send it
* Note: There's a kernel design bug here. The write_wakeup routine has to
* know how many bytes were written in the previous call, but the number of
* bytes written is returned as the result of the tty->driver.write call,
* and there's no guarantee that the tty->driver.write routine will have
* returned before the write_wakeup routine is invoked. If the PC has fast
* Serial DMA hardware, then it's quite possible that the write could complete
* almost instantaneously, meaning that my write_wakeup routine could be
* called immediately, before tty->driver.write has had a chance to return
* the number of bytes that it wrote. In an attempt to guard against this,
* I disable interrupts around the call to tty->driver.write, although even
* this might not work on a symmetric multi-processor system.
*/
InterruptStatus
intstat
=
DisableInterrupts
();
int
num_written
=
tty
->
driver
.
write
(
tty
,
0
,
strip_info
->
tx_head
,
strip_info
->
tx_left
);
if
(
strip_info
->
tx_left
>
0
)
{
int
num_written
=
tty
->
driver
.
write
(
tty
,
0
,
strip_info
->
tx_head
,
strip_info
->
tx_left
);
strip_info
->
tx_left
-=
num_written
;
strip_info
->
tx_head
+=
num_written
;
#ifdef EXT_COUNTERS
strip_info
->
tx_sbytes
+=
num_written
;
#endif
RestoreInterrupts
(
intstat
);
}
else
/* Else start transmission of another packet */
{
}
else
{
/* Else start transmission of another packet */
tty
->
flags
&=
~
(
1
<<
TTY_DO_WRITE_WAKEUP
);
strip_unlock
(
strip_info
);
}
}
static
__u8
*
add_checksum
(
__u8
*
buffer
,
__u8
*
end
)
static
__u8
*
add_checksum
(
__u8
*
buffer
,
__u8
*
end
)
{
__u16
sum
=
0
;
__u8
*
p
=
buffer
;
while
(
p
<
end
)
sum
+=
*
p
++
;
end
[
3
]
=
hextable
[
sum
&
0xF
];
sum
>>=
4
;
end
[
2
]
=
hextable
[
sum
&
0xF
];
sum
>>=
4
;
end
[
1
]
=
hextable
[
sum
&
0xF
];
sum
>>=
4
;
while
(
p
<
end
)
sum
+=
*
p
++
;
end
[
3
]
=
hextable
[
sum
&
0xF
];
sum
>>=
4
;
end
[
2
]
=
hextable
[
sum
&
0xF
];
sum
>>=
4
;
end
[
1
]
=
hextable
[
sum
&
0xF
];
sum
>>=
4
;
end
[
0
]
=
hextable
[
sum
&
0xF
];
return
(
end
+
4
);
return
(
end
+
4
);
}
static
unsigned
char
*
strip_make_packet
(
unsigned
char
*
buffer
,
struct
strip
*
strip_info
,
struct
sk_buff
*
skb
)
static
unsigned
char
*
strip_make_packet
(
unsigned
char
*
buffer
,
struct
strip
*
strip_info
,
struct
sk_buff
*
skb
)
{
__u8
*
ptr
=
buffer
;
__u8
*
stuffstate
=
NULL
;
STRIP_Header
*
header
=
(
STRIP_Header
*
)
skb
->
data
;
STRIP_Header
*
header
=
(
STRIP_Header
*
)
skb
->
data
;
MetricomAddress
haddr
=
header
->
dst_addr
;
int
len
=
skb
->
len
-
sizeof
(
STRIP_Header
);
MetricomKey
key
;
/*HexDump("strip_make_packet", strip_info, skb->data, skb->data + skb->len);
*/
/*HexDump("strip_make_packet", strip_info, skb->data, skb->data + skb->len);
*/
if
(
header
->
protocol
==
htons
(
ETH_P_IP
))
key
=
SIP0Key
;
else
if
(
header
->
protocol
==
htons
(
ETH_P_ARP
))
key
=
ARP0Key
;
else
{
printk
(
KERN_ERR
"%s: strip_make_packet: Unknown packet type 0x%04X
\n
"
,
if
(
header
->
protocol
==
htons
(
ETH_P_IP
))
key
=
SIP0Key
;
else
if
(
header
->
protocol
==
htons
(
ETH_P_ARP
))
key
=
ARP0Key
;
else
{
printk
(
KERN_ERR
"%s: strip_make_packet: Unknown packet type 0x%04X
\n
"
,
strip_info
->
dev
.
name
,
ntohs
(
header
->
protocol
));
return
(
NULL
);
return
(
NULL
);
}
if
(
len
>
strip_info
->
mtu
)
{
printk
(
KERN_ERR
"%s: Dropping oversized transmit packet: %d bytes
\n
"
,
if
(
len
>
strip_info
->
mtu
)
{
printk
(
KERN_ERR
"%s: Dropping oversized transmit packet: %d bytes
\n
"
,
strip_info
->
dev
.
name
,
len
);
return
(
NULL
);
return
(
NULL
);
}
/*
* If we're sending to ourselves, discard the packet.
* (Metricom radios choke if they try to send a packet to their own address.)
*/
if
(
!
memcmp
(
haddr
.
c
,
strip_info
->
true_dev_addr
.
c
,
sizeof
(
haddr
)))
{
printk
(
KERN_ERR
"%s: Dropping packet addressed to self
\n
"
,
strip_info
->
dev
.
name
);
return
(
NULL
);
if
(
!
memcmp
(
haddr
.
c
,
strip_info
->
true_dev_addr
.
c
,
sizeof
(
haddr
)))
{
printk
(
KERN_ERR
"%s: Dropping packet addressed to self
\n
"
,
strip_info
->
dev
.
name
);
return
(
NULL
);
}
/*
* If this is a broadcast packet, send it to our designated Metricom
* 'broadcast hub' radio (First byte of address being 0xFF means broadcast)
*/
if
(
haddr
.
c
[
0
]
==
0xFF
)
{
if
(
haddr
.
c
[
0
]
==
0xFF
)
{
u32
brd
=
0
;
struct
in_device
*
in_dev
=
in_dev_get
(
&
strip_info
->
dev
);
if
(
in_dev
==
NULL
)
...
...
@@ -1450,17 +1375,19 @@ static unsigned char *strip_make_packet(unsigned char *buffer, struct strip *str
in_dev_put
(
in_dev
);
/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */
if
(
!
arp_query
(
haddr
.
c
,
brd
,
&
strip_info
->
dev
))
{
printk
(
KERN_ERR
"%s: Unable to send packet (no broadcast hub configured)
\n
"
,
if
(
!
arp_query
(
haddr
.
c
,
brd
,
&
strip_info
->
dev
))
{
printk
(
KERN_ERR
"%s: Unable to send packet (no broadcast hub configured)
\n
"
,
strip_info
->
dev
.
name
);
return
(
NULL
);
return
(
NULL
);
}
/*
* If we are the broadcast hub, don't bother sending to ourselves.
* (Metricom radios choke if they try to send a packet to their own address.)
*/
if
(
!
memcmp
(
haddr
.
c
,
strip_info
->
true_dev_addr
.
c
,
sizeof
(
haddr
)))
return
(
NULL
);
if
(
!
memcmp
(
haddr
.
c
,
strip_info
->
true_dev_addr
.
c
,
sizeof
(
haddr
)))
return
(
NULL
);
}
*
ptr
++
=
0x0D
;
...
...
@@ -1480,32 +1407,35 @@ static unsigned char *strip_make_packet(unsigned char *buffer, struct strip *str
*
ptr
++
=
key
.
c
[
2
];
*
ptr
++
=
key
.
c
[
3
];
ptr
=
StuffData
(
skb
->
data
+
sizeof
(
STRIP_Header
),
len
,
ptr
,
&
stuffstate
);
ptr
=
StuffData
(
skb
->
data
+
sizeof
(
STRIP_Header
),
len
,
ptr
,
&
stuffstate
);
if
(
strip_info
->
firmware_level
>=
ChecksummedMessages
)
ptr
=
add_checksum
(
buffer
+
1
,
ptr
);
if
(
strip_info
->
firmware_level
>=
ChecksummedMessages
)
ptr
=
add_checksum
(
buffer
+
1
,
ptr
);
*
ptr
++
=
0x0D
;
return
(
ptr
);
return
(
ptr
);
}
static
void
strip_send
(
struct
strip
*
strip_info
,
struct
sk_buff
*
skb
)
{
MetricomAddress
haddr
;
unsigned
char
*
ptr
=
strip_info
->
tx_buff
;
int
doreset
=
(
long
)
jiffies
-
strip_info
->
watchdog_doreset
>=
0
;
int
doprobe
=
(
long
)
jiffies
-
strip_info
->
watchdog_doprobe
>=
0
&&
!
doreset
;
int
doreset
=
(
long
)
jiffies
-
strip_info
->
watchdog_doreset
>=
0
;
int
doprobe
=
(
long
)
jiffies
-
strip_info
->
watchdog_doprobe
>=
0
&&
!
doreset
;
u32
addr
,
brd
;
/*
* 1. If we have a packet, encapsulate it and put it in the buffer
*/
if
(
skb
)
{
if
(
skb
)
{
char
*
newptr
=
strip_make_packet
(
ptr
,
strip_info
,
skb
);
strip_info
->
tx_pps_count
++
;
if
(
!
newptr
)
strip_info
->
tx_dropped
++
;
else
{
if
(
!
newptr
)
strip_info
->
tx_dropped
++
;
else
{
ptr
=
newptr
;
strip_info
->
sx_pps_count
++
;
strip_info
->
tx_packets
++
;
/* Count another successful packet */
...
...
@@ -1513,26 +1443,27 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
strip_info
->
tx_bytes
+=
skb
->
len
;
strip_info
->
tx_rbytes
+=
ptr
-
strip_info
->
tx_buff
;
#endif
/*DumpData("Sending:", strip_info, strip_info->tx_buff, ptr);
*/
/*HexDump("Sending", strip_info, strip_info->tx_buff, ptr);
*/
/*DumpData("Sending:", strip_info, strip_info->tx_buff, ptr);
*/
/*HexDump("Sending", strip_info, strip_info->tx_buff, ptr);
*/
}
}
/*
* 2. If it is time for another tickle, tack it on, after the packet
*/
if
(
doprobe
)
{
if
(
doprobe
)
{
StringDescriptor
ts
=
CommandString
[
strip_info
->
next_command
];
#if TICKLE_TIMERS
{
struct
timeval
tv
;
do_gettimeofday
(
&
tv
);
printk
(
KERN_INFO
"**** Sending tickle string %d at %02d.%06d
\n
"
,
strip_info
->
next_command
,
tv
.
tv_sec
%
100
,
tv
.
tv_usec
);
strip_info
->
next_command
,
tv
.
tv_sec
%
100
,
tv
.
tv_usec
);
}
#endif
if
(
ptr
==
strip_info
->
tx_buff
)
*
ptr
++
=
0x0D
;
if
(
ptr
==
strip_info
->
tx_buff
)
*
ptr
++
=
0x0D
;
*
ptr
++
=
'*'
;
/* First send "**" to provoke an error message */
*
ptr
++
=
'*'
;
...
...
@@ -1541,21 +1472,24 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
memcpy
(
ptr
,
ts
.
string
,
ts
.
length
);
/* Add a checksum ? */
if
(
strip_info
->
firmware_level
<
ChecksummedMessages
)
ptr
+=
ts
.
length
;
else
ptr
=
add_checksum
(
ptr
,
ptr
+
ts
.
length
);
if
(
strip_info
->
firmware_level
<
ChecksummedMessages
)
ptr
+=
ts
.
length
;
else
ptr
=
add_checksum
(
ptr
,
ptr
+
ts
.
length
);
*
ptr
++
=
0x0D
;
/* Terminate the command with a <CR> */
/* Cycle to next periodic command? */
if
(
strip_info
->
firmware_level
>=
StructuredMessages
)
if
(
++
strip_info
->
next_command
>=
ELEMENTS_OF
(
CommandString
))
if
(
++
strip_info
->
next_command
>=
ELEMENTS_OF
(
CommandString
))
strip_info
->
next_command
=
0
;
#ifdef EXT_COUNTERS
strip_info
->
tx_ebytes
+=
ts
.
length
;
#endif
strip_info
->
watchdog_doprobe
=
jiffies
+
10
*
HZ
;
strip_info
->
watchdog_doreset
=
jiffies
+
1
*
HZ
;
/*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev.name);
*/
/*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev.name);
*/
}
/*
...
...
@@ -1569,14 +1503,18 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
* 4. Debugging check to make sure we're not overflowing the buffer.
*/
if
(
strip_info
->
tx_size
-
strip_info
->
tx_left
<
20
)
printk
(
KERN_ERR
"%s: Sending%5d bytes;%5d bytes free.
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
tx_left
,
strip_info
->
tx_size
-
strip_info
->
tx_left
);
printk
(
KERN_ERR
"%s: Sending%5d bytes;%5d bytes free.
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
tx_left
,
strip_info
->
tx_size
-
strip_info
->
tx_left
);
/*
* 5. If watchdog has expired, reset the radio. Note: if there's data waiting in
* the buffer, strip_write_some_more will send it after the reset has finished
*/
if
(
doreset
)
{
ResetRadio
(
strip_info
);
return
;
}
if
(
doreset
)
{
ResetRadio
(
strip_info
);
return
;
}
if
(
1
)
{
struct
in_device
*
in_dev
=
in_dev_get
(
&
strip_info
->
dev
);
...
...
@@ -1607,20 +1545,20 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
* being sent, when in fact they are not, because they are all being dropped
* in the strip_make_packet routine.
*/
if
(
strip_info
->
working
&&
(
long
)
jiffies
-
strip_info
->
gratuitous_arp
>=
0
&&
memcmp
(
strip_info
->
dev
.
dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
))
&&
arp_query
(
haddr
.
c
,
brd
,
&
strip_info
->
dev
))
{
if
(
strip_info
->
working
&&
(
long
)
jiffies
-
strip_info
->
gratuitous_arp
>=
0
&&
memcmp
(
strip_info
->
dev
.
dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
))
&&
arp_query
(
haddr
.
c
,
brd
,
&
strip_info
->
dev
))
{
/*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n",
strip_info->dev.name, strip_info->arp_interval / HZ);*/
strip_info
->
gratuitous_arp
=
jiffies
+
strip_info
->
arp_interval
;
strip_info->dev.name, strip_info->arp_interval / HZ); */
strip_info
->
gratuitous_arp
=
jiffies
+
strip_info
->
arp_interval
;
strip_info
->
arp_interval
*=
2
;
if
(
strip_info
->
arp_interval
>
MaxARPInterval
)
strip_info
->
arp_interval
=
MaxARPInterval
;
if
(
addr
)
arp_send
(
ARPOP_REPLY
,
ETH_P_ARP
,
addr
,
/* Target address of ARP packet is our address */
arp_send
(
ARPOP_REPLY
,
ETH_P_ARP
,
addr
,
/* Target address of ARP packet is our address */
&
strip_info
->
dev
,
/* Device to send packet on */
addr
,
/* Source IP address this ARP packet comes from */
NULL
,
/* Destination HW address is NULL (broadcast it) */
...
...
@@ -1637,28 +1575,25 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
/* Encapsulate a datagram and kick it into a TTY queue. */
static
int
strip_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
strip
*
strip_info
=
(
struct
strip
*
)(
dev
->
priv
);
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
unsigned
long
flags
;
if
(
!
netif_running
(
dev
))
{
printk
(
KERN_ERR
"%s: xmit call when iface is down
\n
"
,
dev
->
name
);
return
(
1
);
if
(
!
netif_running
(
dev
))
{
printk
(
KERN_ERR
"%s: xmit call when iface is down
\n
"
,
dev
->
name
);
return
(
1
);
}
netif_stop_queue
(
dev
);
del_timer
(
&
strip_info
->
idle_timer
);
/* See if someone has been ifconfigging */
if
(
strip_info
->
mtu
!=
strip_info
->
dev
.
mtu
)
strip_changedmtu
(
strip_info
);
if
(
jiffies
-
strip_info
->
pps_timer
>
HZ
)
{
if
(
jiffies
-
strip_info
->
pps_timer
>
HZ
)
{
unsigned
long
t
=
jiffies
-
strip_info
->
pps_timer
;
unsigned
long
rx_pps_count
=
(
strip_info
->
rx_pps_count
*
HZ
*
8
+
t
/
2
)
/
t
;
unsigned
long
tx_pps_count
=
(
strip_info
->
tx_pps_count
*
HZ
*
8
+
t
/
2
)
/
t
;
unsigned
long
sx_pps_count
=
(
strip_info
->
sx_pps_count
*
HZ
*
8
+
t
/
2
)
/
t
;
unsigned
long
rx_pps_count
=
(
strip_info
->
rx_pps_count
*
HZ
*
8
+
t
/
2
)
/
t
;
unsigned
long
tx_pps_count
=
(
strip_info
->
tx_pps_count
*
HZ
*
8
+
t
/
2
)
/
t
;
unsigned
long
sx_pps_count
=
(
strip_info
->
sx_pps_count
*
HZ
*
8
+
t
/
2
)
/
t
;
strip_info
->
pps_timer
=
jiffies
;
strip_info
->
rx_pps_count
=
0
;
...
...
@@ -1680,11 +1615,18 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
strip_info
->
dev
.
name
,
sx_pps_count
/
8
);
}
spin_lock_irqsave
(
&
strip_lock
,
flags
);
/* See if someone has been ifconfigging */
if
(
strip_info
->
mtu
!=
strip_info
->
dev
.
mtu
)
strip_changedmtu
(
strip_info
);
strip_send
(
strip_info
,
skb
);
spin_unlock_irqrestore
(
&
strip_lock
,
flags
);
if
(
skb
)
dev_kfree_skb
(
skb
);
return
(
0
)
;
return
0
;
}
/*
...
...
@@ -1695,7 +1637,7 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
static
void
strip_IdleTask
(
unsigned
long
parameter
)
{
strip_xmit
(
NULL
,
(
struct
net_device
*
)
parameter
);
strip_xmit
(
NULL
,
(
struct
net_device
*
)
parameter
);
}
/*
...
...
@@ -1710,23 +1652,25 @@ static void strip_IdleTask(unsigned long parameter)
*/
static
int
strip_header
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
len
)
unsigned
short
type
,
void
*
daddr
,
void
*
saddr
,
unsigned
len
)
{
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
STRIP_Header
*
header
=
(
STRIP_Header
*
)
skb_push
(
skb
,
sizeof
(
STRIP_Header
));
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
STRIP_Header
*
header
=
(
STRIP_Header
*
)
skb_push
(
skb
,
sizeof
(
STRIP_Header
));
/*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type,
type == ETH_P_IP ? "IP" : type == ETH_P_ARP ? "ARP" : "");
*/
type == ETH_P_IP ? "IP" : type == ETH_P_ARP ? "ARP" : "");
*/
header
->
src_addr
=
strip_info
->
true_dev_addr
;
header
->
protocol
=
htons
(
type
);
/*HexDump("strip_header", (struct strip *)(dev->priv), skb->data, skb->data + skb->len);
*/
/*HexDump("strip_header", (struct strip *)(dev->priv), skb->data, skb->data + skb->len);
*/
if
(
!
daddr
)
return
(
-
dev
->
hard_header_len
);
if
(
!
daddr
)
return
(
-
dev
->
hard_header_len
);
header
->
dst_addr
=
*
(
MetricomAddress
*
)
daddr
;
return
(
dev
->
hard_header_len
);
header
->
dst_addr
=
*
(
MetricomAddress
*
)
daddr
;
return
(
dev
->
hard_header_len
);
}
/*
...
...
@@ -1744,7 +1688,7 @@ static int strip_rebuild_header(struct sk_buff *skb)
/* Arp find returns zero if if knows the address, */
/* or if it doesn't know the address it sends an ARP packet and returns non-zero */
return
arp_find
(
header
->
dst_addr
.
c
,
skb
)
?
1
:
0
;
return
arp_find
(
header
->
dst_addr
.
c
,
skb
)
?
1
:
0
;
#else
return
0
;
#endif
...
...
@@ -1763,21 +1707,25 @@ static int strip_receive_room(struct tty_struct *tty)
* This function parses the response to the ATS300? command,
* extracting the radio version and serial number.
*/
static
void
get_radio_version
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
static
void
get_radio_version
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
{
__u8
*
p
,
*
value_begin
,
*
value_end
;
int
len
;
/* Determine the beginning of the second line of the payload */
p
=
ptr
;
while
(
p
<
end
&&
*
p
!=
10
)
p
++
;
if
(
p
>=
end
)
return
;
while
(
p
<
end
&&
*
p
!=
10
)
p
++
;
if
(
p
>=
end
)
return
;
p
++
;
value_begin
=
p
;
/* Determine the end of line */
while
(
p
<
end
&&
*
p
!=
10
)
p
++
;
if
(
p
>=
end
)
return
;
while
(
p
<
end
&&
*
p
!=
10
)
p
++
;
if
(
p
>=
end
)
return
;
value_end
=
p
;
p
++
;
...
...
@@ -1789,16 +1737,18 @@ static void get_radio_version(struct strip *strip_info, __u8 *ptr, __u8 *end)
sprintf
(
strip_info
->
firmware_version
.
c
,
"%.*s"
,
len
,
value_begin
);
/* Look for the first colon */
while
(
p
<
end
&&
*
p
!=
':'
)
p
++
;
if
(
p
>=
end
)
return
;
while
(
p
<
end
&&
*
p
!=
':'
)
p
++
;
if
(
p
>=
end
)
return
;
/* Skip over the space */
p
+=
2
;
len
=
sizeof
(
SerialNumber
)
-
1
;
if
(
p
+
len
<=
end
)
{
sprintf
(
strip_info
->
serial_number
.
c
,
"%.*s"
,
len
,
p
);
}
else
{
printk
(
KERN_DEBUG
"STRIP: radio serial number shorter (%d) than expected (%d)
\n
"
,
}
else
{
printk
(
KERN_DEBUG
"STRIP: radio serial number shorter (%d) than expected (%d)
\n
"
,
end
-
p
,
len
);
}
}
...
...
@@ -1807,16 +1757,16 @@ static void get_radio_version(struct strip *strip_info, __u8 *ptr, __u8 *end)
* This function parses the response to the ATS325? command,
* extracting the radio battery voltage.
*/
static
void
get_radio_voltage
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
static
void
get_radio_voltage
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
{
int
len
;
len
=
sizeof
(
BatteryVoltage
)
-
1
;
if
(
ptr
+
len
<=
end
)
{
sprintf
(
strip_info
->
battery_voltage
.
c
,
"%.*s"
,
len
,
ptr
);
}
else
{
printk
(
KERN_DEBUG
"STRIP: radio voltage string shorter (%d) than expected (%d)
\n
"
,
}
else
{
printk
(
KERN_DEBUG
"STRIP: radio voltage string shorter (%d) than expected (%d)
\n
"
,
end
-
ptr
,
len
);
}
}
...
...
@@ -1825,55 +1775,62 @@ static void get_radio_voltage(struct strip *strip_info, __u8 *ptr, __u8 *end)
* This function parses the responses to the AT~LA and ATS311 commands,
* which list the radio's neighbours.
*/
static
void
get_radio_neighbours
(
MetricomNodeTable
*
table
,
__u8
*
ptr
,
__u8
*
end
)
static
void
get_radio_neighbours
(
MetricomNodeTable
*
table
,
__u8
*
ptr
,
__u8
*
end
)
{
table
->
num_nodes
=
0
;
while
(
ptr
<
end
&&
table
->
num_nodes
<
NODE_TABLE_SIZE
)
{
while
(
ptr
<
end
&&
table
->
num_nodes
<
NODE_TABLE_SIZE
)
{
MetricomNode
*
node
=
&
table
->
node
[
table
->
num_nodes
++
];
char
*
dst
=
node
->
c
,
*
limit
=
dst
+
sizeof
(
*
node
)
-
1
;
while
(
ptr
<
end
&&
*
ptr
<=
32
)
ptr
++
;
while
(
ptr
<
end
&&
dst
<
limit
&&
*
ptr
!=
10
)
*
dst
++
=
*
ptr
++
;
while
(
ptr
<
end
&&
*
ptr
<=
32
)
ptr
++
;
while
(
ptr
<
end
&&
dst
<
limit
&&
*
ptr
!=
10
)
*
dst
++
=
*
ptr
++
;
*
dst
++
=
0
;
while
(
ptr
<
end
&&
ptr
[
-
1
]
!=
10
)
ptr
++
;
while
(
ptr
<
end
&&
ptr
[
-
1
]
!=
10
)
ptr
++
;
}
do_gettimeofday
(
&
table
->
timestamp
);
}
static
int
get_radio_address
(
struct
strip
*
strip_info
,
__u8
*
p
)
static
int
get_radio_address
(
struct
strip
*
strip_info
,
__u8
*
p
)
{
MetricomAddress
addr
;
if
(
string_to_radio_address
(
&
addr
,
p
))
return
(
1
);
if
(
string_to_radio_address
(
&
addr
,
p
))
return
(
1
);
/* See if our radio address has changed */
if
(
memcmp
(
strip_info
->
true_dev_addr
.
c
,
addr
.
c
,
sizeof
(
addr
)))
{
if
(
memcmp
(
strip_info
->
true_dev_addr
.
c
,
addr
.
c
,
sizeof
(
addr
)))
{
MetricomAddressString
addr_string
;
radio_address_to_string
(
&
addr
,
&
addr_string
);
printk
(
KERN_INFO
"%s: Radio address = %s
\n
"
,
strip_info
->
dev
.
name
,
addr_string
.
c
);
printk
(
KERN_INFO
"%s: Radio address = %s
\n
"
,
strip_info
->
dev
.
name
,
addr_string
.
c
);
strip_info
->
true_dev_addr
=
addr
;
if
(
!
strip_info
->
manual_dev_addr
)
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
addr
;
if
(
!
strip_info
->
manual_dev_addr
)
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
addr
;
/* Give the radio a few seconds to get its head straight, then send an arp */
strip_info
->
gratuitous_arp
=
jiffies
+
15
*
HZ
;
strip_info
->
arp_interval
=
1
*
HZ
;
}
return
(
0
);
return
(
0
);
}
static
int
verify_checksum
(
struct
strip
*
strip_info
)
{
__u8
*
p
=
strip_info
->
sx_buff
;
__u8
*
end
=
strip_info
->
sx_buff
+
strip_info
->
sx_count
-
4
;
u_short
sum
=
(
READHEX16
(
end
[
0
])
<<
12
)
|
(
READHEX16
(
end
[
1
])
<<
8
)
|
u_short
sum
=
(
READHEX16
(
end
[
0
])
<<
12
)
|
(
READHEX16
(
end
[
1
])
<<
8
)
|
(
READHEX16
(
end
[
2
])
<<
4
)
|
(
READHEX16
(
end
[
3
]));
while
(
p
<
end
)
sum
-=
*
p
++
;
if
(
sum
==
0
&&
strip_info
->
firmware_level
==
StructuredMessages
)
{
while
(
p
<
end
)
sum
-=
*
p
++
;
if
(
sum
==
0
&&
strip_info
->
firmware_level
==
StructuredMessages
)
{
strip_info
->
firmware_level
=
ChecksummedMessages
;
printk
(
KERN_INFO
"%s: Radio provides message checksums
\n
"
,
strip_info
->
dev
.
name
);
printk
(
KERN_INFO
"%s: Radio provides message checksums
\n
"
,
strip_info
->
dev
.
name
);
}
return
(
sum
==
0
);
return
(
sum
==
0
);
}
static
void
RecvErr
(
char
*
msg
,
struct
strip
*
strip_info
)
...
...
@@ -1884,56 +1841,54 @@ static void RecvErr(char *msg, struct strip *strip_info)
strip_info
->
rx_errors
++
;
}
static
void
RecvErr_Message
(
struct
strip
*
strip_info
,
__u8
*
sendername
,
const
__u8
*
msg
,
u_long
len
)
static
void
RecvErr_Message
(
struct
strip
*
strip_info
,
__u8
*
sendername
,
const
__u8
*
msg
,
u_long
len
)
{
if
(
has_prefix
(
msg
,
len
,
"001"
))
/* Not in StarMode! */
{
if
(
has_prefix
(
msg
,
len
,
"001"
))
{
/* Not in StarMode! */
RecvErr
(
"Error Msg:"
,
strip_info
);
printk
(
KERN_INFO
"%s: Radio %s is not in StarMode
\n
"
,
strip_info
->
dev
.
name
,
sendername
);
}
else
if
(
has_prefix
(
msg
,
len
,
"002"
))
/* Remap handle */
{
else
if
(
has_prefix
(
msg
,
len
,
"002"
))
{
/* Remap handle */
/* We ignore "Remap handle" messages for now */
}
else
if
(
has_prefix
(
msg
,
len
,
"003"
))
/* Can't resolve name */
{
else
if
(
has_prefix
(
msg
,
len
,
"003"
))
{
/* Can't resolve name */
RecvErr
(
"Error Msg:"
,
strip_info
);
printk
(
KERN_INFO
"%s: Destination radio name is unknown
\n
"
,
strip_info
->
dev
.
name
);
}
else
if
(
has_prefix
(
msg
,
len
,
"004"
))
/* Name too small or missing */
{
else
if
(
has_prefix
(
msg
,
len
,
"004"
))
{
/* Name too small or missing */
strip_info
->
watchdog_doreset
=
jiffies
+
LongTime
;
#if TICKLE_TIMERS
{
struct
timeval
tv
;
do_gettimeofday
(
&
tv
);
printk
(
KERN_INFO
"**** Got ERR_004 response at %02d.%06d
\n
"
,
printk
(
KERN_INFO
"**** Got ERR_004 response at %02d.%06d
\n
"
,
tv
.
tv_sec
%
100
,
tv
.
tv_usec
);
}
#endif
if
(
!
strip_info
->
working
)
{
if
(
!
strip_info
->
working
)
{
strip_info
->
working
=
TRUE
;
printk
(
KERN_INFO
"%s: Radio now in starmode
\n
"
,
strip_info
->
dev
.
name
);
printk
(
KERN_INFO
"%s: Radio now in starmode
\n
"
,
strip_info
->
dev
.
name
);
/*
* If the radio has just entered a working state, we should do our first
* probe ASAP, so that we find out our radio address etc. without delay.
*/
strip_info
->
watchdog_doprobe
=
jiffies
;
}
if
(
strip_info
->
firmware_level
==
NoStructure
&&
sendername
)
{
if
(
strip_info
->
firmware_level
==
NoStructure
&&
sendername
)
{
strip_info
->
firmware_level
=
StructuredMessages
;
strip_info
->
next_command
=
0
;
/* Try to enable checksums ASAP */
printk
(
KERN_INFO
"%s: Radio provides structured messages
\n
"
,
strip_info
->
dev
.
name
);
printk
(
KERN_INFO
"%s: Radio provides structured messages
\n
"
,
strip_info
->
dev
.
name
);
}
if
(
strip_info
->
firmware_level
>=
StructuredMessages
)
{
if
(
strip_info
->
firmware_level
>=
StructuredMessages
)
{
/*
* If this message has a valid checksum on the end, then the call to verify_checksum
* will elevate the firmware_level to ChecksummedMessages for us. (The actual return
...
...
@@ -1944,7 +1899,8 @@ static void RecvErr_Message(struct strip *strip_info, __u8 *sendername, const __
* If the radio has structured messages but we don't yet have all our information about it,
* we should do probes without delay, until we have gathered all the information
*/
if
(
!
GOT_ALL_RADIO_INFO
(
strip_info
))
strip_info
->
watchdog_doprobe
=
jiffies
;
if
(
!
GOT_ALL_RADIO_INFO
(
strip_info
))
strip_info
->
watchdog_doprobe
=
jiffies
;
}
}
...
...
@@ -1954,17 +1910,17 @@ static void RecvErr_Message(struct strip *strip_info, __u8 *sendername, const __
else
if
(
has_prefix
(
msg
,
len
,
"006"
))
/* Header too big */
RecvErr
(
"Error Msg:"
,
strip_info
);
else
if
(
has_prefix
(
msg
,
len
,
"007"
))
/* Body too big */
{
else
if
(
has_prefix
(
msg
,
len
,
"007"
))
{
/* Body too big */
RecvErr
(
"Error Msg:"
,
strip_info
);
printk
(
KERN_ERR
"%s: Error! Packet size too big for radio.
\n
"
,
printk
(
KERN_ERR
"%s: Error! Packet size too big for radio.
\n
"
,
strip_info
->
dev
.
name
);
}
else
if
(
has_prefix
(
msg
,
len
,
"008"
))
/* Bad character in name */
{
else
if
(
has_prefix
(
msg
,
len
,
"008"
))
{
/* Bad character in name */
RecvErr
(
"Error Msg:"
,
strip_info
);
printk
(
KERN_ERR
"%s: Radio name contains illegal character
\n
"
,
printk
(
KERN_ERR
"%s: Radio name contains illegal character
\n
"
,
strip_info
->
dev
.
name
);
}
...
...
@@ -1984,13 +1940,15 @@ static void RecvErr_Message(struct strip *strip_info, __u8 *sendername, const __
RecvErr
(
"Error Msg:"
,
strip_info
);
}
static
void
process_AT_response
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
static
void
process_AT_response
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
{
u_long
len
;
__u8
*
p
=
ptr
;
while
(
p
<
end
&&
p
[
-
1
]
!=
10
)
p
++
;
/* Skip past first newline character */
while
(
p
<
end
&&
p
[
-
1
]
!=
10
)
p
++
;
/* Skip past first newline character */
/* Now ptr points to the AT command, and p points to the text of the response. */
len
=
p
-
ptr
;
len
=
p
-
ptr
;
#if TICKLE_TIMERS
{
...
...
@@ -2001,23 +1959,31 @@ static void process_AT_response(struct strip *strip_info, __u8 *ptr, __u8 *end)
}
#endif
if
(
has_prefix
(
ptr
,
len
,
"ATS300?"
))
get_radio_version
(
strip_info
,
p
,
end
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS305?"
))
get_radio_address
(
strip_info
,
p
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS311?"
))
get_radio_neighbours
(
&
strip_info
->
poletops
,
p
,
end
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS319=7"
))
verify_checksum
(
strip_info
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS325?"
))
get_radio_voltage
(
strip_info
,
p
,
end
);
else
if
(
has_prefix
(
ptr
,
len
,
"AT~LA"
))
get_radio_neighbours
(
&
strip_info
->
portables
,
p
,
end
);
else
RecvErr
(
"Unknown AT Response:"
,
strip_info
);
if
(
has_prefix
(
ptr
,
len
,
"ATS300?"
))
get_radio_version
(
strip_info
,
p
,
end
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS305?"
))
get_radio_address
(
strip_info
,
p
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS311?"
))
get_radio_neighbours
(
&
strip_info
->
poletops
,
p
,
end
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS319=7"
))
verify_checksum
(
strip_info
);
else
if
(
has_prefix
(
ptr
,
len
,
"ATS325?"
))
get_radio_voltage
(
strip_info
,
p
,
end
);
else
if
(
has_prefix
(
ptr
,
len
,
"AT~LA"
))
get_radio_neighbours
(
&
strip_info
->
portables
,
p
,
end
);
else
RecvErr
(
"Unknown AT Response:"
,
strip_info
);
}
static
void
process_ACK
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
static
void
process_ACK
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
{
/* Currently we don't do anything with ACKs from the radio */
}
static
void
process_Info
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
static
void
process_Info
(
struct
strip
*
strip_info
,
__u8
*
ptr
,
__u8
*
end
)
{
if
(
ptr
+
16
>
end
)
RecvErr
(
"Bad Info Msg:"
,
strip_info
);
if
(
ptr
+
16
>
end
)
RecvErr
(
"Bad Info Msg:"
,
strip_info
);
}
static
struct
net_device
*
get_strip_dev
(
struct
strip
*
strip_info
)
...
...
@@ -2026,45 +1992,48 @@ static struct net_device *get_strip_dev(struct strip *strip_info)
/* real radio hardware address, try to find another strip device that has been */
/* manually set to that address that we can 'transfer ownership' of this packet to */
if
(
strip_info
->
manual_dev_addr
&&
!
memcmp
(
strip_info
->
dev
.
dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
))
&&
memcmp
(
&
strip_info
->
true_dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
)))
{
!
memcmp
(
strip_info
->
dev
.
dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
))
&&
memcmp
(
&
strip_info
->
true_dev_addr
,
zero_address
.
c
,
sizeof
(
zero_address
)))
{
struct
net_device
*
dev
;
read_lock_bh
(
&
dev_base_lock
);
dev
=
dev_base
;
while
(
dev
)
{
while
(
dev
)
{
if
(
dev
->
type
==
strip_info
->
dev
.
type
&&
!
memcmp
(
dev
->
dev_addr
,
&
strip_info
->
true_dev_addr
,
sizeof
(
MetricomAddress
)))
{
printk
(
KERN_INFO
"%s: Transferred packet ownership to %s.
\n
"
,
!
memcmp
(
dev
->
dev_addr
,
&
strip_info
->
true_dev_addr
,
sizeof
(
MetricomAddress
)))
{
printk
(
KERN_INFO
"%s: Transferred packet ownership to %s.
\n
"
,
strip_info
->
dev
.
name
,
dev
->
name
);
read_unlock_bh
(
&
dev_base_lock
);
return
(
dev
);
return
(
dev
);
}
dev
=
dev
->
next
;
}
read_unlock_bh
(
&
dev_base_lock
);
}
return
(
&
strip_info
->
dev
);
return
(
&
strip_info
->
dev
);
}
/*
* Send one completely decapsulated datagram to the next layer.
*/
static
void
deliver_packet
(
struct
strip
*
strip_info
,
STRIP_Header
*
header
,
__u16
packetlen
)
static
void
deliver_packet
(
struct
strip
*
strip_info
,
STRIP_Header
*
header
,
__u16
packetlen
)
{
struct
sk_buff
*
skb
=
dev_alloc_skb
(
sizeof
(
STRIP_Header
)
+
packetlen
);
if
(
!
skb
)
{
printk
(
KERN_ERR
"%s: memory squeeze, dropping packet.
\n
"
,
strip_info
->
dev
.
name
);
if
(
!
skb
)
{
printk
(
KERN_ERR
"%s: memory squeeze, dropping packet.
\n
"
,
strip_info
->
dev
.
name
);
strip_info
->
rx_dropped
++
;
}
else
{
memcpy
(
skb_put
(
skb
,
sizeof
(
STRIP_Header
)),
header
,
sizeof
(
STRIP_Header
));
memcpy
(
skb_put
(
skb
,
packetlen
),
strip_info
->
rx_buff
,
packetlen
);
}
else
{
memcpy
(
skb_put
(
skb
,
sizeof
(
STRIP_Header
)),
header
,
sizeof
(
STRIP_Header
));
memcpy
(
skb_put
(
skb
,
packetlen
),
strip_info
->
rx_buff
,
packetlen
);
skb
->
dev
=
get_strip_dev
(
strip_info
);
skb
->
protocol
=
header
->
protocol
;
skb
->
mac
.
raw
=
skb
->
data
;
...
...
@@ -2085,40 +2054,39 @@ static void deliver_packet(struct strip *strip_info, STRIP_Header *header, __u16
}
}
static
void
process_IP_packet
(
struct
strip
*
strip_info
,
STRIP_Header
*
header
,
__u8
*
ptr
,
__u8
*
end
)
static
void
process_IP_packet
(
struct
strip
*
strip_info
,
STRIP_Header
*
header
,
__u8
*
ptr
,
__u8
*
end
)
{
__u16
packetlen
;
/* Decode start of the IP packet header */
ptr
=
UnStuffData
(
ptr
,
end
,
strip_info
->
rx_buff
,
4
);
if
(
!
ptr
)
{
if
(
!
ptr
)
{
RecvErr
(
"IP Packet too short"
,
strip_info
);
return
;
}
packetlen
=
((
__u16
)
strip_info
->
rx_buff
[
2
]
<<
8
)
|
strip_info
->
rx_buff
[
3
];
packetlen
=
((
__u16
)
strip_info
->
rx_buff
[
2
]
<<
8
)
|
strip_info
->
rx_buff
[
3
];
if
(
packetlen
>
MAX_RECV_MTU
)
{
if
(
packetlen
>
MAX_RECV_MTU
)
{
printk
(
KERN_INFO
"%s: Dropping oversized received IP packet: %d bytes
\n
"
,
strip_info
->
dev
.
name
,
packetlen
);
strip_info
->
rx_dropped
++
;
return
;
}
/*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev.name, packetlen);
*/
/*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev.name, packetlen);
*/
/* Decode remainder of the IP packet */
ptr
=
UnStuffData
(
ptr
,
end
,
strip_info
->
rx_buff
+
4
,
packetlen
-
4
);
if
(
!
ptr
)
{
ptr
=
UnStuffData
(
ptr
,
end
,
strip_info
->
rx_buff
+
4
,
packetlen
-
4
);
if
(
!
ptr
)
{
RecvErr
(
"IP Packet too short"
,
strip_info
);
return
;
}
if
(
ptr
<
end
)
{
if
(
ptr
<
end
)
{
RecvErr
(
"IP Packet too long"
,
strip_info
);
return
;
}
...
...
@@ -2128,24 +2096,25 @@ static void process_IP_packet(struct strip *strip_info, STRIP_Header *header, __
deliver_packet
(
strip_info
,
header
,
packetlen
);
}
static
void
process_ARP_packet
(
struct
strip
*
strip_info
,
STRIP_Header
*
header
,
__u8
*
ptr
,
__u8
*
end
)
static
void
process_ARP_packet
(
struct
strip
*
strip_info
,
STRIP_Header
*
header
,
__u8
*
ptr
,
__u8
*
end
)
{
__u16
packetlen
;
struct
arphdr
*
arphdr
=
(
struct
arphdr
*
)
strip_info
->
rx_buff
;
struct
arphdr
*
arphdr
=
(
struct
arphdr
*
)
strip_info
->
rx_buff
;
/* Decode start of the ARP packet */
ptr
=
UnStuffData
(
ptr
,
end
,
strip_info
->
rx_buff
,
8
);
if
(
!
ptr
)
{
if
(
!
ptr
)
{
RecvErr
(
"ARP Packet too short"
,
strip_info
);
return
;
}
packetlen
=
8
+
(
arphdr
->
ar_hln
+
arphdr
->
ar_pln
)
*
2
;
if
(
packetlen
>
MAX_RECV_MTU
)
{
printk
(
KERN_INFO
"%s: Dropping oversized received ARP packet: %d bytes
\n
"
,
if
(
packetlen
>
MAX_RECV_MTU
)
{
printk
(
KERN_INFO
"%s: Dropping oversized received ARP packet: %d bytes
\n
"
,
strip_info
->
dev
.
name
,
packetlen
);
strip_info
->
rx_dropped
++
;
return
;
...
...
@@ -2153,18 +2122,17 @@ static void process_ARP_packet(struct strip *strip_info, STRIP_Header *header, _
/*printk(KERN_INFO "%s: Got %d byte ARP %s\n",
strip_info->dev.name, packetlen,
ntohs(arphdr->ar_op) == ARPOP_REQUEST ? "request" : "reply");
*/
ntohs(arphdr->ar_op) == ARPOP_REQUEST ? "request" : "reply");
*/
/* Decode remainder of the ARP packet */
ptr
=
UnStuffData
(
ptr
,
end
,
strip_info
->
rx_buff
+
8
,
packetlen
-
8
);
if
(
!
ptr
)
{
ptr
=
UnStuffData
(
ptr
,
end
,
strip_info
->
rx_buff
+
8
,
packetlen
-
8
);
if
(
!
ptr
)
{
RecvErr
(
"ARP Packet too short"
,
strip_info
);
return
;
}
if
(
ptr
<
end
)
{
if
(
ptr
<
end
)
{
RecvErr
(
"ARP Packet too long"
,
strip_info
);
return
;
}
...
...
@@ -2189,15 +2157,22 @@ static void process_text_message(struct strip *strip_info)
/* Check for anything that looks like it might be our radio name */
/* (This is here for backwards compatibility with old firmware) */
if
(
len
==
9
&&
get_radio_address
(
strip_info
,
msg
)
==
0
)
return
;
if
(
len
==
9
&&
get_radio_address
(
strip_info
,
msg
)
==
0
)
return
;
if
(
text_equal
(
msg
,
len
,
"OK"
))
return
;
/* Ignore 'OK' responses from prior commands */
if
(
text_equal
(
msg
,
len
,
"ERROR"
))
return
;
/* Ignore 'ERROR' messages */
if
(
has_prefix
(
msg
,
len
,
"ate0q1"
))
return
;
/* Ignore character echo back from the radio */
if
(
text_equal
(
msg
,
len
,
"OK"
))
return
;
/* Ignore 'OK' responses from prior commands */
if
(
text_equal
(
msg
,
len
,
"ERROR"
))
return
;
/* Ignore 'ERROR' messages */
if
(
has_prefix
(
msg
,
len
,
"ate0q1"
))
return
;
/* Ignore character echo back from the radio */
/* Catch other error messages */
/* (This is here for backwards compatibility with old firmware) */
if
(
has_prefix
(
msg
,
len
,
"ERR_"
))
{
RecvErr_Message
(
strip_info
,
NULL
,
&
msg
[
4
],
len
-
4
);
return
;
}
if
(
has_prefix
(
msg
,
len
,
"ERR_"
))
{
RecvErr_Message
(
strip_info
,
NULL
,
&
msg
[
4
],
len
-
4
);
return
;
}
RecvErr
(
"No initial *"
,
strip_info
);
}
...
...
@@ -2219,19 +2194,24 @@ static void process_message(struct strip *strip_info)
__u8
sendername
[
32
],
*
sptr
=
sendername
;
MetricomKey
key
;
/*HexDump("Receiving", strip_info, ptr, end);
*/
/*HexDump("Receiving", strip_info, ptr, end);
*/
/* Check for start of address marker, and then skip over it */
if
(
*
ptr
==
'*'
)
ptr
++
;
else
{
process_text_message
(
strip_info
);
return
;
}
if
(
*
ptr
==
'*'
)
ptr
++
;
else
{
process_text_message
(
strip_info
);
return
;
}
/* Copy out the return address */
while
(
ptr
<
end
&&
*
ptr
!=
'*'
&&
sptr
<
ARRAY_END
(
sendername
)
-
1
)
*
sptr
++
=
*
ptr
++
;
while
(
ptr
<
end
&&
*
ptr
!=
'*'
&&
sptr
<
ARRAY_END
(
sendername
)
-
1
)
*
sptr
++
=
*
ptr
++
;
*
sptr
=
0
;
/* Null terminate the sender name */
/* Check for end of address marker, and skip over it */
if
(
ptr
>=
end
||
*
ptr
!=
'*'
)
{
if
(
ptr
>=
end
||
*
ptr
!=
'*'
)
{
RecvErr
(
"No second *"
,
strip_info
);
return
;
}
...
...
@@ -2239,15 +2219,13 @@ static void process_message(struct strip *strip_info)
/* If the sender name is "&COMMAND", ignore this 'packet' */
/* (This is here for backwards compatibility with old firmware) */
if
(
!
strcmp
(
sendername
,
"&COMMAND"
))
{
if
(
!
strcmp
(
sendername
,
"&COMMAND"
))
{
strip_info
->
firmware_level
=
NoStructure
;
strip_info
->
next_command
=
CompatibilityCommand
;
return
;
}
if
(
ptr
+
4
>
end
)
{
if
(
ptr
+
4
>
end
)
{
RecvErr
(
"No proto key"
,
strip_info
);
return
;
}
...
...
@@ -2259,22 +2237,19 @@ static void process_message(struct strip *strip_info)
key
.
c
[
3
]
=
*
ptr
++
;
/* If we're using checksums, verify the checksum at the end of the packet */
if
(
strip_info
->
firmware_level
>=
ChecksummedMessages
)
{
if
(
strip_info
->
firmware_level
>=
ChecksummedMessages
)
{
end
-=
4
;
/* Chop the last four bytes off the packet (they're the checksum) */
if
(
ptr
>
end
)
{
if
(
ptr
>
end
)
{
RecvErr
(
"Missing Checksum"
,
strip_info
);
return
;
}
if
(
!
verify_checksum
(
strip_info
))
{
if
(
!
verify_checksum
(
strip_info
))
{
RecvErr
(
"Bad Checksum"
,
strip_info
);
return
;
}
}
/*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev.name, sendername);
*/
/*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev.name, sendername);
*/
/*
* Fill in (pseudo) source and destination addresses in the packet.
...
...
@@ -2302,16 +2277,24 @@ static void process_message(struct strip *strip_info)
process_Info
(
strip_info
,
ptr
,
end
);
}
else
if
(
key
.
l
==
ERR_Key
.
l
)
{
strip_info
->
rx_ebytes
+=
(
end
-
ptr
);
RecvErr_Message
(
strip_info
,
sendername
,
ptr
,
end
-
ptr
);
}
else
RecvErr
(
"Unrecognized protocol key"
,
strip_info
);
RecvErr_Message
(
strip_info
,
sendername
,
ptr
,
end
-
ptr
);
}
else
RecvErr
(
"Unrecognized protocol key"
,
strip_info
);
#else
if
(
key
.
l
==
SIP0Key
.
l
)
process_IP_packet
(
strip_info
,
&
header
,
ptr
,
end
);
else
if
(
key
.
l
==
ARP0Key
.
l
)
process_ARP_packet
(
strip_info
,
&
header
,
ptr
,
end
);
else
if
(
key
.
l
==
ATR_Key
.
l
)
process_AT_response
(
strip_info
,
ptr
,
end
);
else
if
(
key
.
l
==
ACK_Key
.
l
)
process_ACK
(
strip_info
,
ptr
,
end
);
else
if
(
key
.
l
==
INF_Key
.
l
)
process_Info
(
strip_info
,
ptr
,
end
);
else
if
(
key
.
l
==
ERR_Key
.
l
)
RecvErr_Message
(
strip_info
,
sendername
,
ptr
,
end
-
ptr
);
else
RecvErr
(
"Unrecognized protocol key"
,
strip_info
);
if
(
key
.
l
==
SIP0Key
.
l
)
process_IP_packet
(
strip_info
,
&
header
,
ptr
,
end
);
else
if
(
key
.
l
==
ARP0Key
.
l
)
process_ARP_packet
(
strip_info
,
&
header
,
ptr
,
end
);
else
if
(
key
.
l
==
ATR_Key
.
l
)
process_AT_response
(
strip_info
,
ptr
,
end
);
else
if
(
key
.
l
==
ACK_Key
.
l
)
process_ACK
(
strip_info
,
ptr
,
end
);
else
if
(
key
.
l
==
INF_Key
.
l
)
process_Info
(
strip_info
,
ptr
,
end
);
else
if
(
key
.
l
==
ERR_Key
.
l
)
RecvErr_Message
(
strip_info
,
sendername
,
ptr
,
end
-
ptr
);
else
RecvErr
(
"Unrecognized protocol key"
,
strip_info
);
#endif
}
...
...
@@ -2327,16 +2310,19 @@ static void process_message(struct strip *strip_info)
* and sent on to some IP layer for further processing.
*/
static
void
strip_receive_buf
(
struct
tty_struct
*
tty
,
const
unsigned
char
*
cp
,
char
*
fp
,
int
count
)
static
void
strip_receive_buf
(
struct
tty_struct
*
tty
,
const
unsigned
char
*
cp
,
char
*
fp
,
int
count
)
{
struct
strip
*
strip_info
=
(
struct
strip
*
)
tty
->
disc_data
;
const
unsigned
char
*
end
=
cp
+
count
;
unsigned
long
flags
;
if
(
!
strip_info
||
strip_info
->
magic
!=
STRIP_MAGIC
||
!
netif_running
(
&
strip_info
->
dev
))
return
;
spin_lock_irqsave
(
&
strip_lock
,
flags
);
/* Argh! mtu change time! - costs us the packet part received at the change */
if
(
strip_info
->
mtu
!=
strip_info
->
dev
.
mtu
)
strip_changedmtu
(
strip_info
);
...
...
@@ -2345,7 +2331,8 @@ strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int
{
struct timeval tv;
do_gettimeofday(&tv);
printk(KERN_INFO "**** strip_receive_buf: %3d bytes at %02d.%06d\n",
printk(KERN_INFO
"**** strip_receive_buf: %3d bytes at %02d.%06d\n",
count, tv.tv_sec % 100, tv.tv_usec);
}
#endif
...
...
@@ -2355,55 +2342,66 @@ strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int
#endif
/* Read the characters out of the buffer */
while
(
cp
<
end
)
{
if
(
fp
&&
*
fp
)
printk
(
KERN_INFO
"%s: %s on serial port
\n
"
,
strip_info
->
dev
.
name
,
TTYERROR
(
*
fp
));
if
(
fp
&&
*
fp
++
&&
!
strip_info
->
discard
)
/* If there's a serial error, record it */
{
while
(
cp
<
end
)
{
if
(
fp
&&
*
fp
)
printk
(
KERN_INFO
"%s: %s on serial port
\n
"
,
strip_info
->
dev
.
name
,
TTYERROR
(
*
fp
));
if
(
fp
&&
*
fp
++
&&
!
strip_info
->
discard
)
{
/* If there's a serial error, record it */
/* If we have some characters in the buffer, discard them */
strip_info
->
discard
=
strip_info
->
sx_count
;
strip_info
->
rx_errors
++
;
}
/* Leading control characters (CR, NL, Tab, etc.) are ignored */
if
(
strip_info
->
sx_count
>
0
||
*
cp
>=
' '
)
{
if
(
*
cp
==
0x0D
)
/* If end of packet, decide what to do with it */
{
if
(
strip_info
->
sx_count
>
0
||
*
cp
>=
' '
)
{
if
(
*
cp
==
0x0D
)
{
/* If end of packet, decide what to do with it */
if
(
strip_info
->
sx_count
>
3000
)
printk
(
KERN_INFO
"%s: Cut a %d byte packet (%d bytes remaining)%s
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
sx_count
,
end
-
cp
-
1
,
strip_info
->
discard
?
" (discarded)"
:
""
);
if
(
strip_info
->
sx_count
>
strip_info
->
sx_size
)
{
printk
(
KERN_INFO
"%s: Cut a %d byte packet (%d bytes remaining)%s
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
sx_count
,
end
-
cp
-
1
,
strip_info
->
discard
?
" (discarded)"
:
""
);
if
(
strip_info
->
sx_count
>
strip_info
->
sx_size
)
{
strip_info
->
rx_over_errors
++
;
printk
(
KERN_INFO
"%s: sx_buff overflow (%d bytes total)
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
sx_count
);
}
else
if
(
strip_info
->
discard
)
printk
(
KERN_INFO
"%s: Discarding bad packet (%d/%d)
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
discard
,
strip_info
->
sx_count
);
else
process_message
(
strip_info
);
printk
(
KERN_INFO
"%s: sx_buff overflow (%d bytes total)
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
sx_count
);
}
else
if
(
strip_info
->
discard
)
printk
(
KERN_INFO
"%s: Discarding bad packet (%d/%d)
\n
"
,
strip_info
->
dev
.
name
,
strip_info
->
discard
,
strip_info
->
sx_count
);
else
process_message
(
strip_info
);
strip_info
->
discard
=
0
;
strip_info
->
sx_count
=
0
;
}
else
{
}
else
{
/* Make sure we have space in the buffer */
if
(
strip_info
->
sx_count
<
strip_info
->
sx_size
)
strip_info
->
sx_buff
[
strip_info
->
sx_count
]
=
*
cp
;
if
(
strip_info
->
sx_count
<
strip_info
->
sx_size
)
strip_info
->
sx_buff
[
strip_info
->
sx_count
]
=
*
cp
;
strip_info
->
sx_count
++
;
}
}
cp
++
;
}
spin_unlock_irqrestore
(
&
strip_lock
,
flags
);
}
/************************************************************************/
/* General control routines */
static
int
set_mac_address
(
struct
strip
*
strip_info
,
MetricomAddress
*
addr
)
static
int
set_mac_address
(
struct
strip
*
strip_info
,
MetricomAddress
*
addr
)
{
/*
* We're using a manually specified address if the address is set
...
...
@@ -2411,26 +2409,30 @@ static int set_mac_address(struct strip *strip_info, MetricomAddress *addr)
* disables manual mode and goes back to automatic address determination
* (tracking the true address that the radio has).
*/
strip_info
->
manual_dev_addr
=
memcmp
(
addr
->
c
,
broadcast_address
.
c
,
sizeof
(
broadcast_address
));
strip_info
->
manual_dev_addr
=
memcmp
(
addr
->
c
,
broadcast_address
.
c
,
sizeof
(
broadcast_address
));
if
(
strip_info
->
manual_dev_addr
)
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
*
addr
;
else
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
strip_info
->
true_dev_addr
;
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
*
addr
;
else
*
(
MetricomAddress
*
)
strip_info
->
dev
.
dev_addr
=
strip_info
->
true_dev_addr
;
return
0
;
}
static
int
dev_set_mac_address
(
struct
net_device
*
dev
,
void
*
addr
)
{
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
struct
sockaddr
*
sa
=
addr
;
printk
(
KERN_INFO
"%s: strip_set_dev_mac_address called
\n
"
,
dev
->
name
);
set_mac_address
(
strip_info
,
(
MetricomAddress
*
)
sa
->
sa_data
);
set_mac_address
(
strip_info
,
(
MetricomAddress
*
)
sa
->
sa_data
);
return
0
;
}
static
struct
net_device_stats
*
strip_get_stats
(
struct
net_device
*
dev
)
{
static
struct
net_device_stats
stats
;
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
memset
(
&
stats
,
0
,
sizeof
(
struct
net_device_stats
));
...
...
@@ -2441,7 +2443,7 @@ static struct net_device_stats *strip_get_stats(struct net_device *dev)
stats
.
tx_errors
=
strip_info
->
tx_errors
;
stats
.
rx_errors
=
strip_info
->
rx_errors
;
stats
.
rx_over_errors
=
strip_info
->
rx_over_errors
;
return
(
&
stats
);
return
(
&
stats
);
}
...
...
@@ -2474,16 +2476,13 @@ static struct net_device_stats *strip_get_stats(struct net_device *dev)
static
int
strip_open_low
(
struct
net_device
*
dev
)
{
struct
strip
*
strip_info
=
(
struct
strip
*
)(
dev
->
priv
);
#if 0
struct in_device *in_dev = dev->ip_ptr;
#endif
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
if
(
strip_info
->
tty
==
NULL
)
return
(
-
ENODEV
);
return
(
-
ENODEV
);
if
(
!
allocate_buffers
(
strip_info
))
return
(
-
ENOMEM
);
return
(
-
ENOMEM
);
strip_info
->
sx_count
=
0
;
strip_info
->
tx_left
=
0
;
...
...
@@ -2494,23 +2493,13 @@ static int strip_open_low(struct net_device *dev)
strip_info
->
next_command
=
CompatibilityCommand
;
strip_info
->
user_baud
=
get_baud
(
strip_info
->
tty
);
#if 0
/*
* Needed because address '0' is special
*
* --ANK Needed it or not needed, it does not matter at all.
* Make it at user level, guys.
*/
if (in_dev->ifa_list->ifa_address == 0)
in_dev->ifa_list->ifa_address = ntohl(0xC0A80001);
#endif
printk
(
KERN_INFO
"%s: Initializing Radio.
\n
"
,
strip_info
->
dev
.
name
);
printk
(
KERN_INFO
"%s: Initializing Radio.
\n
"
,
strip_info
->
dev
.
name
);
ResetRadio
(
strip_info
);
strip_info
->
idle_timer
.
expires
=
jiffies
+
1
*
HZ
;
strip_info
->
idle_timer
.
expires
=
jiffies
+
1
*
HZ
;
add_timer
(
&
strip_info
->
idle_timer
);
netif_wake_queue
(
dev
);
return
(
0
);
return
(
0
);
}
...
...
@@ -2520,7 +2509,7 @@ static int strip_open_low(struct net_device *dev)
static
int
strip_close_low
(
struct
net_device
*
dev
)
{
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
struct
strip
*
strip_info
=
(
struct
strip
*
)
(
dev
->
priv
);
if
(
strip_info
->
tty
==
NULL
)
return
-
EBUSY
;
...
...
@@ -2531,18 +2520,15 @@ static int strip_close_low(struct net_device *dev)
/*
* Free all STRIP frame buffers.
*/
if
(
strip_info
->
rx_buff
)
{
if
(
strip_info
->
rx_buff
)
{
kfree
(
strip_info
->
rx_buff
);
strip_info
->
rx_buff
=
NULL
;
}
if
(
strip_info
->
sx_buff
)
{
if
(
strip_info
->
sx_buff
)
{
kfree
(
strip_info
->
sx_buff
);
strip_info
->
sx_buff
=
NULL
;
}
if
(
strip_info
->
tx_buff
)
{
if
(
strip_info
->
tx_buff
)
{
kfree
(
strip_info
->
tx_buff
);
strip_info
->
tx_buff
=
NULL
;
}
...
...
@@ -2573,7 +2559,7 @@ static int strip_dev_init(struct net_device *dev)
* dev->priv Already holds a pointer to our struct strip
*/
*
(
MetricomAddress
*
)
&
dev
->
broadcast
=
broadcast_address
;
*
(
MetricomAddress
*
)
&
dev
->
broadcast
=
broadcast_address
;
dev
->
dev_addr
[
0
]
=
0
;
dev
->
addr_len
=
sizeof
(
MetricomAddress
);
...
...
@@ -2616,7 +2602,7 @@ static struct strip *strip_alloc(void)
kmalloc
(
sizeof
(
struct
strip
),
GFP_KERNEL
);
if
(
!
strip_info
)
return
(
NULL
);
/* If no more memory, return */
return
NULL
;
/* If no more memory, return */
/*
* Clear the allocated memory
...
...
@@ -2630,8 +2616,7 @@ static struct strip *strip_alloc(void)
* going to be)
*/
while
(
*
s
&&
(
*
s
)
->
dev
.
base_addr
==
channel_id
)
{
while
(
*
s
&&
(
*
s
)
->
dev
.
base_addr
==
channel_id
)
{
channel_id
++
;
s
=
&
(
*
s
)
->
next
;
}
...
...
@@ -2652,17 +2637,17 @@ static struct strip *strip_alloc(void)
strip_info
->
gratuitous_arp
=
jiffies
+
LongTime
;
strip_info
->
arp_interval
=
0
;
init_timer
(
&
strip_info
->
idle_timer
);
strip_info
->
idle_timer
.
data
=
(
long
)
&
strip_info
->
dev
;
strip_info
->
idle_timer
.
data
=
(
long
)
&
strip_info
->
dev
;
strip_info
->
idle_timer
.
function
=
strip_IdleTask
;
/* Note: strip_info->if_name is currently 8 characters long */
sprintf
(
strip_info
->
dev
.
name
,
"st%d"
,
channel_id
);
strip_info
->
dev
.
base_addr
=
channel_id
;
strip_info
->
dev
.
priv
=
(
void
*
)
strip_info
;
strip_info
->
dev
.
priv
=
(
void
*
)
strip_info
;
strip_info
->
dev
.
next
=
NULL
;
strip_info
->
dev
.
init
=
strip_dev_init
;
return
(
strip_info
)
;
return
strip_info
;
}
/*
...
...
@@ -2695,8 +2680,7 @@ static int strip_open(struct tty_struct *tty)
* strip_dev_init() will be called as a side-effect
*/
if
(
register_netdev
(
&
strip_info
->
dev
)
!=
0
)
{
if
(
register_netdev
(
&
strip_info
->
dev
)
!=
0
)
{
printk
(
KERN_ERR
"strip: register_netdev() failed.
\n
"
);
strip_free
(
strip_info
);
return
-
ENFILE
;
...
...
@@ -2719,18 +2703,19 @@ static int strip_open(struct tty_struct *tty)
* Set tty options
*/
tty
->
termios
->
c_iflag
|=
IGNBRK
|
IGNPAR
;
/* Ignore breaks and parity errors. */
tty
->
termios
->
c_iflag
|=
IGNBRK
|
IGNPAR
;
/* Ignore breaks and parity errors. */
tty
->
termios
->
c_cflag
|=
CLOCAL
;
/* Ignore modem control signals. */
tty
->
termios
->
c_cflag
&=
~
HUPCL
;
/* Don't close on hup */
MOD_INC_USE_COUNT
;
printk
(
KERN_INFO
"STRIP: device
\"
%s
\"
activated
\n
"
,
strip_info
->
dev
.
name
);
printk
(
KERN_INFO
"STRIP: device
\"
%s
\"
activated
\n
"
,
strip_info
->
dev
.
name
);
/*
* Done. We have linked the TTY line to a channel.
*/
return
(
strip_info
->
dev
.
base_addr
);
return
(
strip_info
->
dev
.
base_addr
);
}
/*
...
...
@@ -2755,7 +2740,8 @@ static void strip_close(struct tty_struct *tty)
tty
->
disc_data
=
0
;
strip_info
->
tty
=
NULL
;
printk
(
KERN_INFO
"STRIP: device
\"
%s
\"
closed down
\n
"
,
strip_info
->
dev
.
name
);
printk
(
KERN_INFO
"STRIP: device
\"
%s
\"
closed down
\n
"
,
strip_info
->
dev
.
name
);
strip_free
(
strip_info
);
tty
->
disc_data
=
NULL
;
MOD_DEC_USE_COUNT
;
...
...
@@ -2777,20 +2763,18 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file,
if
(
!
strip_info
||
strip_info
->
magic
!=
STRIP_MAGIC
)
return
-
EINVAL
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
SIOCGIFNAME
:
return
copy_to_user
((
void
*
)
arg
,
strip_info
->
dev
.
name
,
strlen
(
strip_info
->
dev
.
name
)
+
1
)
?
-
EFAULT
:
0
;
if
(
copy_to_user
((
void
*
)
arg
,
strip_info
->
dev
.
name
,
strlen
(
strip_info
->
dev
.
name
)
+
1
))
return
-
EFAULT
;
break
;
case
SIOCSIFHWADDR
:
{
MetricomAddress
addr
;
printk
(
KERN_INFO
"%s: SIOCSIFHWADDR
\n
"
,
strip_info
->
dev
.
name
);
return
copy_from_user
(
&
addr
,
(
void
*
)
arg
,
sizeof
(
MetricomAddress
))
?
-
EFAULT
:
set_mac_address
(
strip_info
,
&
addr
)
;
break
;
//
printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev.name);
if
(
copy_from_user
(
&
addr
,
(
void
*
)
arg
,
sizeof
(
MetricomAddress
)))
return
-
EFAULT
;
return
set_mac_address
(
strip_info
,
&
addr
)
;
}
/*
* Allow stty to read, but not set, the serial port
...
...
@@ -2798,13 +2782,13 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file,
case
TCGETS
:
case
TCGETA
:
return
n_tty_ioctl
(
tty
,
(
struct
file
*
)
file
,
cmd
,
(
unsigned
long
)
arg
);
return
n_tty_ioctl
(
tty
,
(
struct
file
*
)
file
,
cmd
,
(
unsigned
long
)
arg
);
break
;
default:
return
-
ENOIOCTLCMD
;
break
;
}
return
0
;
}
...
...
@@ -2828,7 +2812,8 @@ static struct tty_ldisc strip_ldisc = {
* STRIP driver
*/
static
char
signon
[]
__initdata
=
KERN_INFO
"STRIP: Version %s (unlimited channels)
\n
"
;
static
char
signon
[]
__initdata
=
KERN_INFO
"STRIP: Version %s (unlimited channels)
\n
"
;
static
int
__init
strip_init_driver
(
void
)
{
...
...
@@ -2836,11 +2821,14 @@ static int __init strip_init_driver(void)
printk
(
signon
,
StripVersion
);
spin_lock_init
(
&
strip_lock
);
/*
* Fill in our line protocol discipline, and register it
*/
if
((
status
=
tty_register_ldisc
(
N_STRIP
,
&
strip_ldisc
)))
printk
(
KERN_ERR
"STRIP: can't register line discipline (err = %d)
\n
"
,
status
);
printk
(
KERN_ERR
"STRIP: can't register line discipline (err = %d)
\n
"
,
status
);
/*
* Register the status file with /proc
...
...
@@ -2849,9 +2837,11 @@ static int __init strip_init_driver(void)
return
status
;
}
module_init
(
strip_init_driver
);
static
const
char
signoff
[]
__exitdata
=
KERN_INFO
"STRIP: Module Unloaded
\n
"
;
static
const
char
signoff
[]
__exitdata
=
KERN_INFO
"STRIP: Module Unloaded
\n
"
;
static
void
__exit
strip_exit_driver
(
void
)
{
...
...
@@ -2867,6 +2857,7 @@ static void __exit strip_exit_driver(void)
printk
(
signoff
);
}
module_exit
(
strip_exit_driver
);
MODULE_AUTHOR
(
"Stuart Cheshire <cheshire@cs.stanford.edu>"
);
...
...
@@ -2874,4 +2865,3 @@ MODULE_DESCRIPTION("Starmode Radio IP (STRIP) Device Driver");
MODULE_LICENSE
(
"Dual BSD/GPL"
);
MODULE_SUPPORTED_DEVICE
(
"Starmode Radio IP (STRIP) modem"
);
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