Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 368489
b: refs/heads/master
c: e0ae7ba
h: refs/heads/master
i:
  368487: b99ad8e
v: v3
  • Loading branch information
Thierry Escande authored and Samuel Ortiz committed Mar 10, 2013
1 parent 89cafcb commit 8a8934b
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8af362d124ce250cafb50cb488b4beb69fee3373
refs/heads/master: e0ae7bac06ccb90bb0cf7a3362730b48c7d7f1a8
82 changes: 61 additions & 21 deletions trunk/net/nfc/llcp/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,39 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
return tlv;
}

struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap)
{
struct nfc_llcp_sdp_tlv *sdres;
u8 value[2];

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

value[0] = tid;
value[1] = sap;

sdres->tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, value, 2,
&sdres->tlv_len);
if (sdres->tlv == NULL) {
kfree(sdres);
return NULL;
}

sdres->tid = tid;
sdres->sap = sap;

INIT_HLIST_NODE(&sdres->node);

return sdres;
}

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

int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
u8 *tlv_array, u16 tlv_array_len)
{
Expand Down Expand Up @@ -425,48 +458,55 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
return err;
}

int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap)
static struct sk_buff *nfc_llcp_allocate_snl(struct nfc_llcp_local *local,
size_t tlv_length)
{
struct sk_buff *skb;
struct nfc_dev *dev;
u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2];
u16 size = 0;

pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap);

if (local == NULL)
return -ENODEV;
return ERR_PTR(-ENODEV);

dev = local->dev;
if (dev == NULL)
return -ENODEV;

sdres[0] = tid;
sdres[1] = sap;
sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0,
&sdres_tlv_length);
if (sdres_tlv == NULL)
return -ENOMEM;
return ERR_PTR(-ENODEV);

size += LLCP_HEADER_SIZE;
size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
size += sdres_tlv_length;
size += tlv_length;

skb = alloc_skb(size, GFP_KERNEL);
if (skb == NULL) {
kfree(sdres_tlv);
return -ENOMEM;
}
if (skb == NULL)
return ERR_PTR(-ENOMEM);

skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);

skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL);

memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length);
return skb;
}

skb_queue_tail(&local->tx_queue, skb);
int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local,
struct hlist_head *tlv_list, size_t tlvs_len)
{
struct nfc_llcp_sdp_tlv *sdp;
struct hlist_node *n;
struct sk_buff *skb;

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

hlist_for_each_entry_safe(sdp, n, tlv_list, node) {
memcpy(skb_put(skb, sdp->tlv_len), sdp->tlv, sdp->tlv_len);

kfree(sdres_tlv);
hlist_del(&sdp->node);

nfc_llcp_free_sdp_tlv(sdp);
}

skb_queue_tail(&local->tx_queue, skb);

return 0;
}
Expand Down
23 changes: 18 additions & 5 deletions trunk/net/nfc/llcp/llcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,9 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
u16 tlv_len, offset;
char *service_name;
size_t service_name_len;
struct nfc_llcp_sdp_tlv *sdp;
HLIST_HEAD(llc_sdres_list);
size_t sdres_tlvs_len;

dsap = nfc_llcp_dsap(skb);
ssap = nfc_llcp_ssap(skb);
Expand All @@ -1158,6 +1161,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
tlv = &skb->data[LLCP_HEADER_SIZE];
tlv_len = skb->len - LLCP_HEADER_SIZE;
offset = 0;
sdres_tlvs_len = 0;

while (offset < tlv_len) {
type = tlv[0];
Expand All @@ -1175,14 +1179,14 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
!strncmp(service_name, "urn:nfc:sn:sdp",
service_name_len)) {
sap = 1;
goto send_snl;
goto add_snl;
}

llcp_sock = nfc_llcp_sock_from_sn(local, service_name,
service_name_len);
if (!llcp_sock) {
sap = 0;
goto send_snl;
goto add_snl;
}

/*
Expand All @@ -1199,7 +1203,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,

if (sap == LLCP_SAP_MAX) {
sap = 0;
goto send_snl;
goto add_snl;
}

client_count =
Expand All @@ -1216,8 +1220,13 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,

pr_debug("%p %d\n", llcp_sock, sap);

send_snl:
nfc_llcp_send_snl(local, tid, sap);
add_snl:
sdp = nfc_llcp_build_sdres_tlv(tid, sap);
if (sdp == NULL)
goto exit;

sdres_tlvs_len += sdp->tlv_len;
hlist_add_head(&sdp->node, &llc_sdres_list);
break;

default:
Expand All @@ -1228,6 +1237,10 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
offset += length + 2;
tlv += length + 2;
}

exit:
if (!hlist_empty(&llc_sdres_list))
nfc_llcp_send_snl_sdres(local, &llc_sdres_list, sdres_tlvs_len);
}

static void nfc_llcp_rx_work(struct work_struct *work)
Expand Down
16 changes: 15 additions & 1 deletion trunk/net/nfc/llcp/llcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ struct llcp_sock_list {
rwlock_t lock;
};

struct nfc_llcp_sdp_tlv {
u8 *tlv;
u8 tlv_len;

char *uri;
u8 tid;
u8 sap;

struct hlist_node node;
};

struct nfc_llcp_local {
struct list_head list;
struct nfc_dev *dev;
Expand Down Expand Up @@ -218,12 +229,15 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
/* Commands API */
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);
void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);
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(struct nfc_llcp_local *local, u8 tid, u8 sap);
int nfc_llcp_send_snl_sdres(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

0 comments on commit 8a8934b

Please sign in to comment.