Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 368490
b: refs/heads/master
c: d9b8d8e
h: refs/heads/master
v: v3
  • Loading branch information
Thierry Escande authored and Samuel Ortiz committed Mar 10, 2013
1 parent 8a8934b commit 43a4be9
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e0ae7bac06ccb90bb0cf7a3362730b48c7d7f1a8
refs/heads/master: d9b8d8e19b073096d3609bbd60f82148d128b555
12 changes: 12 additions & 0 deletions trunk/include/uapi/linux/nfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ enum nfc_commands {
NFC_CMD_LLC_SET_PARAMS,
NFC_CMD_ENABLE_SE,
NFC_CMD_DISABLE_SE,
NFC_CMD_LLC_SDREQ,
NFC_EVENT_LLC_SDRES,
/* private: internal use only */
__NFC_CMD_AFTER_LAST
};
Expand Down Expand Up @@ -140,11 +142,21 @@ enum nfc_attrs {
NFC_ATTR_LLC_PARAM_RW,
NFC_ATTR_LLC_PARAM_MIUX,
NFC_ATTR_SE,
NFC_ATTR_LLC_SDP,
/* private: internal use only */
__NFC_ATTR_AFTER_LAST
};
#define NFC_ATTR_MAX (__NFC_ATTR_AFTER_LAST - 1)

enum nfc_sdp_attr {
NFC_SDP_ATTR_UNSPEC,
NFC_SDP_ATTR_URI,
NFC_SDP_ATTR_SAP,
/* private: internal use only */
__NFC_SDP_ATTR_AFTER_LAST
};
#define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1)

#define NFC_DEVICE_NAME_MAXSIZE 8
#define NFC_NFCID1_MAXSIZE 10
#define NFC_SENSB_RES_MAXSIZE 12
Expand Down
78 changes: 78 additions & 0 deletions trunk/net/nfc/llcp/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,59 @@ struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap)
return sdres;
}

struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri,
size_t uri_len)
{
struct nfc_llcp_sdp_tlv *sdreq;

pr_debug("uri: %s, len: %zu\n", uri, uri_len);

sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL);
if (sdreq == NULL)
return NULL;

sdreq->tlv_len = uri_len + 3;

if (uri[uri_len - 1] == 0)
sdreq->tlv_len--;

sdreq->tlv = kzalloc(sdreq->tlv_len + 1, GFP_KERNEL);
if (sdreq->tlv == NULL) {
kfree(sdreq);
return NULL;
}

sdreq->tlv[0] = LLCP_TLV_SDREQ;
sdreq->tlv[1] = sdreq->tlv_len - 2;
sdreq->tlv[2] = tid;

sdreq->tid = tid;
sdreq->uri = sdreq->tlv + 3;
memcpy(sdreq->uri, uri, uri_len);

INIT_HLIST_NODE(&sdreq->node);

return sdreq;
}

void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp)
{
kfree(sdp->tlv);
kfree(sdp);
}

void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head)
{
struct nfc_llcp_sdp_tlv *sdp;
struct hlist_node *n;

hlist_for_each_entry_safe(sdp, n, head, node) {
hlist_del(&sdp->node);

nfc_llcp_free_sdp_tlv(sdp);
}
}

int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
u8 *tlv_array, u16 tlv_array_len)
{
Expand Down Expand Up @@ -511,6 +558,37 @@ int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local,
return 0;
}

int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local,
struct hlist_head *tlv_list, size_t tlvs_len)
{
struct nfc_llcp_sdp_tlv *sdreq;
struct hlist_node *n;
struct sk_buff *skb;

skb = nfc_llcp_allocate_snl(local, tlvs_len);
if (IS_ERR(skb))
return PTR_ERR(skb);

mutex_lock(&local->sdreq_lock);

hlist_for_each_entry_safe(sdreq, n, tlv_list, node) {
pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri);

memcpy(skb_put(skb, sdreq->tlv_len), sdreq->tlv,
sdreq->tlv_len);

hlist_del(&sdreq->node);

hlist_add_head(&sdreq->node, &local->pending_sdreqs);
}

mutex_unlock(&local->sdreq_lock);

skb_queue_tail(&local->tx_queue, skb);

return 0;
}

int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
{
struct sk_buff *skb;
Expand Down
32 changes: 32 additions & 0 deletions trunk/net/nfc/llcp/llcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ static void local_release(struct kref *ref)
cancel_work_sync(&local->rx_work);
cancel_work_sync(&local->timeout_work);
kfree_skb(local->rx_pending);
nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs);
kfree(local);
}

Expand Down Expand Up @@ -1147,6 +1148,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
struct nfc_llcp_sdp_tlv *sdp;
HLIST_HEAD(llc_sdres_list);
size_t sdres_tlvs_len;
HLIST_HEAD(nl_sdres_list);

dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
Expand Down Expand Up @@ -1229,6 +1231,30 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
hlist_add_head(&sdp->node, &llc_sdres_list);
break;

case LLCP_TLV_SDRES:
mutex_lock(&local->sdreq_lock);

pr_debug("LLCP_TLV_SDRES: searching tid %d\n", tlv[2]);

hlist_for_each_entry(sdp, &local->pending_sdreqs, node) {
if (sdp->tid != tlv[2])
continue;

sdp->sap = tlv[3];

pr_debug("Found: uri=%s, sap=%d\n",
sdp->uri, sdp->sap);

hlist_del(&sdp->node);

hlist_add_head(&sdp->node, &nl_sdres_list);

break;
}

mutex_unlock(&local->sdreq_lock);
break;

default:
pr_err("Invalid SNL tlv value 0x%x\n", type);
break;
Expand All @@ -1239,6 +1265,9 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
}

exit:
if (!hlist_empty(&nl_sdres_list))
nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list);

if (!hlist_empty(&llc_sdres_list))
nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len);
}
Expand Down Expand Up @@ -1426,6 +1455,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
local->remote_miu = LLCP_DEFAULT_MIU;
local->remote_lto = LLCP_DEFAULT_LTO;

mutex_init(&local->sdreq_lock);
INIT_HLIST_HEAD(&local->pending_sdreqs);

list_add(&local->list, &llcp_devices);

return 0;
Expand Down
9 changes: 9 additions & 0 deletions trunk/net/nfc/llcp/llcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ struct nfc_llcp_local {
u8 remote_opt;
u16 remote_wks;

struct mutex sdreq_lock;
struct hlist_head pending_sdreqs;
u8 sdreq_next_tid;

/* sockets array */
struct llcp_sock_list sockets;
struct llcp_sock_list connecting_sockets;
Expand Down Expand Up @@ -230,14 +234,19 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length);
struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap);
struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri,
size_t uri_len);
void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);
void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head);
void nfc_llcp_recv(void *data, struct sk_buff *skb, int err);
int nfc_llcp_disconnect(struct nfc_llcp_sock *sock);
int nfc_llcp_send_symm(struct nfc_dev *dev);
int nfc_llcp_send_connect(struct nfc_llcp_sock *sock);
int nfc_llcp_send_cc(struct nfc_llcp_sock *sock);
int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local,
struct hlist_head *tlv_list, size_t tlvs_len);
int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local,
struct hlist_head *tlv_list, size_t tlvs_len);
int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason);
int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock);
int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
Expand Down
Loading

0 comments on commit 43a4be9

Please sign in to comment.