Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
d6222fb0
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
d6222fb0
编写于
10月 04, 2011
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://github.com/padovan/bluetooth-next
上级
76ed94be
c510eae3
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
157 addition
and
196 deletion
+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
未找到文件。
drivers/bluetooth/btusb.c
浏览文件 @
d6222fb0
...
...
@@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{
USB_DEVICE_INFO
(
0xe0
,
0x01
,
0x01
)
},
/* Broadcom SoftSailing reporting vendor specific */
{
USB_DEVICE
(
0x05ac
,
0x21e1
)
},
/* Apple MacBookPro 7,1 */
{
USB_DEVICE
(
0x05ac
,
0x8213
)
},
...
...
@@ -708,8 +711,7 @@ static int btusb_send_frame(struct sk_buff *skb)
break
;
case
HCI_ACLDATA_PKT
:
if
(
!
data
->
bulk_tx_ep
||
(
hdev
->
conn_hash
.
acl_num
<
1
&&
hdev
->
conn_hash
.
le_num
<
1
))
if
(
!
data
->
bulk_tx_ep
)
return
-
ENODEV
;
urb
=
usb_alloc_urb
(
0
,
GFP_ATOMIC
);
...
...
include/net/bluetooth/l2cap.h
浏览文件 @
d6222fb0
...
...
@@ -354,8 +354,8 @@ struct l2cap_chan {
__u8
retry_count
;
__u8
num_acked
;
__u16
sdu_len
;
__u16
partial_sdu_len
;
struct
sk_buff
*
sdu
;
struct
sk_buff
*
sdu_last_frag
;
__u8
remote_tx_win
;
__u8
remote_max_tx
;
...
...
@@ -448,7 +448,6 @@ enum {
#define L2CAP_CONF_MAX_CONF_RSP 2
enum
{
CONN_SAR_SDU
,
CONN_SREJ_SENT
,
CONN_WAIT_F
,
CONN_SREJ_ACT
,
...
...
net/bluetooth/af_bluetooth.c
浏览文件 @
d6222fb0
...
...
@@ -349,7 +349,7 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
}
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
);
if
(
!
copied
)
copied
=
-
EFAULT
;
...
...
@@ -361,7 +361,33 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
sock_recv_ts_and_drops
(
msg
,
sk
,
skb
);
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
)
{
skb_queue_head
(
&
sk
->
sk_receive_queue
,
skb
);
break
;
...
...
net/bluetooth/bnep/core.c
浏览文件 @
d6222fb0
...
...
@@ -492,7 +492,10 @@ static int bnep_session(void *arg)
/* RX */
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
bnep_rx_frame
(
s
,
skb
);
if
(
!
skb_linearize
(
skb
))
bnep_rx_frame
(
s
,
skb
);
else
kfree_skb
(
skb
);
}
if
(
sk
->
sk_state
!=
BT_CONNECTED
)
...
...
net/bluetooth/cmtp/core.c
浏览文件 @
d6222fb0
...
...
@@ -302,7 +302,10 @@ static int cmtp_session(void *arg)
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
cmtp_recv_frame
(
session
,
skb
);
if
(
!
skb_linearize
(
skb
))
cmtp_recv_frame
(
session
,
skb
);
else
kfree_skb
(
skb
);
}
cmtp_process_transmit
(
session
);
...
...
net/bluetooth/hci_conn.c
浏览文件 @
d6222fb0
...
...
@@ -56,15 +56,15 @@ static void hci_le_connect(struct hci_conn *conn)
conn
->
sec_level
=
BT_SECURITY_LOW
;
memset
(
&
cp
,
0
,
sizeof
(
cp
));
cp
.
scan_interval
=
cpu_to_le16
(
0x00
04
);
cp
.
scan_window
=
cpu_to_le16
(
0x00
04
);
cp
.
scan_interval
=
cpu_to_le16
(
0x00
60
);
cp
.
scan_window
=
cpu_to_le16
(
0x00
30
);
bacpy
(
&
cp
.
peer_addr
,
&
conn
->
dst
);
cp
.
peer_addr_type
=
conn
->
dst_type
;
cp
.
conn_interval_min
=
cpu_to_le16
(
0x00
0
8
);
cp
.
conn_interval_max
=
cpu_to_le16
(
0x0
100
);
cp
.
supervision_timeout
=
cpu_to_le16
(
0x00
64
);
cp
.
min_ce_len
=
cpu_to_le16
(
0x000
1
);
cp
.
max_ce_len
=
cpu_to_le16
(
0x000
1
);
cp
.
conn_interval_min
=
cpu_to_le16
(
0x00
2
8
);
cp
.
conn_interval_max
=
cpu_to_le16
(
0x0
038
);
cp
.
supervision_timeout
=
cpu_to_le16
(
0x00
2a
);
cp
.
min_ce_len
=
cpu_to_le16
(
0x000
0
);
cp
.
max_ce_len
=
cpu_to_le16
(
0x000
0
);
hci_send_cmd
(
hdev
,
HCI_OP_LE_CREATE_CONN
,
sizeof
(
cp
),
&
cp
);
}
...
...
net/bluetooth/hci_event.c
浏览文件 @
d6222fb0
...
...
@@ -2174,7 +2174,10 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_lock
(
hdev
);
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
);
conn
->
disc_timeout
=
HCI_PAIRING_TIMEOUT
;
hci_conn_put
(
conn
);
...
...
@@ -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
);
}
unlock:
hci_dev_unlock
(
hdev
);
}
...
...
@@ -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
,
struct
sk_buff
*
skb
)
{
struct
hci_ev_le_advertising_info
*
ev
;
u8
num_reports
;
num_reports
=
skb
->
data
[
0
];
ev
=
(
void
*
)
&
skb
->
data
[
1
];
u8
num_reports
=
skb
->
data
[
0
];
void
*
ptr
=
&
skb
->
data
[
1
];
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
);
ptr
+=
sizeof
(
*
ev
)
+
ev
->
length
+
1
;
}
hci_dev_unlock
(
hdev
);
...
...
net/bluetooth/hidp/core.c
浏览文件 @
d6222fb0
...
...
@@ -716,12 +716,18 @@ static int hidp_session(void *arg)
while
((
skb
=
skb_dequeue
(
&
ctrl_sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
hidp_recv_ctrl_frame
(
session
,
skb
);
if
(
!
skb_linearize
(
skb
))
hidp_recv_ctrl_frame
(
session
,
skb
);
else
kfree_skb
(
skb
);
}
while
((
skb
=
skb_dequeue
(
&
intr_sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
hidp_recv_intr_frame
(
session
,
skb
);
if
(
!
skb_linearize
(
skb
))
hidp_recv_intr_frame
(
session
,
skb
);
else
kfree_skb
(
skb
);
}
hidp_process_transmit
(
session
);
...
...
net/bluetooth/l2cap_core.c
浏览文件 @
d6222fb0
...
...
@@ -1245,7 +1245,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *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
;
u16
flags
;
...
...
@@ -1261,7 +1261,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
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
;
u16
control
,
fcs
;
...
...
@@ -1327,7 +1327,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
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
;
u16
control
,
fcs
;
...
...
@@ -1465,7 +1465,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
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
l2cap_conn
*
conn
=
chan
->
conn
;
...
...
@@ -1495,7 +1495,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr
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
l2cap_conn
*
conn
=
chan
->
conn
;
...
...
@@ -1572,7 +1572,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan,
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_head
sar_queue
;
...
...
@@ -3128,102 +3128,104 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
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
;
int
err
;
/* skb->len reflects data in skb as well as all fragments
* 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
)
{
case
L2CAP_SDU_UNSEGMENTED
:
if
(
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
)
)
goto
drop
;
if
(
chan
->
sdu
)
break
;
return
chan
->
ops
->
recv
(
chan
->
data
,
skb
);
err
=
chan
->
ops
->
recv
(
chan
->
data
,
skb
);
break
;
case
L2CAP_SDU_START
:
if
(
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
)
)
goto
drop
;
if
(
chan
->
sdu
)
break
;
chan
->
sdu_len
=
get_unaligned_le16
(
skb
->
data
);
skb_pull
(
skb
,
2
);
if
(
chan
->
sdu_len
>
chan
->
imtu
)
goto
disconnect
;
chan
->
sdu
=
bt_skb_alloc
(
chan
->
sdu_len
,
GFP_ATOMIC
);
if
(
!
chan
->
sdu
)
return
-
ENOMEM
;
if
(
chan
->
sdu_len
>
chan
->
imtu
)
{
err
=
-
EMSGSIZE
;
break
;
}
/* pull sdu_len bytes only after alloc, because of Local Busy
* condition we have to be sure that this will be executed
* only once, i.e., when alloc does not fail */
skb_pull
(
skb
,
2
);
if
(
skb
->
len
>=
chan
->
sdu_len
)
break
;
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
)
;
chan
->
partial_sdu_len
=
skb
->
len
;
s
kb
=
NULL
;
err
=
0
;
break
;
case
L2CAP_SDU_CONTINUE
:
if
(
!
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
goto
disconnect
;
if
(
!
chan
->
sdu
)
goto
disconnect
;
break
;
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
chan
->
sdu_len
)
goto
drop
;
append_skb_frag
(
chan
->
sdu
,
skb
,
&
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
;
err
=
0
;
break
;
case
L2CAP_SDU_END
:
if
(
!
test_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
))
goto
disconnect
;
if
(
!
chan
->
sdu
)
goto
disconnect
;
chan
->
partial_sdu_len
+=
skb
->
len
;
if
(
chan
->
partial_sdu_len
>
chan
->
imtu
)
goto
drop
;
break
;
if
(
chan
->
partial_sdu_len
!=
chan
->
sdu_len
)
goto
drop
;
append_skb_frag
(
chan
->
sdu
,
skb
,
&
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
);
if
(
!
_skb
)
{
return
-
ENOMEM
;
}
err
=
chan
->
ops
->
recv
(
chan
->
data
,
chan
->
sdu
);
err
=
chan
->
ops
->
recv
(
chan
->
data
,
_skb
);
if
(
err
<
0
)
{
kfree_skb
(
_skb
);
return
err
;
if
(
!
err
)
{
/* Reassembly complete */
chan
->
sdu
=
NULL
;
chan
->
sdu_last_frag
=
NULL
;
chan
->
sdu_len
=
0
;
}
clear_bit
(
CONN_SAR_SDU
,
&
chan
->
conn_state
);
kfree_skb
(
chan
->
sdu
);
break
;
}
kfree_skb
(
skb
);
return
0
;
drop:
kfree_skb
(
chan
->
sdu
);
chan
->
sdu
=
NULL
;
if
(
err
)
{
kfree_skb
(
skb
);
kfree_skb
(
chan
->
sdu
);
chan
->
sdu
=
NULL
;
chan
->
sdu_last_frag
=
NULL
;
chan
->
sdu_len
=
0
;
}
disconnect:
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
kfree_skb
(
skb
);
return
0
;
return
err
;
}
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)
}
}
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
)
{
struct
sk_buff
*
skb
;
...
...
@@ -3384,7 +3293,7 @@ static void l2cap_check_srej_gap(struct l2cap_chan *chan, u8 tx_seq)
skb
=
skb_dequeue
(
&
chan
->
srej_q
);
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
)
{
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
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
;
if
(
err
<
0
)
{
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
tx_seq
=
__get_txseq
(
control
);
if
(
chan
->
expected_tx_seq
==
tx_seq
)
chan
->
expected_tx_seq
=
(
chan
->
expected_tx_seq
+
1
)
%
64
;
else
chan
->
expected_tx_seq
=
(
tx_seq
+
1
)
%
64
;
if
(
chan
->
expected_tx_seq
!=
tx_seq
)
{
/* Frame(s) missing - must discard partial SDU */
kfree_skb
(
chan
->
sdu
);
chan
->
sdu
=
NULL
;
chan
->
sdu_last_frag
=
NULL
;
chan
->
sdu_len
=
0
;
l2cap_streaming_reassembly_sdu
(
chan
,
skb
,
control
);
/* TODO: Notify userland of missing data */
}
chan
->
expected_tx_seq
=
(
tx_seq
+
1
)
%
64
;
if
(
l2cap_reassemble_sdu
(
chan
,
skb
,
control
)
==
-
EMSGSIZE
)
l2cap_send_disconn_req
(
chan
->
conn
,
chan
,
ECONNRESET
);
goto
done
;
...
...
net/bluetooth/rfcomm/core.c
浏览文件 @
d6222fb0
...
...
@@ -1853,7 +1853,10 @@ static inline void rfcomm_process_rx(struct rfcomm_session *s)
/* Get data directly from socket receive queue without copying it. */
while
((
skb
=
skb_dequeue
(
&
sk
->
sk_receive_queue
)))
{
skb_orphan
(
skb
);
rfcomm_recv_frame
(
s
,
skb
);
if
(
!
skb_linearize
(
skb
))
rfcomm_recv_frame
(
s
,
skb
);
else
kfree_skb
(
skb
);
}
if
(
sk
->
sk_state
==
BT_CLOSED
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录