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
2e486868
Commit
2e486868
authored
Jun 11, 2012
by
John W. Linville
Browse files
Options
Browse Files
Download
Plain Diff
Merge tag 'nfc-next-3.6-1' of
git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-3.0
parents
934b9d1e
51ad304c
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1106 additions
and
392 deletions
+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
No files found.
drivers/nfc/pn533.c
View file @
2e486868
...
...
@@ -45,6 +45,9 @@ static const struct usb_device_id pn533_table[] = {
};
MODULE_DEVICE_TABLE
(
usb
,
pn533_table
);
/* How much time we spend listening for initiators */
#define PN533_LISTEN_TIME 2
/* frame definitions */
#define PN533_FRAME_TAIL_SIZE 2
#define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \
...
...
@@ -74,6 +77,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_CMD_IN_RELEASE 0x52
#define PN533_CMD_IN_JUMP_FOR_DEP 0x56
#define PN533_CMD_TG_INIT_AS_TARGET 0x8c
#define PN533_CMD_TG_GET_DATA 0x86
#define PN533_CMD_TG_SET_DATA 0x8e
#define PN533_CMD_RESPONSE(cmd) (cmd + 1)
/* PN533 Return codes */
...
...
@@ -81,6 +88,9 @@ MODULE_DEVICE_TABLE(usb, pn533_table);
#define PN533_CMD_MI_MASK 0x40
#define PN533_CMD_RET_SUCCESS 0x00
/* PN533 status codes */
#define PN533_STATUS_TARGET_RELEASED 0x29
struct
pn533
;
typedef
int
(
*
pn533_cmd_complete_t
)
(
struct
pn533
*
dev
,
void
*
arg
,
...
...
@@ -97,8 +107,14 @@ struct pn533_fw_version {
};
/* PN533_CMD_RF_CONFIGURATION */
#define PN533_CFGITEM_TIMING 0x02
#define PN533_CFGITEM_MAX_RETRIES 0x05
#define PN533_CONFIG_TIMING_102 0xb
#define PN533_CONFIG_TIMING_204 0xc
#define PN533_CONFIG_TIMING_409 0xd
#define PN533_CONFIG_TIMING_819 0xe
#define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00
#define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF
...
...
@@ -108,6 +124,12 @@ struct pn533_config_max_retries {
u8
mx_rty_passive_act
;
}
__packed
;
struct
pn533_config_timing
{
u8
rfu
;
u8
atr_res_timeout
;
u8
dep_timeout
;
}
__packed
;
/* PN533_CMD_IN_LIST_PASSIVE_TARGET */
/* felica commands opcode */
...
...
@@ -144,6 +166,7 @@ enum {
PN533_POLL_MOD_424KBPS_FELICA
,
PN533_POLL_MOD_106KBPS_JEWEL
,
PN533_POLL_MOD_847KBPS_B
,
PN533_LISTEN_MOD
,
__PN533_POLL_MOD_AFTER_LAST
,
};
...
...
@@ -211,6 +234,9 @@ const struct pn533_poll_modulations poll_mod[] = {
},
.
len
=
3
,
},
[
PN533_LISTEN_MOD
]
=
{
.
len
=
0
,
},
};
/* PN533_CMD_IN_ATR */
...
...
@@ -237,7 +263,7 @@ struct pn533_cmd_jump_dep {
u8
active
;
u8
baud
;
u8
next
;
u8
gt
[];
u8
data
[];
}
__packed
;
struct
pn533_cmd_jump_dep_response
{
...
...
@@ -253,6 +279,29 @@ struct pn533_cmd_jump_dep_response {
u8
gt
[];
}
__packed
;
/* PN533_TG_INIT_AS_TARGET */
#define PN533_INIT_TARGET_PASSIVE 0x1
#define PN533_INIT_TARGET_DEP 0x2
#define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3
#define PN533_INIT_TARGET_RESP_ACTIVE 0x1
#define PN533_INIT_TARGET_RESP_DEP 0x4
struct
pn533_cmd_init_target
{
u8
mode
;
u8
mifare
[
6
];
u8
felica
[
18
];
u8
nfcid3
[
10
];
u8
gb_len
;
u8
gb
[];
}
__packed
;
struct
pn533_cmd_init_target_response
{
u8
mode
;
u8
cmd
[];
}
__packed
;
struct
pn533
{
struct
usb_device
*
udev
;
struct
usb_interface
*
interface
;
...
...
@@ -270,22 +319,31 @@ struct pn533 {
struct
workqueue_struct
*
wq
;
struct
work_struct
cmd_work
;
struct
work_struct
poll_work
;
struct
work_struct
mi_work
;
struct
work_struct
tg_work
;
struct
timer_list
listen_timer
;
struct
pn533_frame
*
wq_in_frame
;
int
wq_in_error
;
int
cancel_listen
;
pn533_cmd_complete_t
cmd_complete
;
void
*
cmd_complete_arg
;
struct
semaphore
cmd_lock
;
struct
mutex
cmd_lock
;
u8
cmd
;
struct
pn533_poll_modulations
*
poll_mod_active
[
PN533_POLL_MOD_MAX
+
1
];
u8
poll_mod_count
;
u8
poll_mod_curr
;
u32
poll_protocols
;
u32
listen_protocols
;
u8
*
gb
;
size_t
gb_len
;
u8
tgt_available_prots
;
u8
tgt_active_prot
;
u8
tgt_mode
;
};
struct
pn533_frame
{
...
...
@@ -405,7 +463,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work)
PN533_FRAME_CMD_PARAMS_LEN
(
in_frame
));
if
(
rc
!=
-
EINPROGRESS
)
up
(
&
dev
->
cmd_lock
);
mutex_unlock
(
&
dev
->
cmd_lock
);
}
static
void
pn533_recv_response
(
struct
urb
*
urb
)
...
...
@@ -583,7 +641,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
if
(
down
_trylock
(
&
dev
->
cmd_lock
))
if
(
!
mutex
_trylock
(
&
dev
->
cmd_lock
))
return
-
EBUSY
;
rc
=
__pn533_send_cmd_frame_async
(
dev
,
out_frame
,
in_frame
,
...
...
@@ -593,7 +651,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev,
return
0
;
error:
up
(
&
dev
->
cmd_lock
);
mutex_unlock
(
&
dev
->
cmd_lock
);
return
rc
;
}
...
...
@@ -963,6 +1021,11 @@ static int pn533_target_found(struct pn533 *dev,
return
0
;
}
static
inline
void
pn533_poll_next_mod
(
struct
pn533
*
dev
)
{
dev
->
poll_mod_curr
=
(
dev
->
poll_mod_curr
+
1
)
%
dev
->
poll_mod_count
;
}
static
void
pn533_poll_reset_mod_list
(
struct
pn533
*
dev
)
{
dev
->
poll_mod_count
=
0
;
...
...
@@ -975,102 +1038,283 @@ static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index)
dev
->
poll_mod_count
++
;
}
static
void
pn533_poll_create_mod_list
(
struct
pn533
*
dev
,
u32
protocols
)
static
void
pn533_poll_create_mod_list
(
struct
pn533
*
dev
,
u32
im_protocols
,
u32
tm_protocols
)
{
pn533_poll_reset_mod_list
(
dev
);
if
(
protocols
&
NFC_PROTO_MIFARE_MASK
||
protocols
&
NFC_PROTO_ISO14443_MASK
||
protocols
&
NFC_PROTO_NFC_DEP_MASK
)
if
(
im_
protocols
&
NFC_PROTO_MIFARE_MASK
||
im_
protocols
&
NFC_PROTO_ISO14443_MASK
||
im_
protocols
&
NFC_PROTO_NFC_DEP_MASK
)
pn533_poll_add_mod
(
dev
,
PN533_POLL_MOD_106KBPS_A
);
if
(
protocols
&
NFC_PROTO_FELICA_MASK
||
protocols
&
NFC_PROTO_NFC_DEP_MASK
)
{
if
(
im_
protocols
&
NFC_PROTO_FELICA_MASK
||
im_
protocols
&
NFC_PROTO_NFC_DEP_MASK
)
{
pn533_poll_add_mod
(
dev
,
PN533_POLL_MOD_212KBPS_FELICA
);
pn533_poll_add_mod
(
dev
,
PN533_POLL_MOD_424KBPS_FELICA
);
}
if
(
protocols
&
NFC_PROTO_JEWEL_MASK
)
if
(
im_
protocols
&
NFC_PROTO_JEWEL_MASK
)
pn533_poll_add_mod
(
dev
,
PN533_POLL_MOD_106KBPS_JEWEL
);
if
(
protocols
&
NFC_PROTO_ISO14443_MASK
)
if
(
im_
protocols
&
NFC_PROTO_ISO14443_MASK
)
pn533_poll_add_mod
(
dev
,
PN533_POLL_MOD_847KBPS_B
);
if
(
tm_protocols
)
pn533_poll_add_mod
(
dev
,
PN533_LISTEN_MOD
);
}
static
void
pn533_start_poll_frame
(
struct
pn533_frame
*
frame
,
struct
pn533_poll_modulations
*
mod
)
static
int
pn533_start_poll_complete
(
struct
pn533
*
dev
,
void
*
arg
,
u8
*
params
,
int
params_len
)
{
struct
pn533_poll_response
*
resp
;
int
rc
;
pn533_tx_frame_init
(
frame
,
PN533_CMD_IN_LIST_PASSIVE_TARGET
);
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
memcpy
(
PN533_FRAME_CMD_PARAMS_PTR
(
frame
),
&
mod
->
data
,
mod
->
len
);
frame
->
datalen
+=
mod
->
len
;
resp
=
(
struct
pn533_poll_response
*
)
params
;
if
(
resp
->
nbtg
)
{
rc
=
pn533_target_found
(
dev
,
resp
,
params_len
);
/* We must stop the poll after a valid target found */
if
(
rc
==
0
)
{
pn533_poll_reset_mod_list
(
dev
);
return
0
;
}
}
return
-
EAGAIN
;
}
static
int
pn533_init_target_frame
(
struct
pn533_frame
*
frame
,
u8
*
gb
,
size_t
gb_len
)
{
struct
pn533_cmd_init_target
*
cmd
;
size_t
cmd_len
;
u8
felica_params
[
18
]
=
{
0x1
,
0xfe
,
/* DEP */
0x0
,
0x0
,
0x0
,
0x0
,
0x0
,
0x0
,
/* random */
0x0
,
0x0
,
0x0
,
0x0
,
0x0
,
0x0
,
0x0
,
0x0
,
0xff
,
0xff
};
/* System code */
u8
mifare_params
[
6
]
=
{
0x1
,
0x1
,
/* SENS_RES */
0x0
,
0x0
,
0x0
,
0x40
};
/* SEL_RES for DEP */
cmd_len
=
sizeof
(
struct
pn533_cmd_init_target
)
+
gb_len
+
1
;
cmd
=
kzalloc
(
cmd_len
,
GFP_KERNEL
);
if
(
cmd
==
NULL
)
return
-
ENOMEM
;
pn533_tx_frame_init
(
frame
,
PN533_CMD_TG_INIT_AS_TARGET
);
/* DEP support only */
cmd
->
mode
|=
PN533_INIT_TARGET_DEP
;
/* Felica params */
memcpy
(
cmd
->
felica
,
felica_params
,
18
);
get_random_bytes
(
cmd
->
felica
+
2
,
6
);
/* NFCID3 */
memset
(
cmd
->
nfcid3
,
0
,
10
);
memcpy
(
cmd
->
nfcid3
,
cmd
->
felica
,
8
);
/* MIFARE params */
memcpy
(
cmd
->
mifare
,
mifare_params
,
6
);
/* General bytes */
cmd
->
gb_len
=
gb_len
;
memcpy
(
cmd
->
gb
,
gb
,
gb_len
);
/* Len Tk */
cmd
->
gb
[
gb_len
]
=
0
;
memcpy
(
PN533_FRAME_CMD_PARAMS_PTR
(
frame
),
cmd
,
cmd_len
);
frame
->
datalen
+=
cmd_len
;
pn533_tx_frame_finish
(
frame
);
kfree
(
cmd
);
return
0
;
}
static
int
pn533_start_poll_complete
(
struct
pn533
*
dev
,
void
*
arg
,
#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
static
int
pn533_tm_get_data_complete
(
struct
pn533
*
dev
,
void
*
arg
,
u8
*
params
,
int
params_len
)
{
struct
pn533_poll_response
*
resp
;
struct
pn533_poll_modulations
*
next_mod
;
int
rc
;
struct
sk_buff
*
skb_resp
=
arg
;
struct
pn533_frame
*
in_frame
=
(
struct
pn533_frame
*
)
skb_resp
->
data
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
if
(
params_len
==
-
ENOENT
)
{
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"Polling operation has been"
" stopped"
);
goto
stop_poll
;
if
(
params_len
<
0
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when starting as a target"
,
params_len
);
return
params_len
;
}
if
(
params_len
>
0
&&
params
[
0
]
!=
0
)
{
nfc_tm_deactivated
(
dev
->
nfc_dev
);
dev
->
tgt_mode
=
0
;
kfree_skb
(
skb_resp
);
return
0
;
}
skb_put
(
skb_resp
,
PN533_FRAME_SIZE
(
in_frame
));
skb_pull
(
skb_resp
,
PN533_CMD_DATAEXCH_HEAD_LEN
);
skb_trim
(
skb_resp
,
skb_resp
->
len
-
PN533_FRAME_TAIL_SIZE
);
return
nfc_tm_data_received
(
dev
->
nfc_dev
,
skb_resp
);
}
static
void
pn533_wq_tg_get_data
(
struct
work_struct
*
work
)
{
struct
pn533
*
dev
=
container_of
(
work
,
struct
pn533
,
tg_work
);
struct
pn533_frame
*
in_frame
;
struct
sk_buff
*
skb_resp
;
size_t
skb_resp_len
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
skb_resp_len
=
PN533_CMD_DATAEXCH_HEAD_LEN
+
PN533_CMD_DATAEXCH_DATA_MAXLEN
+
PN533_FRAME_TAIL_SIZE
;
skb_resp
=
nfc_alloc_recv_skb
(
skb_resp_len
,
GFP_KERNEL
);
if
(
!
skb_resp
)
return
;
in_frame
=
(
struct
pn533_frame
*
)
skb_resp
->
data
;
pn533_tx_frame_init
(
dev
->
out_frame
,
PN533_CMD_TG_GET_DATA
);
pn533_tx_frame_finish
(
dev
->
out_frame
);
pn533_send_cmd_frame_async
(
dev
,
dev
->
out_frame
,
in_frame
,
skb_resp_len
,
pn533_tm_get_data_complete
,
skb_resp
,
GFP_KERNEL
);
return
;
}
#define ATR_REQ_GB_OFFSET 17
static
int
pn533_init_target_complete
(
struct
pn533
*
dev
,
void
*
arg
,
u8
*
params
,
int
params_len
)
{
struct
pn533_cmd_init_target_response
*
resp
;
u8
frame
,
comm_mode
=
NFC_COMM_PASSIVE
,
*
gb
;
size_t
gb_len
;
int
rc
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
if
(
params_len
<
0
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when running poll"
,
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when starting as a target"
,
params_len
);
goto
stop_poll
;
return
params_len
;
}
resp
=
(
struct
pn533_poll_response
*
)
params
;
if
(
resp
->
nbtg
)
{
rc
=
pn533_target_found
(
dev
,
resp
,
params_len
);
if
(
params_len
<
ATR_REQ_GB_OFFSET
+
1
)
return
-
EINVAL
;
/* We must stop the poll after a valid target found */
if
(
rc
==
0
)
goto
stop_poll
;
resp
=
(
struct
pn533_cmd_init_target_response
*
)
params
;
if
(
rc
!=
-
EAGAIN
)
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"The target found is"
" not valid - continuing to poll"
);
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"Target mode 0x%x param len %d
\n
"
,
resp
->
mode
,
params_len
);
frame
=
resp
->
mode
&
PN533_INIT_TARGET_RESP_FRAME_MASK
;
if
(
frame
==
PN533_INIT_TARGET_RESP_ACTIVE
)
comm_mode
=
NFC_COMM_ACTIVE
;
/* Again, only DEP */
if
((
resp
->
mode
&
PN533_INIT_TARGET_RESP_DEP
)
==
0
)
return
-
EOPNOTSUPP
;
gb
=
resp
->
cmd
+
ATR_REQ_GB_OFFSET
;
gb_len
=
params_len
-
(
ATR_REQ_GB_OFFSET
+
1
);
rc
=
nfc_tm_activated
(
dev
->
nfc_dev
,
NFC_PROTO_NFC_DEP_MASK
,
comm_mode
,
gb
,
gb_len
);
if
(
rc
<
0
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error when signaling target activation"
);
return
rc
;
}
dev
->
poll_mod_curr
=
(
dev
->
poll_mod_curr
+
1
)
%
dev
->
poll_mod_count
;
dev
->
tgt_mode
=
1
;
next_mod
=
dev
->
poll_mod_active
[
dev
->
poll_mod_curr
]
;
queue_work
(
dev
->
wq
,
&
dev
->
tg_work
)
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"Polling next modulation (0x%x)"
,
dev
->
poll_mod_curr
);
return
0
;
}
static
void
pn533_listen_mode_timer
(
unsigned
long
data
)
{
struct
pn533
*
dev
=
(
struct
pn533
*
)
data
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"Listen mode timeout"
);
/* An ack will cancel the last issued command (poll) */
pn533_send_ack
(
dev
,
GFP_ATOMIC
);
dev
->
cancel_listen
=
1
;
mutex_unlock
(
&
dev
->
cmd_lock
);
pn533_poll_next_mod
(
dev
);
queue_work
(
dev
->
wq
,
&
dev
->
poll_work
);
}
pn533_start_poll_frame
(
dev
->
out_frame
,
next_mod
);
static
int
pn533_poll_complete
(
struct
pn533
*
dev
,
void
*
arg
,
u8
*
params
,
int
params_len
)
{
struct
pn533_poll_modulations
*
cur_mod
;
int
rc
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
/* Don't need to down the semaphore again */
rc
=
__pn533_send_cmd_frame_async
(
dev
,
dev
->
out_frame
,
dev
->
in_frame
,
dev
->
in_maxlen
,
pn533_start_poll_complete
,
NULL
,
GFP_ATOMIC
);
if
(
params_len
==
-
ENOENT
)
{
if
(
dev
->
poll_mod_count
!=
0
)
return
0
;
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Polling operation has been stopped"
);
if
(
rc
==
-
EPERM
)
{
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"Cannot poll next modulation"
" because poll has been stopped"
);
goto
stop_poll
;
}
if
(
rc
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when trying to poll"
" next modulation"
,
rc
);
if
(
params_len
<
0
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when running poll"
,
params_len
);
goto
stop_poll
;
}
/* Inform caller function to do not up the semaphore */
return
-
EINPROGRESS
;
cur_mod
=
dev
->
poll_mod_active
[
dev
->
poll_mod_curr
];
if
(
cur_mod
->
len
==
0
)
{
del_timer
(
&
dev
->
listen_timer
);
return
pn533_init_target_complete
(
dev
,
arg
,
params
,
params_len
);
}
else
{
rc
=
pn533_start_poll_complete
(
dev
,
arg
,
params
,
params_len
);
if
(
!
rc
)
return
rc
;
}
pn533_poll_next_mod
(
dev
);
queue_work
(
dev
->
wq
,
&
dev
->
poll_work
);
return
0
;
stop_poll:
pn533_poll_reset_mod_list
(
dev
);
...
...
@@ -1078,61 +1322,104 @@ static int pn533_start_poll_complete(struct pn533 *dev, void *arg,
return
0
;
}
static
int
pn533_start_poll
(
struct
nfc_dev
*
nfc_dev
,
u32
protocols
)
static
void
pn533_build_poll_frame
(
struct
pn533
*
dev
,
struct
pn533_frame
*
frame
,
struct
pn533_poll_modulations
*
mod
)
{
struct
pn533
*
dev
=
nfc_get_drvdata
(
nfc_dev
);
struct
pn533_poll_modulations
*
start_mod
;
int
rc
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"mod len %d
\n
"
,
mod
->
len
);
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s - protocols=0x%x"
,
__func__
,
protocols
);
if
(
mod
->
len
==
0
)
{
/* Listen mode */
pn533_init_target_frame
(
frame
,
dev
->
gb
,
dev
->
gb_len
);
}
else
{
/* Polling mode */
pn533_tx_frame_init
(
frame
,
PN533_CMD_IN_LIST_PASSIVE_TARGET
);
if
(
dev
->
poll_mod_count
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Polling operation already"
" active"
);
return
-
EBUSY
;
}
memcpy
(
PN533_FRAME_CMD_PARAMS_PTR
(
frame
),
&
mod
->
data
,
mod
->
len
);
frame
->
datalen
+=
mod
->
len
;
if
(
dev
->
tgt_active_prot
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Cannot poll with a target"
" already activated"
);
return
-
EBUSY
;
pn533_tx_frame_finish
(
frame
);
}
}
pn533_poll_create_mod_list
(
dev
,
protocols
);
static
int
pn533_send_poll_frame
(
struct
pn533
*
dev
)
{
struct
pn533_poll_modulations
*
cur_mod
;
int
rc
;
if
(
!
dev
->
poll_mod_count
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"No valid protocols"
" specified"
);
rc
=
-
EINVAL
;
goto
error
;
cur_mod
=
dev
->
poll_mod_active
[
dev
->
poll_mod_curr
];
pn533_build_poll_frame
(
dev
,
dev
->
out_frame
,
cur_mod
);
rc
=
pn533_send_cmd_frame_async
(
dev
,
dev
->
out_frame
,
dev
->
in_frame
,
dev
->
in_maxlen
,
pn533_poll_complete
,
NULL
,
GFP_KERNEL
);
if
(
rc
)
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Polling loop error %d"
,
rc
);
return
rc
;
}
static
void
pn533_wq_poll
(
struct
work_struct
*
work
)
{
struct
pn533
*
dev
=
container_of
(
work
,
struct
pn533
,
poll_work
);
struct
pn533_poll_modulations
*
cur_mod
;
int
rc
;
cur_mod
=
dev
->
poll_mod_active
[
dev
->
poll_mod_curr
];
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s cancel_listen %d modulation len %d"
,
__func__
,
dev
->
cancel_listen
,
cur_mod
->
len
);
if
(
dev
->
cancel_listen
==
1
)
{
dev
->
cancel_listen
=
0
;
usb_kill_urb
(
dev
->
in_urb
);
}
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"It will poll %d modulations types"
,
dev
->
poll_mod_count
);
rc
=
pn533_send_poll_frame
(
dev
);
if
(
rc
)
return
;
dev
->
poll_mod_curr
=
0
;
start_mod
=
dev
->
poll_mod_active
[
dev
->
poll_mod_curr
]
;
if
(
cur_mod
->
len
==
0
&&
dev
->
poll_mod_count
>
1
)
mod_timer
(
&
dev
->
listen_timer
,
jiffies
+
PN533_LISTEN_TIME
*
HZ
)
;
pn533_start_poll_frame
(
dev
->
out_frame
,
start_mod
);
return
;
}
rc
=
pn533_send_cmd_frame_async
(
dev
,
dev
->
out_frame
,
dev
->
in_frame
,
dev
->
in_maxlen
,
pn533_start_poll_complete
,
NULL
,
GFP_KERNEL
);
static
int
pn533_start_poll
(
struct
nfc_dev
*
nfc_dev
,
u32
im_protocols
,
u32
tm_protocols
)
{
struct
pn533
*
dev
=
nfc_get_drvdata
(
nfc_dev
);
if
(
rc
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when trying to"
" start poll"
,
rc
);
goto
error
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s: im protocols 0x%x tm protocols 0x%x"
,
__func__
,
im_protocols
,
tm_protocols
);
if
(
dev
->
tgt_active_prot
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Cannot poll with a target already activated"
);
return
-
EBUSY
;
}
dev
->
poll_protocols
=
protocols
;
if
(
dev
->
tgt_mode
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Cannot poll while already being activated"
);
return
-
EBUSY
;
}
return
0
;
if
(
tm_protocols
)
{
dev
->
gb
=
nfc_get_local_general_bytes
(
nfc_dev
,
&
dev
->
gb_len
);
if
(
dev
->
gb
==
NULL
)
tm_protocols
=
0
;
}
error:
pn533_poll_reset_mod_list
(
dev
);
return
rc
;
dev
->
poll_mod_curr
=
0
;
pn533_poll_create_mod_list
(
dev
,
im_protocols
,
tm_protocols
);
dev
->
poll_protocols
=
im_protocols
;
dev
->
listen_protocols
=
tm_protocols
;
return
pn533_send_poll_frame
(
dev
);
}
static
void
pn533_stop_poll
(
struct
nfc_dev
*
nfc_dev
)
...
...
@@ -1141,6 +1428,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
del_timer
(
&
dev
->
listen_timer
);
if
(
!
dev
->
poll_mod_count
)
{
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"Polling operation was not"
" running"
);
...
...
@@ -1152,6 +1441,8 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev)
/* prevent pn533_start_poll_complete to issue a new poll meanwhile */
usb_kill_urb
(
dev
->
in_urb
);
pn533_poll_reset_mod_list
(
dev
);
}
static
int
pn533_activate_target_nfcdep
(
struct
pn533
*
dev
)
...
...
@@ -1349,13 +1640,29 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
return
0
;
}
static
int
pn533_mod_to_baud
(
struct
pn533
*
dev
)
{
switch
(
dev
->
poll_mod_curr
)
{
case
PN533_POLL_MOD_106KBPS_A
:
return
0
;
case
PN533_POLL_MOD_212KBPS_FELICA
:
return
1
;
case
PN533_POLL_MOD_424KBPS_FELICA
:
return
2
;
default:
return
-
EINVAL
;
}
}
#define PASSIVE_DATA_LEN 5
static
int
pn533_dep_link_up
(
struct
nfc_dev
*
nfc_dev
,
struct
nfc_target
*
target
,
u8
comm_mode
,
u8
*
gb
,
size_t
gb_len
)
{
struct
pn533
*
dev
=
nfc_get_drvdata
(
nfc_dev
);
struct
pn533_cmd_jump_dep
*
cmd
;
u8
cmd_len
;
int
rc
;
u8
cmd_len
,
*
data_ptr
;
u8
passive_data
[
PASSIVE_DATA_LEN
]
=
{
0x00
,
0xff
,
0xff
,
0x00
,
0x3
};
int
rc
,
baud
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
...
...
@@ -1371,7 +1678,17 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
return
-
EBUSY
;
}
baud
=
pn533_mod_to_baud
(
dev
);
if
(
baud
<
0
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Invalid curr modulation %d"
,
dev
->
poll_mod_curr
);
return
baud
;
}
cmd_len
=
sizeof
(
struct
pn533_cmd_jump_dep
)
+
gb_len
;
if
(
comm_mode
==
NFC_COMM_PASSIVE
)
cmd_len
+=
PASSIVE_DATA_LEN
;
cmd
=
kzalloc
(
cmd_len
,
GFP_KERNEL
);
if
(
cmd
==
NULL
)
return
-
ENOMEM
;
...
...
@@ -1379,10 +1696,18 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
pn533_tx_frame_init
(
dev
->
out_frame
,
PN533_CMD_IN_JUMP_FOR_DEP
);
cmd
->
active
=
!
comm_mode
;
cmd
->
baud
=
0
;
cmd
->
next
=
0
;
cmd
->
baud
=
baud
;
data_ptr
=
cmd
->
data
;
if
(
comm_mode
==
NFC_COMM_PASSIVE
&&
cmd
->
baud
>
0
)
{
memcpy
(
data_ptr
,
passive_data
,
PASSIVE_DATA_LEN
);
cmd
->
next
|=
1
;
data_ptr
+=
PASSIVE_DATA_LEN
;
}
if
(
gb
!=
NULL
&&
gb_len
>
0
)
{
cmd
->
next
=
4
;
/* We have some Gi */
memcpy
(
cmd
->
gt
,
gb
,
gb_len
);
cmd
->
next
|
=
4
;
/* We have some Gi */
memcpy
(
data_ptr
,
gb
,
gb_len
);
}
else
{
cmd
->
next
=
0
;
}
...
...
@@ -1407,15 +1732,25 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
static
int
pn533_dep_link_down
(
struct
nfc_dev
*
nfc_dev
)
{
pn533_deactivate_target
(
nfc_dev
,
0
);
struct
pn533
*
dev
=
nfc_get_drvdata
(
nfc_dev
);
pn533_poll_reset_mod_list
(
dev
);
if
(
dev
->
tgt_mode
||
dev
->
tgt_active_prot
)
{
pn533_send_ack
(
dev
,
GFP_KERNEL
);
usb_kill_urb
(
dev
->
in_urb
);
}
dev
->
tgt_active_prot
=
0
;
dev
->
tgt_mode
=
0
;
skb_queue_purge
(
&
dev
->
resp_q
);
return
0
;
}
#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3)
#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262
static
int
pn533_data_exchange_tx_frame
(
struct
pn533
*
dev
,
struct
sk_buff
*
skb
)
static
int
pn533_build_tx_frame
(
struct
pn533
*
dev
,
struct
sk_buff
*
skb
,
bool
target
)
{
int
payload_len
=
skb
->
len
;
struct
pn533_frame
*
out_frame
;
...
...
@@ -1432,14 +1767,20 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)
return
-
ENOSYS
;
}
if
(
target
==
true
)
{
skb_push
(
skb
,
PN533_CMD_DATAEXCH_HEAD_LEN
);
out_frame
=
(
struct
pn533_frame
*
)
skb
->
data
;
pn533_tx_frame_init
(
out_frame
,
PN533_CMD_IN_DATA_EXCHANGE
);
tg
=
1
;
memcpy
(
PN533_FRAME_CMD_PARAMS_PTR
(
out_frame
),
&
tg
,
sizeof
(
u8
));
out_frame
->
datalen
+=
sizeof
(
u8
);
}
else
{
skb_push
(
skb
,
PN533_CMD_DATAEXCH_HEAD_LEN
-
1
);
out_frame
=
(
struct
pn533_frame
*
)
skb
->
data
;
pn533_tx_frame_init
(
out_frame
,
PN533_CMD_TG_SET_DATA
);
}
/* The data is already in the out_frame, just update the datalen */
out_frame
->
datalen
+=
payload_len
;
...
...
@@ -1550,7 +1891,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
return
0
;
}
static
int
pn533_
data_exchang
e
(
struct
nfc_dev
*
nfc_dev
,
static
int
pn533_
transceiv
e
(
struct
nfc_dev
*
nfc_dev
,
struct
nfc_target
*
target
,
struct
sk_buff
*
skb
,
data_exchange_cb_t
cb
,
void
*
cb_context
)
{
...
...
@@ -1570,7 +1911,7 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev,
goto
error
;
}
rc
=
pn533_
data_exchange_tx_frame
(
dev
,
skb
);
rc
=
pn533_
build_tx_frame
(
dev
,
skb
,
true
);
if
(
rc
)
goto
error
;
...
...
@@ -1618,6 +1959,63 @@ static int pn533_data_exchange(struct nfc_dev *nfc_dev,
return
rc
;
}
static
int
pn533_tm_send_complete
(
struct
pn533
*
dev
,
void
*
arg
,
u8
*
params
,
int
params_len
)
{
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
if
(
params_len
<
0
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when sending data"
,
params_len
);
return
params_len
;
}
if
(
params_len
>
0
&&
params
[
0
]
!=
0
)
{
nfc_tm_deactivated
(
dev
->
nfc_dev
);
dev
->
tgt_mode
=
0
;
return
0
;
}
queue_work
(
dev
->
wq
,
&
dev
->
tg_work
);
return
0
;
}
static
int
pn533_tm_send
(
struct
nfc_dev
*
nfc_dev
,
struct
sk_buff
*
skb
)
{
struct
pn533
*
dev
=
nfc_get_drvdata
(
nfc_dev
);
struct
pn533_frame
*
out_frame
;
int
rc
;
nfc_dev_dbg
(
&
dev
->
interface
->
dev
,
"%s"
,
__func__
);
rc
=
pn533_build_tx_frame
(
dev
,
skb
,
false
);
if
(
rc
)
goto
error
;
out_frame
=
(
struct
pn533_frame
*
)
skb
->
data
;
rc
=
pn533_send_cmd_frame_async
(
dev
,
out_frame
,
dev
->
in_frame
,
dev
->
in_maxlen
,
pn533_tm_send_complete
,
NULL
,
GFP_KERNEL
);
if
(
rc
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error %d when trying to send data"
,
rc
);
goto
error
;
}
return
0
;
error:
kfree_skb
(
skb
);
return
rc
;
}
static
void
pn533_wq_mi_recv
(
struct
work_struct
*
work
)
{
struct
pn533
*
dev
=
container_of
(
work
,
struct
pn533
,
mi_work
);
...
...
@@ -1638,7 +2036,7 @@ static void pn533_wq_mi_recv(struct work_struct *work)
skb_reserve
(
skb_cmd
,
PN533_CMD_DATAEXCH_HEAD_LEN
);
rc
=
pn533_
data_exchange_tx_frame
(
dev
,
skb_cmd
);
rc
=
pn533_
build_tx_frame
(
dev
,
skb_cmd
,
true
);
if
(
rc
)
goto
error_frame
;
...
...
@@ -1677,7 +2075,7 @@ static void pn533_wq_mi_recv(struct work_struct *work)
kfree
(
arg
);
up
(
&
dev
->
cmd_lock
);
mutex_unlock
(
&
dev
->
cmd_lock
);
}
static
int
pn533_set_configuration
(
struct
pn533
*
dev
,
u8
cfgitem
,
u8
*
cfgdata
,
...
...
@@ -1712,7 +2110,8 @@ struct nfc_ops pn533_nfc_ops = {
.
stop_poll
=
pn533_stop_poll
,
.
activate_target
=
pn533_activate_target
,
.
deactivate_target
=
pn533_deactivate_target
,
.
data_exchange
=
pn533_data_exchange
,
.
im_transceive
=
pn533_transceive
,
.
tm_send
=
pn533_tm_send
,
};
static
int
pn533_probe
(
struct
usb_interface
*
interface
,
...
...
@@ -1723,6 +2122,7 @@ static int pn533_probe(struct usb_interface *interface,
struct
usb_host_interface
*
iface_desc
;
struct
usb_endpoint_descriptor
*
endpoint
;
struct
pn533_config_max_retries
max_retries
;
struct
pn533_config_timing
timing
;
int
in_endpoint
=
0
;
int
out_endpoint
=
0
;
int
rc
=
-
ENOMEM
;
...
...
@@ -1735,7 +2135,7 @@ static int pn533_probe(struct usb_interface *interface,
dev
->
udev
=
usb_get_dev
(
interface_to_usbdev
(
interface
));
dev
->
interface
=
interface
;
sema_init
(
&
dev
->
cmd_lock
,
1
);
mutex_init
(
&
dev
->
cmd_lock
);
iface_desc
=
interface
->
cur_altsetting
;
for
(
i
=
0
;
i
<
iface_desc
->
desc
.
bNumEndpoints
;
++
i
)
{
...
...
@@ -1779,12 +2179,18 @@ static int pn533_probe(struct usb_interface *interface,
INIT_WORK
(
&
dev
->
cmd_work
,
pn533_wq_cmd_complete
);
INIT_WORK
(
&
dev
->
mi_work
,
pn533_wq_mi_recv
);
INIT_WORK
(
&
dev
->
tg_work
,
pn533_wq_tg_get_data
);
INIT_WORK
(
&
dev
->
poll_work
,
pn533_wq_poll
);
dev
->
wq
=
alloc_workqueue
(
"pn533"
,
WQ_NON_REENTRANT
|
WQ_UNBOUND
|
WQ_MEM_RECLAIM
,
1
);
if
(
dev
->
wq
==
NULL
)
goto
error
;
init_timer
(
&
dev
->
listen_timer
);
dev
->
listen_timer
.
data
=
(
unsigned
long
)
dev
;
dev
->
listen_timer
.
function
=
pn533_listen_mode_timer
;
skb_queue_head_init
(
&
dev
->
resp_q
);
usb_set_intfdata
(
interface
,
dev
);
...
...
@@ -1830,13 +2236,29 @@ static int pn533_probe(struct usb_interface *interface,
if
(
rc
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error on setting MAX_RETRIES"
" config"
);
goto
free_nfc_dev
;
goto
unregister_nfc_dev
;
}
timing
.
rfu
=
PN533_CONFIG_TIMING_102
;
timing
.
atr_res_timeout
=
PN533_CONFIG_TIMING_204
;
timing
.
dep_timeout
=
PN533_CONFIG_TIMING_409
;
rc
=
pn533_set_configuration
(
dev
,
PN533_CFGITEM_TIMING
,
(
u8
*
)
&
timing
,
sizeof
(
timing
));
if
(
rc
)
{
nfc_dev_err
(
&
dev
->
interface
->
dev
,
"Error on setting RF timings"
);
goto
unregister_nfc_dev
;
}
return
0
;
unregister_nfc_dev:
nfc_unregister_device
(
dev
->
nfc_dev
);
free_nfc_dev:
nfc_free_device
(
dev
->
nfc_dev
);
destroy_wq:
destroy_workqueue
(
dev
->
wq
);
error:
...
...
@@ -1865,6 +2287,8 @@ static void pn533_disconnect(struct usb_interface *interface)
skb_queue_purge
(
&
dev
->
resp_q
);
del_timer
(
&
dev
->
listen_timer
);
kfree
(
dev
->
in_frame
);
usb_free_urb
(
dev
->
in_urb
);
kfree
(
dev
->
out_frame
);
...
...
drivers/nfc/pn544_hci.c
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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,12 +408,7 @@ 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
);
...
...
@@ -424,12 +418,20 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb,
if
(
dev
->
ops
->
check_presence
)
del_timer_sync
(
&
dev
->
check_pres_timer
);
rc
=
dev
->
ops
->
data_exchang
e
(
dev
,
dev
->
active_target
,
skb
,
cb
,
rc
=
dev
->
ops
->
im_transceiv
e
(
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
;
}
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
View file @
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,7 +512,7 @@ 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
,
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
)
{
...
...
@@ -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
View file @
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
View file @
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,7 +117,7 @@ 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
,
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
View file @
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
;
write_lock
(
&
l
->
lock
);
sk_add_node
(
sk
,
&
l
->
head
);
write_unlock
(
&
l
->
lock
);
}
mutex_lock
(
&
local
->
socket_lock
);
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
);
}
for
(
i
=
0
;
i
<
LLCP_MAX_SAP
;
i
++
)
{
parent
=
local
->
sockets
[
i
];
if
(
parent
==
NULL
)
continue
;
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
;
/* Release all child sockets */
list_for_each_entry_safe
(
s
,
n
,
&
parent
->
list
,
list
)
{
list_del_init
(
&
s
->
list
);
sk
=
&
s
->
sk
;
write_lock
(
&
local
->
sockets
.
lock
);
sk_for_each_safe
(
sk
,
node
,
tmp
,
&
local
->
sockets
.
head
)
{
llcp_sock
=
nfc_llcp_sock
(
sk
)
;
lock_sock
(
sk
);
if
(
sk
->
sk_state
==
LLCP_CONNECTED
)
nfc_put_device
(
s
->
dev
);
sk
->
sk_state
=
LLCP_CLOSED
;
release_sock
(
sk
);
nfc_put_device
(
llcp_sock
->
dev
);
sock_orphan
(
sk
);
s
->
local
=
NULL
;
}
parent_sk
=
&
parent
->
sk
;
lock_sock
(
parent_sk
);
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,33 +407,11 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
return
-
EINVAL
;
}
return
nfc_llcp_parse_tlv
(
local
,
return
nfc_llcp_parse_
gb_
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
));
}
static
u8
nfc_llcp_dsap
(
struct
sk_buff
*
pdu
)
{
return
(
pdu
->
data
[
0
]
&
0xfc
)
>>
2
;
...
...
@@ -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
)
{
read_unlock
(
&
local
->
sockets
.
lock
);
if
(
llcp_sock
==
NULL
)
return
NULL
;
sock_hold
(
&
llcp_sock
->
sk
);
mutex_unlock
(
&
local
->
socket_lock
);
return
llcp_sock
;
}
}
}
pr_err
(
"Could not find socket for %d %d
\n
"
,
ssap
,
dsap
);
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
;
mutex_unlock
(
&
local
->
socket_lock
);
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
;
}
read_unlock
(
&
local
->
sockets
.
lock
);
if
(
llcp_sock
==
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,10 +789,20 @@ 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
)
{
/* 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
);
}
}
...
...
@@ -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,10 +870,14 @@ 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
],
/* 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
;
...
...
@@ -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
View file @
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,7 +191,9 @@ 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
,
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 */
...
...
net/nfc/llcp/sock.c
View file @
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
);
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
View file @
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,7 +522,7 @@ 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
,
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
)
{
...
...
@@ -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
View file @
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
View file @
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
);
...
...
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