mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 13:51:44 +00:00
NFC: 3.15: First pull request
This is the NFC pull request for 3.15. With this one we have: - Support for ISO 15693 a.k.a. NFC vicinity a.k.a. Type 5 tags. ISO 15693 are long range (1 - 2 meters) vicinity tags/cards. The kernel now supports those through the NFC netlink and digital APIs. - Support for TI's trf7970a chipset. This chipset relies on the NFC digital layer and the driver currently supports type 2, 4A and 5 tags. - Support for NXP's pn544 secure firmare download. The pn544 C3 chipsets relies on a different firmware download protocal than the C2 one. We now support both and use the right one depending on the version we detect at runtime. - Support for 4A tags from the NFC digital layer. - A bunch of cleanups and minor fixes from Axel Lin and Thierry Escande. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTI1oQAAoJEIqAPN1PVmxKmxgP/iiwhQwsehiUZ6oXYjAc06WT e+vmJwHuDgbEnr5QDSIdpeaKuxYtCErbFcG4SD5+thTQNEeiRsmTLYdkwZ0FCDF+ WKU3F59EdUZu4F0GyUXvt8lUC3D96bJSIHMCJdg1YDJtyaJcuITeK7lW325CK4hF 4ik0+HXcv9mt/Dq4k6xgqdgCOSz7o9dJSbzw5NTCN1I+G6CNgYrvYqSmvsKut2C7 DQvFu8KhbUkSlXgY61YIA2qpf1hfATkfgLdSsjGJfYdKvWLUAyKbEwoG8dkFA38Y yqc49SJ6DJ4FGmSt4Qm2VtRa8HLqwjA30jBEeb7Zog80j7zEBS+th0NJxqDWp/82 eaeNdfrA5d17CHiR9ODuGOFt3VJZeN83u+JCli3FKGF727A/2Z0UI8UgnB5ZfcbZ +5IxV6mQp/h8H4AaQzGQ88x2xibhnrW/XYmTpoxj7CcT3AdbGw/IerZXf+afXBce iyJZ+Ktr6d5zFucCbm0QyZDSwAhfYDIYGiM6AIM3oum9n3K31dA0Qxy6saMiiK8c ArYY6raQbRCaOBVCI8JI6PoQFvw5MNug40v7Q/G88dElte9mSLsGslVVhCNBpAVB Atdwa+I3gwgsea1oqGJo0rSEaWv6PsOeQcFG8boDoQDUvgapzk17bTCz4k2DlXO5 U0Q/GcJnFEdcDhqVKqP5 =xikL -----END PGP SIGNATURE----- Merge tag 'nfc-next-3.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next Samuel Ortiz <sameo@linux.intel.com> says: "NFC: 3.15: First pull request This is the NFC pull request for 3.15. With this one we have: - Support for ISO 15693 a.k.a. NFC vicinity a.k.a. Type 5 tags. ISO 15693 are long range (1 - 2 meters) vicinity tags/cards. The kernel now supports those through the NFC netlink and digital APIs. - Support for TI's trf7970a chipset. This chipset relies on the NFC digital layer and the driver currently supports type 2, 4A and 5 tags. - Support for NXP's pn544 secure firmare download. The pn544 C3 chipsets relies on a different firmware download protocal than the C2 one. We now support both and use the right one depending on the version we detect at runtime. - Support for 4A tags from the NFC digital layer. - A bunch of cleanups and minor fixes from Axel Lin and Thierry Escande." Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
commit
20d83f2464
34
Documentation/devicetree/bindings/net/nfc/trf7970a.txt
Normal file
34
Documentation/devicetree/bindings/net/nfc/trf7970a.txt
Normal file
@ -0,0 +1,34 @@
|
||||
* Texas Instruments TRF7970A RFID/NFC/15693 Transceiver
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "ti,trf7970a".
|
||||
- spi-max-frequency: Maximum SPI frequency (<= 2000000).
|
||||
- interrupt-parent: phandle of parent interrupt handler.
|
||||
- interrupts: A single interrupt specifier.
|
||||
- ti,enable-gpios: Two GPIO entries used for 'EN' and 'EN2' pins on the
|
||||
TRF7970A.
|
||||
- vin-supply: Regulator for supply voltage to VIN pin
|
||||
|
||||
Optional SoC Specific Properties:
|
||||
- pinctrl-names: Contains only one value - "default".
|
||||
- pintctrl-0: Specifies the pin control groups used for this controller.
|
||||
|
||||
Example (for ARM-based BeagleBone with TRF7970A on SPI1):
|
||||
|
||||
&spi1 {
|
||||
status = "okay";
|
||||
|
||||
nfc@0 {
|
||||
compatible = "ti,trf7970a";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&trf7970a_default>;
|
||||
spi-max-frequency = <2000000>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <14 0>;
|
||||
ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>,
|
||||
<&gpio2 5 GPIO_ACTIVE_LOW>;
|
||||
vin-supply = <&ldo3_reg>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
@ -6067,6 +6067,7 @@ F: include/net/nfc/
|
||||
F: include/uapi/linux/nfc.h
|
||||
F: drivers/nfc/
|
||||
F: include/linux/platform_data/pn544.h
|
||||
F: Documentation/devicetree/bindings/net/nfc/
|
||||
|
||||
NFS, SUNRPC, AND LOCKD CLIENTS
|
||||
M: Trond Myklebust <trond.myklebust@primarydata.com>
|
||||
|
@ -26,6 +26,18 @@ config NFC_WILINK
|
||||
Say Y here to compile support for Texas Instrument's NFC WiLink driver
|
||||
into the kernel or say M to compile it as module.
|
||||
|
||||
config NFC_TRF7970A
|
||||
tristate "Texas Instruments TRF7970a NFC driver"
|
||||
depends on SPI && NFC_DIGITAL
|
||||
help
|
||||
This option enables the NFC driver for Texas Instruments' TRF7970a
|
||||
device. Such device supports 5 different protocols: ISO14443A,
|
||||
ISO14443B, FeLiCa, ISO15693 and ISO18000-3.
|
||||
|
||||
Say Y here to compile support for TRF7970a into the kernel or
|
||||
say M to compile it as a module. The module will be called
|
||||
trf7970a.ko.
|
||||
|
||||
config NFC_MEI_PHY
|
||||
tristate "MEI bus NFC device support"
|
||||
depends on INTEL_MEI && NFC_HCI
|
||||
|
@ -10,5 +10,6 @@ obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o
|
||||
obj-$(CONFIG_NFC_SIM) += nfcsim.o
|
||||
obj-$(CONFIG_NFC_PORT100) += port100.o
|
||||
obj-$(CONFIG_NFC_MRVL) += nfcmrvl/
|
||||
obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o
|
||||
|
||||
ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
|
||||
|
@ -55,26 +55,14 @@
|
||||
NFC_PROTO_NFC_DEP_MASK)
|
||||
|
||||
static const struct usb_device_id pn533_table[] = {
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||
.idVendor = PN533_VENDOR_ID,
|
||||
.idProduct = PN533_PRODUCT_ID,
|
||||
.driver_info = PN533_DEVICE_STD,
|
||||
},
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||
.idVendor = SCM_VENDOR_ID,
|
||||
.idProduct = SCL3711_PRODUCT_ID,
|
||||
.driver_info = PN533_DEVICE_STD,
|
||||
},
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||
.idVendor = SONY_VENDOR_ID,
|
||||
.idProduct = PASORI_PRODUCT_ID,
|
||||
.driver_info = PN533_DEVICE_PASORI,
|
||||
},
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||
.idVendor = ACS_VENDOR_ID,
|
||||
.idProduct = ACR122U_PRODUCT_ID,
|
||||
.driver_info = PN533_DEVICE_ACR122U,
|
||||
},
|
||||
{ USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID),
|
||||
.driver_info = PN533_DEVICE_STD },
|
||||
{ USB_DEVICE(SCM_VENDOR_ID, SCL3711_PRODUCT_ID),
|
||||
.driver_info = PN533_DEVICE_STD },
|
||||
{ USB_DEVICE(SONY_VENDOR_ID, PASORI_PRODUCT_ID),
|
||||
.driver_info = PN533_DEVICE_PASORI },
|
||||
{ USB_DEVICE(ACS_VENDOR_ID, ACR122U_PRODUCT_ID),
|
||||
.driver_info = PN533_DEVICE_ACR122U },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, pn533_table);
|
||||
|
@ -58,8 +58,19 @@ MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table);
|
||||
|
||||
#define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c"
|
||||
|
||||
/*
|
||||
* Exposed through the 4 most significant bytes
|
||||
* from the HCI SW_VERSION first byte, a.k.a.
|
||||
* SW RomLib.
|
||||
*/
|
||||
#define PN544_HW_VARIANT_C2 0xa
|
||||
#define PN544_HW_VARIANT_C3 0xb
|
||||
|
||||
#define PN544_FW_CMD_RESET 0x01
|
||||
#define PN544_FW_CMD_WRITE 0x08
|
||||
#define PN544_FW_CMD_CHECK 0x06
|
||||
#define PN544_FW_CMD_SECURE_WRITE 0x0C
|
||||
#define PN544_FW_CMD_SECURE_CHUNK_WRITE 0x0D
|
||||
|
||||
struct pn544_i2c_fw_frame_write {
|
||||
u8 cmd;
|
||||
@ -88,13 +99,31 @@ struct pn544_i2c_fw_blob {
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
struct pn544_i2c_fw_secure_frame {
|
||||
u8 cmd;
|
||||
u16 be_datalen;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct pn544_i2c_fw_secure_blob {
|
||||
u64 header;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
#define PN544_FW_CMD_RESULT_TIMEOUT 0x01
|
||||
#define PN544_FW_CMD_RESULT_BAD_CRC 0x02
|
||||
#define PN544_FW_CMD_RESULT_ACCESS_DENIED 0x08
|
||||
#define PN544_FW_CMD_RESULT_PROTOCOL_ERROR 0x0B
|
||||
#define PN544_FW_CMD_RESULT_INVALID_PARAMETER 0x11
|
||||
#define PN544_FW_CMD_RESULT_UNSUPPORTED_COMMAND 0x13
|
||||
#define PN544_FW_CMD_RESULT_INVALID_LENGTH 0x18
|
||||
#define PN544_FW_CMD_RESULT_CRYPTOGRAPHIC_ERROR 0x19
|
||||
#define PN544_FW_CMD_RESULT_VERSION_CONDITIONS_ERROR 0x1D
|
||||
#define PN544_FW_CMD_RESULT_MEMORY_ERROR 0x20
|
||||
#define PN544_FW_CMD_RESULT_CHUNK_OK 0x21
|
||||
#define PN544_FW_CMD_RESULT_WRITE_FAILED 0x74
|
||||
#define PN544_FW_CMD_RESULT_COMMAND_REJECTED 0xE0
|
||||
#define PN544_FW_CMD_RESULT_CHUNK_ERROR 0xE6
|
||||
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
|
||||
@ -104,11 +133,17 @@ struct pn544_i2c_fw_blob {
|
||||
#define PN544_FW_I2C_WRITE_DATA_MAX_LEN MIN((PN544_FW_I2C_MAX_PAYLOAD -\
|
||||
PN544_FW_I2C_WRITE_FRAME_HEADER_LEN),\
|
||||
PN544_FW_WRITE_BUFFER_MAX_LEN)
|
||||
#define PN544_FW_SECURE_CHUNK_WRITE_HEADER_LEN 3
|
||||
#define PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN (PN544_FW_I2C_MAX_PAYLOAD -\
|
||||
PN544_FW_SECURE_CHUNK_WRITE_HEADER_LEN)
|
||||
#define PN544_FW_SECURE_FRAME_HEADER_LEN 3
|
||||
#define PN544_FW_SECURE_BLOB_HEADER_LEN 8
|
||||
|
||||
#define FW_WORK_STATE_IDLE 1
|
||||
#define FW_WORK_STATE_START 2
|
||||
#define FW_WORK_STATE_WAIT_WRITE_ANSWER 3
|
||||
#define FW_WORK_STATE_WAIT_CHECK_ANSWER 4
|
||||
#define FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER 5
|
||||
|
||||
struct pn544_i2c_phy {
|
||||
struct i2c_client *i2c_dev;
|
||||
@ -119,6 +154,8 @@ struct pn544_i2c_phy {
|
||||
unsigned int gpio_fw;
|
||||
unsigned int en_polarity;
|
||||
|
||||
u8 hw_variant;
|
||||
|
||||
struct work_struct fw_work;
|
||||
int fw_work_state;
|
||||
char firmware_name[NFC_FIRMWARE_NAME_MAXSIZE + 1];
|
||||
@ -127,6 +164,8 @@ struct pn544_i2c_phy {
|
||||
size_t fw_blob_size;
|
||||
const u8 *fw_blob_data;
|
||||
size_t fw_written;
|
||||
size_t fw_size;
|
||||
|
||||
int fw_cmd_result;
|
||||
|
||||
int powered;
|
||||
@ -390,6 +429,8 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy)
|
||||
switch (response.status) {
|
||||
case 0:
|
||||
return 0;
|
||||
case PN544_FW_CMD_RESULT_CHUNK_OK:
|
||||
return response.status;
|
||||
case PN544_FW_CMD_RESULT_TIMEOUT:
|
||||
return -ETIMEDOUT;
|
||||
case PN544_FW_CMD_RESULT_BAD_CRC:
|
||||
@ -400,9 +441,20 @@ static int pn544_hci_i2c_fw_read_status(struct pn544_i2c_phy *phy)
|
||||
return -EPROTO;
|
||||
case PN544_FW_CMD_RESULT_INVALID_PARAMETER:
|
||||
return -EINVAL;
|
||||
case PN544_FW_CMD_RESULT_UNSUPPORTED_COMMAND:
|
||||
return -ENOTSUPP;
|
||||
case PN544_FW_CMD_RESULT_INVALID_LENGTH:
|
||||
return -EBADMSG;
|
||||
case PN544_FW_CMD_RESULT_CRYPTOGRAPHIC_ERROR:
|
||||
return -ENOKEY;
|
||||
case PN544_FW_CMD_RESULT_VERSION_CONDITIONS_ERROR:
|
||||
return -EINVAL;
|
||||
case PN544_FW_CMD_RESULT_MEMORY_ERROR:
|
||||
return -ENOMEM;
|
||||
case PN544_FW_CMD_RESULT_COMMAND_REJECTED:
|
||||
return -EACCES;
|
||||
case PN544_FW_CMD_RESULT_WRITE_FAILED:
|
||||
case PN544_FW_CMD_RESULT_CHUNK_ERROR:
|
||||
return -EIO;
|
||||
default:
|
||||
return -EIO;
|
||||
@ -469,7 +521,8 @@ static struct nfc_phy_ops i2c_phy_ops = {
|
||||
.disable = pn544_hci_i2c_disable,
|
||||
};
|
||||
|
||||
static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name)
|
||||
static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name,
|
||||
u8 hw_variant)
|
||||
{
|
||||
struct pn544_i2c_phy *phy = phy_id;
|
||||
|
||||
@ -477,6 +530,7 @@ static int pn544_hci_i2c_fw_download(void *phy_id, const char *firmware_name)
|
||||
|
||||
strcpy(phy->firmware_name, firmware_name);
|
||||
|
||||
phy->hw_variant = hw_variant;
|
||||
phy->fw_work_state = FW_WORK_STATE_START;
|
||||
|
||||
schedule_work(&phy->fw_work);
|
||||
@ -598,12 +652,93 @@ static int pn544_hci_i2c_fw_write_chunk(struct pn544_i2c_phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pn544_hci_i2c_fw_secure_write_frame_cmd(struct pn544_i2c_phy *phy,
|
||||
const u8 *data, u16 datalen)
|
||||
{
|
||||
u8 buf[PN544_FW_I2C_MAX_PAYLOAD];
|
||||
struct pn544_i2c_fw_secure_frame *chunk;
|
||||
int chunklen;
|
||||
int r;
|
||||
|
||||
if (datalen > PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN)
|
||||
datalen = PN544_FW_SECURE_CHUNK_WRITE_DATA_MAX_LEN;
|
||||
|
||||
chunk = (struct pn544_i2c_fw_secure_frame *) buf;
|
||||
|
||||
chunk->cmd = PN544_FW_CMD_SECURE_CHUNK_WRITE;
|
||||
|
||||
put_unaligned_be16(datalen, &chunk->be_datalen);
|
||||
|
||||
memcpy(chunk->data, data, datalen);
|
||||
|
||||
chunklen = sizeof(chunk->cmd) + sizeof(chunk->be_datalen) + datalen;
|
||||
|
||||
r = i2c_master_send(phy->i2c_dev, buf, chunklen);
|
||||
|
||||
if (r == chunklen)
|
||||
return datalen;
|
||||
else if (r < 0)
|
||||
return r;
|
||||
else
|
||||
return -EIO;
|
||||
|
||||
}
|
||||
|
||||
static int pn544_hci_i2c_fw_secure_write_frame(struct pn544_i2c_phy *phy)
|
||||
{
|
||||
struct pn544_i2c_fw_secure_frame *framep;
|
||||
int r;
|
||||
|
||||
framep = (struct pn544_i2c_fw_secure_frame *) phy->fw_blob_data;
|
||||
if (phy->fw_written == 0)
|
||||
phy->fw_blob_size = get_unaligned_be16(&framep->be_datalen)
|
||||
+ PN544_FW_SECURE_FRAME_HEADER_LEN;
|
||||
|
||||
/* Only secure write command can be chunked*/
|
||||
if (phy->fw_blob_size > PN544_FW_I2C_MAX_PAYLOAD &&
|
||||
framep->cmd != PN544_FW_CMD_SECURE_WRITE)
|
||||
return -EINVAL;
|
||||
|
||||
/* The firmware also have other commands, we just send them directly */
|
||||
if (phy->fw_blob_size < PN544_FW_I2C_MAX_PAYLOAD) {
|
||||
r = i2c_master_send(phy->i2c_dev,
|
||||
(const char *) phy->fw_blob_data, phy->fw_blob_size);
|
||||
|
||||
if (r == phy->fw_blob_size)
|
||||
goto exit;
|
||||
else if (r < 0)
|
||||
return r;
|
||||
else
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
r = pn544_hci_i2c_fw_secure_write_frame_cmd(phy,
|
||||
phy->fw_blob_data + phy->fw_written,
|
||||
phy->fw_blob_size - phy->fw_written);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
exit:
|
||||
phy->fw_written += r;
|
||||
phy->fw_work_state = FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER;
|
||||
|
||||
/* SW reset command will not trig any response from PN544 */
|
||||
if (framep->cmd == PN544_FW_CMD_RESET) {
|
||||
pn544_hci_i2c_enable_mode(phy, PN544_FW_MODE);
|
||||
phy->fw_cmd_result = 0;
|
||||
schedule_work(&phy->fw_work);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pn544_hci_i2c_fw_work(struct work_struct *work)
|
||||
{
|
||||
struct pn544_i2c_phy *phy = container_of(work, struct pn544_i2c_phy,
|
||||
fw_work);
|
||||
int r;
|
||||
struct pn544_i2c_fw_blob *blob;
|
||||
struct pn544_i2c_fw_secure_blob *secure_blob;
|
||||
|
||||
switch (phy->fw_work_state) {
|
||||
case FW_WORK_STATE_START:
|
||||
@ -614,13 +749,29 @@ static void pn544_hci_i2c_fw_work(struct work_struct *work)
|
||||
if (r < 0)
|
||||
goto exit_state_start;
|
||||
|
||||
blob = (struct pn544_i2c_fw_blob *) phy->fw->data;
|
||||
phy->fw_blob_size = get_unaligned_be32(&blob->be_size);
|
||||
phy->fw_blob_dest_addr = get_unaligned_be32(&blob->be_destaddr);
|
||||
phy->fw_blob_data = blob->data;
|
||||
|
||||
phy->fw_written = 0;
|
||||
r = pn544_hci_i2c_fw_write_chunk(phy);
|
||||
|
||||
switch (phy->hw_variant) {
|
||||
case PN544_HW_VARIANT_C2:
|
||||
blob = (struct pn544_i2c_fw_blob *) phy->fw->data;
|
||||
phy->fw_blob_size = get_unaligned_be32(&blob->be_size);
|
||||
phy->fw_blob_dest_addr = get_unaligned_be32(
|
||||
&blob->be_destaddr);
|
||||
phy->fw_blob_data = blob->data;
|
||||
|
||||
r = pn544_hci_i2c_fw_write_chunk(phy);
|
||||
break;
|
||||
case PN544_HW_VARIANT_C3:
|
||||
secure_blob = (struct pn544_i2c_fw_secure_blob *)
|
||||
phy->fw->data;
|
||||
phy->fw_blob_data = secure_blob->data;
|
||||
phy->fw_size = phy->fw->size;
|
||||
r = pn544_hci_i2c_fw_secure_write_frame(phy);
|
||||
break;
|
||||
default:
|
||||
r = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
exit_state_start:
|
||||
if (r < 0)
|
||||
@ -672,6 +823,35 @@ exit_state_wait_check_answer:
|
||||
pn544_hci_i2c_fw_work_complete(phy, r);
|
||||
break;
|
||||
|
||||
case FW_WORK_STATE_WAIT_SECURE_WRITE_ANSWER:
|
||||
r = phy->fw_cmd_result;
|
||||
if (r < 0)
|
||||
goto exit_state_wait_secure_write_answer;
|
||||
|
||||
if (r == PN544_FW_CMD_RESULT_CHUNK_OK) {
|
||||
r = pn544_hci_i2c_fw_secure_write_frame(phy);
|
||||
goto exit_state_wait_secure_write_answer;
|
||||
}
|
||||
|
||||
if (phy->fw_written == phy->fw_blob_size) {
|
||||
secure_blob = (struct pn544_i2c_fw_secure_blob *)
|
||||
(phy->fw_blob_data + phy->fw_blob_size);
|
||||
phy->fw_size -= phy->fw_blob_size +
|
||||
PN544_FW_SECURE_BLOB_HEADER_LEN;
|
||||
if (phy->fw_size >= PN544_FW_SECURE_BLOB_HEADER_LEN
|
||||
+ PN544_FW_SECURE_FRAME_HEADER_LEN) {
|
||||
phy->fw_blob_data = secure_blob->data;
|
||||
|
||||
phy->fw_written = 0;
|
||||
r = pn544_hci_i2c_fw_secure_write_frame(phy);
|
||||
}
|
||||
}
|
||||
|
||||
exit_state_wait_secure_write_answer:
|
||||
if (r < 0 || phy->fw_size == 0)
|
||||
pn544_hci_i2c_fw_work_complete(phy, r);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -786,7 +786,7 @@ static int pn544_hci_fw_download(struct nfc_hci_dev *hdev,
|
||||
if (info->fw_download == NULL)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return info->fw_download(info->phy_id, firmware_name);
|
||||
return info->fw_download(info->phy_id, firmware_name, hdev->sw_romlib);
|
||||
}
|
||||
|
||||
static int pn544_hci_discover_se(struct nfc_hci_dev *hdev)
|
||||
|
@ -25,7 +25,8 @@
|
||||
#define PN544_HCI_MODE 0
|
||||
#define PN544_FW_MODE 1
|
||||
|
||||
typedef int (*fw_download_t)(void *context, const char *firmware_name);
|
||||
typedef int (*fw_download_t)(void *context, const char *firmware_name,
|
||||
u8 hw_variant);
|
||||
|
||||
int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
|
||||
int phy_headroom, int phy_tailroom, int phy_payload,
|
||||
|
@ -27,7 +27,8 @@
|
||||
#define PORT100_PROTOCOLS (NFC_PROTO_JEWEL_MASK | \
|
||||
NFC_PROTO_MIFARE_MASK | \
|
||||
NFC_PROTO_FELICA_MASK | \
|
||||
NFC_PROTO_NFC_DEP_MASK)
|
||||
NFC_PROTO_NFC_DEP_MASK | \
|
||||
NFC_PROTO_ISO14443_MASK)
|
||||
|
||||
#define PORT100_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC | \
|
||||
NFC_DIGITAL_DRV_CAPS_TG_CRC)
|
||||
@ -139,6 +140,8 @@ static const struct port100_in_rf_setting in_rf_settings[] = {
|
||||
.in_recv_set_number = 15,
|
||||
.in_recv_comm_type = PORT100_COMM_TYPE_IN_106A,
|
||||
},
|
||||
/* Ensures the array has NFC_DIGITAL_RF_TECH_LAST elements */
|
||||
[NFC_DIGITAL_RF_TECH_LAST] = { 0 },
|
||||
};
|
||||
|
||||
/**
|
||||
@ -174,6 +177,9 @@ static const struct port100_tg_rf_setting tg_rf_settings[] = {
|
||||
.tg_set_number = 8,
|
||||
.tg_comm_type = PORT100_COMM_TYPE_TG_424F,
|
||||
},
|
||||
/* Ensures the array has NFC_DIGITAL_RF_TECH_LAST elements */
|
||||
[NFC_DIGITAL_RF_TECH_LAST] = { 0 },
|
||||
|
||||
};
|
||||
|
||||
#define PORT100_IN_PROT_INITIAL_GUARD_TIME 0x00
|
||||
@ -293,6 +299,10 @@ in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = {
|
||||
{ PORT100_IN_PROT_CHECK_CRC, 0 },
|
||||
{ PORT100_IN_PROT_END, 0 },
|
||||
},
|
||||
[NFC_DIGITAL_FRAMING_NFCA_T4T] = {
|
||||
/* nfc_digital_framing_nfca_standard_with_crc_a */
|
||||
{ PORT100_IN_PROT_END, 0 },
|
||||
},
|
||||
[NFC_DIGITAL_FRAMING_NFCA_NFC_DEP] = {
|
||||
/* nfc_digital_framing_nfca_standard */
|
||||
{ PORT100_IN_PROT_END, 0 },
|
||||
@ -330,6 +340,10 @@ in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = {
|
||||
[NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = {
|
||||
{ PORT100_IN_PROT_END, 0 },
|
||||
},
|
||||
/* Ensures the array has NFC_DIGITAL_FRAMING_LAST elements */
|
||||
[NFC_DIGITAL_FRAMING_LAST] = {
|
||||
{ PORT100_IN_PROT_END, 0 },
|
||||
},
|
||||
};
|
||||
|
||||
static struct port100_protocol
|
||||
@ -371,6 +385,10 @@ tg_protocols[][PORT100_TG_MAX_NUM_PROTOCOLS + 1] = {
|
||||
{ PORT100_TG_PROT_RF_OFF, 1 },
|
||||
{ PORT100_TG_PROT_END, 0 },
|
||||
},
|
||||
/* Ensures the array has NFC_DIGITAL_FRAMING_LAST elements */
|
||||
[NFC_DIGITAL_FRAMING_LAST] = {
|
||||
{ PORT100_TG_PROT_END, 0 },
|
||||
},
|
||||
};
|
||||
|
||||
struct port100 {
|
||||
@ -1356,10 +1374,7 @@ static struct nfc_digital_ops port100_digital_ops = {
|
||||
};
|
||||
|
||||
static const struct usb_device_id port100_table[] = {
|
||||
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||
.idVendor = SONY_VENDOR_ID,
|
||||
.idProduct = RCS380_PRODUCT_ID,
|
||||
},
|
||||
{ USB_DEVICE(SONY_VENDOR_ID, RCS380_PRODUCT_ID), },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, port100_table);
|
||||
|
1370
drivers/nfc/trf7970a.c
Normal file
1370
drivers/nfc/trf7970a.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,7 @@ enum {
|
||||
NFC_DIGITAL_RF_TECH_106A = 0,
|
||||
NFC_DIGITAL_RF_TECH_212F,
|
||||
NFC_DIGITAL_RF_TECH_424F,
|
||||
NFC_DIGITAL_RF_TECH_ISO15693,
|
||||
|
||||
NFC_DIGITAL_RF_TECH_LAST,
|
||||
};
|
||||
@ -50,6 +51,7 @@ enum {
|
||||
|
||||
NFC_DIGITAL_FRAMING_NFCA_T1T,
|
||||
NFC_DIGITAL_FRAMING_NFCA_T2T,
|
||||
NFC_DIGITAL_FRAMING_NFCA_T4T,
|
||||
NFC_DIGITAL_FRAMING_NFCA_NFC_DEP,
|
||||
|
||||
NFC_DIGITAL_FRAMING_NFCF,
|
||||
@ -57,6 +59,9 @@ enum {
|
||||
NFC_DIGITAL_FRAMING_NFCF_NFC_DEP,
|
||||
NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED,
|
||||
|
||||
NFC_DIGITAL_FRAMING_ISO15693_INVENTORY,
|
||||
NFC_DIGITAL_FRAMING_ISO15693_T5T,
|
||||
|
||||
NFC_DIGITAL_FRAMING_LAST,
|
||||
};
|
||||
|
||||
@ -204,6 +209,8 @@ struct nfc_digital_dev {
|
||||
u8 curr_rf_tech;
|
||||
u8 curr_nfc_dep_pni;
|
||||
|
||||
u16 target_fsc;
|
||||
|
||||
int (*skb_check_crc)(struct sk_buff *skb);
|
||||
void (*skb_add_crc)(struct sk_buff *skb);
|
||||
};
|
||||
|
@ -111,6 +111,9 @@ struct nfc_target {
|
||||
u8 sensf_res[NFC_SENSF_RES_MAXSIZE];
|
||||
u8 hci_reader_gate;
|
||||
u8 logical_idx;
|
||||
u8 is_iso15693;
|
||||
u8 iso15693_dsfid;
|
||||
u8 iso15693_uid[NFC_ISO15693_UID_MAXSIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -150,6 +150,8 @@ enum nfc_commands {
|
||||
* @NFC_ATTR_SE_TYPE: Secure element type (UICC or EMBEDDED)
|
||||
* @NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS: Firmware download operation status
|
||||
* @NFC_ATTR_APDU: Secure element APDU
|
||||
* @NFC_ATTR_TARGET_ISO15693_DSFID: ISO 15693 Data Storage Format Identifier
|
||||
* @NFC_ATTR_TARGET_ISO15693_UID: ISO 15693 Unique Identifier
|
||||
*/
|
||||
enum nfc_attrs {
|
||||
NFC_ATTR_UNSPEC,
|
||||
@ -178,6 +180,8 @@ enum nfc_attrs {
|
||||
NFC_ATTR_SE_AID,
|
||||
NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS,
|
||||
NFC_ATTR_SE_APDU,
|
||||
NFC_ATTR_TARGET_ISO15693_DSFID,
|
||||
NFC_ATTR_TARGET_ISO15693_UID,
|
||||
/* private: internal use only */
|
||||
__NFC_ATTR_AFTER_LAST
|
||||
};
|
||||
@ -200,6 +204,7 @@ enum nfc_sdp_attr {
|
||||
#define NFC_SENSF_RES_MAXSIZE 18
|
||||
#define NFC_GB_MAXSIZE 48
|
||||
#define NFC_FIRMWARE_NAME_MAXSIZE 32
|
||||
#define NFC_ISO15693_UID_MAXSIZE 8
|
||||
|
||||
/* NFC protocols */
|
||||
#define NFC_PROTO_JEWEL 1
|
||||
@ -208,8 +213,9 @@ enum nfc_sdp_attr {
|
||||
#define NFC_PROTO_ISO14443 4
|
||||
#define NFC_PROTO_NFC_DEP 5
|
||||
#define NFC_PROTO_ISO14443_B 6
|
||||
#define NFC_PROTO_ISO15693 7
|
||||
|
||||
#define NFC_PROTO_MAX 7
|
||||
#define NFC_PROTO_MAX 8
|
||||
|
||||
/* NFC communication modes */
|
||||
#define NFC_COMM_ACTIVE 0
|
||||
@ -227,6 +233,7 @@ enum nfc_sdp_attr {
|
||||
#define NFC_PROTO_ISO14443_MASK (1 << NFC_PROTO_ISO14443)
|
||||
#define NFC_PROTO_NFC_DEP_MASK (1 << NFC_PROTO_NFC_DEP)
|
||||
#define NFC_PROTO_ISO14443_B_MASK (1 << NFC_PROTO_ISO14443_B)
|
||||
#define NFC_PROTO_ISO15693_MASK (1 << NFC_PROTO_ISO15693)
|
||||
|
||||
/* NFC Secure Elements */
|
||||
#define NFC_SE_UICC 0x1
|
||||
|
@ -280,9 +280,6 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dev->n_targets == 0)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < dev->n_targets; i++) {
|
||||
if (dev->targets[i].idx == target_idx)
|
||||
return &dev->targets[i];
|
||||
@ -546,9 +543,9 @@ error:
|
||||
|
||||
struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx)
|
||||
{
|
||||
struct nfc_se *se, *n;
|
||||
struct nfc_se *se;
|
||||
|
||||
list_for_each_entry_safe(se, n, &dev->secure_elements, list)
|
||||
list_for_each_entry(se, &dev->secure_elements, list)
|
||||
if (se->idx == se_idx)
|
||||
return se;
|
||||
|
||||
@ -655,9 +652,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len)
|
||||
{
|
||||
pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len);
|
||||
|
||||
if (gb_len > NFC_MAX_GT_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
return nfc_llcp_set_remote_gb(dev, gb, gb_len);
|
||||
}
|
||||
EXPORT_SYMBOL(nfc_set_remote_general_bytes);
|
||||
|
@ -72,6 +72,12 @@ void digital_poll_next_tech(struct nfc_digital_dev *ddev);
|
||||
|
||||
int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech);
|
||||
int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech);
|
||||
int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech);
|
||||
|
||||
int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev,
|
||||
struct sk_buff *skb);
|
||||
int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev,
|
||||
struct sk_buff *skb);
|
||||
|
||||
int digital_target_found(struct nfc_digital_dev *ddev,
|
||||
struct nfc_target *target, u8 protocol);
|
||||
|
@ -25,6 +25,8 @@
|
||||
#define DIGITAL_PROTO_NFCF_RF_TECH \
|
||||
(NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK)
|
||||
|
||||
#define DIGITAL_PROTO_ISO15693_RF_TECH NFC_PROTO_ISO15693_MASK
|
||||
|
||||
struct digital_cmd {
|
||||
struct list_head queue;
|
||||
|
||||
@ -331,6 +333,18 @@ int digital_target_found(struct nfc_digital_dev *ddev,
|
||||
}
|
||||
break;
|
||||
|
||||
case NFC_PROTO_ISO15693:
|
||||
framing = NFC_DIGITAL_FRAMING_ISO15693_T5T;
|
||||
check_crc = digital_skb_check_crc_b;
|
||||
add_crc = digital_skb_add_crc_b;
|
||||
break;
|
||||
|
||||
case NFC_PROTO_ISO14443:
|
||||
framing = NFC_DIGITAL_FRAMING_NFCA_T4T;
|
||||
check_crc = digital_skb_check_crc_a;
|
||||
add_crc = digital_skb_add_crc_a;
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("Invalid protocol %d\n", protocol);
|
||||
return -EINVAL;
|
||||
@ -461,7 +475,7 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols,
|
||||
digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A,
|
||||
digital_in_send_sens_req);
|
||||
|
||||
if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) {
|
||||
if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) {
|
||||
digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F,
|
||||
digital_in_send_sensf_req);
|
||||
|
||||
@ -469,7 +483,11 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols,
|
||||
digital_in_send_sensf_req);
|
||||
}
|
||||
|
||||
if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
||||
if (matching_im_protocols & DIGITAL_PROTO_ISO15693_RF_TECH)
|
||||
digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_ISO15693,
|
||||
digital_in_send_iso15693_inv_req);
|
||||
|
||||
if (matching_tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
||||
if (ddev->ops->tg_listen_mdaa) {
|
||||
digital_add_poll_tech(ddev, 0,
|
||||
digital_tg_listen_mdaa);
|
||||
@ -607,20 +625,30 @@ static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg,
|
||||
|
||||
if (IS_ERR(resp)) {
|
||||
rc = PTR_ERR(resp);
|
||||
resp = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ddev->curr_protocol == NFC_PROTO_MIFARE)
|
||||
if (ddev->curr_protocol == NFC_PROTO_MIFARE) {
|
||||
rc = digital_in_recv_mifare_res(resp);
|
||||
else
|
||||
rc = ddev->skb_check_crc(resp);
|
||||
/* crc check is done in digital_in_recv_mifare_res() */
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ddev->curr_protocol == NFC_PROTO_ISO14443) {
|
||||
rc = digital_in_iso_dep_pull_sod(ddev, resp);
|
||||
if (rc)
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = ddev->skb_check_crc(resp);
|
||||
|
||||
done:
|
||||
if (rc) {
|
||||
kfree_skb(resp);
|
||||
resp = NULL;
|
||||
}
|
||||
|
||||
done:
|
||||
data_exch->cb(data_exch->cb_context, resp, rc);
|
||||
|
||||
kfree(data_exch);
|
||||
@ -632,6 +660,7 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target,
|
||||
{
|
||||
struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev);
|
||||
struct digital_data_exch *data_exch;
|
||||
int rc;
|
||||
|
||||
data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL);
|
||||
if (!data_exch) {
|
||||
@ -642,13 +671,27 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target,
|
||||
data_exch->cb = cb;
|
||||
data_exch->cb_context = cb_context;
|
||||
|
||||
if (ddev->curr_protocol == NFC_PROTO_NFC_DEP)
|
||||
return digital_in_send_dep_req(ddev, target, skb, data_exch);
|
||||
if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) {
|
||||
rc = digital_in_send_dep_req(ddev, target, skb, data_exch);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ddev->curr_protocol == NFC_PROTO_ISO14443) {
|
||||
rc = digital_in_iso_dep_push_sod(ddev, skb);
|
||||
if (rc)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ddev->skb_add_crc(skb);
|
||||
|
||||
return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete,
|
||||
data_exch);
|
||||
rc = digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete,
|
||||
data_exch);
|
||||
|
||||
exit:
|
||||
if (rc)
|
||||
kfree(data_exch);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct nfc_ops digital_nfc_ops = {
|
||||
@ -700,6 +743,10 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops,
|
||||
ddev->protocols |= NFC_PROTO_FELICA_MASK;
|
||||
if (supported_protocols & NFC_PROTO_NFC_DEP_MASK)
|
||||
ddev->protocols |= NFC_PROTO_NFC_DEP_MASK;
|
||||
if (supported_protocols & NFC_PROTO_ISO15693_MASK)
|
||||
ddev->protocols |= NFC_PROTO_ISO15693_MASK;
|
||||
if (supported_protocols & NFC_PROTO_ISO14443_MASK)
|
||||
ddev->protocols |= NFC_PROTO_ISO14443_MASK;
|
||||
|
||||
ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN;
|
||||
ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN;
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04))
|
||||
#define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60))
|
||||
#define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20)
|
||||
#define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40)
|
||||
|
||||
#define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00)
|
||||
@ -51,6 +52,34 @@
|
||||
#define DIGITAL_SENSF_REQ_RC_SC 1
|
||||
#define DIGITAL_SENSF_REQ_RC_AP 2
|
||||
|
||||
#define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01
|
||||
|
||||
#define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1)
|
||||
#define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2)
|
||||
#define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5)
|
||||
#define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0)
|
||||
#define DIGITAL_ISO15693_RES_IS_VALID(flags) \
|
||||
(!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR))
|
||||
|
||||
#define DIGITAL_ISO_DEP_I_PCB 0x02
|
||||
#define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01)
|
||||
|
||||
#define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0)
|
||||
|
||||
#define DIGITAL_ISO_DEP_I_BLOCK 0x00
|
||||
|
||||
#define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08)
|
||||
|
||||
static const u8 digital_ats_fsc[] = {
|
||||
16, 24, 32, 40, 48, 64, 96, 128,
|
||||
};
|
||||
|
||||
#define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F)
|
||||
#define DIGITAL_ATS_MAX_FSC 256
|
||||
|
||||
#define DIGITAL_RATS_BYTE1 0xE0
|
||||
#define DIGITAL_RATS_PARAM 0x80
|
||||
|
||||
struct digital_sdd_res {
|
||||
u8 nfcid1[4];
|
||||
u8 bcc;
|
||||
@ -82,9 +111,127 @@ struct digital_sensf_res {
|
||||
u8 rd[2];
|
||||
} __packed;
|
||||
|
||||
struct digital_iso15693_inv_req {
|
||||
u8 flags;
|
||||
u8 cmd;
|
||||
u8 mask_len;
|
||||
u64 mask;
|
||||
} __packed;
|
||||
|
||||
struct digital_iso15693_inv_res {
|
||||
u8 flags;
|
||||
u8 dsfid;
|
||||
u64 uid;
|
||||
} __packed;
|
||||
|
||||
static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev,
|
||||
struct nfc_target *target);
|
||||
|
||||
int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u8 pcb;
|
||||
u8 block_type;
|
||||
|
||||
if (skb->len < 1)
|
||||
return -EIO;
|
||||
|
||||
pcb = *skb->data;
|
||||
block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb);
|
||||
|
||||
/* No support fo R-block nor S-block */
|
||||
if (block_type != DIGITAL_ISO_DEP_I_BLOCK) {
|
||||
pr_err("ISO_DEP R-block and S-block not supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) {
|
||||
pr_err("DID field in ISO_DEP PCB not supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
skb_pull(skb, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
/*
|
||||
* Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must
|
||||
* not be greater than remote FSC
|
||||
*/
|
||||
if (skb->len + 3 > ddev->target_fsc)
|
||||
return -EIO;
|
||||
|
||||
skb_push(skb, 1);
|
||||
|
||||
*skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni;
|
||||
|
||||
ddev->curr_nfc_dep_pni =
|
||||
DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg,
|
||||
struct sk_buff *resp)
|
||||
{
|
||||
struct nfc_target *target = arg;
|
||||
u8 fsdi;
|
||||
int rc;
|
||||
|
||||
if (IS_ERR(resp)) {
|
||||
rc = PTR_ERR(resp);
|
||||
resp = NULL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (resp->len < 2) {
|
||||
rc = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fsdi = DIGITAL_ATS_FSCI(resp->data[1]);
|
||||
if (fsdi >= 8)
|
||||
ddev->target_fsc = DIGITAL_ATS_MAX_FSC;
|
||||
else
|
||||
ddev->target_fsc = digital_ats_fsc[fsdi];
|
||||
|
||||
ddev->curr_nfc_dep_pni = 0;
|
||||
|
||||
rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443);
|
||||
|
||||
exit:
|
||||
dev_kfree_skb(resp);
|
||||
kfree(target);
|
||||
|
||||
if (rc)
|
||||
digital_poll_next_tech(ddev);
|
||||
}
|
||||
|
||||
static int digital_in_send_rats(struct nfc_digital_dev *ddev,
|
||||
struct nfc_target *target)
|
||||
{
|
||||
int rc;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = digital_skb_alloc(ddev, 2);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
*skb_put(skb, 1) = DIGITAL_RATS_BYTE1;
|
||||
*skb_put(skb, 1) = DIGITAL_RATS_PARAM;
|
||||
|
||||
rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats,
|
||||
target);
|
||||
if (rc)
|
||||
kfree_skb(skb);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
|
||||
struct sk_buff *resp)
|
||||
{
|
||||
@ -122,8 +269,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
|
||||
goto exit_free_skb;
|
||||
}
|
||||
|
||||
target->sel_res = sel_res;
|
||||
|
||||
if (DIGITAL_SEL_RES_IS_T2T(sel_res)) {
|
||||
nfc_proto = NFC_PROTO_MIFARE;
|
||||
} else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) {
|
||||
rc = digital_in_send_rats(ddev, target);
|
||||
if (rc)
|
||||
goto exit;
|
||||
/*
|
||||
* Skip target_found and don't free it for now. This will be
|
||||
* done when receiving the ATS
|
||||
*/
|
||||
goto exit_free_skb;
|
||||
} else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) {
|
||||
nfc_proto = NFC_PROTO_NFC_DEP;
|
||||
} else {
|
||||
@ -131,8 +289,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
target->sel_res = sel_res;
|
||||
|
||||
rc = digital_target_found(ddev, target, nfc_proto);
|
||||
|
||||
exit:
|
||||
@ -473,6 +629,93 @@ int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev,
|
||||
void *arg, struct sk_buff *resp)
|
||||
{
|
||||
struct digital_iso15693_inv_res *res;
|
||||
struct nfc_target *target = NULL;
|
||||
int rc;
|
||||
|
||||
if (IS_ERR(resp)) {
|
||||
rc = PTR_ERR(resp);
|
||||
resp = NULL;
|
||||
goto out_free_skb;
|
||||
}
|
||||
|
||||
if (resp->len != sizeof(*res)) {
|
||||
rc = -EIO;
|
||||
goto out_free_skb;
|
||||
}
|
||||
|
||||
res = (struct digital_iso15693_inv_res *)resp->data;
|
||||
|
||||
if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) {
|
||||
PROTOCOL_ERR("ISO15693 - 10.3.1");
|
||||
rc = -EINVAL;
|
||||
goto out_free_skb;
|
||||
}
|
||||
|
||||
target = kzalloc(sizeof(*target), GFP_KERNEL);
|
||||
if (!target) {
|
||||
rc = -ENOMEM;
|
||||
goto out_free_skb;
|
||||
}
|
||||
|
||||
target->is_iso15693 = 1;
|
||||
target->iso15693_dsfid = res->dsfid;
|
||||
memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid));
|
||||
|
||||
rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693);
|
||||
|
||||
kfree(target);
|
||||
|
||||
out_free_skb:
|
||||
dev_kfree_skb(resp);
|
||||
|
||||
if (rc)
|
||||
digital_poll_next_tech(ddev);
|
||||
}
|
||||
|
||||
int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech)
|
||||
{
|
||||
struct digital_iso15693_inv_req *req;
|
||||
struct sk_buff *skb;
|
||||
int rc;
|
||||
|
||||
rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
|
||||
NFC_DIGITAL_RF_TECH_ISO15693);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
|
||||
NFC_DIGITAL_FRAMING_ISO15693_INVENTORY);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
skb = digital_skb_alloc(ddev, sizeof(*req));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */
|
||||
req = (struct digital_iso15693_inv_req *)skb->data;
|
||||
|
||||
/* Single sub-carrier, high data rate, no AFI, single slot
|
||||
* Inventory command
|
||||
*/
|
||||
req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE |
|
||||
DIGITAL_ISO15693_REQ_FLAG_INVENTORY |
|
||||
DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS;
|
||||
req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ;
|
||||
req->mask_len = 0;
|
||||
|
||||
rc = digital_in_send_cmd(ddev, skb, 30,
|
||||
digital_in_recv_iso15693_inv_res, NULL);
|
||||
if (rc)
|
||||
kfree_skb(skb);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -20,14 +20,12 @@
|
||||
|
||||
#include "llc.h"
|
||||
|
||||
static struct list_head llc_engines;
|
||||
static LIST_HEAD(llc_engines);
|
||||
|
||||
int nfc_llc_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
INIT_LIST_HEAD(&llc_engines);
|
||||
|
||||
r = nfc_llc_nop_register();
|
||||
if (r)
|
||||
goto exit;
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
|
||||
|
||||
static struct list_head llcp_devices;
|
||||
static LIST_HEAD(llcp_devices);
|
||||
|
||||
static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
|
||||
|
||||
@ -293,9 +293,9 @@ static void nfc_llcp_sdreq_timer(unsigned long data)
|
||||
|
||||
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
|
||||
{
|
||||
struct nfc_llcp_local *local, *n;
|
||||
struct nfc_llcp_local *local;
|
||||
|
||||
list_for_each_entry_safe(local, n, &llcp_devices, list)
|
||||
list_for_each_entry(local, &llcp_devices, list)
|
||||
if (local->dev == dev)
|
||||
return local;
|
||||
|
||||
@ -609,14 +609,16 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
|
||||
|
||||
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
|
||||
{
|
||||
struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
|
||||
struct nfc_llcp_local *local;
|
||||
|
||||
if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
local = nfc_llcp_find_local(dev);
|
||||
if (local == NULL) {
|
||||
pr_err("No LLCP device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (gb_len < 3)
|
||||
return -EINVAL;
|
||||
|
||||
memset(local->remote_gb, 0, NFC_MAX_GT_LEN);
|
||||
memcpy(local->remote_gb, gb, gb_len);
|
||||
@ -1622,8 +1624,6 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
|
||||
|
||||
int __init nfc_llcp_init(void)
|
||||
{
|
||||
INIT_LIST_HEAD(&llcp_devices);
|
||||
|
||||
return nfc_llcp_sock_init();
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ static int __nci_request(struct nci_dev *ndev,
|
||||
|
||||
ndev->req_status = NCI_REQ_PEND;
|
||||
|
||||
init_completion(&ndev->req_completion);
|
||||
reinit_completion(&ndev->req_completion);
|
||||
req(ndev, opt);
|
||||
completion_rc =
|
||||
wait_for_completion_interruptible_timeout(&ndev->req_completion,
|
||||
@ -709,6 +709,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
|
||||
ndev->ops = ops;
|
||||
ndev->tx_headroom = tx_headroom;
|
||||
ndev->tx_tailroom = tx_tailroom;
|
||||
init_completion(&ndev->req_completion);
|
||||
|
||||
ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops,
|
||||
supported_protocols,
|
||||
|
@ -105,7 +105,7 @@ int nci_spi_send(struct nci_spi *nspi,
|
||||
if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED)
|
||||
goto done;
|
||||
|
||||
init_completion(&nspi->req_completion);
|
||||
reinit_completion(&nspi->req_completion);
|
||||
completion_rc = wait_for_completion_interruptible_timeout(
|
||||
&nspi->req_completion,
|
||||
NCI_SPI_SEND_TIMEOUT);
|
||||
@ -145,6 +145,7 @@ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi,
|
||||
|
||||
nspi->spi = spi;
|
||||
nspi->ndev = ndev;
|
||||
init_completion(&nspi->req_completion);
|
||||
|
||||
return nspi;
|
||||
}
|
||||
|
@ -94,6 +94,14 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
|
||||
target->sensf_res))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (target->is_iso15693) {
|
||||
if (nla_put_u8(msg, NFC_ATTR_TARGET_ISO15693_DSFID,
|
||||
target->iso15693_dsfid) ||
|
||||
nla_put(msg, NFC_ATTR_TARGET_ISO15693_UID,
|
||||
sizeof(target->iso15693_uid), target->iso15693_uid))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
return genlmsg_end(msg, hdr);
|
||||
|
||||
nla_put_failure:
|
||||
|
Loading…
Reference in New Issue
Block a user