static void nfcsim_wq_recv(struct work_struct *work) { struct nfcsim *dev = container_of(work, struct nfcsim, recv_work.work); mutex_lock(&dev->lock); if (dev->shutting_down || !dev->up || !dev->clone_skb) { dev_kfree_skb(dev->clone_skb); goto exit; } if (dev->initiator) { if (!dev->cb) { DEV_ERR(dev, "Null recv callback\n"); dev_kfree_skb(dev->clone_skb); goto exit; } dev->cb(dev->cb_context, dev->clone_skb, 0); dev->cb = NULL; } else { nfc_tm_data_received(dev->nfc_dev, dev->clone_skb); } exit: dev->clone_skb = NULL; mutex_unlock(&dev->lock); }
static void nci_add_rx_data_frag(struct nci_dev *ndev, struct sk_buff *skb, __u8 pbf, __u8 conn_id, __u8 status) { int reassembly_len; int err = 0; if (status) { err = status; goto exit; } if (ndev->rx_data_reassembly) { reassembly_len = ndev->rx_data_reassembly->len; /* first, make enough room for the already accumulated data */ if (skb_cow_head(skb, reassembly_len)) { pr_err("error adding room for accumulated rx data\n"); kfree_skb(skb); skb = NULL; kfree_skb(ndev->rx_data_reassembly); ndev->rx_data_reassembly = NULL; err = -ENOMEM; goto exit; } /* second, combine the two fragments */ memcpy(skb_push(skb, reassembly_len), ndev->rx_data_reassembly->data, reassembly_len); /* third, free old reassembly */ kfree_skb(ndev->rx_data_reassembly); ndev->rx_data_reassembly = NULL; } if (pbf == NCI_PBF_CONT) { /* need to wait for next fragment, store skb and exit */ ndev->rx_data_reassembly = skb; return; } exit: if (ndev->nfc_dev->rf_mode == NFC_RF_TARGET) { /* Data received in Target mode, forward to nfc core */ err = nfc_tm_data_received(ndev->nfc_dev, skb); if (err) pr_err("unable to handle received data\n"); } else { nci_data_exchange_complete(ndev, skb, conn_id, err); } }
/* * Returns: * <= 0: driver handled the event, skb consumed * 1: driver does not handle the event, please do standard processing */ static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, struct sk_buff *skb) { struct sk_buff *rgb_skb = NULL; int r; pr_debug("hci event %d", event); switch (event) { case PN544_HCI_EVT_ACTIVATED: if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) { r = nfc_hci_target_discovered(hdev, gate); } else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, &rgb_skb); if (r < 0) goto exit; r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, NFC_COMM_PASSIVE, rgb_skb->data, rgb_skb->len); kfree_skb(rgb_skb); } else { r = -EINVAL; } break; case PN544_HCI_EVT_DEACTIVATED: r = nfc_hci_send_event(hdev, gate, NFC_HCI_EVT_END_OPERATION, NULL, 0); break; case PN544_HCI_EVT_RCV_DATA: if (skb->len < 2) { r = -EPROTO; goto exit; } if (skb->data[0] != 0) { pr_debug("data0 %d", skb->data[0]); r = -EPROTO; goto exit; } skb_pull(skb, 2); return nfc_tm_data_received(hdev->ndev, skb); default: return 1; } exit: kfree_skb(skb); return r; }
static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, struct sk_buff *skb) { int r; u8 mode; pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate); switch (event) { case MICROREAD_EVT_MREAD_CARD_FOUND: microread_target_discovered(hdev, gate, skb); return 0; case MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF: if (skb->len < 1) { kfree_skb(skb); return -EPROTO; } if (skb->data[skb->len - 1]) { kfree_skb(skb); return -EIO; } skb_trim(skb, skb->len - 1); r = nfc_tm_data_received(hdev->ndev, skb); break; case MICROREAD_EVT_MCARD_FIELD_ON: case MICROREAD_EVT_MCARD_FIELD_OFF: kfree_skb(skb); return 0; case MICROREAD_EVT_P2P_TARGET_ACTIVATED: r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, NFC_COMM_PASSIVE, skb->data, skb->len); kfree_skb(skb); break; case MICROREAD_EVT_MCARD_EXCHANGE: if (skb->len < 1) { kfree_skb(skb); return -EPROTO; } if (skb->data[skb->len-1]) { kfree_skb(skb); return -EIO; } skb_trim(skb, skb->len - 1); r = nfc_tm_data_received(hdev->ndev, skb); break; case MICROREAD_EVT_P2P_TARGET_DEACTIVATED: kfree_skb(skb); mode = 0xff; r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); if (r) break; r = nfc_hci_send_event(hdev, gate, MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0); break; default: return 1; } return r; }