1cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* 2cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * HCI based Driver for Inside Secure microread NFC Chip 3cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * 4cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * Copyright (C) 2013 Intel Corporation. All rights reserved. 5cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * 6cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * This program is free software; you can redistribute it and/or modify it 7cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * under the terms and conditions of the GNU General Public License, 8cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * version 2, as published by the Free Software Foundation. 9cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * 10cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * This program is distributed in the hope that it will be useful, 11cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * but WITHOUT ANY WARRANTY; without even the implied warranty of 12cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * GNU General Public License for more details. 14cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * 15cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * You should have received a copy of the GNU General Public License 1698b32decc83ed3137e3ddbc918b102f8fc406b6dJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>. 17cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade */ 18cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 1917936b43f0fdede23582d83a45622751409c99b9Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2017936b43f0fdede23582d83a45622751409c99b9Joe Perches 21cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <linux/module.h> 22cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <linux/delay.h> 23cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <linux/slab.h> 24cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <linux/crc-ccitt.h> 25cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 26cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <linux/nfc.h> 27cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <net/nfc/nfc.h> 28cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <net/nfc/hci.h> 29cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include <net/nfc/llc.h> 30cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 31cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#include "microread.h" 32cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 33cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Proprietary gates, events, commands and registers */ 34cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Admin */ 35cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_ADM NFC_HCI_ADMIN_GATE 36cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MGT 0x01 37cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_OS 0x02 38cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_TESTRF 0x03 39cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_LOOPBACK NFC_HCI_LOOPBACK_GATE 40cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_IDT NFC_HCI_ID_MGMT_GATE 41cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_LMS NFC_HCI_LINK_MGMT_GATE 42cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 43cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Reader */ 44cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_GEN 0x10 45cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_ISO_B NFC_HCI_RF_READER_B_GATE 46cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_NFC_T1 0x12 47cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_ISO_A NFC_HCI_RF_READER_A_GATE 48cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_NFC_T3 0x14 49cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_ISO_15_3 0x15 50cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_ISO_15_2 0x16 51cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_ISO_B_3 0x17 52cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_BPRIME 0x18 53cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MREAD_ISO_A_3 0x19 54cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 55cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Card */ 56cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_GEN 0x20 57cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_ISO_B 0x21 58cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_BPRIME 0x22 59cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_ISO_A 0x23 60cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_NFC_T3 0x24 61cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_ISO_15_3 0x25 62cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_ISO_15_2 0x26 63cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_ISO_B_2 0x27 64cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_MCARD_ISO_CUSTOM 0x28 65cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_SECURE_ELEMENT 0x2F 66cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 67cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* P2P */ 68cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_P2P_GEN 0x30 69cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_P2P_TARGET 0x31 70cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PAR_P2P_TARGET_MODE 0x01 71cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PAR_P2P_TARGET_GT 0x04 72cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_GATE_ID_P2P_INITIATOR 0x32 73cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PAR_P2P_INITIATOR_GI 0x01 74cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PAR_P2P_INITIATOR_GT 0x03 75cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 76cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Those pipes are created/opened by default in the chip */ 77cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_LMS 0x00 78cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_ADMIN 0x01 79cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_MGT 0x02 80cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_OS 0x03 81cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_LOOPBACK 0x04 82cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_IDT 0x05 83cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B 0x08 84cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_BPRIME 0x09 85cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_A 0x0A 86cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_3 0x0B 87cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_2 0x0C 88cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_NFC_T3 0x0D 89cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B_2 0x0E 90cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MCARD_CUSTOM 0x0F 91cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B 0x10 92cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1 0x11 93cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A 0x12 94cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_3 0x13 95cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_2 0x14 96cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3 0x15 97cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B_3 0x16 98cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_BPRIME 0x17 99cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3 0x18 100cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_MREAD_GEN 0x1B 101cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_STACKED_ELEMENT 0x1C 102cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_INSTANCES 0x1D 103cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_TESTRF 0x1E 104cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_P2P_TARGET 0x1F 105cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_PIPE_ID_HDS_P2P_INITIATOR 0x20 106cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 107cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Events */ 108cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MREAD_DISCOVERY_OCCURED NFC_HCI_EVT_TARGET_DISCOVERED 109cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MREAD_CARD_FOUND 0x3D 110cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A_ATQA 0 111cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A_SAK 2 112cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A_LEN 3 113cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A_UID 4 114cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A3_ATQA 0 115cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A3_SAK 2 116cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A3_LEN 3 117cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_A3_UID 4 118cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_B_UID 0 119cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_T1_ATQA 0 120cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_T1_UID 4 121cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EMCF_T3_UID 0 122cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MREAD_DISCOVERY_START NFC_HCI_EVT_READER_REQUESTED 123cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MREAD_DISCOVERY_START_SOME 0x3E 124cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MREAD_DISCOVERY_STOP NFC_HCI_EVT_END_OPERATION 125cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MREAD_SIM_REQUESTS 0x3F 126cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MCARD_EXCHANGE NFC_HCI_EVT_TARGET_DISCOVERED 127cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF 0x20 128cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF 0x21 129cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MCARD_FIELD_ON 0x11 130cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_P2P_TARGET_ACTIVATED 0x13 131cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_P2P_TARGET_DEACTIVATED 0x12 132cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_EVT_MCARD_FIELD_OFF 0x14 133cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 134cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Commands */ 135cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_CMD_MREAD_EXCHANGE 0x10 136cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_CMD_MREAD_SUBSCRIBE 0x3F 137cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 138cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Hosts IDs */ 139cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_ELT_ID_HDS NFC_HCI_TERMINAL_HOST_ID 140cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_ELT_ID_SIM NFC_HCI_UICC_HOST_ID 141cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_ELT_ID_SE1 0x03 142cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_ELT_ID_SE2 0x04 143cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_ELT_ID_SE3 0x05 144cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 145cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic struct nfc_hci_gate microread_gates[] = { 146cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_ADM, MICROREAD_PIPE_ID_ADMIN}, 147cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_LOOPBACK, MICROREAD_PIPE_ID_HDS_LOOPBACK}, 148cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_IDT, MICROREAD_PIPE_ID_HDS_IDT}, 149cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_LMS, MICROREAD_PIPE_ID_LMS}, 150cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_MREAD_ISO_B, MICROREAD_PIPE_ID_HDS_MREAD_ISO_B}, 151cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_MREAD_ISO_A, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A}, 152cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_MREAD_ISO_A_3, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3}, 153cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_MGT, MICROREAD_PIPE_ID_MGT}, 154cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_OS, MICROREAD_PIPE_ID_OS}, 155cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_MREAD_NFC_T1, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1}, 156cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_MREAD_NFC_T3, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3}, 157cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_P2P_TARGET, MICROREAD_PIPE_ID_HDS_P2P_TARGET}, 158cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade {MICROREAD_GATE_ID_P2P_INITIATOR, MICROREAD_PIPE_ID_HDS_P2P_INITIATOR} 159cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade}; 160cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 161cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* Largest headroom needed for outgoing custom commands */ 162cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_CMDS_HEADROOM 2 163cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_CMD_TAILROOM 2 164cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 165cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestruct microread_info { 166cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_phy_ops *phy_ops; 167cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade void *phy_id; 168cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 169cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_hci_dev *hdev; 170cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 171cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int async_cb_type; 172cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade data_exchange_cb_t async_cb; 173cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade void *async_cb_context; 174cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade}; 175cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 176cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_open(struct nfc_hci_dev *hdev) 177cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 178cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct microread_info *info = nfc_hci_get_clientdata(hdev); 179cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 180cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return info->phy_ops->enable(info->phy_id); 181cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 182cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 183cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic void microread_close(struct nfc_hci_dev *hdev) 184cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 185cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct microread_info *info = nfc_hci_get_clientdata(hdev); 186cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 187cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->phy_ops->disable(info->phy_id); 188cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 189cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 190cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_hci_ready(struct nfc_hci_dev *hdev) 191cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 192cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int r; 193cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 param[4]; 194cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 195cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] = 0x03; 196cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, 197cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMD_MREAD_SUBSCRIBE, param, 1, NULL); 198cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 199cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 200cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 201cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A_3, 202cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL); 203cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 204cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 205cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 206cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] = 0x00; 207cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[1] = 0x03; 208cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[2] = 0x00; 209cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_B, 210cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMD_MREAD_SUBSCRIBE, param, 3, NULL); 211cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 212cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 213cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 214cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T1, 215cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL); 216cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 217cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 218cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 219cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] = 0xFF; 220cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[1] = 0xFF; 221cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[2] = 0x00; 222cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[3] = 0x00; 223cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T3, 224cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMD_MREAD_SUBSCRIBE, param, 4, NULL); 225cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 226cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 227cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 228cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 229cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) 230cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 231cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct microread_info *info = nfc_hci_get_clientdata(hdev); 232cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 233cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return info->phy_ops->write(info->phy_id, skb); 234cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 235cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 236cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_start_poll(struct nfc_hci_dev *hdev, 237cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u32 im_protocols, u32 tm_protocols) 238cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 239cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int r; 240cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 241cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 param[2]; 242cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 mode; 243cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 244cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] = 0x00; 245cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[1] = 0x00; 246cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 247cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (im_protocols & NFC_PROTO_ISO14443_MASK) 248cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] |= (1 << 2); 249cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 250cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (im_protocols & NFC_PROTO_ISO14443_B_MASK) 251cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] |= 1; 252cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 253cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (im_protocols & NFC_PROTO_MIFARE_MASK) 254cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[1] |= 1; 255cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 256cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (im_protocols & NFC_PROTO_JEWEL_MASK) 257cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] |= (1 << 1); 258cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 259cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (im_protocols & NFC_PROTO_FELICA_MASK) 260cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[0] |= (1 << 5); 261cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 262cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (im_protocols & NFC_PROTO_NFC_DEP_MASK) 263cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param[1] |= (1 << 1); 264cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 265cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { 266cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade hdev->gb = nfc_get_local_general_bytes(hdev->ndev, 267cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade &hdev->gb_len); 268cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (hdev->gb == NULL || hdev->gb_len == 0) { 269cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 270cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 271cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 272cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 273cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 274cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, 275cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0); 276cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 277cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 278cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 279cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade mode = 0xff; 280cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, 281cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); 282cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 283cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 284cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 285cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { 286cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_INITIATOR, 287cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_PAR_P2P_INITIATOR_GI, 288cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade hdev->gb, hdev->gb_len); 289cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 290cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 291cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 292cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 293cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { 294cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, 295cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_PAR_P2P_TARGET_GT, 296cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade hdev->gb, hdev->gb_len); 297cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 298cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 299cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 300cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade mode = 0x02; 301cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, 302cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); 303cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 304cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 305cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 306cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 307cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, 308cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_EVT_MREAD_DISCOVERY_START_SOME, 309cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade param, 2); 310cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 311cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 312cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_dep_link_up(struct nfc_hci_dev *hdev, 313cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_target *target, u8 comm_mode, 314cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 *gb, size_t gb_len) 315cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 316cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct sk_buff *rgb_skb = NULL; 317cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int r; 318cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 319cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_get_param(hdev, target->hci_reader_gate, 320cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_PAR_P2P_INITIATOR_GT, &rgb_skb); 321cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r < 0) 322cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 323cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 324cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { 325cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = -EPROTO; 326cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade goto exit; 327cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 328cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 329cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, 330cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade rgb_skb->len); 331cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r == 0) 332cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, 333cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade NFC_RF_INITIATOR); 334cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadeexit: 335cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(rgb_skb); 336cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 337cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 338cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 339cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 340cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_dep_link_down(struct nfc_hci_dev *hdev) 341cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 342cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_INITIATOR, 343cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0); 344cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 345cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 346cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, 347cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_target *target) 348cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 349cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade switch (gate) { 350cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_P2P_INITIATOR: 351cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; 352cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 353cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade default: 354cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return -EPROTO; 355cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 356cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 357cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return 0; 358cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 359cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 360cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_complete_target_discovered(struct nfc_hci_dev *hdev, 361cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 gate, 362cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_target *target) 363cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 364cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return 0; 365cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 366cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 367cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade#define MICROREAD_CB_TYPE_READER_ALL 1 368cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 369cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic void microread_im_transceive_cb(void *context, struct sk_buff *skb, 370cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int err) 371cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 372cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct microread_info *info = context; 373cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 374cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade switch (info->async_cb_type) { 375cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_CB_TYPE_READER_ALL: 376cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (err == 0) { 377cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (skb->len == 0) { 378cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade err = -EPROTO; 379cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 380cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->async_cb(info->async_cb_context, NULL, 381cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade -EPROTO); 382cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return; 383cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 384cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 385cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (skb->data[skb->len - 1] != 0) { 386cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade err = nfc_hci_result_to_errno( 387cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb->data[skb->len - 1]); 388cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 389cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->async_cb(info->async_cb_context, NULL, 390cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade err); 391cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return; 392cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 393cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 394cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb_trim(skb, skb->len - 1); /* RF Error ind. */ 395cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 396cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->async_cb(info->async_cb_context, skb, err); 397cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 398cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade default: 399cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (err == 0) 400cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 401cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 402cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 403cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 404cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 405cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade/* 406cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * Returns: 407cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * <= 0: driver handled the data exchange 408cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade * 1: driver doesn't especially handle, please do standard processing 409cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade */ 410cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_im_transceive(struct nfc_hci_dev *hdev, 411cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_target *target, 412cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct sk_buff *skb, data_exchange_cb_t cb, 413cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade void *cb_context) 414cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 415cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct microread_info *info = nfc_hci_get_clientdata(hdev); 416cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 control_bits; 417cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u16 crc; 418cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 419cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade pr_info("data exchange to gate 0x%x\n", target->hci_reader_gate); 420cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 421cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (target->hci_reader_gate == MICROREAD_GATE_ID_P2P_INITIATOR) { 422cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade *skb_push(skb, 1) = 0; 423cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 424cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return nfc_hci_send_event(hdev, target->hci_reader_gate, 425cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF, 426cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb->data, skb->len); 427cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 428cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 429cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade switch (target->hci_reader_gate) { 430cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_ISO_A: 431cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade control_bits = 0xCB; 432cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 433cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_ISO_A_3: 434cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade control_bits = 0xCB; 435cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 436cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_ISO_B: 437cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade control_bits = 0xCB; 438cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 439cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_NFC_T1: 440cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade control_bits = 0x1B; 441cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 442cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade crc = crc_ccitt(0xffff, skb->data, skb->len); 443cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade crc = ~crc; 444cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade *skb_put(skb, 1) = crc & 0xff; 445cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade *skb_put(skb, 1) = crc >> 8; 446cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 447cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_NFC_T3: 448cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade control_bits = 0xDB; 449cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 450cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade default: 451cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade pr_info("Abort im_transceive to invalid gate 0x%x\n", 452cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade target->hci_reader_gate); 453cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return 1; 454cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 455cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 456cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade *skb_push(skb, 1) = control_bits; 457cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 458cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->async_cb_type = MICROREAD_CB_TYPE_READER_ALL; 459cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->async_cb = cb; 460cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->async_cb_context = cb_context; 461cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 462cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 463cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMD_MREAD_EXCHANGE, 464cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb->data, skb->len, 465cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade microread_im_transceive_cb, info); 466cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 467cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 468cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) 469cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 470cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int r; 471cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 472cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_TARGET, 473cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_EVT_MCARD_EXCHANGE, 474cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb->data, skb->len); 475cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 476cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 477cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 478cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 479cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 480cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 481cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate, 482cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct sk_buff *skb) 483cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 484cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_target *targets; 485cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int r = 0; 486cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 487cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade pr_info("target discovered to gate 0x%x\n", gate); 488cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 489cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); 490cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (targets == NULL) { 491cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = -ENOMEM; 492cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade goto exit; 493cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 494cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 495cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->hci_reader_gate = gate; 496cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 497cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade switch (gate) { 498cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_ISO_A: 499cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->supported_protocols = 500cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A_SAK]); 501cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->sens_res = 502cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]); 503cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK]; 504cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN]; 505d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter if (targets->nfcid1_len > sizeof(targets->nfcid1)) { 506d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter r = -EINVAL; 507d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter goto exit_free; 508d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter } 509d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID], 510d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter targets->nfcid1_len); 511cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 512cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_ISO_A_3: 513cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->supported_protocols = 514cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A3_SAK]); 515cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->sens_res = 516cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]); 517cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK]; 518cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN]; 519d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter if (targets->nfcid1_len > sizeof(targets->nfcid1)) { 520d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter r = -EINVAL; 521d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter goto exit_free; 522d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter } 523d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID], 524d07f1e8600ccb885c8f4143402b8912f7d827bcbDan Carpenter targets->nfcid1_len); 525cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 526cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_ISO_B: 527cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; 528cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_B_UID], 4); 529cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->nfcid1_len = 4; 530cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 531cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_NFC_T1: 532cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->supported_protocols = NFC_PROTO_JEWEL_MASK; 533cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->sens_res = 534cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade le16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_T1_ATQA]); 535cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T1_UID], 4); 536cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->nfcid1_len = 4; 537cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 538cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_GATE_ID_MREAD_NFC_T3: 539cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->supported_protocols = NFC_PROTO_FELICA_MASK; 540cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T3_UID], 8); 541cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade targets->nfcid1_len = 8; 542cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 543cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade default: 544cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade pr_info("discard target discovered to gate 0x%x\n", gate); 545cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade goto exit_free; 546cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 547cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 548cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_targets_found(hdev->ndev, targets, 1); 549cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 550cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadeexit_free: 551cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree(targets); 552cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 553cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadeexit: 554cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 555cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 556cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 55717936b43f0fdede23582d83a45622751409c99b9Joe Perches pr_err("Failed to handle discovered target err=%d\n", r); 558cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 559cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 560cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic int microread_event_received(struct nfc_hci_dev *hdev, u8 gate, 561cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 event, struct sk_buff *skb) 562cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 563cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int r; 564cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade u8 mode; 565cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 566cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate); 567cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 568cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade switch (event) { 569cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_EVT_MREAD_CARD_FOUND: 570cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade microread_target_discovered(hdev, gate, skb); 571cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return 0; 572cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 573cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF: 574cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (skb->len < 1) { 575cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 576cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return -EPROTO; 577cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 578cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 579cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (skb->data[skb->len - 1]) { 580cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 581cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return -EIO; 582cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 583cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 584cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb_trim(skb, skb->len - 1); 585cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 586cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_tm_data_received(hdev->ndev, skb); 587cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 588cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 589cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_EVT_MCARD_FIELD_ON: 590cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_EVT_MCARD_FIELD_OFF: 591cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 592cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return 0; 593cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 594cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_EVT_P2P_TARGET_ACTIVATED: 595cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, 596cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade NFC_COMM_PASSIVE, skb->data, 597cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb->len); 598cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 599cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 600cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 601cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 602cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_EVT_MCARD_EXCHANGE: 603cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (skb->len < 1) { 604cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 605cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return -EPROTO; 606cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 607cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 608cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (skb->data[skb->len-1]) { 609cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 610cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return -EIO; 611cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 612cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 613cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade skb_trim(skb, skb->len - 1); 614cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 615cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_tm_data_received(hdev->ndev, skb); 616cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 617cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 618cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade case MICROREAD_EVT_P2P_TARGET_DEACTIVATED: 619cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree_skb(skb); 620cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 621cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade mode = 0xff; 622cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, 623cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); 624cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 625cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 626cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 627cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_send_event(hdev, gate, 628cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 629cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 0); 630cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade break; 631cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 632cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade default: 633cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return 1; 634cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 635cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 636cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 637cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 638cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 639cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadestatic struct nfc_hci_ops microread_hci_ops = { 640cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .open = microread_open, 641cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .close = microread_close, 642cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .hci_ready = microread_hci_ready, 643cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .xmit = microread_xmit, 644cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .start_poll = microread_start_poll, 645cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .dep_link_up = microread_dep_link_up, 646cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .dep_link_down = microread_dep_link_down, 647cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .target_from_gate = microread_target_from_gate, 648cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .complete_target_discovered = microread_complete_target_discovered, 649cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .im_transceive = microread_im_transceive, 650cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .tm_send = microread_tm_send, 651cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .check_presence = NULL, 652cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade .event_received = microread_event_received, 653cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade}; 654cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 655cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadeint microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, 656cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int phy_headroom, int phy_tailroom, int phy_payload, 657cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_hci_dev **hdev) 658cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 659cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct microread_info *info; 660cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade unsigned long quirks = 0; 6610b456c418a5595b9d67f300c9ac6a2441e774603Samuel Ortiz u32 protocols; 662cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct nfc_hci_init_data init_data; 663cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade int r; 664cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 665cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info = kzalloc(sizeof(struct microread_info), GFP_KERNEL); 666cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (!info) { 667cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = -ENOMEM; 668cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade goto err_info_alloc; 669cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 670cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 671cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->phy_ops = phy_ops; 672cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->phy_id = phy_id; 673cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 674cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade init_data.gate_count = ARRAY_SIZE(microread_gates); 675cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade memcpy(init_data.gates, microread_gates, sizeof(microread_gates)); 676cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 677cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade strcpy(init_data.session_id, "MICROREA"); 678cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 679cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); 680cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 681cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade protocols = NFC_PROTO_JEWEL_MASK | 682cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade NFC_PROTO_MIFARE_MASK | 683cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade NFC_PROTO_FELICA_MASK | 684cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade NFC_PROTO_ISO14443_MASK | 685cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade NFC_PROTO_ISO14443_B_MASK | 686cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade NFC_PROTO_NFC_DEP_MASK; 687cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 688cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade info->hdev = nfc_hci_allocate_device(µread_hci_ops, &init_data, 6890b456c418a5595b9d67f300c9ac6a2441e774603Samuel Ortiz quirks, protocols, llc_name, 690cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade phy_headroom + 691cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMDS_HEADROOM, 692cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade phy_tailroom + 693cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade MICROREAD_CMD_TAILROOM, 694cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade phy_payload); 695cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (!info->hdev) { 69617936b43f0fdede23582d83a45622751409c99b9Joe Perches pr_err("Cannot allocate nfc hdev\n"); 697cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = -ENOMEM; 698cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade goto err_alloc_hdev; 699cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade } 700cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 701cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade nfc_hci_set_clientdata(info->hdev, info); 702cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 703cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade r = nfc_hci_register_device(info->hdev); 704cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade if (r) 705cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade goto err_regdev; 706cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 707cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade *hdev = info->hdev; 708cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 709cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return 0; 710cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 711cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadeerr_regdev: 712cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade nfc_hci_free_device(info->hdev); 713cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 714cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadeerr_alloc_hdev: 715cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree(info); 716cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 717cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadeerr_info_alloc: 718cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade return r; 719cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 720cfad1ba87150e198be9ea32367a24e500e59de2cEric LapuyadeEXPORT_SYMBOL(microread_probe); 721cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 722cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyadevoid microread_remove(struct nfc_hci_dev *hdev) 723cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade{ 724cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade struct microread_info *info = nfc_hci_get_clientdata(hdev); 725cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 726cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade nfc_hci_unregister_device(hdev); 727cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade nfc_hci_free_device(hdev); 728cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade kfree(info); 729cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade} 730cfad1ba87150e198be9ea32367a24e500e59de2cEric LapuyadeEXPORT_SYMBOL(microread_remove); 731cfad1ba87150e198be9ea32367a24e500e59de2cEric Lapuyade 732cfad1ba87150e198be9ea32367a24e500e59de2cEric LapuyadeMODULE_LICENSE("GPL"); 733cfad1ba87150e198be9ea32367a24e500e59de2cEric LapuyadeMODULE_DESCRIPTION(DRIVER_DESC); 734