Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
2e486868
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
163
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2e486868
编写于
6月 11, 2012
作者:
J
John W. Linville
浏览文件
操作
浏览文件
下载
差异文件
Merge tag 'nfc-next-3.6-1' of
git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-3.0
上级
934b9d1e
51ad304c
变更
16
展开全部
隐藏空白更改
内联
并排
Showing
16 changed file
with
1106 addition
and
392 deletion
+1106
-392
drivers/nfc/pn533.c
drivers/nfc/pn533.c
+543
-119
drivers/nfc/pn544_hci.c
drivers/nfc/pn544_hci.c
+6
-4
include/linux/nfc.h
include/linux/nfc.h
+12
-0
include/net/nfc/hci.h
include/net/nfc/hci.h
+2
-1
include/net/nfc/nfc.h
include/net/nfc/nfc.h
+11
-3
include/net/nfc/shdlc.h
include/net/nfc/shdlc.h
+2
-1
net/nfc/core.c
net/nfc/core.c
+89
-30
net/nfc/hci/core.c
net/nfc/hci/core.c
+7
-6
net/nfc/hci/shdlc.c
net/nfc/hci/shdlc.c
+4
-2
net/nfc/llcp/commands.c
net/nfc/llcp/commands.c
+44
-10
net/nfc/llcp/llcp.c
net/nfc/llcp/llcp.c
+251
-170
net/nfc/llcp/llcp.h
net/nfc/llcp/llcp.h
+20
-6
net/nfc/llcp/sock.c
net/nfc/llcp/sock.c
+19
-28
net/nfc/nci/core.c
net/nfc/nci/core.c
+8
-7
net/nfc/netlink.c
net/nfc/netlink.c
+77
-4
net/nfc/nfc.h
net/nfc/nfc.h
+11
-1
未找到文件。
drivers/nfc/pn533.c
浏览文件 @
2e486868
此差异已折叠。
点击以展开。
drivers/nfc/pn544_hci.c
浏览文件 @
2e486868
...
...
@@ -576,7 +576,8 @@ static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb)
return
pn544_hci_i2c_write
(
client
,
skb
->
data
,
skb
->
len
);
}
static
int
pn544_hci_start_poll
(
struct
nfc_shdlc
*
shdlc
,
u32
protocols
)
static
int
pn544_hci_start_poll
(
struct
nfc_shdlc
*
shdlc
,
u32
im_protocols
,
u32
tm_protocols
)
{
struct
nfc_hci_dev
*
hdev
=
nfc_shdlc_get_hci_dev
(
shdlc
);
u8
phases
=
0
;
...
...
@@ -584,7 +585,8 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
u8
duration
[
2
];
u8
activated
;
pr_info
(
DRIVER_DESC
": %s protocols = %d
\n
"
,
__func__
,
protocols
);
pr_info
(
DRIVER_DESC
": %s protocols 0x%x 0x%x
\n
"
,
__func__
,
im_protocols
,
tm_protocols
);
r
=
nfc_hci_send_event
(
hdev
,
NFC_HCI_RF_READER_A_GATE
,
NFC_HCI_EVT_END_OPERATION
,
NULL
,
0
);
...
...
@@ -604,10 +606,10 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols)
if
(
r
<
0
)
return
r
;
if
(
protocols
&
(
NFC_PROTO_ISO14443_MASK
|
NFC_PROTO_MIFARE_MASK
|
if
(
im_
protocols
&
(
NFC_PROTO_ISO14443_MASK
|
NFC_PROTO_MIFARE_MASK
|
NFC_PROTO_JEWEL_MASK
))
phases
|=
1
;
/* Type A */
if
(
protocols
&
NFC_PROTO_FELICA_MASK
)
{
if
(
im_
protocols
&
NFC_PROTO_FELICA_MASK
)
{
phases
|=
(
1
<<
2
);
/* Type F 212 */
phases
|=
(
1
<<
3
);
/* Type F 424 */
}
...
...
include/linux/nfc.h
浏览文件 @
2e486868
...
...
@@ -56,6 +56,10 @@
* %NFC_ATTR_PROTOCOLS)
* @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed
* (it sends %NFC_ATTR_DEVICE_INDEX)
* @NFC_EVENT_TM_ACTIVATED: event emitted when the adapter is activated in
* target mode.
* @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated
* from target mode.
*/
enum
nfc_commands
{
NFC_CMD_UNSPEC
,
...
...
@@ -71,6 +75,8 @@ enum nfc_commands {
NFC_EVENT_DEVICE_ADDED
,
NFC_EVENT_DEVICE_REMOVED
,
NFC_EVENT_TARGET_LOST
,
NFC_EVENT_TM_ACTIVATED
,
NFC_EVENT_TM_DEACTIVATED
,
/* private: internal use only */
__NFC_CMD_AFTER_LAST
};
...
...
@@ -94,6 +100,8 @@ enum nfc_commands {
* @NFC_ATTR_TARGET_SENSF_RES: NFC-F targets extra information, max 18 bytes
* @NFC_ATTR_COMM_MODE: Passive or active mode
* @NFC_ATTR_RF_MODE: Initiator or target
* @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for
* @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for
*/
enum
nfc_attrs
{
NFC_ATTR_UNSPEC
,
...
...
@@ -109,6 +117,8 @@ enum nfc_attrs {
NFC_ATTR_COMM_MODE
,
NFC_ATTR_RF_MODE
,
NFC_ATTR_DEVICE_POWERED
,
NFC_ATTR_IM_PROTOCOLS
,
NFC_ATTR_TM_PROTOCOLS
,
/* private: internal use only */
__NFC_ATTR_AFTER_LAST
};
...
...
@@ -118,6 +128,7 @@ enum nfc_attrs {
#define NFC_NFCID1_MAXSIZE 10
#define NFC_SENSB_RES_MAXSIZE 12
#define NFC_SENSF_RES_MAXSIZE 18
#define NFC_GB_MAXSIZE 48
/* NFC protocols */
#define NFC_PROTO_JEWEL 1
...
...
@@ -135,6 +146,7 @@ enum nfc_attrs {
/* NFC RF modes */
#define NFC_RF_INITIATOR 0
#define NFC_RF_TARGET 1
#define NFC_RF_NONE 2
/* NFC protocols masks used in bitsets */
#define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL)
...
...
include/net/nfc/hci.h
浏览文件 @
2e486868
...
...
@@ -31,7 +31,8 @@ struct nfc_hci_ops {
void
(
*
close
)
(
struct
nfc_hci_dev
*
hdev
);
int
(
*
hci_ready
)
(
struct
nfc_hci_dev
*
hdev
);
int
(
*
xmit
)
(
struct
nfc_hci_dev
*
hdev
,
struct
sk_buff
*
skb
);
int
(
*
start_poll
)
(
struct
nfc_hci_dev
*
hdev
,
u32
protocols
);
int
(
*
start_poll
)
(
struct
nfc_hci_dev
*
hdev
,
u32
im_protocols
,
u32
tm_protocols
);
int
(
*
target_from_gate
)
(
struct
nfc_hci_dev
*
hdev
,
u8
gate
,
struct
nfc_target
*
target
);
int
(
*
complete_target_discovered
)
(
struct
nfc_hci_dev
*
hdev
,
u8
gate
,
...
...
include/net/nfc/nfc.h
浏览文件 @
2e486868
...
...
@@ -53,7 +53,8 @@ struct nfc_target;
struct
nfc_ops
{
int
(
*
dev_up
)(
struct
nfc_dev
*
dev
);
int
(
*
dev_down
)(
struct
nfc_dev
*
dev
);
int
(
*
start_poll
)(
struct
nfc_dev
*
dev
,
u32
protocols
);
int
(
*
start_poll
)(
struct
nfc_dev
*
dev
,
u32
im_protocols
,
u32
tm_protocols
);
void
(
*
stop_poll
)(
struct
nfc_dev
*
dev
);
int
(
*
dep_link_up
)(
struct
nfc_dev
*
dev
,
struct
nfc_target
*
target
,
u8
comm_mode
,
u8
*
gb
,
size_t
gb_len
);
...
...
@@ -62,9 +63,10 @@ struct nfc_ops {
u32
protocol
);
void
(
*
deactivate_target
)(
struct
nfc_dev
*
dev
,
struct
nfc_target
*
target
);
int
(
*
data_exchang
e
)(
struct
nfc_dev
*
dev
,
struct
nfc_target
*
target
,
int
(
*
im_transceiv
e
)(
struct
nfc_dev
*
dev
,
struct
nfc_target
*
target
,
struct
sk_buff
*
skb
,
data_exchange_cb_t
cb
,
void
*
cb_context
);
int
(
*
tm_send
)(
struct
nfc_dev
*
dev
,
struct
sk_buff
*
skb
);
int
(
*
check_presence
)(
struct
nfc_dev
*
dev
,
struct
nfc_target
*
target
);
};
...
...
@@ -99,10 +101,10 @@ struct nfc_dev {
int
targets_generation
;
struct
device
dev
;
bool
dev_up
;
u8
rf_mode
;
bool
polling
;
struct
nfc_target
*
active_target
;
bool
dep_link_up
;
u32
dep_rf_mode
;
struct
nfc_genl_data
genl_data
;
u32
supported_protocols
;
...
...
@@ -188,6 +190,7 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp);
int
nfc_set_remote_general_bytes
(
struct
nfc_dev
*
dev
,
u8
*
gt
,
u8
gt_len
);
u8
*
nfc_get_local_general_bytes
(
struct
nfc_dev
*
dev
,
size_t
*
gb_len
);
int
nfc_targets_found
(
struct
nfc_dev
*
dev
,
struct
nfc_target
*
targets
,
int
ntargets
);
...
...
@@ -196,4 +199,9 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx);
int
nfc_dep_link_is_up
(
struct
nfc_dev
*
dev
,
u32
target_idx
,
u8
comm_mode
,
u8
rf_mode
);
int
nfc_tm_activated
(
struct
nfc_dev
*
dev
,
u32
protocol
,
u8
comm_mode
,
u8
*
gb
,
size_t
gb_len
);
int
nfc_tm_deactivated
(
struct
nfc_dev
*
dev
);
int
nfc_tm_data_received
(
struct
nfc_dev
*
dev
,
struct
sk_buff
*
skb
);
#endif
/* __NET_NFC_H */
include/net/nfc/shdlc.h
浏览文件 @
2e486868
...
...
@@ -27,7 +27,8 @@ struct nfc_shdlc_ops {
void
(
*
close
)
(
struct
nfc_shdlc
*
shdlc
);
int
(
*
hci_ready
)
(
struct
nfc_shdlc
*
shdlc
);
int
(
*
xmit
)
(
struct
nfc_shdlc
*
shdlc
,
struct
sk_buff
*
skb
);
int
(
*
start_poll
)
(
struct
nfc_shdlc
*
shdlc
,
u32
protocols
);
int
(
*
start_poll
)
(
struct
nfc_shdlc
*
shdlc
,
u32
im_protocols
,
u32
tm_protocols
);
int
(
*
target_from_gate
)
(
struct
nfc_shdlc
*
shdlc
,
u8
gate
,
struct
nfc_target
*
target
);
int
(
*
complete_target_discovered
)
(
struct
nfc_shdlc
*
shdlc
,
u8
gate
,
...
...
net/nfc/core.c
浏览文件 @
2e486868
...
...
@@ -121,14 +121,14 @@ int nfc_dev_down(struct nfc_dev *dev)
* The device remains polling for targets until a target is found or
* the nfc_stop_poll function is called.
*/
int
nfc_start_poll
(
struct
nfc_dev
*
dev
,
u32
protocols
)
int
nfc_start_poll
(
struct
nfc_dev
*
dev
,
u32
im_protocols
,
u32
tm_
protocols
)
{
int
rc
;
pr_debug
(
"dev_name
=%s protocols=
0x%x
\n
"
,
dev_name
(
&
dev
->
dev
),
protocols
);
pr_debug
(
"dev_name
%s initiator protocols 0x%x target protocols
0x%x
\n
"
,
dev_name
(
&
dev
->
dev
),
im_protocols
,
tm_
protocols
);
if
(
!
protocols
)
if
(
!
im_protocols
&&
!
tm_
protocols
)
return
-
EINVAL
;
device_lock
(
&
dev
->
dev
);
...
...
@@ -143,9 +143,11 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
goto
error
;
}
rc
=
dev
->
ops
->
start_poll
(
dev
,
protocols
);
if
(
!
rc
)
rc
=
dev
->
ops
->
start_poll
(
dev
,
im_protocols
,
tm_
protocols
);
if
(
!
rc
)
{
dev
->
polling
=
true
;
dev
->
rf_mode
=
NFC_RF_NONE
;
}
error:
device_unlock
(
&
dev
->
dev
);
...
...
@@ -235,8 +237,10 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode)
}
rc
=
dev
->
ops
->
dep_link_up
(
dev
,
target
,
comm_mode
,
gb
,
gb_len
);
if
(
!
rc
)
if
(
!
rc
)
{
dev
->
active_target
=
target
;
dev
->
rf_mode
=
NFC_RF_INITIATOR
;
}
error:
device_unlock
(
&
dev
->
dev
);
...
...
@@ -264,11 +268,6 @@ int nfc_dep_link_down(struct nfc_dev *dev)
goto
error
;
}
if
(
dev
->
dep_rf_mode
==
NFC_RF_TARGET
)
{
rc
=
-
EOPNOTSUPP
;
goto
error
;
}
rc
=
dev
->
ops
->
dep_link_down
(
dev
);
if
(
!
rc
)
{
dev
->
dep_link_up
=
false
;
...
...
@@ -286,7 +285,6 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
u8
comm_mode
,
u8
rf_mode
)
{
dev
->
dep_link_up
=
true
;
dev
->
dep_rf_mode
=
rf_mode
;
nfc_llcp_mac_is_up
(
dev
,
target_idx
,
comm_mode
,
rf_mode
);
...
...
@@ -330,6 +328,7 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
rc
=
dev
->
ops
->
activate_target
(
dev
,
target
,
protocol
);
if
(
!
rc
)
{
dev
->
active_target
=
target
;
dev
->
rf_mode
=
NFC_RF_INITIATOR
;
if
(
dev
->
ops
->
check_presence
)
mod_timer
(
&
dev
->
check_pres_timer
,
jiffies
+
...
...
@@ -409,27 +408,30 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
goto
error
;
}
if
(
dev
->
active_target
==
NULL
)
{
rc
=
-
ENOTCONN
;
kfree_skb
(
skb
);
goto
error
;
}
if
(
dev
->
rf_mode
==
NFC_RF_INITIATOR
&&
dev
->
active_target
!=
NULL
)
{
if
(
dev
->
active_target
->
idx
!=
target_idx
)
{
rc
=
-
EADDRNOTAVAIL
;
kfree_skb
(
skb
);
goto
error
;
}
if
(
dev
->
active_target
->
idx
!=
target_idx
)
{
rc
=
-
EADDRNOTAVAIL
;
if
(
dev
->
ops
->
check_presence
)
del_timer_sync
(
&
dev
->
check_pres_timer
);
rc
=
dev
->
ops
->
im_transceive
(
dev
,
dev
->
active_target
,
skb
,
cb
,
cb_context
);
if
(
!
rc
&&
dev
->
ops
->
check_presence
)
mod_timer
(
&
dev
->
check_pres_timer
,
jiffies
+
msecs_to_jiffies
(
NFC_CHECK_PRES_FREQ_MS
));
}
else
if
(
dev
->
rf_mode
==
NFC_RF_TARGET
&&
dev
->
ops
->
tm_send
!=
NULL
)
{
rc
=
dev
->
ops
->
tm_send
(
dev
,
skb
);
}
else
{
rc
=
-
ENOTCONN
;
kfree_skb
(
skb
);
goto
error
;
}
if
(
dev
->
ops
->
check_presence
)
del_timer_sync
(
&
dev
->
check_pres_timer
);
rc
=
dev
->
ops
->
data_exchange
(
dev
,
dev
->
active_target
,
skb
,
cb
,
cb_context
);
if
(
!
rc
&&
dev
->
ops
->
check_presence
)
mod_timer
(
&
dev
->
check_pres_timer
,
jiffies
+
msecs_to_jiffies
(
NFC_CHECK_PRES_FREQ_MS
));
error:
device_unlock
(
&
dev
->
dev
);
...
...
@@ -447,6 +449,63 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
}
EXPORT_SYMBOL
(
nfc_set_remote_general_bytes
);
u8
*
nfc_get_local_general_bytes
(
struct
nfc_dev
*
dev
,
size_t
*
gb_len
)
{
pr_debug
(
"dev_name=%s
\n
"
,
dev_name
(
&
dev
->
dev
));
return
nfc_llcp_general_bytes
(
dev
,
gb_len
);
}
EXPORT_SYMBOL
(
nfc_get_local_general_bytes
);
int
nfc_tm_data_received
(
struct
nfc_dev
*
dev
,
struct
sk_buff
*
skb
)
{
/* Only LLCP target mode for now */
if
(
dev
->
dep_link_up
==
false
)
{
kfree_skb
(
skb
);
return
-
ENOLINK
;
}
return
nfc_llcp_data_received
(
dev
,
skb
);
}
EXPORT_SYMBOL
(
nfc_tm_data_received
);
int
nfc_tm_activated
(
struct
nfc_dev
*
dev
,
u32
protocol
,
u8
comm_mode
,
u8
*
gb
,
size_t
gb_len
)
{
int
rc
;
device_lock
(
&
dev
->
dev
);
dev
->
polling
=
false
;
if
(
gb
!=
NULL
)
{
rc
=
nfc_set_remote_general_bytes
(
dev
,
gb
,
gb_len
);
if
(
rc
<
0
)
goto
out
;
}
dev
->
rf_mode
=
NFC_RF_TARGET
;
if
(
protocol
==
NFC_PROTO_NFC_DEP_MASK
)
nfc_dep_link_is_up
(
dev
,
0
,
comm_mode
,
NFC_RF_TARGET
);
rc
=
nfc_genl_tm_activated
(
dev
,
protocol
);
out:
device_unlock
(
&
dev
->
dev
);
return
rc
;
}
EXPORT_SYMBOL
(
nfc_tm_activated
);
int
nfc_tm_deactivated
(
struct
nfc_dev
*
dev
)
{
dev
->
dep_link_up
=
false
;
return
nfc_genl_tm_deactivated
(
dev
);
}
EXPORT_SYMBOL
(
nfc_tm_deactivated
);
/**
* nfc_alloc_send_skb - allocate a skb for data exchange responses
*
...
...
@@ -678,7 +737,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
struct
nfc_dev
*
dev
;
if
(
!
ops
->
start_poll
||
!
ops
->
stop_poll
||
!
ops
->
activate_target
||
!
ops
->
deactivate_target
||
!
ops
->
data_exchang
e
)
!
ops
->
deactivate_target
||
!
ops
->
im_transceiv
e
)
return
NULL
;
if
(
!
supported_protocols
)
...
...
net/nfc/hci/core.c
浏览文件 @
2e486868
...
...
@@ -481,12 +481,13 @@ static int hci_dev_down(struct nfc_dev *nfc_dev)
return
0
;
}
static
int
hci_start_poll
(
struct
nfc_dev
*
nfc_dev
,
u32
protocols
)
static
int
hci_start_poll
(
struct
nfc_dev
*
nfc_dev
,
u32
im_protocols
,
u32
tm_protocols
)
{
struct
nfc_hci_dev
*
hdev
=
nfc_get_drvdata
(
nfc_dev
);
if
(
hdev
->
ops
->
start_poll
)
return
hdev
->
ops
->
start_poll
(
hdev
,
protocols
);
return
hdev
->
ops
->
start_poll
(
hdev
,
im_protocols
,
tm_
protocols
);
else
return
nfc_hci_send_event
(
hdev
,
NFC_HCI_RF_READER_A_GATE
,
NFC_HCI_EVT_READER_REQUESTED
,
NULL
,
0
);
...
...
@@ -511,9 +512,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev,
{
}
static
int
hci_
data_exchang
e
(
struct
nfc_dev
*
nfc_dev
,
struct
nfc_target
*
target
,
struct
sk_buff
*
skb
,
data_exchange_cb_t
cb
,
void
*
cb_context
)
static
int
hci_
transceiv
e
(
struct
nfc_dev
*
nfc_dev
,
struct
nfc_target
*
target
,
struct
sk_buff
*
skb
,
data_exchange_cb_t
cb
,
void
*
cb_context
)
{
struct
nfc_hci_dev
*
hdev
=
nfc_get_drvdata
(
nfc_dev
);
int
r
;
...
...
@@ -579,7 +580,7 @@ static struct nfc_ops hci_nfc_ops = {
.
stop_poll
=
hci_stop_poll
,
.
activate_target
=
hci_activate_target
,
.
deactivate_target
=
hci_deactivate_target
,
.
data_exchange
=
hci_data_exchang
e
,
.
im_transceive
=
hci_transceiv
e
,
.
check_presence
=
hci_check_presence
,
};
...
...
net/nfc/hci/shdlc.c
浏览文件 @
2e486868
...
...
@@ -765,14 +765,16 @@ static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
return
0
;
}
static
int
nfc_shdlc_start_poll
(
struct
nfc_hci_dev
*
hdev
,
u32
protocols
)
static
int
nfc_shdlc_start_poll
(
struct
nfc_hci_dev
*
hdev
,
u32
im_protocols
,
u32
tm_protocols
)
{
struct
nfc_shdlc
*
shdlc
=
nfc_hci_get_clientdata
(
hdev
);
pr_debug
(
"
\n
"
);
if
(
shdlc
->
ops
->
start_poll
)
return
shdlc
->
ops
->
start_poll
(
shdlc
,
protocols
);
return
shdlc
->
ops
->
start_poll
(
shdlc
,
im_protocols
,
tm_protocols
);
return
0
;
}
...
...
net/nfc/llcp/commands.c
浏览文件 @
2e486868
...
...
@@ -51,7 +51,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type)
return
tlv
[
2
];
}
static
u
8
llcp_tlv16
(
u8
*
tlv
,
u8
type
)
static
u
16
llcp_tlv16
(
u8
*
tlv
,
u8
type
)
{
if
(
tlv
[
0
]
!=
type
||
tlv
[
1
]
!=
llcp_tlv_length
[
tlv
[
0
]])
return
0
;
...
...
@@ -67,7 +67,7 @@ static u8 llcp_tlv_version(u8 *tlv)
static
u16
llcp_tlv_miux
(
u8
*
tlv
)
{
return
llcp_tlv16
(
tlv
,
LLCP_TLV_MIUX
)
&
0x7f
;
return
llcp_tlv16
(
tlv
,
LLCP_TLV_MIUX
)
&
0x7f
f
;
}
static
u16
llcp_tlv_wks
(
u8
*
tlv
)
...
...
@@ -117,8 +117,8 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
return
tlv
;
}
int
nfc_llcp_parse_tlv
(
struct
nfc_llcp_local
*
local
,
u8
*
tlv_array
,
u16
tlv_array_len
)
int
nfc_llcp_parse_
gb_
tlv
(
struct
nfc_llcp_local
*
local
,
u8
*
tlv_array
,
u16
tlv_array_len
)
{
u8
*
tlv
=
tlv_array
,
type
,
length
,
offset
=
0
;
...
...
@@ -149,8 +149,45 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
case
LLCP_TLV_OPT
:
local
->
remote_opt
=
llcp_tlv_opt
(
tlv
);
break
;
default:
pr_err
(
"Invalid gt tlv value 0x%x
\n
"
,
type
);
break
;
}
offset
+=
length
+
2
;
tlv
+=
length
+
2
;
}
pr_debug
(
"version 0x%x miu %d lto %d opt 0x%x wks 0x%x
\n
"
,
local
->
remote_version
,
local
->
remote_miu
,
local
->
remote_lto
,
local
->
remote_opt
,
local
->
remote_wks
);
return
0
;
}
int
nfc_llcp_parse_connection_tlv
(
struct
nfc_llcp_sock
*
sock
,
u8
*
tlv_array
,
u16
tlv_array_len
)
{
u8
*
tlv
=
tlv_array
,
type
,
length
,
offset
=
0
;
pr_debug
(
"TLV array length %d
\n
"
,
tlv_array_len
);
if
(
sock
==
NULL
)
return
-
ENOTCONN
;
while
(
offset
<
tlv_array_len
)
{
type
=
tlv
[
0
];
length
=
tlv
[
1
];
pr_debug
(
"type 0x%x length %d
\n
"
,
type
,
length
);
switch
(
type
)
{
case
LLCP_TLV_MIUX
:
sock
->
miu
=
llcp_tlv_miux
(
tlv
)
+
128
;
break
;
case
LLCP_TLV_RW
:
local
->
remote_
rw
=
llcp_tlv_rw
(
tlv
);
sock
->
rw
=
llcp_tlv_rw
(
tlv
);
break
;
case
LLCP_TLV_SN
:
break
;
...
...
@@ -163,10 +200,7 @@ int nfc_llcp_parse_tlv(struct nfc_llcp_local *local,
tlv
+=
length
+
2
;
}
pr_debug
(
"version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d
\n
"
,
local
->
remote_version
,
local
->
remote_miu
,
local
->
remote_lto
,
local
->
remote_opt
,
local
->
remote_wks
,
local
->
remote_rw
);
pr_debug
(
"sock %p rw %d miu %d
\n
"
,
sock
,
sock
->
rw
,
sock
->
miu
);
return
0
;
}
...
...
@@ -474,7 +508,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
while
(
remaining_len
>
0
)
{
frag_len
=
min_t
(
size_t
,
local
->
remote_
miu
,
remaining_len
);
frag_len
=
min_t
(
size_t
,
sock
->
miu
,
remaining_len
);
pr_debug
(
"Fragment %zd bytes remaining %zd"
,
frag_len
,
remaining_len
);
...
...
net/nfc/llcp/llcp.c
浏览文件 @
2e486868
...
...
@@ -31,47 +31,41 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
static
struct
list_head
llcp_devices
;
static
void
nfc_llcp_socket_release
(
struct
nfc_llcp_local
*
local
)
void
nfc_llcp_sock_link
(
struct
llcp_sock_list
*
l
,
struct
sock
*
sk
)
{
struct
nfc_llcp_sock
*
parent
,
*
s
,
*
n
;
struct
sock
*
sk
,
*
parent_sk
;
int
i
;
mutex_lock
(
&
local
->
socket_lock
);
for
(
i
=
0
;
i
<
LLCP_MAX_SAP
;
i
++
)
{
parent
=
local
->
sockets
[
i
];
if
(
parent
==
NULL
)
continue
;
/* Release all child sockets */
list_for_each_entry_safe
(
s
,
n
,
&
parent
->
list
,
list
)
{
list_del_init
(
&
s
->
list
);
sk
=
&
s
->
sk
;
lock_sock
(
sk
);
if
(
sk
->
sk_state
==
LLCP_CONNECTED
)
nfc_put_device
(
s
->
dev
);
write_lock
(
&
l
->
lock
);
sk_add_node
(
sk
,
&
l
->
head
);
write_unlock
(
&
l
->
lock
);
}
sk
->
sk_state
=
LLCP_CLOSED
;
void
nfc_llcp_sock_unlink
(
struct
llcp_sock_list
*
l
,
struct
sock
*
sk
)
{
write_lock
(
&
l
->
lock
);
sk_del_node_init
(
sk
);
write_unlock
(
&
l
->
lock
);
}
release_sock
(
sk
);
static
void
nfc_llcp_socket_release
(
struct
nfc_llcp_local
*
local
)
{
struct
sock
*
sk
;
struct
hlist_node
*
node
,
*
tmp
;
struct
nfc_llcp_sock
*
llcp_sock
;
sock_orphan
(
s
k
);
write_lock
(
&
local
->
sockets
.
loc
k
);
s
->
local
=
NULL
;
}
sk_for_each_safe
(
sk
,
node
,
tmp
,
&
local
->
sockets
.
head
)
{
llcp_sock
=
nfc_llcp_sock
(
sk
);
parent_sk
=
&
parent
->
sk
;
lock_sock
(
sk
)
;
lock_sock
(
parent_sk
);
if
(
sk
->
sk_state
==
LLCP_CONNECTED
)
nfc_put_device
(
llcp_sock
->
dev
);
if
(
parent_
sk
->
sk_state
==
LLCP_LISTEN
)
{
if
(
sk
->
sk_state
==
LLCP_LISTEN
)
{
struct
nfc_llcp_sock
*
lsk
,
*
n
;
struct
sock
*
accept_sk
;
list_for_each_entry_safe
(
lsk
,
n
,
&
parent
->
accept_queue
,
list_for_each_entry_safe
(
lsk
,
n
,
&
llcp_sock
->
accept_queue
,
accept_queue
)
{
accept_sk
=
&
lsk
->
sk
;
lock_sock
(
accept_sk
);
...
...
@@ -83,24 +77,53 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
release_sock
(
accept_sk
);
sock_orphan
(
accept_sk
);
lsk
->
local
=
NULL
;
}
}
if
(
parent_sk
->
sk_state
==
LLCP_CONNECTED
)
nfc_put_device
(
parent
->
dev
);
parent_sk
->
sk_state
=
LLCP_CLOSED
;
sk
->
sk_state
=
LLCP_CLOSED
;
release_sock
(
parent_
sk
);
release_sock
(
sk
);
sock_orphan
(
parent_
sk
);
sock_orphan
(
sk
);
parent
->
local
=
NULL
;
sk_del_node_init
(
sk
)
;
}
mutex_unlock
(
&
local
->
socket_lock
);
write_unlock
(
&
local
->
sockets
.
lock
);
}
struct
nfc_llcp_local
*
nfc_llcp_local_get
(
struct
nfc_llcp_local
*
local
)
{
kref_get
(
&
local
->
ref
);
return
local
;
}
static
void
local_release
(
struct
kref
*
ref
)
{
struct
nfc_llcp_local
*
local
;
local
=
container_of
(
ref
,
struct
nfc_llcp_local
,
ref
);
list_del
(
&
local
->
list
);
nfc_llcp_socket_release
(
local
);
del_timer_sync
(
&
local
->
link_timer
);
skb_queue_purge
(
&
local
->
tx_queue
);
destroy_workqueue
(
local
->
tx_wq
);
destroy_workqueue
(
local
->
rx_wq
);
destroy_workqueue
(
local
->
timeout_wq
);
kfree_skb
(
local
->
rx_pending
);
kfree
(
local
);
}
int
nfc_llcp_local_put
(
struct
nfc_llcp_local
*
local
)
{
WARN_ON
(
local
==
NULL
);
if
(
local
==
NULL
)
return
0
;
return
kref_put
(
&
local
->
ref
,
local_release
);
}
static
void
nfc_llcp_clear_sdp
(
struct
nfc_llcp_local
*
local
)
...
...
@@ -384,31 +407,9 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
return
-
EINVAL
;
}
return
nfc_llcp_parse_tlv
(
local
,
&
local
->
remote_gb
[
3
],
local
->
remote_gb_len
-
3
);
}
static
void
nfc_llcp_tx_work
(
struct
work_struct
*
work
)
{
struct
nfc_llcp_local
*
local
=
container_of
(
work
,
struct
nfc_llcp_local
,
tx_work
);
struct
sk_buff
*
skb
;
skb
=
skb_dequeue
(
&
local
->
tx_queue
);
if
(
skb
!=
NULL
)
{
pr_debug
(
"Sending pending skb
\n
"
);
print_hex_dump
(
KERN_DEBUG
,
"LLCP Tx: "
,
DUMP_PREFIX_OFFSET
,
16
,
1
,
skb
->
data
,
skb
->
len
,
true
);
nfc_data_exchange
(
local
->
dev
,
local
->
target_idx
,
skb
,
nfc_llcp_recv
,
local
);
}
else
{
nfc_llcp_send_symm
(
local
->
dev
);
}
mod_timer
(
&
local
->
link_timer
,
jiffies
+
msecs_to_jiffies
(
local
->
remote_lto
));
return
nfc_llcp_parse_gb_tlv
(
local
,
&
local
->
remote_gb
[
3
],
local
->
remote_gb_len
-
3
);
}
static
u8
nfc_llcp_dsap
(
struct
sk_buff
*
pdu
)
...
...
@@ -443,46 +444,146 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
sock
->
recv_ack_n
=
(
sock
->
recv_n
-
1
)
%
16
;
}
static
void
nfc_llcp_tx_work
(
struct
work_struct
*
work
)
{
struct
nfc_llcp_local
*
local
=
container_of
(
work
,
struct
nfc_llcp_local
,
tx_work
);
struct
sk_buff
*
skb
;
struct
sock
*
sk
;
struct
nfc_llcp_sock
*
llcp_sock
;
skb
=
skb_dequeue
(
&
local
->
tx_queue
);
if
(
skb
!=
NULL
)
{
sk
=
skb
->
sk
;
llcp_sock
=
nfc_llcp_sock
(
sk
);
if
(
llcp_sock
!=
NULL
)
{
int
ret
;
pr_debug
(
"Sending pending skb
\n
"
);
print_hex_dump
(
KERN_DEBUG
,
"LLCP Tx: "
,
DUMP_PREFIX_OFFSET
,
16
,
1
,
skb
->
data
,
skb
->
len
,
true
);
ret
=
nfc_data_exchange
(
local
->
dev
,
local
->
target_idx
,
skb
,
nfc_llcp_recv
,
local
);
if
(
!
ret
&&
nfc_llcp_ptype
(
skb
)
==
LLCP_PDU_I
)
{
skb
=
skb_get
(
skb
);
skb_queue_tail
(
&
llcp_sock
->
tx_pending_queue
,
skb
);
}
}
else
{
nfc_llcp_send_symm
(
local
->
dev
);
}
}
else
{
nfc_llcp_send_symm
(
local
->
dev
);
}
mod_timer
(
&
local
->
link_timer
,
jiffies
+
msecs_to_jiffies
(
2
*
local
->
remote_lto
));
}
static
struct
nfc_llcp_sock
*
nfc_llcp_connecting_sock_get
(
struct
nfc_llcp_local
*
local
,
u8
ssap
)
{
struct
sock
*
sk
;
struct
nfc_llcp_sock
*
llcp_sock
;
struct
hlist_node
*
node
;
read_lock
(
&
local
->
connecting_sockets
.
lock
);
sk_for_each
(
sk
,
node
,
&
local
->
connecting_sockets
.
head
)
{
llcp_sock
=
nfc_llcp_sock
(
sk
);
if
(
llcp_sock
->
ssap
==
ssap
)
{
sock_hold
(
&
llcp_sock
->
sk
);
goto
out
;
}
}
llcp_sock
=
NULL
;
out:
read_unlock
(
&
local
->
connecting_sockets
.
lock
);
return
llcp_sock
;
}
static
struct
nfc_llcp_sock
*
nfc_llcp_sock_get
(
struct
nfc_llcp_local
*
local
,
u8
ssap
,
u8
dsap
)
{
struct
nfc_llcp_sock
*
sock
,
*
llcp_sock
,
*
n
;
struct
sock
*
sk
;
struct
hlist_node
*
node
;
struct
nfc_llcp_sock
*
llcp_sock
;
pr_debug
(
"ssap dsap %d %d
\n
"
,
ssap
,
dsap
);
if
(
ssap
==
0
&&
dsap
==
0
)
return
NULL
;
mutex_lock
(
&
local
->
socket_lock
);
sock
=
local
->
sockets
[
ssap
];
if
(
sock
==
NULL
)
{
mutex_unlock
(
&
local
->
socket_lock
);
return
NULL
;
}
read_lock
(
&
local
->
sockets
.
lock
);
pr_debug
(
"root dsap %d (%d)
\n
"
,
sock
->
dsap
,
dsap
)
;
llcp_sock
=
NULL
;
if
(
sock
->
dsap
==
dsap
)
{
sock_hold
(
&
sock
->
sk
);
mutex_unlock
(
&
local
->
socket_lock
);
return
sock
;
sk_for_each
(
sk
,
node
,
&
local
->
sockets
.
head
)
{
llcp_sock
=
nfc_llcp_sock
(
sk
);
if
(
llcp_sock
->
ssap
==
ssap
&&
llcp_sock
->
dsap
==
dsap
)
break
;
}
list_for_each_entry_safe
(
llcp_sock
,
n
,
&
sock
->
list
,
list
)
{
pr_debug
(
"llcp_sock %p sk %p dsap %d
\n
"
,
llcp_sock
,
&
llcp_sock
->
sk
,
llcp_sock
->
dsap
);
if
(
llcp_sock
->
dsap
==
dsap
)
{
sock_hold
(
&
llcp_sock
->
sk
);
mutex_unlock
(
&
local
->
socket_lock
);
return
llcp_sock
;
}
read_unlock
(
&
local
->
sockets
.
lock
);
if
(
llcp_sock
==
NULL
)
return
NULL
;
sock_hold
(
&
llcp_sock
->
sk
);
return
llcp_sock
;
}
static
struct
nfc_llcp_sock
*
nfc_llcp_sock_get_sn
(
struct
nfc_llcp_local
*
local
,
u8
*
sn
,
size_t
sn_len
)
{
struct
sock
*
sk
;
struct
hlist_node
*
node
;
struct
nfc_llcp_sock
*
llcp_sock
;
pr_debug
(
"sn %zd
\n
"
,
sn_len
);
if
(
sn
==
NULL
||
sn_len
==
0
)
return
NULL
;
read_lock
(
&
local
->
sockets
.
lock
);
llcp_sock
=
NULL
;
sk_for_each
(
sk
,
node
,
&
local
->
sockets
.
head
)
{
llcp_sock
=
nfc_llcp_sock
(
sk
);
if
(
llcp_sock
->
sk
.
sk_state
!=
LLCP_LISTEN
)
continue
;
if
(
llcp_sock
->
service_name
==
NULL
||
llcp_sock
->
service_name_len
==
0
)
continue
;
if
(
llcp_sock
->
service_name_len
!=
sn_len
)
continue
;
if
(
memcmp
(
sn
,
llcp_sock
->
service_name
,
sn_len
)
==
0
)
break
;
}
pr_err
(
"Could not find socket for %d %d
\n
"
,
ssap
,
dsap
);
read_unlock
(
&
local
->
sockets
.
lock
);
mutex_unlock
(
&
local
->
socket_lock
);
if
(
llcp_sock
==
NULL
)
return
NULL
;
return
NULL
;
sock_hold
(
&
llcp_sock
->
sk
);
return
llcp_sock
;
}
static
void
nfc_llcp_sock_put
(
struct
nfc_llcp_sock
*
sock
)
...
...
@@ -518,35 +619,19 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
{
struct
sock
*
new_sk
,
*
parent
;
struct
nfc_llcp_sock
*
sock
,
*
new_sock
;
u8
dsap
,
ssap
,
bound_sap
,
reason
;
u8
dsap
,
ssap
,
reason
;
dsap
=
nfc_llcp_dsap
(
skb
);
ssap
=
nfc_llcp_ssap
(
skb
);
pr_debug
(
"%d %d
\n
"
,
dsap
,
ssap
);
nfc_llcp_parse_tlv
(
local
,
&
skb
->
data
[
LLCP_HEADER_SIZE
],
skb
->
len
-
LLCP_HEADER_SIZE
);
if
(
dsap
!=
LLCP_SAP_SDP
)
{
bound_sap
=
dsap
;
mutex_lock
(
&
local
->
socket_lock
);
sock
=
local
->
sockets
[
dsap
];
if
(
sock
==
NULL
)
{
mutex_unlock
(
&
local
->
socket_lock
);
sock
=
nfc_llcp_sock_get
(
local
,
dsap
,
LLCP_SAP_SDP
);
if
(
sock
==
NULL
||
sock
->
sk
.
sk_state
!=
LLCP_LISTEN
)
{
reason
=
LLCP_DM_NOBOUND
;
goto
fail
;
}
sock_hold
(
&
sock
->
sk
);
mutex_unlock
(
&
local
->
socket_lock
);
lock_sock
(
&
sock
->
sk
);
if
(
sock
->
dsap
==
LLCP_SAP_SDP
&&
sock
->
sk
.
sk_state
==
LLCP_LISTEN
)
goto
enqueue
;
}
else
{
u8
*
sn
;
size_t
sn_len
;
...
...
@@ -559,40 +644,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
pr_debug
(
"Service name length %zu
\n
"
,
sn_len
);
mutex_lock
(
&
local
->
socket_lock
);
for
(
bound_sap
=
0
;
bound_sap
<
LLCP_LOCAL_SAP_OFFSET
;
bound_sap
++
)
{
sock
=
local
->
sockets
[
bound_sap
];
if
(
sock
==
NULL
)
continue
;
if
(
sock
->
service_name
==
NULL
||
sock
->
service_name_len
==
0
)
continue
;
if
(
sock
->
service_name_len
!=
sn_len
)
continue
;
if
(
sock
->
dsap
==
LLCP_SAP_SDP
&&
sock
->
sk
.
sk_state
==
LLCP_LISTEN
&&
!
memcmp
(
sn
,
sock
->
service_name
,
sn_len
))
{
pr_debug
(
"Found service name at SAP %d
\n
"
,
bound_sap
);
sock_hold
(
&
sock
->
sk
);
mutex_unlock
(
&
local
->
socket_lock
);
lock_sock
(
&
sock
->
sk
);
goto
enqueue
;
}
sock
=
nfc_llcp_sock_get_sn
(
local
,
sn
,
sn_len
);
if
(
sock
==
NULL
)
{
reason
=
LLCP_DM_NOBOUND
;
goto
fail
;
}
mutex_unlock
(
&
local
->
socket_lock
);
}
reason
=
LLCP_DM_NOBOUND
;
goto
fail
;
lock_sock
(
&
sock
->
sk
);
enqueue:
parent
=
&
sock
->
sk
;
if
(
sk_acceptq_is_full
(
parent
))
{
...
...
@@ -612,15 +672,19 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
new_sock
=
nfc_llcp_sock
(
new_sk
);
new_sock
->
dev
=
local
->
dev
;
new_sock
->
local
=
local
;
new_sock
->
local
=
nfc_llcp_local_get
(
local
);
new_sock
->
miu
=
local
->
remote_miu
;
new_sock
->
nfc_protocol
=
sock
->
nfc_protocol
;
new_sock
->
ssap
=
bound_
sap
;
new_sock
->
ssap
=
sock
->
s
sap
;
new_sock
->
dsap
=
ssap
;
new_sock
->
parent
=
parent
;
nfc_llcp_parse_connection_tlv
(
new_sock
,
&
skb
->
data
[
LLCP_HEADER_SIZE
],
skb
->
len
-
LLCP_HEADER_SIZE
);
pr_debug
(
"new sock %p sk %p
\n
"
,
new_sock
,
&
new_sock
->
sk
);
list_add_tail
(
&
new_sock
->
list
,
&
sock
->
list
);
nfc_llcp_sock_link
(
&
local
->
sockets
,
new_sk
);
nfc_llcp_accept_enqueue
(
&
sock
->
sk
,
new_sk
);
...
...
@@ -654,12 +718,12 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
pr_debug
(
"Remote ready %d tx queue len %d remote rw %d"
,
sock
->
remote_ready
,
skb_queue_len
(
&
sock
->
tx_pending_queue
),
local
->
remote_
rw
);
sock
->
rw
);
/* Try to queue some I frames for transmission */
while
(
sock
->
remote_ready
&&
skb_queue_len
(
&
sock
->
tx_pending_queue
)
<
local
->
remote_
rw
)
{
struct
sk_buff
*
pdu
,
*
pending_pdu
;
skb_queue_len
(
&
sock
->
tx_pending_queue
)
<
sock
->
rw
)
{
struct
sk_buff
*
pdu
;
pdu
=
skb_dequeue
(
&
sock
->
tx_queue
);
if
(
pdu
==
NULL
)
...
...
@@ -668,10 +732,7 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock)
/* Update N(S)/N(R) */
nfc_llcp_set_nrns
(
sock
,
pdu
);
pending_pdu
=
skb_clone
(
pdu
,
GFP_KERNEL
);
skb_queue_tail
(
&
local
->
tx_queue
,
pdu
);
skb_queue_tail
(
&
sock
->
tx_pending_queue
,
pending_pdu
);
nr_frames
++
;
}
...
...
@@ -728,11 +789,21 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
llcp_sock
->
send_ack_n
=
nr
;
skb_queue_walk_safe
(
&
llcp_sock
->
tx_pending_queue
,
s
,
tmp
)
if
(
nfc_llcp_ns
(
s
)
<=
nr
)
{
skb_unlink
(
s
,
&
llcp_sock
->
tx_pending_queue
);
kfree_skb
(
s
);
}
/* Remove and free all skbs until ns == nr */
skb_queue_walk_safe
(
&
llcp_sock
->
tx_pending_queue
,
s
,
tmp
)
{
skb_unlink
(
s
,
&
llcp_sock
->
tx_pending_queue
);
kfree_skb
(
s
);
if
(
nfc_llcp_ns
(
s
)
==
nr
)
break
;
}
/* Re-queue the remaining skbs for transmission */
skb_queue_reverse_walk_safe
(
&
llcp_sock
->
tx_pending_queue
,
s
,
tmp
)
{
skb_unlink
(
s
,
&
llcp_sock
->
tx_pending_queue
);
skb_queue_head
(
&
local
->
tx_queue
,
s
);
}
}
if
(
ptype
==
LLCP_PDU_RR
)
...
...
@@ -740,7 +811,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
else
if
(
ptype
==
LLCP_PDU_RNR
)
llcp_sock
->
remote_ready
=
false
;
if
(
nfc_llcp_queue_i_frames
(
llcp_sock
)
==
0
)
if
(
nfc_llcp_queue_i_frames
(
llcp_sock
)
==
0
&&
ptype
==
LLCP_PDU_I
)
nfc_llcp_send_rr
(
llcp_sock
);
release_sock
(
sk
);
...
...
@@ -791,11 +862,7 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
dsap
=
nfc_llcp_dsap
(
skb
);
ssap
=
nfc_llcp_ssap
(
skb
);
llcp_sock
=
nfc_llcp_sock_get
(
local
,
dsap
,
ssap
);
if
(
llcp_sock
==
NULL
)
llcp_sock
=
nfc_llcp_sock_get
(
local
,
dsap
,
LLCP_SAP_SDP
);
llcp_sock
=
nfc_llcp_connecting_sock_get
(
local
,
dsap
);
if
(
llcp_sock
==
NULL
)
{
pr_err
(
"Invalid CC
\n
"
);
nfc_llcp_send_dm
(
local
,
dsap
,
ssap
,
LLCP_DM_NOCONN
);
...
...
@@ -803,11 +870,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb)
return
;
}
llcp_sock
->
dsap
=
ssap
;
sk
=
&
llcp_sock
->
sk
;
nfc_llcp_parse_tlv
(
local
,
&
skb
->
data
[
LLCP_HEADER_SIZE
],
skb
->
len
-
LLCP_HEADER_SIZE
);
/* Unlink from connecting and link to the client array */
nfc_llcp_sock_unlink
(
&
local
->
connecting_sockets
,
sk
);
nfc_llcp_sock_link
(
&
local
->
sockets
,
sk
);
llcp_sock
->
dsap
=
ssap
;
nfc_llcp_parse_connection_tlv
(
llcp_sock
,
&
skb
->
data
[
LLCP_HEADER_SIZE
],
skb
->
len
-
LLCP_HEADER_SIZE
);
sk
->
sk_state
=
LLCP_CONNECTED
;
sk
->
sk_state_change
(
sk
);
...
...
@@ -891,6 +962,21 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
return
;
}
int
nfc_llcp_data_received
(
struct
nfc_dev
*
dev
,
struct
sk_buff
*
skb
)
{
struct
nfc_llcp_local
*
local
;
local
=
nfc_llcp_find_local
(
dev
);
if
(
local
==
NULL
)
return
-
ENODEV
;
local
->
rx_pending
=
skb_get
(
skb
);
del_timer
(
&
local
->
link_timer
);
queue_work
(
local
->
rx_wq
,
&
local
->
rx_work
);
return
0
;
}
void
nfc_llcp_mac_is_down
(
struct
nfc_dev
*
dev
)
{
struct
nfc_llcp_local
*
local
;
...
...
@@ -943,8 +1029,8 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
local
->
dev
=
ndev
;
INIT_LIST_HEAD
(
&
local
->
list
);
kref_init
(
&
local
->
ref
);
mutex_init
(
&
local
->
sdp_lock
);
mutex_init
(
&
local
->
socket_lock
);
init_timer
(
&
local
->
link_timer
);
local
->
link_timer
.
data
=
(
unsigned
long
)
local
;
local
->
link_timer
.
function
=
nfc_llcp_symm_timer
;
...
...
@@ -984,11 +1070,13 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
goto
err_rx_wq
;
}
local
->
sockets
.
lock
=
__RW_LOCK_UNLOCKED
(
local
->
sockets
.
lock
);
local
->
connecting_sockets
.
lock
=
__RW_LOCK_UNLOCKED
(
local
->
connecting_sockets
.
lock
);
nfc_llcp_build_gb
(
local
);
local
->
remote_miu
=
LLCP_DEFAULT_MIU
;
local
->
remote_lto
=
LLCP_DEFAULT_LTO
;
local
->
remote_rw
=
LLCP_DEFAULT_RW
;
list_add
(
&
llcp_devices
,
&
local
->
list
);
...
...
@@ -1015,14 +1103,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
return
;
}
list_del
(
&
local
->
list
);
nfc_llcp_socket_release
(
local
);
del_timer_sync
(
&
local
->
link_timer
);
skb_queue_purge
(
&
local
->
tx_queue
);
destroy_workqueue
(
local
->
tx_wq
);
destroy_workqueue
(
local
->
rx_wq
);
kfree_skb
(
local
->
rx_pending
);
kfree
(
local
);
nfc_llcp_local_put
(
local
);
}
int
__init
nfc_llcp_init
(
void
)
...
...
net/nfc/llcp/llcp.h
浏览文件 @
2e486868
...
...
@@ -40,12 +40,18 @@ enum llcp_state {
struct
nfc_llcp_sock
;
struct
llcp_sock_list
{
struct
hlist_head
head
;
rwlock_t
lock
;
};
struct
nfc_llcp_local
{
struct
list_head
list
;
struct
nfc_dev
*
dev
;
struct
kref
ref
;
struct
mutex
sdp_lock
;
struct
mutex
socket_lock
;
struct
timer_list
link_timer
;
struct
sk_buff_head
tx_queue
;
...
...
@@ -77,24 +83,26 @@ struct nfc_llcp_local {
u16
remote_lto
;
u8
remote_opt
;
u16
remote_wks
;
u8
remote_rw
;
/* sockets array */
struct
nfc_llcp_sock
*
sockets
[
LLCP_MAX_SAP
];
struct
llcp_sock_list
sockets
;
struct
llcp_sock_list
connecting_sockets
;
};
struct
nfc_llcp_sock
{
struct
sock
sk
;
struct
list_head
list
;
struct
nfc_dev
*
dev
;
struct
nfc_llcp_local
*
local
;
u32
target_idx
;
u32
nfc_protocol
;
/* Link parameters */
u8
ssap
;
u8
dsap
;
char
*
service_name
;
size_t
service_name_len
;
u8
rw
;
u16
miu
;
/* Link variables */
u8
send_n
;
...
...
@@ -164,7 +172,11 @@ struct nfc_llcp_sock {
#define LLCP_DM_REJ 0x03
void
nfc_llcp_sock_link
(
struct
llcp_sock_list
*
l
,
struct
sock
*
s
);
void
nfc_llcp_sock_unlink
(
struct
llcp_sock_list
*
l
,
struct
sock
*
s
);
struct
nfc_llcp_local
*
nfc_llcp_find_local
(
struct
nfc_dev
*
dev
);
struct
nfc_llcp_local
*
nfc_llcp_local_get
(
struct
nfc_llcp_local
*
local
);
int
nfc_llcp_local_put
(
struct
nfc_llcp_local
*
local
);
u8
nfc_llcp_get_sdp_ssap
(
struct
nfc_llcp_local
*
local
,
struct
nfc_llcp_sock
*
sock
);
u8
nfc_llcp_get_local_ssap
(
struct
nfc_llcp_local
*
local
);
...
...
@@ -179,8 +191,10 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk);
struct
sock
*
nfc_llcp_accept_dequeue
(
struct
sock
*
sk
,
struct
socket
*
newsock
);
/* TLV API */
int
nfc_llcp_parse_tlv
(
struct
nfc_llcp_local
*
local
,
u8
*
tlv_array
,
u16
tlv_array_len
);
int
nfc_llcp_parse_gb_tlv
(
struct
nfc_llcp_local
*
local
,
u8
*
tlv_array
,
u16
tlv_array_len
);
int
nfc_llcp_parse_connection_tlv
(
struct
nfc_llcp_sock
*
sock
,
u8
*
tlv_array
,
u16
tlv_array_len
);
/* Commands API */
void
nfc_llcp_recv
(
void
*
data
,
struct
sk_buff
*
skb
,
int
err
);
...
...
net/nfc/llcp/sock.c
浏览文件 @
2e486868
...
...
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
}
llcp_sock
->
dev
=
dev
;
llcp_sock
->
local
=
local
;
llcp_sock
->
local
=
nfc_llcp_local_get
(
local
)
;
llcp_sock
->
nfc_protocol
=
llcp_addr
.
nfc_protocol
;
llcp_sock
->
service_name_len
=
min_t
(
unsigned
int
,
llcp_addr
.
service_name_len
,
...
...
@@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
if
(
llcp_sock
->
ssap
==
LLCP_MAX_SAP
)
goto
put_dev
;
local
->
sockets
[
llcp_sock
->
ssap
]
=
llcp_sock
;
nfc_llcp_sock_link
(
&
local
->
sockets
,
sk
)
;
pr_debug
(
"Socket bound to SAP %d
\n
"
,
llcp_sock
->
ssap
);
...
...
@@ -379,15 +379,6 @@ static int llcp_sock_release(struct socket *sock)
goto
out
;
}
mutex_lock
(
&
local
->
socket_lock
);
if
(
llcp_sock
==
local
->
sockets
[
llcp_sock
->
ssap
])
local
->
sockets
[
llcp_sock
->
ssap
]
=
NULL
;
else
list_del_init
(
&
llcp_sock
->
list
);
mutex_unlock
(
&
local
->
socket_lock
);
lock_sock
(
sk
);
/* Send a DISC */
...
...
@@ -412,14 +403,12 @@ static int llcp_sock_release(struct socket *sock)
}
}
/* Freeing the SAP */
if
((
sk
->
sk_state
==
LLCP_CONNECTED
&&
llcp_sock
->
ssap
>
LLCP_LOCAL_SAP_OFFSET
)
||
sk
->
sk_state
==
LLCP_BOUND
||
sk
->
sk_state
==
LLCP_LISTEN
)
nfc_llcp_put_ssap
(
llcp_sock
->
local
,
llcp_sock
->
ssap
);
nfc_llcp_put_ssap
(
llcp_sock
->
local
,
llcp_sock
->
ssap
);
release_sock
(
sk
);
nfc_llcp_sock_unlink
(
&
local
->
sockets
,
sk
);
out:
sock_orphan
(
sk
);
sock_put
(
sk
);
...
...
@@ -487,7 +476,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
}
llcp_sock
->
dev
=
dev
;
llcp_sock
->
local
=
local
;
llcp_sock
->
local
=
nfc_llcp_local_get
(
local
);
llcp_sock
->
miu
=
llcp_sock
->
local
->
remote_miu
;
llcp_sock
->
ssap
=
nfc_llcp_get_local_ssap
(
local
);
if
(
llcp_sock
->
ssap
==
LLCP_SAP_MAX
)
{
ret
=
-
ENOMEM
;
...
...
@@ -505,21 +495,26 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
llcp_sock
->
service_name_len
,
GFP_KERNEL
);
local
->
sockets
[
llcp_sock
->
ssap
]
=
llcp_sock
;
nfc_llcp_sock_link
(
&
local
->
connecting_sockets
,
sk
)
;
ret
=
nfc_llcp_send_connect
(
llcp_sock
);
if
(
ret
)
goto
put_dev
;
goto
sock_unlink
;
ret
=
sock_wait_state
(
sk
,
LLCP_CONNECTED
,
sock_sndtimeo
(
sk
,
flags
&
O_NONBLOCK
));
if
(
ret
)
goto
put_dev
;
goto
sock_unlink
;
release_sock
(
sk
);
return
0
;
sock_unlink:
nfc_llcp_put_ssap
(
local
,
llcp_sock
->
ssap
);
nfc_llcp_sock_unlink
(
&
local
->
connecting_sockets
,
sk
);
put_dev:
nfc_put_device
(
dev
);
...
...
@@ -684,13 +679,14 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
llcp_sock
->
ssap
=
0
;
llcp_sock
->
dsap
=
LLCP_SAP_SDP
;
llcp_sock
->
rw
=
LLCP_DEFAULT_RW
;
llcp_sock
->
miu
=
LLCP_DEFAULT_MIU
;
llcp_sock
->
send_n
=
llcp_sock
->
send_ack_n
=
0
;
llcp_sock
->
recv_n
=
llcp_sock
->
recv_ack_n
=
0
;
llcp_sock
->
remote_ready
=
1
;
skb_queue_head_init
(
&
llcp_sock
->
tx_queue
);
skb_queue_head_init
(
&
llcp_sock
->
tx_pending_queue
);
skb_queue_head_init
(
&
llcp_sock
->
tx_backlog_queue
);
INIT_LIST_HEAD
(
&
llcp_sock
->
list
);
INIT_LIST_HEAD
(
&
llcp_sock
->
accept_queue
);
if
(
sock
!=
NULL
)
...
...
@@ -701,8 +697,6 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
void
nfc_llcp_sock_free
(
struct
nfc_llcp_sock
*
sock
)
{
struct
nfc_llcp_local
*
local
=
sock
->
local
;
kfree
(
sock
->
service_name
);
skb_queue_purge
(
&
sock
->
tx_queue
);
...
...
@@ -711,12 +705,9 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
list_del_init
(
&
sock
->
accept_queue
);
if
(
local
!=
NULL
&&
sock
==
local
->
sockets
[
sock
->
ssap
])
local
->
sockets
[
sock
->
ssap
]
=
NULL
;
else
list_del_init
(
&
sock
->
list
);
sock
->
parent
=
NULL
;
nfc_llcp_local_put
(
sock
->
local
);
}
static
int
llcp_sock_create
(
struct
net
*
net
,
struct
socket
*
sock
,
...
...
net/nfc/nci/core.c
浏览文件 @
2e486868
...
...
@@ -387,7 +387,8 @@ static int nci_dev_down(struct nfc_dev *nfc_dev)
return
nci_close_device
(
ndev
);
}
static
int
nci_start_poll
(
struct
nfc_dev
*
nfc_dev
,
__u32
protocols
)
static
int
nci_start_poll
(
struct
nfc_dev
*
nfc_dev
,
__u32
im_protocols
,
__u32
tm_protocols
)
{
struct
nci_dev
*
ndev
=
nfc_get_drvdata
(
nfc_dev
);
int
rc
;
...
...
@@ -413,11 +414,11 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols)
return
-
EBUSY
;
}
rc
=
nci_request
(
ndev
,
nci_rf_discover_req
,
protocols
,
rc
=
nci_request
(
ndev
,
nci_rf_discover_req
,
im_
protocols
,
msecs_to_jiffies
(
NCI_RF_DISC_TIMEOUT
));
if
(
!
rc
)
ndev
->
poll_prots
=
protocols
;
ndev
->
poll_prots
=
im_
protocols
;
return
rc
;
}
...
...
@@ -521,9 +522,9 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
}
}
static
int
nci_
data_exchang
e
(
struct
nfc_dev
*
nfc_dev
,
struct
nfc_target
*
target
,
struct
sk_buff
*
skb
,
data_exchange_cb_t
cb
,
void
*
cb_context
)
static
int
nci_
transceiv
e
(
struct
nfc_dev
*
nfc_dev
,
struct
nfc_target
*
target
,
struct
sk_buff
*
skb
,
data_exchange_cb_t
cb
,
void
*
cb_context
)
{
struct
nci_dev
*
ndev
=
nfc_get_drvdata
(
nfc_dev
);
int
rc
;
...
...
@@ -556,7 +557,7 @@ static struct nfc_ops nci_nfc_ops = {
.
stop_poll
=
nci_stop_poll
,
.
activate_target
=
nci_activate_target
,
.
deactivate_target
=
nci_deactivate_target
,
.
data_exchange
=
nci_data_exchang
e
,
.
im_transceive
=
nci_transceiv
e
,
};
/* ---- Interface to NCI drivers ---- */
...
...
net/nfc/netlink.c
浏览文件 @
2e486868
...
...
@@ -49,6 +49,8 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
[
NFC_ATTR_COMM_MODE
]
=
{
.
type
=
NLA_U8
},
[
NFC_ATTR_RF_MODE
]
=
{
.
type
=
NLA_U8
},
[
NFC_ATTR_DEVICE_POWERED
]
=
{
.
type
=
NLA_U8
},
[
NFC_ATTR_IM_PROTOCOLS
]
=
{
.
type
=
NLA_U32
},
[
NFC_ATTR_TM_PROTOCOLS
]
=
{
.
type
=
NLA_U32
},
};
static
int
nfc_genl_send_target
(
struct
sk_buff
*
msg
,
struct
nfc_target
*
target
,
...
...
@@ -219,6 +221,68 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx)
return
-
EMSGSIZE
;
}
int
nfc_genl_tm_activated
(
struct
nfc_dev
*
dev
,
u32
protocol
)
{
struct
sk_buff
*
msg
;
void
*
hdr
;
msg
=
nlmsg_new
(
NLMSG_GOODSIZE
,
GFP_KERNEL
);
if
(
!
msg
)
return
-
ENOMEM
;
hdr
=
genlmsg_put
(
msg
,
0
,
0
,
&
nfc_genl_family
,
0
,
NFC_EVENT_TM_ACTIVATED
);
if
(
!
hdr
)
goto
free_msg
;
if
(
nla_put_u32
(
msg
,
NFC_ATTR_DEVICE_INDEX
,
dev
->
idx
))
goto
nla_put_failure
;
if
(
nla_put_u32
(
msg
,
NFC_ATTR_TM_PROTOCOLS
,
protocol
))
goto
nla_put_failure
;
genlmsg_end
(
msg
,
hdr
);
genlmsg_multicast
(
msg
,
0
,
nfc_genl_event_mcgrp
.
id
,
GFP_KERNEL
);
return
0
;
nla_put_failure:
genlmsg_cancel
(
msg
,
hdr
);
free_msg:
nlmsg_free
(
msg
);
return
-
EMSGSIZE
;
}
int
nfc_genl_tm_deactivated
(
struct
nfc_dev
*
dev
)
{
struct
sk_buff
*
msg
;
void
*
hdr
;
msg
=
nlmsg_new
(
NLMSG_GOODSIZE
,
GFP_KERNEL
);
if
(
!
msg
)
return
-
ENOMEM
;
hdr
=
genlmsg_put
(
msg
,
0
,
0
,
&
nfc_genl_family
,
0
,
NFC_EVENT_TM_DEACTIVATED
);
if
(
!
hdr
)
goto
free_msg
;
if
(
nla_put_u32
(
msg
,
NFC_ATTR_DEVICE_INDEX
,
dev
->
idx
))
goto
nla_put_failure
;
genlmsg_end
(
msg
,
hdr
);
genlmsg_multicast
(
msg
,
0
,
nfc_genl_event_mcgrp
.
id
,
GFP_KERNEL
);
return
0
;
nla_put_failure:
genlmsg_cancel
(
msg
,
hdr
);
free_msg:
nlmsg_free
(
msg
);
return
-
EMSGSIZE
;
}
int
nfc_genl_device_added
(
struct
nfc_dev
*
dev
)
{
struct
sk_buff
*
msg
;
...
...
@@ -519,16 +583,25 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
struct
nfc_dev
*
dev
;
int
rc
;
u32
idx
;
u32
protocols
;
u32
im_protocols
=
0
,
tm_protocols
=
0
;
pr_debug
(
"Poll start
\n
"
);
if
(
!
info
->
attrs
[
NFC_ATTR_DEVICE_INDEX
]
||
!
info
->
attrs
[
NFC_ATTR_PROTOCOLS
])
((
!
info
->
attrs
[
NFC_ATTR_IM_PROTOCOLS
]
&&
!
info
->
attrs
[
NFC_ATTR_PROTOCOLS
])
&&
!
info
->
attrs
[
NFC_ATTR_TM_PROTOCOLS
]))
return
-
EINVAL
;
idx
=
nla_get_u32
(
info
->
attrs
[
NFC_ATTR_DEVICE_INDEX
]);
protocols
=
nla_get_u32
(
info
->
attrs
[
NFC_ATTR_PROTOCOLS
]);
if
(
info
->
attrs
[
NFC_ATTR_TM_PROTOCOLS
])
tm_protocols
=
nla_get_u32
(
info
->
attrs
[
NFC_ATTR_TM_PROTOCOLS
]);
if
(
info
->
attrs
[
NFC_ATTR_IM_PROTOCOLS
])
im_protocols
=
nla_get_u32
(
info
->
attrs
[
NFC_ATTR_IM_PROTOCOLS
]);
else
if
(
info
->
attrs
[
NFC_ATTR_PROTOCOLS
])
im_protocols
=
nla_get_u32
(
info
->
attrs
[
NFC_ATTR_PROTOCOLS
]);
dev
=
nfc_get_device
(
idx
);
if
(
!
dev
)
...
...
@@ -536,7 +609,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
mutex_lock
(
&
dev
->
genl_data
.
genl_data_mutex
);
rc
=
nfc_start_poll
(
dev
,
protocols
);
rc
=
nfc_start_poll
(
dev
,
im_protocols
,
tm_
protocols
);
if
(
!
rc
)
dev
->
genl_data
.
poll_req_pid
=
info
->
snd_pid
;
...
...
net/nfc/nfc.h
浏览文件 @
2e486868
...
...
@@ -55,6 +55,7 @@ int nfc_llcp_register_device(struct nfc_dev *dev);
void
nfc_llcp_unregister_device
(
struct
nfc_dev
*
dev
);
int
nfc_llcp_set_remote_gb
(
struct
nfc_dev
*
dev
,
u8
*
gb
,
u8
gb_len
);
u8
*
nfc_llcp_general_bytes
(
struct
nfc_dev
*
dev
,
size_t
*
general_bytes_len
);
int
nfc_llcp_data_received
(
struct
nfc_dev
*
dev
,
struct
sk_buff
*
skb
);
int
__init
nfc_llcp_init
(
void
);
void
nfc_llcp_exit
(
void
);
...
...
@@ -90,6 +91,12 @@ static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len)
return
NULL
;
}
static
inline
int
nfc_llcp_data_received
(
struct
nfc_dev
*
dev
,
struct
sk_buff
*
skb
)
{
return
0
;
}
static
inline
int
nfc_llcp_init
(
void
)
{
return
0
;
...
...
@@ -128,6 +135,9 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
u8
comm_mode
,
u8
rf_mode
);
int
nfc_genl_dep_link_down_event
(
struct
nfc_dev
*
dev
);
int
nfc_genl_tm_activated
(
struct
nfc_dev
*
dev
,
u32
protocol
);
int
nfc_genl_tm_deactivated
(
struct
nfc_dev
*
dev
);
struct
nfc_dev
*
nfc_get_device
(
unsigned
int
idx
);
static
inline
void
nfc_put_device
(
struct
nfc_dev
*
dev
)
...
...
@@ -158,7 +168,7 @@ int nfc_dev_up(struct nfc_dev *dev);
int
nfc_dev_down
(
struct
nfc_dev
*
dev
);
int
nfc_start_poll
(
struct
nfc_dev
*
dev
,
u32
protocols
);
int
nfc_start_poll
(
struct
nfc_dev
*
dev
,
u32
im_protocols
,
u32
tm_
protocols
);
int
nfc_stop_poll
(
struct
nfc_dev
*
dev
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录