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
e4c609fe
Commit
e4c609fe
authored
Oct 03, 2002
by
Maksim Krasnyanskiy
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux-bt.bkbits.net/bt-2.5
into viper.qualcomm.com:/usr/src/bt-2.5
parents
706e5455
fcde38d4
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
411 additions
and
308 deletions
+411
-308
include/net/bluetooth/bluetooth.h
include/net/bluetooth/bluetooth.h
+1
-10
include/net/bluetooth/hci.h
include/net/bluetooth/hci.h
+14
-22
include/net/bluetooth/hci_core.h
include/net/bluetooth/hci_core.h
+6
-7
net/bluetooth/af_bluetooth.c
net/bluetooth/af_bluetooth.c
+9
-6
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+3
-6
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+76
-35
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+5
-8
net/bluetooth/hci_sock.c
net/bluetooth/hci_sock.c
+38
-21
net/bluetooth/l2cap.c
net/bluetooth/l2cap.c
+195
-125
net/bluetooth/lib.c
net/bluetooth/lib.c
+1
-1
net/bluetooth/sco.c
net/bluetooth/sco.c
+63
-67
No files found.
include/net/bluetooth/bluetooth.h
View file @
e4c609fe
...
...
@@ -50,6 +50,7 @@
#define BTPROTO_HCI 1
#define BTPROTO_SCO 2
#define BTPROTO_RFCOMM 3
#define BTPROTO_BNEP 4
#define SOL_HCI 0
#define SOL_L2CAP 6
...
...
@@ -199,14 +200,4 @@ int hci_sock_cleanup(void);
int
bterr
(
__u16
code
);
#ifndef MODULE_LICENSE
#define MODULE_LICENSE(x)
#endif
#ifndef list_for_each_safe
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#endif
#endif
/* __BLUETOOTH_H */
include/net/bluetooth/hci.h
View file @
e4c609fe
...
...
@@ -113,10 +113,10 @@ enum {
#define ACL_PTYPE_MASK (~SCO_PTYPE_MASK)
/* ACL flags */
#define ACL_CONT 0x0
00
1
#define ACL_START 0x0
00
2
#define ACL_ACTIVE_BCAST 0x0
010
#define ACL_PICO_BCAST 0x0
020
#define ACL_CONT 0x01
#define ACL_START 0x02
#define ACL_ACTIVE_BCAST 0x0
4
#define ACL_PICO_BCAST 0x0
8
/* Baseband links */
#define SCO_LINK 0x00
...
...
@@ -542,7 +542,7 @@ typedef struct {
bdaddr_t
bdaddr
;
__u8
role
;
}
__attribute__
((
packed
))
evt_role_change
;
#define EVT_ROLE_CHANGE_SIZE
1
#define EVT_ROLE_CHANGE_SIZE
8
#define EVT_PIN_CODE_REQ 0x16
typedef
struct
{
...
...
@@ -658,9 +658,15 @@ struct sockaddr_hci {
#define HCI_DEV_NONE 0xffff
struct
hci_filter
{
__u32
type_mask
;
__u32
event_mask
[
2
];
__u16
opcode
;
unsigned
long
type_mask
;
unsigned
long
event_mask
[
2
];
__u16
opcode
;
};
struct
hci_ufilter
{
__u32
type_mask
;
__u32
event_mask
[
2
];
__u16
opcode
;
};
#define HCI_FLT_TYPE_BITS 31
...
...
@@ -668,20 +674,6 @@ struct hci_filter {
#define HCI_FLT_OGF_BITS 63
#define HCI_FLT_OCF_BITS 127
#if BITS_PER_LONG == 64
static
inline
void
hci_set_bit
(
int
nr
,
void
*
addr
)
{
*
((
__u32
*
)
addr
+
(
nr
>>
5
))
|=
((
__u32
)
1
<<
(
nr
&
31
));
}
static
inline
int
hci_test_bit
(
int
nr
,
void
*
addr
)
{
return
*
((
__u32
*
)
addr
+
(
nr
>>
5
))
&
((
__u32
)
1
<<
(
nr
&
31
));
}
#else
#define hci_set_bit set_bit
#define hci_test_bit test_bit
#endif
/* Ioctl requests structures */
struct
hci_dev_stats
{
__u32
err_rx
;
...
...
include/net/bluetooth/hci_core.h
View file @
e4c609fe
...
...
@@ -149,7 +149,7 @@ struct hci_conn {
extern
struct
hci_proto
*
hci_proto
[];
extern
struct
list_head
hdev_list
;
extern
spin
lock_t
hdev_list_lock
;
extern
rw
lock_t
hdev_list_lock
;
/* ----- Inquiry cache ----- */
#define INQUIRY_CACHE_AGE_MAX (HZ*30) // 30 seconds
...
...
@@ -339,8 +339,8 @@ static inline void hci_sched_tx(struct hci_dev *hdev)
/* ----- HCI protocols ----- */
struct
hci_proto
{
char
*
name
;
__u32
id
;
__u32
flags
;
unsigned
int
id
;
unsigned
long
flags
;
void
*
priv
;
...
...
@@ -450,12 +450,11 @@ struct hci_pinfo {
#define HCI_SFLT_MAX_OGF 4
struct
hci_sec_filter
{
__u32
type_mask
;
__u32
event_mask
[
2
];
__u32
ocf_mask
[
HCI_SFLT_MAX_OGF
+
1
][
4
];
unsigned
long
type_mask
;
unsigned
long
event_mask
[
2
];
unsigned
long
ocf_mask
[
HCI_SFLT_MAX_OGF
+
1
][
4
];
};
/* ----- HCI requests ----- */
#define HCI_REQ_DONE 0
#define HCI_REQ_PEND 1
...
...
net/bluetooth/af_bluetooth.c
View file @
e4c609fe
...
...
@@ -27,7 +27,7 @@
*
* $Id: af_bluetooth.c,v 1.3 2002/04/17 17:37:15 maxk Exp $
*/
#define VERSION "2.
0
"
#define VERSION "2.
2
"
#include <linux/config.h>
#include <linux/module.h>
...
...
@@ -57,7 +57,7 @@
#endif
/* Bluetooth sockets */
#define BLUEZ_MAX_PROTO
4
#define BLUEZ_MAX_PROTO
5
static
struct
net_proto_family
*
bluez_proto
[
BLUEZ_MAX_PROTO
];
static
kmem_cache_t
*
bluez_sock_cache
;
...
...
@@ -136,18 +136,18 @@ struct sock *bluez_sock_alloc(struct socket *sock, int proto, int pi_size, int p
void
bluez_sock_link
(
struct
bluez_sock_list
*
l
,
struct
sock
*
sk
)
{
write_lock
(
&
l
->
lock
);
write_lock
_bh
(
&
l
->
lock
);
sk
->
next
=
l
->
head
;
l
->
head
=
sk
;
sock_hold
(
sk
);
write_unlock
(
&
l
->
lock
);
write_unlock
_bh
(
&
l
->
lock
);
}
void
bluez_sock_unlink
(
struct
bluez_sock_list
*
l
,
struct
sock
*
sk
)
{
struct
sock
**
skp
;
write_lock
(
&
l
->
lock
);
write_lock
_bh
(
&
l
->
lock
);
for
(
skp
=
&
l
->
head
;
*
skp
;
skp
=
&
((
*
skp
)
->
next
))
{
if
(
*
skp
==
sk
)
{
*
skp
=
sk
->
next
;
...
...
@@ -155,7 +155,7 @@ void bluez_sock_unlink(struct bluez_sock_list *l, struct sock *sk)
break
;
}
}
write_unlock
(
&
l
->
lock
);
write_unlock
_bh
(
&
l
->
lock
);
}
void
bluez_accept_enqueue
(
struct
sock
*
parent
,
struct
sock
*
sk
)
...
...
@@ -265,6 +265,9 @@ unsigned int bluez_sock_poll(struct file * file, struct socket *sock, poll_table
if
(
sk
->
state
==
BT_CLOSED
)
mask
|=
POLLHUP
;
if
(
sk
->
state
==
BT_CONNECT
||
sk
->
state
==
BT_CONNECT2
)
return
mask
;
if
(
sock_writeable
(
sk
))
mask
|=
POLLOUT
|
POLLWRNORM
|
POLLWRBAND
;
else
...
...
net/bluetooth/hci_conn.c
View file @
e4c609fe
...
...
@@ -73,7 +73,7 @@ void hci_acl_connect(struct hci_conn *conn)
bacpy
(
&
cp
.
bdaddr
,
&
conn
->
dst
);
if
((
ie
=
inquiry_cache_lookup
(
hdev
,
&
conn
->
dst
))
&&
inquiry_entry_age
(
ie
)
>
INQUIRY_ENTRY_AGE_MAX
)
{
inquiry_entry_age
(
ie
)
<=
INQUIRY_ENTRY_AGE_MAX
)
{
cp
.
pscan_rep_mode
=
ie
->
info
.
pscan_rep_mode
;
cp
.
pscan_mode
=
ie
->
info
.
pscan_mode
;
cp
.
clock_offset
=
ie
->
info
.
clock_offset
|
__cpu_to_le16
(
0x8000
);
...
...
@@ -188,9 +188,6 @@ int hci_conn_del(struct hci_conn *conn)
acl
->
link
=
NULL
;
hci_conn_put
(
acl
);
}
/* Unacked frames */
hdev
->
sco_cnt
+=
conn
->
sent
;
}
else
{
struct
hci_conn
*
sco
=
conn
->
link
;
if
(
sco
)
...
...
@@ -220,7 +217,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
BT_DBG
(
"%s -> %s"
,
batostr
(
src
),
batostr
(
dst
));
spin
_lock_bh
(
&
hdev_list_lock
);
read
_lock_bh
(
&
hdev_list_lock
);
list_for_each
(
p
,
&
hdev_list
)
{
struct
hci_dev
*
d
;
...
...
@@ -248,7 +245,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
if
(
hdev
)
hci_dev_hold
(
hdev
);
spin
_unlock_bh
(
&
hdev_list_lock
);
read
_unlock_bh
(
&
hdev_list_lock
);
return
hdev
;
}
...
...
net/bluetooth/hci_core.c
View file @
e4c609fe
...
...
@@ -30,6 +30,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kmod.h>
#include <linux/types.h>
#include <linux/errno.h>
...
...
@@ -66,7 +67,7 @@ rwlock_t hci_task_lock = RW_LOCK_UNLOCKED;
/* HCI device list */
LIST_HEAD
(
hdev_list
);
spinlock_t
hdev_list_lock
;
rwlock_t
hdev_list_lock
=
RW_LOCK_UNLOCKED
;
/* HCI protocols */
#define HCI_MAX_PROTO 2
...
...
@@ -75,7 +76,6 @@ struct hci_proto *hci_proto[HCI_MAX_PROTO];
/* HCI notifiers list */
static
struct
notifier_block
*
hci_notifier
;
/* ---- HCI notifications ---- */
int
hci_register_notifier
(
struct
notifier_block
*
nb
)
...
...
@@ -93,6 +93,32 @@ void hci_notify(struct hci_dev *hdev, int event)
notifier_call_chain
(
&
hci_notifier
,
event
,
hdev
);
}
/* ---- HCI hotplug support ---- */
#ifdef CONFIG_HOTPLUG
static
int
hci_run_hotplug
(
char
*
dev
,
char
*
action
)
{
char
*
argv
[
3
],
*
envp
[
5
],
dstr
[
20
],
astr
[
32
];
sprintf
(
dstr
,
"DEVICE=%s"
,
dev
);
sprintf
(
astr
,
"ACTION=%s"
,
action
);
argv
[
0
]
=
hotplug_path
;
argv
[
1
]
=
"bluetooth"
;
argv
[
2
]
=
NULL
;
envp
[
0
]
=
"HOME=/"
;
envp
[
1
]
=
"PATH=/sbin:/bin:/usr/sbin:/usr/bin"
;
envp
[
2
]
=
dstr
;
envp
[
3
]
=
astr
;
envp
[
4
]
=
NULL
;
return
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
}
#else
#define hci_run_hotplug(A...)
#endif
/* ---- HCI requests ---- */
...
...
@@ -270,7 +296,7 @@ struct hci_dev *hci_dev_get(int index)
if
(
index
<
0
)
return
NULL
;
spin
_lock
(
&
hdev_list_lock
);
read
_lock
(
&
hdev_list_lock
);
list_for_each
(
p
,
&
hdev_list
)
{
hdev
=
list_entry
(
p
,
struct
hci_dev
,
list
);
if
(
hdev
->
id
==
index
)
{
...
...
@@ -280,7 +306,7 @@ struct hci_dev *hci_dev_get(int index)
}
hdev
=
NULL
;
done:
spin
_unlock
(
&
hdev_list_lock
);
read
_unlock
(
&
hdev_list_lock
);
return
hdev
;
}
...
...
@@ -699,7 +725,7 @@ int hci_get_dev_list(unsigned long arg)
return
-
ENOMEM
;
dr
=
dl
->
dev_req
;
spin
_lock_bh
(
&
hdev_list_lock
);
read
_lock_bh
(
&
hdev_list_lock
);
list_for_each
(
p
,
&
hdev_list
)
{
struct
hci_dev
*
hdev
;
hdev
=
list_entry
(
p
,
struct
hci_dev
,
list
);
...
...
@@ -708,7 +734,7 @@ int hci_get_dev_list(unsigned long arg)
if
(
++
n
>=
dev_num
)
break
;
}
spin
_unlock_bh
(
&
hdev_list_lock
);
read
_unlock_bh
(
&
hdev_list_lock
);
dl
->
dev_num
=
n
;
size
=
n
*
sizeof
(
struct
hci_dev_req
)
+
sizeof
(
__u16
);
...
...
@@ -768,7 +794,7 @@ int hci_register_dev(struct hci_dev *hdev)
if
(
!
hdev
->
open
||
!
hdev
->
close
||
!
hdev
->
destruct
)
return
-
EINVAL
;
spin
_lock_bh
(
&
hdev_list_lock
);
write
_lock_bh
(
&
hdev_list_lock
);
/* Find first available device id */
list_for_each
(
p
,
&
hdev_list
)
{
...
...
@@ -807,11 +833,12 @@ int hci_register_dev(struct hci_dev *hdev)
atomic_set
(
&
hdev
->
promisc
,
0
);
hci_notify
(
hdev
,
HCI_DEV_REG
);
MOD_INC_USE_COUNT
;
spin_unlock_bh
(
&
hdev_list_lock
);
write_unlock_bh
(
&
hdev_list_lock
);
hci_notify
(
hdev
,
HCI_DEV_REG
);
hci_run_hotplug
(
hdev
->
name
,
"register"
);
return
id
;
}
...
...
@@ -821,13 +848,15 @@ int hci_unregister_dev(struct hci_dev *hdev)
{
BT_DBG
(
"%p name %s type %d"
,
hdev
,
hdev
->
name
,
hdev
->
type
);
spin
_lock_bh
(
&
hdev_list_lock
);
write
_lock_bh
(
&
hdev_list_lock
);
list_del
(
&
hdev
->
list
);
spin
_unlock_bh
(
&
hdev_list_lock
);
write
_unlock_bh
(
&
hdev_list_lock
);
hci_dev_do_close
(
hdev
);
hci_notify
(
hdev
,
HCI_DEV_UNREG
);
hci_run_hotplug
(
hdev
->
name
,
"unregister"
);
hci_dev_put
(
hdev
);
MOD_DEC_USE_COUNT
;
...
...
@@ -1103,14 +1132,13 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
{
struct
conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
hci_conn
*
conn
=
NULL
;
int
num
=
0
,
min
=
0xffff
;
int
num
=
0
,
min
=
~
0
;
struct
list_head
*
p
;
/* We don't have to lock device here. Connections are always
* added and removed with TX task disabled. */
list_for_each
(
p
,
&
h
->
list
)
{
struct
hci_conn
*
c
;
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
!=
type
||
c
->
state
!=
BT_CONNECTED
...
...
@@ -1118,14 +1146,15 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
continue
;
num
++
;
if
(
c
->
sent
<
min
||
type
==
SCO_LINK
)
{
if
(
c
->
sent
<
min
)
{
min
=
c
->
sent
;
conn
=
c
;
}
}
if
(
conn
)
{
int
q
=
hdev
->
acl_cnt
/
num
;
int
cnt
=
(
type
==
ACL_LINK
?
hdev
->
acl_cnt
:
hdev
->
sco_cnt
);
int
q
=
cnt
/
num
;
*
quote
=
q
?
q
:
1
;
}
else
*
quote
=
0
;
...
...
@@ -1134,6 +1163,25 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
return
conn
;
}
static
inline
void
hci_acl_tx_to
(
struct
hci_dev
*
hdev
)
{
struct
conn_hash
*
h
=
&
hdev
->
conn_hash
;
struct
list_head
*
p
;
struct
hci_conn
*
c
;
BT_ERR
(
"%s ACL tx timeout"
,
hdev
->
name
);
/* Kill stalled connections */
list_for_each
(
p
,
&
h
->
list
)
{
c
=
list_entry
(
p
,
struct
hci_conn
,
list
);
if
(
c
->
type
==
ACL_LINK
&&
c
->
sent
)
{
BT_ERR
(
"%s killing stalled ACL connection %s"
,
hdev
->
name
,
batostr
(
&
c
->
dst
));
hci_acl_disconn
(
c
,
0x13
);
}
}
}
static
inline
void
hci_sched_acl
(
struct
hci_dev
*
hdev
)
{
struct
hci_conn
*
conn
;
...
...
@@ -1142,21 +1190,19 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
if
(
!
hdev
->
acl_cnt
&&
(
jiffies
-
hdev
->
acl_last_tx
)
>
HZ
*
5
)
{
BT_ERR
(
"%s ACL tx timeout"
,
hdev
->
name
);
hdev
->
acl_cnt
++
;
}
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if
(
!
hdev
->
acl_cnt
&&
(
jiffies
-
hdev
->
acl_last_tx
)
>
(
HZ
*
45
))
hci_acl_tx_to
(
hdev
);
while
(
hdev
->
acl_cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
ACL_LINK
,
&
quote
)))
{
while
(
quote
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
while
(
quote
--
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
BT_DBG
(
"skb %p len %d"
,
skb
,
skb
->
len
);
hci_send_frame
(
skb
);
hdev
->
acl_last_tx
=
jiffies
;
conn
->
sent
++
;
hdev
->
acl_cnt
--
;
quote
--
;
conn
->
sent
++
;
}
}
}
...
...
@@ -1170,15 +1216,14 @@ static inline void hci_sched_sco(struct hci_dev *hdev)
BT_DBG
(
"%s"
,
hdev
->
name
);
while
((
conn
=
hci_low_sent
(
hdev
,
SCO_LINK
,
&
quote
)))
{
while
(
quote
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
while
(
hdev
->
sco_cnt
&&
(
conn
=
hci_low_sent
(
hdev
,
SCO_LINK
,
&
quote
)))
{
while
(
quote
--
&&
(
skb
=
skb_dequeue
(
&
conn
->
data_q
)))
{
BT_DBG
(
"skb %p len %d"
,
skb
,
skb
->
len
);
hci_send_frame
(
skb
);
//
conn->sent++;
//hdev->sco_cnt--;
quote
--
;
conn
->
sent
++
;
if
(
conn
->
sent
==
~
0
)
conn
->
sent
=
0
;
}
}
}
...
...
@@ -1205,7 +1250,6 @@ static void hci_tx_task(unsigned long arg)
read_unlock
(
&
hci_task_lock
);
}
/* ----- HCI RX task (incomming data proccessing) ----- */
/* ACL data packet */
...
...
@@ -1367,9 +1411,6 @@ static void hci_cmd_task(unsigned long arg)
int
hci_core_init
(
void
)
{
/* Init locks */
spin_lock_init
(
&
hdev_list_lock
);
return
0
;
}
...
...
net/bluetooth/hci_event.c
View file @
e4c609fe
...
...
@@ -352,15 +352,12 @@ static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
hci_dev_lock
(
hdev
);
acl
=
conn_hash_lookup_handle
(
hdev
,
handle
);
if
(
!
acl
||
!
(
sco
=
acl
->
link
))
{
hci_dev_unlock
(
hdev
);
break
;
}
if
(
acl
&&
(
sco
=
acl
->
link
))
{
sco
->
state
=
BT_CLOSED
;
sco
->
state
=
BT_CLOSED
;
hci_proto_connect_cfm
(
sco
,
status
);
hci_conn_del
(
sco
);
hci_proto_connect_cfm
(
sco
,
status
);
hci_conn_del
(
sco
);
}
hci_dev_unlock
(
hdev
);
}
...
...
net/bluetooth/hci_sock.c
View file @
e4c609fe
...
...
@@ -86,7 +86,7 @@ static struct bluez_sock_list hci_sk_list = {
/* Send frame to RAW socket */
void
hci_send_to_sock
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
{
struct
sock
*
sk
;
struct
sock
*
sk
;
BT_DBG
(
"hdev %p len %d"
,
hdev
,
skb
->
len
);
...
...
@@ -105,13 +105,13 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
/* Apply filter */
flt
=
&
hci_pi
(
sk
)
->
filter
;
if
(
!
hci_
test_bit
((
skb
->
pkt_type
&
HCI_FLT_TYPE_BITS
),
&
flt
->
type_mask
))
if
(
!
test_bit
((
skb
->
pkt_type
&
HCI_FLT_TYPE_BITS
),
&
flt
->
type_mask
))
continue
;
if
(
skb
->
pkt_type
==
HCI_EVENT_PKT
)
{
register
int
evt
=
(
*
(
__u8
*
)
skb
->
data
&
HCI_FLT_EVENT_BITS
);
if
(
!
hci_test_bit
(
evt
,
&
flt
->
event_mask
))
if
(
!
test_bit
(
evt
,
flt
->
event_mask
))
continue
;
if
(
flt
->
opcode
&&
((
evt
==
EVT_CMD_COMPLETE
&&
...
...
@@ -249,7 +249,7 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long a
err
=
hci_sock_bound_ioctl
(
sk
,
cmd
,
arg
);
release_sock
(
sk
);
return
err
;
}
;
}
}
static
int
hci_sock_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
addr
,
int
addr_len
)
...
...
@@ -393,12 +393,12 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len,
err
=
-
EPERM
;
if
(
skb
->
pkt_type
==
HCI_COMMAND_PKT
)
{
__
u16
opcode
=
__le16_to_cpu
(
*
(
__u16
*
)
skb
->
data
);
__
u16
ogf
=
cmd_opcode_ogf
(
opcode
)
-
1
;
__
u16
ocf
=
cmd_opcode_ocf
(
opcode
)
&
HCI_FLT_OCF_BITS
;
u16
opcode
=
__le16_to_cpu
(
*
(
__u16
*
)
skb
->
data
);
u16
ogf
=
cmd_opcode_ogf
(
opcode
)
-
1
;
u16
ocf
=
cmd_opcode_ocf
(
opcode
)
&
HCI_FLT_OCF_BITS
;
if
(
ogf
>
HCI_SFLT_MAX_OGF
||
!
hci_test_bit
(
ocf
,
&
hci_sec_filter
.
ocf_mask
[
ogf
]))
!
test_bit
(
ocf
,
hci_sec_filter
.
ocf_mask
[
ogf
]))
goto
drop
;
}
else
goto
drop
;
...
...
@@ -420,8 +420,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len,
int
hci_sock_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
len
)
{
struct
hci_ufilter
uf
=
{
.
opcode
=
0
};
struct
sock
*
sk
=
sock
->
sk
;
struct
hci_filter
flt
=
{
opcode
:
0
};
int
err
=
0
,
opt
=
0
;
BT_DBG
(
"sk %p, opt %d"
,
sk
,
optname
);
...
...
@@ -454,32 +454,40 @@ int hci_sock_setsockopt(struct socket *sock, int level, int optname, char *optva
break
;
case
HCI_FILTER
:
len
=
MIN
(
len
,
sizeof
(
struct
hci_filter
));
if
(
copy_from_user
(
&
flt
,
optval
,
len
))
{
len
=
MIN
(
len
,
sizeof
(
uf
));
if
(
copy_from_user
(
&
uf
,
optval
,
len
))
{
err
=
-
EFAULT
;
break
;
}
if
(
!
capable
(
CAP_NET_RAW
))
{
flt
.
type_mask
&=
hci_sec_filter
.
type_mask
;
flt
.
event_mask
[
0
]
&=
hci_sec_filter
.
event_mask
[
0
]
;
flt
.
event_mask
[
1
]
&=
hci_sec_filter
.
event_mask
[
1
]
;
uf
.
type_mask
&=
hci_sec_filter
.
type_mask
;
uf
.
event_mask
[
0
]
&=
*
((
u32
*
)
hci_sec_filter
.
event_mask
+
0
)
;
uf
.
event_mask
[
1
]
&=
*
((
u32
*
)
hci_sec_filter
.
event_mask
+
1
)
;
}
{
struct
hci_filter
*
f
=
&
hci_pi
(
sk
)
->
filter
;
memcpy
(
&
hci_pi
(
sk
)
->
filter
,
&
flt
,
len
);
break
;
f
->
type_mask
=
uf
.
type_mask
;
f
->
opcode
=
uf
.
opcode
;
*
((
u32
*
)
f
->
event_mask
+
0
)
=
uf
.
event_mask
[
0
];
*
((
u32
*
)
f
->
event_mask
+
1
)
=
uf
.
event_mask
[
0
];
}
break
;
default:
err
=
-
ENOPROTOOPT
;
break
;
}
;
}
release_sock
(
sk
);
return
err
;
}
int
hci_sock_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
struct
hci_ufilter
uf
;
struct
sock
*
sk
=
sock
->
sk
;
int
len
,
opt
;
...
...
@@ -508,15 +516,24 @@ int hci_sock_getsockopt(struct socket *sock, int level, int optname, char *optva
break
;
case
HCI_FILTER
:
len
=
MIN
(
len
,
sizeof
(
struct
hci_filter
));
if
(
copy_to_user
(
optval
,
&
hci_pi
(
sk
)
->
filter
,
len
))
{
struct
hci_filter
*
f
=
&
hci_pi
(
sk
)
->
filter
;
uf
.
type_mask
=
f
->
type_mask
;
uf
.
opcode
=
f
->
opcode
;
uf
.
event_mask
[
0
]
=
*
((
u32
*
)
f
->
event_mask
+
0
);
uf
.
event_mask
[
0
]
=
*
((
u32
*
)
f
->
event_mask
+
1
);
}
len
=
MIN
(
len
,
sizeof
(
uf
));
if
(
copy_to_user
(
optval
,
&
uf
,
len
))
return
-
EFAULT
;
break
;
default:
return
-
ENOPROTOOPT
;
break
;
}
;
}
return
0
;
}
...
...
net/bluetooth/l2cap.c
View file @
e4c609fe
This diff is collapsed.
Click to expand it.
net/bluetooth/lib.c
View file @
e4c609fe
...
...
@@ -105,7 +105,7 @@ int bterr(__u16 code)
return
EACCES
;
case
0x06
:
return
E
INVAL
;
return
E
BADE
;
case
0x07
:
return
ENOMEM
;
...
...
net/bluetooth/sco.c
View file @
e4c609fe
...
...
@@ -27,7 +27,7 @@
*
* $Id: sco.c,v 1.3 2002/04/17 17:37:16 maxk Exp $
*/
#define VERSION "0.
2
"
#define VERSION "0.
3
"
#include <linux/config.h>
#include <linux/module.h>
...
...
@@ -67,16 +67,15 @@ static struct bluez_sock_list sco_sk_list = {
.
lock
=
RW_LOCK_UNLOCKED
};
static
inline
int
sco_chan_add
(
struct
sco_conn
*
conn
,
struct
sock
*
sk
,
struct
sock
*
parent
);
static
void
__
sco_chan_add
(
struct
sco_conn
*
conn
,
struct
sock
*
sk
,
struct
sock
*
parent
);
static
void
sco_chan_del
(
struct
sock
*
sk
,
int
err
);
static
inline
struct
sock
*
sco_chan_get
(
struct
sco_conn
*
conn
);
static
int
sco_conn_del
(
struct
hci_conn
*
conn
,
int
err
);
static
void
sco_sock_close
(
struct
sock
*
sk
);
static
void
sco_sock_kill
(
struct
sock
*
sk
);
/* ----
- SCO timers --
---- */
/* ----
SCO timers
---- */
static
void
sco_sock_timeout
(
unsigned
long
arg
)
{
struct
sock
*
sk
=
(
struct
sock
*
)
arg
;
...
...
@@ -115,7 +114,7 @@ static void sco_sock_init_timer(struct sock *sk)
sk
->
timer
.
data
=
(
unsigned
long
)
sk
;
}
/* ----
---- SCO connections -----
---- */
/* ----
SCO connections
---- */
static
struct
sco_conn
*
sco_conn_add
(
struct
hci_conn
*
hcon
,
__u8
status
)
{
struct
hci_dev
*
hdev
=
hcon
->
hdev
;
...
...
@@ -150,6 +149,15 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status)
return
conn
;
}
static
inline
struct
sock
*
sco_chan_get
(
struct
sco_conn
*
conn
)
{
struct
sock
*
sk
=
NULL
;
sco_conn_lock
(
conn
);
sk
=
conn
->
sk
;
sco_conn_unlock
(
conn
);
return
sk
;
}
static
int
sco_conn_del
(
struct
hci_conn
*
hcon
,
int
err
)
{
struct
sco_conn
*
conn
;
...
...
@@ -176,6 +184,20 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
return
0
;
}
static
inline
int
sco_chan_add
(
struct
sco_conn
*
conn
,
struct
sock
*
sk
,
struct
sock
*
parent
)
{
int
err
=
0
;
sco_conn_lock
(
conn
);
if
(
conn
->
sk
)
{
err
=
-
EBUSY
;
}
else
{
__sco_chan_add
(
conn
,
sk
,
parent
);
}
sco_conn_unlock
(
conn
);
return
err
;
}
int
sco_connect
(
struct
sock
*
sk
)
{
bdaddr_t
*
src
=
&
bluez_sk
(
sk
)
->
src
;
...
...
@@ -462,23 +484,20 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
goto
done
;
}
write_lock
(
&
sco_sk_list
.
lock
);
write_lock
_bh
(
&
sco_sk_list
.
lock
);
if
(
bacmp
(
src
,
BDADDR_ANY
)
&&
__sco_get_sock_by_addr
(
src
))
{
err
=
-
EADDRINUSE
;
goto
unlock
;
}
else
{
/* Save source address */
bacpy
(
&
bluez_sk
(
sk
)
->
src
,
&
sa
->
sco_bdaddr
);
sk
->
state
=
BT_BOUND
;
}
/* Save source address */
bacpy
(
&
bluez_sk
(
sk
)
->
src
,
&
sa
->
sco_bdaddr
);
sk
->
state
=
BT_BOUND
;
unlock:
write_unlock
(
&
sco_sk_list
.
lock
);
write_unlock_bh
(
&
sco_sk_list
.
lock
);
done:
release_sock
(
sk
);
return
err
;
}
...
...
@@ -649,7 +668,7 @@ int sco_sock_setsockopt(struct socket *sock, int level, int optname, char *optva
default:
err
=
-
ENOPROTOOPT
;
break
;
}
;
}
release_sock
(
sk
);
return
err
;
...
...
@@ -703,7 +722,7 @@ int sco_sock_getsockopt(struct socket *sock, int level, int optname, char *optva
default:
err
=
-
ENOPROTOOPT
;
break
;
}
;
}
release_sock
(
sk
);
return
err
;
...
...
@@ -735,29 +754,6 @@ static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *
bluez_accept_enqueue
(
parent
,
sk
);
}
static
inline
int
sco_chan_add
(
struct
sco_conn
*
conn
,
struct
sock
*
sk
,
struct
sock
*
parent
)
{
int
err
=
0
;
sco_conn_lock
(
conn
);
if
(
conn
->
sk
)
{
err
=
-
EBUSY
;
}
else
{
__sco_chan_add
(
conn
,
sk
,
parent
);
}
sco_conn_unlock
(
conn
);
return
err
;
}
static
inline
struct
sock
*
sco_chan_get
(
struct
sco_conn
*
conn
)
{
struct
sock
*
sk
=
NULL
;
sco_conn_lock
(
conn
);
sk
=
conn
->
sk
;
sco_conn_unlock
(
conn
);
return
sk
;
}
/* Delete channel.
* Must be called on the locked socket. */
static
void
sco_chan_del
(
struct
sock
*
sk
,
int
err
)
...
...
@@ -895,7 +891,7 @@ static int sco_sock_dump(char *buf, struct bluez_sock_list *list)
struct
sock
*
sk
;
char
*
ptr
=
buf
;
write_lock
(
&
list
->
lock
);
read_lock_bh
(
&
list
->
lock
);
for
(
sk
=
list
->
head
;
sk
;
sk
=
sk
->
next
)
{
pi
=
sco_pi
(
sk
);
...
...
@@ -904,7 +900,7 @@ static int sco_sock_dump(char *buf, struct bluez_sock_list *list)
sk
->
state
);
}
write_unlock
(
&
list
->
lock
);
read_unlock_bh
(
&
list
->
lock
);
ptr
+=
sprintf
(
ptr
,
"
\n
"
);
...
...
@@ -936,36 +932,36 @@ static int sco_read_proc(char *buf, char **start, off_t offset, int count, int *
}
static
struct
proto_ops
sco_sock_ops
=
{
.
family
=
PF_BLUETOOTH
,
.
release
=
sco_sock_release
,
.
bind
=
sco_sock_bind
,
.
connect
=
sco_sock_connect
,
.
listen
=
sco_sock_listen
,
.
accept
=
sco_sock_accept
,
.
getname
=
sco_sock_getname
,
.
sendmsg
=
sco_sock_sendmsg
,
.
recvmsg
=
bluez_sock_recvmsg
,
.
poll
=
bluez_sock_poll
,
.
socketpair
=
sock_no_socketpair
,
.
ioctl
=
sock_no_ioctl
,
.
s
hutdown
=
sock_no_shutdown
,
.
s
etsockopt
=
sco_sock_setsockopt
,
.
getsockopt
=
sco_sock_g
etsockopt
,
.
mmap
=
sock_no_mmap
.
family
=
PF_BLUETOOTH
,
.
release
=
sco_sock_release
,
.
bind
=
sco_sock_bind
,
.
connect
=
sco_sock_connect
,
.
listen
=
sco_sock_listen
,
.
accept
=
sco_sock_accept
,
.
getname
=
sco_sock_getname
,
.
sendmsg
=
sco_sock_sendmsg
,
.
recvmsg
=
bluez_sock_recvmsg
,
.
poll
=
bluez_sock_poll
,
.
ioctl
=
sock_no_ioctl
,
.
mmap
=
sock_no_mmap
,
.
s
ocketpair
=
sock_no_socketpair
,
.
s
hutdown
=
sock_no_shutdown
,
.
setsockopt
=
sco_sock_s
etsockopt
,
.
getsockopt
=
sco_sock_getsockopt
};
static
struct
net_proto_family
sco_sock_family_ops
=
{
.
family
=
PF_BLUETOOTH
,
.
create
=
sco_sock_create
.
family
=
PF_BLUETOOTH
,
.
create
=
sco_sock_create
};
static
struct
hci_proto
sco_hci_proto
=
{
.
name
=
"SCO"
,
.
id
=
HCI_PROTO_SCO
,
.
connect_ind
=
sco_connect_ind
,
.
connect_cfm
=
sco_connect_cfm
,
.
disconn_ind
=
sco_disconn_ind
,
.
recv_scodata
=
sco_recv_scodata
,
.
name
=
"SCO"
,
.
id
=
HCI_PROTO_SCO
,
.
connect_ind
=
sco_connect_ind
,
.
connect_cfm
=
sco_connect_cfm
,
.
disconn_ind
=
sco_disconn_ind
,
.
recv_scodata
=
sco_recv_scodata
};
int
__init
sco_init
(
void
)
...
...
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