aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2015-10-25 17:54:21 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2015-10-26 01:53:12 -0400
commitd8cd37ed2fc871c66b4c79c59f651dc2cdf7091c (patch)
tree4fcc84a67e9cc2c259ecf6e3cf34f5ff67e49722 /net/nfc
parent500c4ef02277eaadbfe20537f963b6221f6ac007 (diff)
NFC: nci: Fix improper management of HCI return code
When sending HCI data over NCI, HCI return code is part of the NCI data. In order to get correctly the HCI return code, we assume the NCI communication is successful and extract the return code for the nci_hci functions return code. This is done because nci_to_errno does not match hci return code value. Cc: stable@vger.kernel.org Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/nci/hci.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c
index 321889ee2107..b07092f4111b 100644
--- a/net/nfc/nci/hci.c
+++ b/net/nfc/nci/hci.c
@@ -101,6 +101,20 @@ struct nci_hcp_packet {
101#define NCI_HCP_MSG_GET_CMD(header) (header & 0x3f) 101#define NCI_HCP_MSG_GET_CMD(header) (header & 0x3f)
102#define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f) 102#define NCI_HCP_MSG_GET_PIPE(header) (header & 0x7f)
103 103
104static int nci_hci_result_to_errno(u8 result)
105{
106 switch (result) {
107 case NCI_HCI_ANY_OK:
108 return 0;
109 case NCI_HCI_ANY_E_REG_PAR_UNKNOWN:
110 return -EOPNOTSUPP;
111 case NCI_HCI_ANY_E_TIMEOUT:
112 return -ETIME;
113 default:
114 return -1;
115 }
116}
117
104/* HCI core */ 118/* HCI core */
105static void nci_hci_reset_pipes(struct nci_hci_dev *hdev) 119static void nci_hci_reset_pipes(struct nci_hci_dev *hdev)
106{ 120{
@@ -218,7 +232,8 @@ int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
218 const u8 *param, size_t param_len, 232 const u8 *param, size_t param_len,
219 struct sk_buff **skb) 233 struct sk_buff **skb)
220{ 234{
221 struct nci_conn_info *conn_info; 235 struct nci_hcp_message *message;
236 struct nci_conn_info *conn_info;
222 struct nci_data data; 237 struct nci_data data;
223 int r; 238 int r;
224 u8 pipe = ndev->hci_dev->gate2pipe[gate]; 239 u8 pipe = ndev->hci_dev->gate2pipe[gate];
@@ -238,9 +253,15 @@ int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate, u8 cmd,
238 253
239 r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data, 254 r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
240 msecs_to_jiffies(NCI_DATA_TIMEOUT)); 255 msecs_to_jiffies(NCI_DATA_TIMEOUT));
241 256 if (r == NCI_STATUS_OK) {
242 if (r == NCI_STATUS_OK && skb) 257 message = (struct nci_hcp_message *)conn_info->rx_skb->data;
243 *skb = conn_info->rx_skb; 258 r = nci_hci_result_to_errno(
259 NCI_HCP_MSG_GET_CMD(message->header));
260 skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
261
262 if (!r && skb)
263 *skb = conn_info->rx_skb;
264 }
244 265
245 return r; 266 return r;
246} 267}
@@ -334,9 +355,6 @@ static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
334 struct nci_conn_info *conn_info; 355 struct nci_conn_info *conn_info;
335 u8 status = result; 356 u8 status = result;
336 357
337 if (result != NCI_HCI_ANY_OK)
338 goto exit;
339
340 conn_info = ndev->hci_dev->conn_info; 358 conn_info = ndev->hci_dev->conn_info;
341 if (!conn_info) { 359 if (!conn_info) {
342 status = NCI_STATUS_REJECTED; 360 status = NCI_STATUS_REJECTED;
@@ -346,7 +364,7 @@ static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe,
346 conn_info->rx_skb = skb; 364 conn_info->rx_skb = skb;
347 365
348exit: 366exit:
349 nci_req_complete(ndev, status); 367 nci_req_complete(ndev, NCI_STATUS_OK);
350} 368}
351 369
352/* Receive hcp message for pipe, with type and cmd. 370/* Receive hcp message for pipe, with type and cmd.
@@ -401,7 +419,7 @@ void nci_hci_data_received_cb(void *context,
401{ 419{
402 struct nci_dev *ndev = (struct nci_dev *)context; 420 struct nci_dev *ndev = (struct nci_dev *)context;
403 struct nci_hcp_packet *packet; 421 struct nci_hcp_packet *packet;
404 u8 pipe, type, instruction; 422 u8 pipe, type;
405 struct sk_buff *hcp_skb; 423 struct sk_buff *hcp_skb;
406 struct sk_buff *frag_skb; 424 struct sk_buff *frag_skb;
407 int msg_len; 425 int msg_len;
@@ -440,7 +458,7 @@ void nci_hci_data_received_cb(void *context,
440 *skb_put(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN) = pipe; 458 *skb_put(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN) = pipe;
441 459
442 skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) { 460 skb_queue_walk(&ndev->hci_dev->rx_hcp_frags, frag_skb) {
443 msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN; 461 msg_len = frag_skb->len - NCI_HCI_HCP_PACKET_HEADER_LEN;
444 memcpy(skb_put(hcp_skb, msg_len), frag_skb->data + 462 memcpy(skb_put(hcp_skb, msg_len), frag_skb->data +
445 NCI_HCI_HCP_PACKET_HEADER_LEN, msg_len); 463 NCI_HCI_HCP_PACKET_HEADER_LEN, msg_len);
446 } 464 }
@@ -458,11 +476,10 @@ void nci_hci_data_received_cb(void *context,
458 packet = (struct nci_hcp_packet *)hcp_skb->data; 476 packet = (struct nci_hcp_packet *)hcp_skb->data;
459 type = NCI_HCP_MSG_GET_TYPE(packet->message.header); 477 type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
460 if (type == NCI_HCI_HCP_RESPONSE) { 478 if (type == NCI_HCI_HCP_RESPONSE) {
461 pipe = packet->header; 479 pipe = NCI_HCP_MSG_GET_PIPE(packet->header);
462 instruction = NCI_HCP_MSG_GET_CMD(packet->message.header); 480 skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN);
463 skb_pull(hcp_skb, NCI_HCI_HCP_PACKET_HEADER_LEN + 481 nci_hci_hcp_message_rx(ndev, pipe, type,
464 NCI_HCI_HCP_MESSAGE_HEADER_LEN); 482 NCI_STATUS_OK, hcp_skb);
465 nci_hci_hcp_message_rx(ndev, pipe, type, instruction, hcp_skb);
466 } else { 483 } else {
467 skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb); 484 skb_queue_tail(&ndev->hci_dev->msg_rx_queue, hcp_skb);
468 schedule_work(&ndev->hci_dev->msg_rx_work); 485 schedule_work(&ndev->hci_dev->msg_rx_work);
@@ -494,6 +511,7 @@ EXPORT_SYMBOL(nci_hci_open_pipe);
494int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx, 511int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
495 const u8 *param, size_t param_len) 512 const u8 *param, size_t param_len)
496{ 513{
514 struct nci_hcp_message *message;
497 struct nci_conn_info *conn_info; 515 struct nci_conn_info *conn_info;
498 struct nci_data data; 516 struct nci_data data;
499 int r; 517 int r;
@@ -526,6 +544,12 @@ int nci_hci_set_param(struct nci_dev *ndev, u8 gate, u8 idx,
526 r = nci_request(ndev, nci_hci_send_data_req, 544 r = nci_request(ndev, nci_hci_send_data_req,
527 (unsigned long)&data, 545 (unsigned long)&data,
528 msecs_to_jiffies(NCI_DATA_TIMEOUT)); 546 msecs_to_jiffies(NCI_DATA_TIMEOUT));
547 if (r == NCI_STATUS_OK) {
548 message = (struct nci_hcp_message *)conn_info->rx_skb->data;
549 r = nci_hci_result_to_errno(
550 NCI_HCP_MSG_GET_CMD(message->header));
551 skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
552 }
529 553
530 kfree(tmp); 554 kfree(tmp);
531 return r; 555 return r;
@@ -535,6 +559,7 @@ EXPORT_SYMBOL(nci_hci_set_param);
535int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx, 559int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
536 struct sk_buff **skb) 560 struct sk_buff **skb)
537{ 561{
562 struct nci_hcp_message *message;
538 struct nci_conn_info *conn_info; 563 struct nci_conn_info *conn_info;
539 struct nci_data data; 564 struct nci_data data;
540 int r; 565 int r;
@@ -559,8 +584,15 @@ int nci_hci_get_param(struct nci_dev *ndev, u8 gate, u8 idx,
559 r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data, 584 r = nci_request(ndev, nci_hci_send_data_req, (unsigned long)&data,
560 msecs_to_jiffies(NCI_DATA_TIMEOUT)); 585 msecs_to_jiffies(NCI_DATA_TIMEOUT));
561 586
562 if (r == NCI_STATUS_OK) 587 if (r == NCI_STATUS_OK) {
563 *skb = conn_info->rx_skb; 588 message = (struct nci_hcp_message *)conn_info->rx_skb->data;
589 r = nci_hci_result_to_errno(
590 NCI_HCP_MSG_GET_CMD(message->header));
591 skb_pull(conn_info->rx_skb, NCI_HCI_HCP_MESSAGE_HEADER_LEN);
592
593 if (!r && skb)
594 *skb = conn_info->rx_skb;
595 }
564 596
565 return r; 597 return r;
566} 598}