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
Kirill Smelkov
linux
Commits
d6222fb0
Commit
d6222fb0
authored
Oct 04, 2011
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://github.com/padovan/bluetooth-next
parents
76ed94be
c510eae3
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
157 additions
and
196 deletions
+157
-196
drivers/bluetooth/btusb.c
drivers/bluetooth/btusb.c
+4
-2
include/net/bluetooth/l2cap.h
include/net/bluetooth/l2cap.h
+1
-2
net/bluetooth/af_bluetooth.c
net/bluetooth/af_bluetooth.c
+28
-2
net/bluetooth/bnep/core.c
net/bluetooth/bnep/core.c
+4
-1
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/core.c
+4
-1
net/bluetooth/hci_conn.c
net/bluetooth/hci_conn.c
+7
-7
net/bluetooth/hci_event.c
net/bluetooth/hci_event.c
+11
-9
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+8
-2
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_core.c
+86
-169
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/core.c
+4
-1
No files found.
drivers/bluetooth/btusb.c
View file @
d6222fb0
...
@@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = {
...
@@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
/* Generic Bluetooth USB device */
{
USB_DEVICE_INFO
(
0xe0
,
0x01
,
0x01
)
},
{
USB_DEVICE_INFO
(
0xe0
,
0x01
,
0x01
)
},
/* Broadcom SoftSailing reporting vendor specific */
{
USB_DEVICE
(
0x05ac
,
0x21e1
)
},
/* Apple MacBookPro 7,1 */
/* Apple MacBookPro 7,1 */
{
USB_DEVICE
(
0x05ac
,
0x8213
)
},
{
USB_DEVICE
(
0x05ac
,
0x8213
)
},
...
@@ -708,8 +711,7 @@ static int btusb_send_frame(struct sk_buff *skb)
...
@@ -708,8 +711,7 @@ static int btusb_send_frame(struct sk_buff *skb)
break
;
break
;
case
HCI_ACLDATA_PKT
:
case
HCI_ACLDATA_PKT
:
if
(
!
data
->
bulk_tx_ep
||
(
hdev
->
conn_hash
.
acl_num
<
1
&&
if
(
!
data
->
bulk_tx_ep
)
hdev
->
conn_hash
.
le_num
<
1
))
return
-
ENODEV
;
return
-
ENODEV
;
urb
=
usb_alloc_urb
(
0
,
GFP_ATOMIC
);
urb
=
usb_alloc_urb
(
0
,
GFP_ATOMIC
);
...
...
include/net/bluetooth/l2cap.h
View file @
d6222fb0
...
@@ -354,8 +354,8 @@ struct l2cap_chan {
...
@@ -354,8 +354,8 @@ struct l2cap_chan {
__u8
retry_count
;
__u8
retry_count
;
__u8
num_acked
;
__u8
num_acked
;
__u16
sdu_len
;
__u16
sdu_len
;
__u16
partial_sdu_len
;
struct
sk_buff
*
sdu
;
struct
sk_buff
*
sdu
;
struct
sk_buff
*
sdu_last_frag
;
__u8
remote_tx_win
;
__u8
remote_tx_win
;
__u8
remote_max_tx
;
__u8
remote_max_tx
;
...
@@ -448,7 +448,6 @@ enum {
...
@@ -448,7 +448,6 @@ enum {
#define L2CAP_CONF_MAX_CONF_RSP 2
#define L2CAP_CONF_MAX_CONF_RSP 2
enum
{
enum
{
CONN_SAR_SDU
,
CONN_SREJ_SENT
,
CONN_SREJ_SENT
,
CONN_WAIT_F
,
CONN_WAIT_F
,
CONN_SREJ_ACT
,
CONN_SREJ_ACT
,
...
...
net/bluetooth/af_bluetooth.c
View file @
d6222fb0
...
@@ -349,7 +349,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
...
@@ -349,7 +349,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
}
}
chunk
=
min_t
(
unsigned
int
,
skb
->
len
,
size
);
chunk
=
min_t
(
unsigned
int
,
skb
->
len
,
size
);
if
(
memcpy_toiovec
(
msg
->
msg_iov
,
skb
->
data
,
chunk
))
{
if
(
skb_copy_datagram_iovec
(
skb
,
0
,
msg
->
msg_iov
,
chunk
))
{
skb_queue_head
(
&
sk
->
sk_receive_queue
,
skb
);
skb_queue_head
(
&
sk
->
sk_receive_queue
,
skb
);
if
(
!
copied
)
if
(
!
copied
)
copied
=
-
EFAULT
;
copied
=
-
EFAULT
;
...
@@ -361,7 +361,33 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
...
@@ -361,7 +361,33 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
sock_recv_ts_and_drops
(
msg
,
sk
,
skb
);
sock_recv_ts_and_drops
(
msg
,
sk
,
skb
);
if
(
!
(
flags
&
MSG_PEEK
))
{
if
(
!
(
flags
&
MSG_PEEK
))
{
skb_pull
(
skb
,
chunk
);
int
skb_len
=
skb_headlen
(
skb
);
if
(
chunk
<=
skb_len
)
{
__skb_pull
(
skb
,
chunk
);
}
else
{
struct
sk_buff
*
frag
;
__skb_pull
(
skb
,
skb_len
);
chunk
-=
skb_len
;
skb_walk_frags
(
skb
,
frag
)
{
if
(
chunk
<=
frag
->
len
)
{
/* Pulling partial data */
skb
->
len
-=
chunk
;
skb
->
data_len
-=
chunk
;
__skb_pull
(
frag
,
chunk
);
break
;
}
else
if
(
frag
->
len
)
{
/* Pulling all frag data */
chunk
-=
frag
->
len
;
skb
->
len
-=
frag
->
len
;
skb
->
data_len
-=
frag
->
len
;
__skb_pull
(
frag
,
frag
->
len
);
}
}
}
if
(
skb
->
len
)
{
if
(
skb
->
len
)
{
skb_queue_head
(
&
sk
->
sk_receive_queue
,
skb
);
skb_queue_head
(
&
sk
->
sk_receive_queue
,
skb
);
break
;
break
;
...
...
net/bluetooth/bnep/core.c
View file @
d6222fb0
...
@@ -492,7 +492,10 @@ static int bnep_session(void *arg)
...
@@ -492,7 +492,10 @@ static int bnep_session(void *arg)
/* RX */
/* RX */
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
skb_orphan
(
skb
);
if
(
!
skb_linearize
(
skb
))
bnep_rx_frame
(
s
,
skb
);
bnep_rx_frame
(
s
,
skb
);
else
kfree_skb
(
skb
);
}
}
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
...
...
net/bluetooth/cmtp/core.c
View file @
d6222fb0
...
@@ -302,7 +302,10 @@ static int cmtp_session(void *arg)
...
@@ -302,7 +302,10 @@ static int cmtp_session(void *arg)
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
skb_orphan
(
skb
);
if
(
!
skb_linearize
(
skb
))
cmtp_recv_frame
(
session
,
skb
);
cmtp_recv_frame
(
session
,
skb
);
else
kfree_skb
(
skb
);
}
}
cmtp_process_transmit
(
session
);
cmtp_process_transmit
(
session
);
...
...
net/bluetooth/hci_conn.c
View file @
d6222fb0
...
@@ -56,15 +56,15 @@ static void hci_le_connect(struct hci_conn *conn)
...
@@ -56,15 +56,15 @@ static void hci_le_connect(struct hci_conn *conn)
conn
->
sec_level
=
BT_SECURITY_LOW
;
conn
->
sec_level
=
BT_SECURITY_LOW
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
memset
(
&
cp
,
0
,
sizeof
(
cp
));
cp
.
scan_interval
=
cpu_to_le16
(
0x00
04
);
cp
.
scan_interval
=
cpu_to_le16
(
0x00
60
);
cp
.
scan_window
=
cpu_to_le16
(
0x00
04
);
cp
.
scan_window
=
cpu_to_le16
(
0x00
30
);
bacpy
(
&
cp
.
peer_addr
,
&
conn
->
dst
);
bacpy
(
&
cp
.
peer_addr
,
&
conn
->
dst
);
cp
.
peer_addr_type
=
conn
->
dst_type
;
cp
.
peer_addr_type
=
conn
->
dst_type
;
cp
.
conn_interval_min
=
cpu_to_le16
(
0x00
0
8
);
cp
.
conn_interval_min
=
cpu_to_le16
(
0x00
2
8
);
cp
.
conn_interval_max
=
cpu_to_le16
(
0x0
100
);
cp
.
conn_interval_max
=
cpu_to_le16
(
0x0
038
);
cp
.
supervision_timeout
=
cpu_to_le16
(
0x00
64
);
cp
.
supervision_timeout
=
cpu_to_le16
(
0x00
2a
);
cp
.
min_ce_len
=
cpu_to_le16
(
0x000
1
);
cp
.
min_ce_len
=
cpu_to_le16
(
0x000
0
);
cp
.
max_ce_len
=
cpu_to_le16
(
0x000
1
);
cp
.
max_ce_len
=
cpu_to_le16
(
0x000
0
);
hci_send_cmd
(
hdev
,
HCI_OP_LE_CREATE_CONN
,
sizeof
(
cp
),
&
cp
);
hci_send_cmd
(
hdev
,
HCI_OP_LE_CREATE_CONN
,
sizeof
(
cp
),
&
cp
);
}
}
...
...
net/bluetooth/hci_event.c
View file @
d6222fb0
...
@@ -2174,7 +2174,10 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2174,7 +2174,10 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
conn
=
hci_conn_hash_lookup_ba
(
hdev
,
ACL_LINK
,
&
ev
->
bdaddr
);
if
(
conn
&&
conn
->
state
==
BT_CONNECTED
)
{
if
(
!
conn
)
goto
unlock
;
if
(
conn
->
state
==
BT_CONNECTED
)
{
hci_conn_hold
(
conn
);
hci_conn_hold
(
conn
);
conn
->
disc_timeout
=
HCI_PAIRING_TIMEOUT
;
conn
->
disc_timeout
=
HCI_PAIRING_TIMEOUT
;
hci_conn_put
(
conn
);
hci_conn_put
(
conn
);
...
@@ -2194,6 +2197,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2194,6 +2197,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
mgmt_pin_code_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
secure
);
mgmt_pin_code_request
(
hdev
->
id
,
&
ev
->
bdaddr
,
secure
);
}
}
unlock:
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
}
}
...
@@ -2834,19 +2838,17 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
...
@@ -2834,19 +2838,17 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
static
inline
void
hci_le_adv_report_evt
(
struct
hci_dev
*
hdev
,
static
inline
void
hci_le_adv_report_evt
(
struct
hci_dev
*
hdev
,
struct
sk_buff
*
skb
)
struct
sk_buff
*
skb
)
{
{
struct
hci_ev_le_advertising_info
*
ev
;
u8
num_reports
=
skb
->
data
[
0
];
u8
num_reports
;
void
*
ptr
=
&
skb
->
data
[
1
];
num_reports
=
skb
->
data
[
0
];
ev
=
(
void
*
)
&
skb
->
data
[
1
];
hci_dev_lock
(
hdev
);
hci_dev_lock
(
hdev
);
hci_add_adv_entry
(
hdev
,
ev
);
while
(
num_reports
--
)
{
struct
hci_ev_le_advertising_info
*
ev
=
ptr
;
while
(
--
num_reports
)
{
ev
=
(
void
*
)
(
ev
->
data
+
ev
->
length
+
1
);
hci_add_adv_entry
(
hdev
,
ev
);
hci_add_adv_entry
(
hdev
,
ev
);
ptr
+=
sizeof
(
*
ev
)
+
ev
->
length
+
1
;
}
}
hci_dev_unlock
(
hdev
);
hci_dev_unlock
(
hdev
);
...
...
net/bluetooth/hidp/core.c
View file @
d6222fb0
...
@@ -716,12 +716,18 @@ static int hidp_session(void *arg)
...
@@ -716,12 +716,18 @@ static int hidp_session(void *arg)
while
((
skb
=
skb_dequeue
(
&
ctrl_sk
->
sk_receive_queue
)))
{
while
((
skb
=
skb_dequeue
(
&
ctrl_sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
skb_orphan
(
skb
);
if
(
!
skb_linearize
(
skb
))
hidp_recv_ctrl_frame
(
session
,
skb
);
hidp_recv_ctrl_frame
(
session
,
skb
);
else
kfree_skb
(
skb
);
}
}
while
((
skb
=
skb_dequeue
(
&
intr_sk
->
sk_receive_queue
)))
{
while
((
skb
=
skb_dequeue
(
&
intr_sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
skb_orphan
(
skb
);
if
(
!
skb_linearize
(
skb
))
hidp_recv_intr_frame
(
session
,
skb
);
hidp_recv_intr_frame
(
session
,
skb
);
else
kfree_skb
(
skb
);
}
}
hidp_process_transmit
(
session
);
hidp_process_transmit
(
session
);
...
...
net/bluetooth/l2cap_core.c
View file @
d6222fb0
...
@@ -1245,7 +1245,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
...
@@ -1245,7 +1245,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
__clear_retrans_timer
(
chan
);
__clear_retrans_timer
(
chan
);
}
}
void
l2cap_do_send
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
)
static
void
l2cap_do_send
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
)
{
{
struct
hci_conn
*
hcon
=
chan
->
conn
->
hcon
;
struct
hci_conn
*
hcon
=
chan
->
conn
->
hcon
;
u16
flags
;
u16
flags
;
...
@@ -1261,7 +1261,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
...
@@ -1261,7 +1261,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
hci_send_acl
(
hcon
,
skb
,
flags
);
hci_send_acl
(
hcon
,
skb
,
flags
);
}
}
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
)
static
void
l2cap_streaming_send
(
struct
l2cap_chan
*
chan
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
u16
control
,
fcs
;
u16
control
,
fcs
;
...
@@ -1327,7 +1327,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
...
@@ -1327,7 +1327,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
l2cap_do_send
(
chan
,
tx_skb
);
l2cap_do_send
(
chan
,
tx_skb
);
}
}
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
)
static
int
l2cap_ertm_send
(
struct
l2cap_chan
*
chan
)
{
{
struct
sk_buff
*
skb
,
*
tx_skb
;
struct
sk_buff
*
skb
,
*
tx_skb
;
u16
control
,
fcs
;
u16
control
,
fcs
;
...
@@ -1465,7 +1465,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
...
@@ -1465,7 +1465,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
return
sent
;
return
sent
;
}
}
struct
sk_buff
*
l2cap_create_connless_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
st
atic
st
ruct
sk_buff
*
l2cap_create_connless_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
{
{
struct
sock
*
sk
=
chan
->
sk
;
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
...
@@ -1495,7 +1495,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr
...
@@ -1495,7 +1495,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr
return
skb
;
return
skb
;
}
}
struct
sk_buff
*
l2cap_create_basic_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
st
atic
st
ruct
sk_buff
*
l2cap_create_basic_pdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
{
{
struct
sock
*
sk
=
chan
->
sk
;
struct
sock
*
sk
=
chan
->
sk
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
struct
l2cap_conn
*
conn
=
chan
->
conn
;
...
@@ -1572,7 +1572,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
...
@@ -1572,7 +1572,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
return
skb
;
return
skb
;
}
}
int
l2cap_sar_segment_sdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
static
int
l2cap_sar_segment_sdu
(
struct
l2cap_chan
*
chan
,
struct
msghdr
*
msg
,
size_t
len
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
sk_buff_head
sar_queue
;
struct
sk_buff_head
sar_queue
;
...
@@ -3128,102 +3128,104 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
...
@@ -3128,102 +3128,104 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
return
0
;
return
0
;
}
}
static
int
l2cap_ertm_reassembly_sdu
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
,
u16
control
)
static
void
append_skb_frag
(
struct
sk_buff
*
skb
,
struct
sk_buff
*
new_frag
,
struct
sk_buff
**
last_frag
)
{
{
struct
sk_buff
*
_skb
;
/* skb->len reflects data in skb as well as all fragments
int
err
;
* skb->data_len reflects only data in fragments
*/
if
(
!
skb_has_frag_list
(
skb
))
skb_shinfo
(
skb
)
->
frag_list
=
new_frag
;
new_frag
->
next
=
NULL
;
(
*
last_frag
)
->
next
=
new_frag
;
*
last_frag
=
new_frag
;
skb
->
len
+=
new_frag
->
len
;
skb
->
data_len
+=
new_frag
->
len
;
skb
->
truesize
+=
new_frag
->
truesize
;
}
static
int
l2cap_reassemble_sdu
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
,
u16
control
)
{
int
err
=
-
EINVAL
;
switch
(
control
&
L2CAP_CTRL_SAR
)
{
switch
(
control
&
L2CAP_CTRL_SAR
)
{
case
L2CAP_SDU_UNSEGMENTED
:
case
L2CAP_SDU_UNSEGMENTED
:
if
(
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
)
)
if
(
chan
->
sdu
)
goto
drop
;
break
;
return
chan
->
ops
->
recv
(
chan
->
data
,
skb
);
err
=
chan
->
ops
->
recv
(
chan
->
data
,
skb
);
break
;
case
L2CAP_SDU_START
:
case
L2CAP_SDU_START
:
if
(
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
)
)
if
(
chan
->
sdu
)
goto
drop
;
break
;
chan
->
sdu_len
=
get_unaligned_le16
(
skb
->
data
);
chan
->
sdu_len
=
get_unaligned_le16
(
skb
->
data
);
skb_pull
(
skb
,
2
);
if
(
chan
->
sdu_len
>
chan
->
imtu
)
if
(
chan
->
sdu_len
>
chan
->
imtu
)
{
goto
disconnect
;
err
=
-
EMSGSIZE
;
break
;
chan
->
sdu
=
bt_skb_alloc
(
chan
->
sdu_len
,
GFP_ATOMIC
);
}
if
(
!
chan
->
sdu
)
return
-
ENOMEM
;
/* pull sdu_len bytes only after alloc, because of Local Busy
if
(
skb
->
len
>=
chan
->
sdu_len
)
* condition we have to be sure that this will be executed
break
;
* only once, i.e., when alloc does not fail */
skb_pull
(
skb
,
2
);
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
chan
->
sdu
=
skb
;
chan
->
sdu_last_frag
=
skb
;
s
et_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
)
;
s
kb
=
NULL
;
chan
->
partial_sdu_len
=
skb
->
len
;
err
=
0
;
break
;
break
;
case
L2CAP_SDU_CONTINUE
:
case
L2CAP_SDU_CONTINUE
:
if
(
!
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
goto
disconnect
;
if
(
!
chan
->
sdu
)
if
(
!
chan
->
sdu
)
goto
disconnect
;
break
;
chan
->
partial_sdu_len
+=
skb
->
len
;
append_skb_frag
(
chan
->
sdu
,
skb
,
if
(
chan
->
partial_sdu_len
>
chan
->
sdu_len
)
&
chan
->
sdu_last_frag
);
goto
drop
;
skb
=
NULL
;
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
if
(
chan
->
sdu
->
len
>=
chan
->
sdu_len
)
break
;
err
=
0
;
break
;
break
;
case
L2CAP_SDU_END
:
case
L2CAP_SDU_END
:
if
(
!
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
goto
disconnect
;
if
(
!
chan
->
sdu
)
if
(
!
chan
->
sdu
)
goto
disconnect
;
break
;
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
chan
->
imtu
)
goto
drop
;
if
(
chan
->
partial_sdu_len
!=
chan
->
sdu_len
)
append_skb_frag
(
chan
->
sdu
,
skb
,
goto
drop
;
&
chan
->
sdu_last_frag
);
skb
=
NULL
;
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
if
(
chan
->
sdu
->
len
!=
chan
->
sdu_len
)
break
;
_skb
=
skb_clone
(
chan
->
sdu
,
GFP_ATOMIC
);
err
=
chan
->
ops
->
recv
(
chan
->
data
,
chan
->
sdu
);
if
(
!
_skb
)
{
return
-
ENOMEM
;
}
err
=
chan
->
ops
->
recv
(
chan
->
data
,
_skb
);
if
(
!
err
)
{
if
(
err
<
0
)
{
/* Reassembly complete */
kfree_skb
(
_skb
);
chan
->
sdu
=
NULL
;
return
err
;
chan
->
sdu_last_frag
=
NULL
;
chan
->
sdu_len
=
0
;
}
}
clear_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
);
kfree_skb
(
chan
->
sdu
);
break
;
break
;
}
}
if
(
err
)
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
0
;
drop:
kfree_skb
(
chan
->
sdu
);
kfree_skb
(
chan
->
sdu
);
chan
->
sdu
=
NULL
;
chan
->
sdu
=
NULL
;
chan
->
sdu_last_frag
=
NULL
;
chan
->
sdu_len
=
0
;
}
disconnect:
return
err
;
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
kfree_skb
(
skb
);
return
0
;
}
}
static
void
l2cap_ertm_enter_local_busy
(
struct
l2cap_chan
*
chan
)
static
void
l2cap_ertm_enter_local_busy
(
struct
l2cap_chan
*
chan
)
...
@@ -3277,99 +3279,6 @@ void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
...
@@ -3277,99 +3279,6 @@ void l2cap_chan_busy(struct l2cap_chan *chan, int busy)
}
}
}
}
static
int
l2cap_streaming_reassembly_sdu
(
struct
l2cap_chan
*
chan
,
struct
sk_buff
*
skb
,
u16
control
)
{
struct
sk_buff
*
_skb
;
int
err
=
-
EINVAL
;
/*
* TODO: We have to notify the userland if some data is lost with the
* Streaming Mode.
*/
switch
(
control
&
L2CAP_CTRL_SAR
)
{
case
L2CAP_SDU_UNSEGMENTED
:
if
(
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
{
kfree_skb
(
chan
->
sdu
);
break
;
}
err
=
chan
->
ops
->
recv
(
chan
->
data
,
skb
);
if
(
!
err
)
return
0
;
break
;
case
L2CAP_SDU_START
:
if
(
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
{
kfree_skb
(
chan
->
sdu
);
break
;
}
chan
->
sdu_len
=
get_unaligned_le16
(
skb
->
data
);
skb_pull
(
skb
,
2
);
if
(
chan
->
sdu_len
>
chan
->
imtu
)
{
err
=
-
EMSGSIZE
;
break
;
}
chan
->
sdu
=
bt_skb_alloc
(
chan
->
sdu_len
,
GFP_ATOMIC
);
if
(
!
chan
->
sdu
)
{
err
=
-
ENOMEM
;
break
;
}
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
set_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
);
chan
->
partial_sdu_len
=
skb
->
len
;
err
=
0
;
break
;
case
L2CAP_SDU_CONTINUE
:
if
(
!
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
break
;
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
chan
->
sdu_len
)
kfree_skb
(
chan
->
sdu
);
else
err
=
0
;
break
;
case
L2CAP_SDU_END
:
if
(
!
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
break
;
memcpy
(
skb_put
(
chan
->
sdu
,
skb
->
len
),
skb
->
data
,
skb
->
len
);
clear_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
);
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
chan
->
imtu
)
goto
drop
;
if
(
chan
->
partial_sdu_len
==
chan
->
sdu_len
)
{
_skb
=
skb_clone
(
chan
->
sdu
,
GFP_ATOMIC
);
err
=
chan
->
ops
->
recv
(
chan
->
data
,
_skb
);
if
(
err
<
0
)
kfree_skb
(
_skb
);
}
err
=
0
;
drop:
kfree_skb
(
chan
->
sdu
);
break
;
}
kfree_skb
(
skb
);
return
err
;
}
static
void
l2cap_check_srej_gap
(
struct
l2cap_chan
*
chan
,
u8
tx_seq
)
static
void
l2cap_check_srej_gap
(
struct
l2cap_chan
*
chan
,
u8
tx_seq
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
...
@@ -3384,7 +3293,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
...
@@ -3384,7 +3293,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
skb
=
skb_dequeue
(
&
chan
->
srej_q
);
skb
=
skb_dequeue
(
&
chan
->
srej_q
);
control
=
bt_cb
(
skb
)
->
sar
<<
L2CAP_CTRL_SAR_SHIFT
;
control
=
bt_cb
(
skb
)
->
sar
<<
L2CAP_CTRL_SAR_SHIFT
;
err
=
l2cap_
ertm_reassembly
_sdu
(
chan
,
skb
,
control
);
err
=
l2cap_
reassemble
_sdu
(
chan
,
skb
,
control
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
...
@@ -3544,7 +3453,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
...
@@ -3544,7 +3453,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
return
0
;
return
0
;
}
}
err
=
l2cap_
ertm_reassembly
_sdu
(
chan
,
skb
,
rx_control
);
err
=
l2cap_
reassemble
_sdu
(
chan
,
skb
,
rx_control
);
chan
->
buffer_seq
=
(
chan
->
buffer_seq
+
1
)
%
64
;
chan
->
buffer_seq
=
(
chan
->
buffer_seq
+
1
)
%
64
;
if
(
err
<
0
)
{
if
(
err
<
0
)
{
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
...
@@ -3860,12 +3769,20 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
...
@@ -3860,12 +3769,20 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
tx_seq
=
__get_txseq
(
control
);
tx_seq
=
__get_txseq
(
control
);
if
(
chan
->
expected_tx_seq
==
tx_seq
)
if
(
chan
->
expected_tx_seq
!=
tx_seq
)
{
chan
->
expected_tx_seq
=
(
chan
->
expected_tx_seq
+
1
)
%
64
;
/* Frame(s) missing - must discard partial SDU */
else
kfree_skb
(
chan
->
sdu
);
chan
->
sdu
=
NULL
;
chan
->
sdu_last_frag
=
NULL
;
chan
->
sdu_len
=
0
;
/* TODO: Notify userland of missing data */
}
chan
->
expected_tx_seq
=
(
tx_seq
+
1
)
%
64
;
chan
->
expected_tx_seq
=
(
tx_seq
+
1
)
%
64
;
l2cap_streaming_reassembly_sdu
(
chan
,
skb
,
control
);
if
(
l2cap_reassemble_sdu
(
chan
,
skb
,
control
)
==
-
EMSGSIZE
)
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
goto
done
;
goto
done
;
...
...
net/bluetooth/rfcomm/core.c
View file @
d6222fb0
...
@@ -1853,7 +1853,10 @@ static inline void rfcomm_process_rx(struct rfcomm_session *s)
...
@@ -1853,7 +1853,10 @@ static inline void rfcomm_process_rx(struct rfcomm_session *s)
/* Get data directly from socket receive queue without copying it. */
/* Get data directly from socket receive queue without copying it. */
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
skb_orphan
(
skb
);
if
(
!
skb_linearize
(
skb
))
rfcomm_recv_frame
(
s
,
skb
);
rfcomm_recv_frame
(
s
,
skb
);
else
kfree_skb
(
skb
);
}
}
if
(
sk
->
sk_state
==
BT_CLOSED
)
{
if
(
sk
->
sk_state
==
BT_CLOSED
)
{
...
...
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