Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
98c4cae1
Commit
98c4cae1
authored
Jun 19, 2005
by
Christoph Hellwig
Committed by
Jeff Garzik
Jun 27, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] orinoco: monitor mode support
Patch from Pavel Roskin
parent
8f2abf44
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
180 additions
and
29 deletions
+180
-29
drivers/net/wireless/orinoco.c
drivers/net/wireless/orinoco.c
+179
-29
drivers/net/wireless/orinoco.h
drivers/net/wireless/orinoco.h
+1
-0
No files found.
drivers/net/wireless/orinoco.c
View file @
98c4cae1
...
@@ -499,6 +499,10 @@ static int ignore_disconnect; /* = 0 */
...
@@ -499,6 +499,10 @@ static int ignore_disconnect; /* = 0 */
module_param
(
ignore_disconnect
,
int
,
0644
);
module_param
(
ignore_disconnect
,
int
,
0644
);
MODULE_PARM_DESC
(
ignore_disconnect
,
"Don't report lost link to the network layer"
);
MODULE_PARM_DESC
(
ignore_disconnect
,
"Don't report lost link to the network layer"
);
static
int
force_monitor
;
/* = 0 */
module_param
(
force_monitor
,
int
,
0644
);
MODULE_PARM_DESC
(
force_monitor
,
"Allow monitor mode for all firmware versions"
);
/********************************************************************/
/********************************************************************/
/* Compile time configuration and compatibility stuff */
/* Compile time configuration and compatibility stuff */
/********************************************************************/
/********************************************************************/
...
@@ -670,6 +674,10 @@ static inline void set_port_type(struct orinoco_private *priv)
...
@@ -670,6 +674,10 @@ static inline void set_port_type(struct orinoco_private *priv)
priv
->
createibss
=
1
;
priv
->
createibss
=
1
;
}
}
break
;
break
;
case
IW_MODE_MONITOR
:
priv
->
port_type
=
3
;
priv
->
createibss
=
0
;
break
;
default:
default:
printk
(
KERN_ERR
"%s: Invalid priv->iw_mode in set_port_type()
\n
"
,
printk
(
KERN_ERR
"%s: Invalid priv->iw_mode in set_port_type()
\n
"
,
priv
->
ndev
->
name
);
priv
->
ndev
->
name
);
...
@@ -856,7 +864,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
...
@@ -856,7 +864,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
return
1
;
return
1
;
}
}
if
(
!
netif_carrier_ok
(
dev
))
{
if
(
!
netif_carrier_ok
(
dev
)
||
(
priv
->
iw_mode
==
IW_MODE_MONITOR
)
)
{
/* Oops, the firmware hasn't established a connection,
/* Oops, the firmware hasn't established a connection,
silently drop the packet (this seems to be the
silently drop the packet (this seems to be the
safest approach). */
safest approach). */
...
@@ -1118,6 +1126,117 @@ static void orinoco_stat_gather(struct net_device *dev,
...
@@ -1118,6 +1126,117 @@ static void orinoco_stat_gather(struct net_device *dev,
}
}
}
}
/*
* orinoco_rx_monitor - handle received monitor frames.
*
* Arguments:
* dev network device
* rxfid received FID
* desc rx descriptor of the frame
*
* Call context: interrupt
*/
static
void
orinoco_rx_monitor
(
struct
net_device
*
dev
,
u16
rxfid
,
struct
hermes_rx_descriptor
*
desc
)
{
u32
hdrlen
=
30
;
/* return full header by default */
u32
datalen
=
0
;
u16
fc
;
int
err
;
int
len
;
struct
sk_buff
*
skb
;
struct
orinoco_private
*
priv
=
netdev_priv
(
dev
);
struct
net_device_stats
*
stats
=
&
priv
->
stats
;
hermes_t
*
hw
=
&
priv
->
hw
;
len
=
le16_to_cpu
(
desc
->
data_len
);
/* Determine the size of the header and the data */
fc
=
le16_to_cpu
(
desc
->
frame_ctl
);
switch
(
fc
&
IEEE80211_FCTL_FTYPE
)
{
case
IEEE80211_FTYPE_DATA
:
if
((
fc
&
IEEE80211_FCTL_TODS
)
&&
(
fc
&
IEEE80211_FCTL_FROMDS
))
hdrlen
=
30
;
else
hdrlen
=
24
;
datalen
=
len
;
break
;
case
IEEE80211_FTYPE_MGMT
:
hdrlen
=
24
;
datalen
=
len
;
break
;
case
IEEE80211_FTYPE_CTL
:
switch
(
fc
&
IEEE80211_FCTL_STYPE
)
{
case
IEEE80211_STYPE_PSPOLL
:
case
IEEE80211_STYPE_RTS
:
case
IEEE80211_STYPE_CFEND
:
case
IEEE80211_STYPE_CFENDACK
:
hdrlen
=
16
;
break
;
case
IEEE80211_STYPE_CTS
:
case
IEEE80211_STYPE_ACK
:
hdrlen
=
10
;
break
;
}
break
;
default:
/* Unknown frame type */
break
;
}
/* sanity check the length */
if
(
datalen
>
IEEE80211_DATA_LEN
+
12
)
{
printk
(
KERN_DEBUG
"%s: oversized monitor frame, "
"data length = %d
\n
"
,
dev
->
name
,
datalen
);
err
=
-
EIO
;
stats
->
rx_length_errors
++
;
goto
update_stats
;
}
skb
=
dev_alloc_skb
(
hdrlen
+
datalen
);
if
(
!
skb
)
{
printk
(
KERN_WARNING
"%s: Cannot allocate skb for monitor frame
\n
"
,
dev
->
name
);
err
=
-
ENOMEM
;
goto
drop
;
}
/* Copy the 802.11 header to the skb */
memcpy
(
skb_put
(
skb
,
hdrlen
),
&
(
desc
->
frame_ctl
),
hdrlen
);
skb
->
mac
.
raw
=
skb
->
data
;
/* If any, copy the data from the card to the skb */
if
(
datalen
>
0
)
{
err
=
hermes_bap_pread
(
hw
,
IRQ_BAP
,
skb_put
(
skb
,
datalen
),
ALIGN
(
datalen
,
2
),
rxfid
,
HERMES_802_2_OFFSET
);
if
(
err
)
{
printk
(
KERN_ERR
"%s: error %d reading monitor frame
\n
"
,
dev
->
name
,
err
);
goto
drop
;
}
}
skb
->
dev
=
dev
;
skb
->
ip_summed
=
CHECKSUM_NONE
;
skb
->
pkt_type
=
PACKET_OTHERHOST
;
skb
->
protocol
=
__constant_htons
(
ETH_P_802_2
);
dev
->
last_rx
=
jiffies
;
stats
->
rx_packets
++
;
stats
->
rx_bytes
+=
skb
->
len
;
netif_rx
(
skb
);
return
;
drop:
dev_kfree_skb_irq
(
skb
);
update_stats:
stats
->
rx_errors
++
;
stats
->
rx_dropped
++
;
}
static
void
__orinoco_ev_rx
(
struct
net_device
*
dev
,
hermes_t
*
hw
)
static
void
__orinoco_ev_rx
(
struct
net_device
*
dev
,
hermes_t
*
hw
)
{
{
struct
orinoco_private
*
priv
=
netdev_priv
(
dev
);
struct
orinoco_private
*
priv
=
netdev_priv
(
dev
);
...
@@ -1137,24 +1256,29 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
...
@@ -1137,24 +1256,29 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
if
(
err
)
{
if
(
err
)
{
printk
(
KERN_ERR
"%s: error %d reading Rx descriptor. "
printk
(
KERN_ERR
"%s: error %d reading Rx descriptor. "
"Frame dropped.
\n
"
,
dev
->
name
,
err
);
"Frame dropped.
\n
"
,
dev
->
name
,
err
);
stats
->
rx_errors
++
;
goto
update_stats
;
goto
drop
;
}
}
status
=
le16_to_cpu
(
desc
.
status
);
status
=
le16_to_cpu
(
desc
.
status
);
if
(
status
&
HERMES_RXSTAT_ERR
)
{
if
(
status
&
HERMES_RXSTAT_BADCRC
)
{
if
(
status
&
HERMES_RXSTAT_UNDECRYPTABLE
)
{
DEBUG
(
1
,
"%s: Bad CRC on Rx. Frame dropped.
\n
"
,
wstats
->
discard
.
code
++
;
dev
->
name
);
DEBUG
(
1
,
"%s: Undecryptable frame on Rx. Frame dropped.
\n
"
,
stats
->
rx_crc_errors
++
;
dev
->
name
);
goto
update_stats
;
}
else
{
}
stats
->
rx_crc_errors
++
;
DEBUG
(
1
,
"%s: Bad CRC on Rx. Frame dropped.
\n
"
,
dev
->
name
);
}
stats
->
rx_errors
++
;
/* Handle frames in monitor mode */
goto
drop
;
if
(
priv
->
iw_mode
==
IW_MODE_MONITOR
)
{
orinoco_rx_monitor
(
dev
,
rxfid
,
&
desc
);
return
;
}
if
(
status
&
HERMES_RXSTAT_UNDECRYPTABLE
)
{
DEBUG
(
1
,
"%s: Undecryptable frame on Rx. Frame dropped.
\n
"
,
dev
->
name
);
wstats
->
discard
.
code
++
;
goto
update_stats
;
}
}
length
=
le16_to_cpu
(
desc
.
data_len
);
length
=
le16_to_cpu
(
desc
.
data_len
);
...
@@ -1165,15 +1289,13 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
...
@@ -1165,15 +1289,13 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
/* At least on Symbol firmware with PCF we get quite a
/* At least on Symbol firmware with PCF we get quite a
lot of these legitimately - Poll frames with no
lot of these legitimately - Poll frames with no
data. */
data. */
stats
->
rx_dropped
++
;
return
;
goto
drop
;
}
}
if
(
length
>
IEEE802_11_DATA_LEN
)
{
if
(
length
>
IEEE802_11_DATA_LEN
)
{
printk
(
KERN_WARNING
"%s: Oversized frame received (%d bytes)
\n
"
,
printk
(
KERN_WARNING
"%s: Oversized frame received (%d bytes)
\n
"
,
dev
->
name
,
length
);
dev
->
name
,
length
);
stats
->
rx_length_errors
++
;
stats
->
rx_length_errors
++
;
stats
->
rx_errors
++
;
goto
update_stats
;
goto
drop
;
}
}
/* We need space for the packet data itself, plus an ethernet
/* We need space for the packet data itself, plus an ethernet
...
@@ -1185,7 +1307,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
...
@@ -1185,7 +1307,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
if
(
!
skb
)
{
if
(
!
skb
)
{
printk
(
KERN_WARNING
"%s: Can't allocate skb for Rx
\n
"
,
printk
(
KERN_WARNING
"%s: Can't allocate skb for Rx
\n
"
,
dev
->
name
);
dev
->
name
);
goto
drop
;
goto
update_stats
;
}
}
/* We'll prepend the header, so reserve space for it. The worst
/* We'll prepend the header, so reserve space for it. The worst
...
@@ -1199,7 +1321,6 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
...
@@ -1199,7 +1321,6 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
if
(
err
)
{
if
(
err
)
{
printk
(
KERN_ERR
"%s: error %d reading frame. "
printk
(
KERN_ERR
"%s: error %d reading frame. "
"Frame dropped.
\n
"
,
dev
->
name
,
err
);
"Frame dropped.
\n
"
,
dev
->
name
,
err
);
stats
->
rx_errors
++
;
goto
drop
;
goto
drop
;
}
}
...
@@ -1245,11 +1366,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
...
@@ -1245,11 +1366,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
return
;
return
;
drop:
drop:
dev_kfree_skb_irq
(
skb
);
update_stats:
stats
->
rx_errors
++
;
stats
->
rx_dropped
++
;
stats
->
rx_dropped
++
;
if
(
skb
)
dev_kfree_skb_irq
(
skb
);
return
;
}
}
/********************************************************************/
/********************************************************************/
...
@@ -2065,6 +2185,20 @@ static int __orinoco_program_rids(struct net_device *dev)
...
@@ -2065,6 +2185,20 @@ static int __orinoco_program_rids(struct net_device *dev)
}
}
}
}
if
(
priv
->
iw_mode
==
IW_MODE_MONITOR
)
{
/* Enable monitor mode */
dev
->
type
=
ARPHRD_IEEE80211
;
err
=
hermes_docmd_wait
(
hw
,
HERMES_CMD_TEST
|
HERMES_TEST_MONITOR
,
0
,
NULL
);
}
else
{
/* Disable monitor mode */
dev
->
type
=
ARPHRD_ETHER
;
err
=
hermes_docmd_wait
(
hw
,
HERMES_CMD_TEST
|
HERMES_TEST_STOP
,
0
,
NULL
);
}
if
(
err
)
return
err
;
/* Set promiscuity / multicast*/
/* Set promiscuity / multicast*/
priv
->
promiscuous
=
0
;
priv
->
promiscuous
=
0
;
priv
->
mc_count
=
0
;
priv
->
mc_count
=
0
;
...
@@ -2413,6 +2547,7 @@ static int determine_firmware(struct net_device *dev)
...
@@ -2413,6 +2547,7 @@ static int determine_firmware(struct net_device *dev)
priv
->
has_pm
=
(
firmver
>=
0x40020
);
/* Don't work in 7.52 ? */
priv
->
has_pm
=
(
firmver
>=
0x40020
);
/* Don't work in 7.52 ? */
priv
->
ibss_port
=
1
;
priv
->
ibss_port
=
1
;
priv
->
has_hostscan
=
(
firmver
>=
0x8000a
);
priv
->
has_hostscan
=
(
firmver
>=
0x8000a
);
priv
->
broken_monitor
=
(
firmver
>=
0x80000
);
/* Tested with Agere firmware :
/* Tested with Agere firmware :
* 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
* 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
...
@@ -2980,6 +3115,15 @@ static int orinoco_ioctl_setmode(struct net_device *dev,
...
@@ -2980,6 +3115,15 @@ static int orinoco_ioctl_setmode(struct net_device *dev,
case
IW_MODE_INFRA
:
case
IW_MODE_INFRA
:
break
;
break
;
case
IW_MODE_MONITOR
:
if
(
priv
->
broken_monitor
&&
!
force_monitor
)
{
printk
(
KERN_WARNING
"%s: Monitor mode support is "
"buggy in this firmware, not enabling
\n
"
,
dev
->
name
);
err
=
-
EOPNOTSUPP
;
}
break
;
default:
default:
err
=
-
EOPNOTSUPP
;
err
=
-
EOPNOTSUPP
;
break
;
break
;
...
@@ -3355,11 +3499,9 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
...
@@ -3355,11 +3499,9 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
unsigned
long
flags
;
unsigned
long
flags
;
int
err
=
-
EINPROGRESS
;
/* Call commit handler */
int
err
=
-
EINPROGRESS
;
/* Call commit handler */
/* We can only use this in Ad-Hoc demo mode to set the operating
/* In infrastructure mode the AP sets the channel */
* frequency, or in IBSS mode to set the frequency where the IBSS
if
(
priv
->
iw_mode
==
IW_MODE_INFRA
)
* will be created - Jean II */
return
-
EBUSY
;
if
(
priv
->
iw_mode
!=
IW_MODE_ADHOC
)
return
-
EOPNOTSUPP
;
if
(
(
frq
->
e
==
0
)
&&
(
frq
->
m
<=
1000
)
)
{
if
(
(
frq
->
e
==
0
)
&&
(
frq
->
m
<=
1000
)
)
{
/* Setting by channel number */
/* Setting by channel number */
...
@@ -3383,7 +3525,15 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
...
@@ -3383,7 +3525,15 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
if
(
orinoco_lock
(
priv
,
&
flags
)
!=
0
)
if
(
orinoco_lock
(
priv
,
&
flags
)
!=
0
)
return
-
EBUSY
;
return
-
EBUSY
;
priv
->
channel
=
chan
;
priv
->
channel
=
chan
;
if
(
priv
->
iw_mode
==
IW_MODE_MONITOR
)
{
/* Fast channel change - no commit if successful */
hermes_t
*
hw
=
&
priv
->
hw
;
err
=
hermes_docmd_wait
(
hw
,
HERMES_CMD_TEST
|
HERMES_TEST_SET_CHANNEL
,
chan
,
NULL
);
}
orinoco_unlock
(
priv
,
&
flags
);
orinoco_unlock
(
priv
,
&
flags
);
return
err
;
return
err
;
...
...
drivers/net/wireless/orinoco.h
View file @
98c4cae1
...
@@ -94,6 +94,7 @@ struct orinoco_private {
...
@@ -94,6 +94,7 @@ struct orinoco_private {
unsigned
int
has_sensitivity
:
1
;
unsigned
int
has_sensitivity
:
1
;
unsigned
int
has_hostscan
:
1
;
unsigned
int
has_hostscan
:
1
;
unsigned
int
broken_disableport
:
1
;
unsigned
int
broken_disableport
:
1
;
unsigned
int
broken_monitor
:
1
;
/* Configuration paramaters */
/* Configuration paramaters */
u32
iw_mode
;
u32
iw_mode
;
...
...
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