12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646 |
- /*
- * NFC Digital Protocol stack
- * Copyright (c) 2013, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
- #define pr_fmt(fmt) "digital: %s: " fmt, __func__
- #include "digital.h"
- #define DIGITAL_NFC_DEP_N_RETRY_NACK 2
- #define DIGITAL_NFC_DEP_N_RETRY_ATN 2
- #define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4
- #define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5
- #define DIGITAL_NFC_DEP_NFCA_SOD_SB 0xF0
- #define DIGITAL_CMD_ATR_REQ 0x00
- #define DIGITAL_CMD_ATR_RES 0x01
- #define DIGITAL_CMD_PSL_REQ 0x04
- #define DIGITAL_CMD_PSL_RES 0x05
- #define DIGITAL_CMD_DEP_REQ 0x06
- #define DIGITAL_CMD_DEP_RES 0x07
- #define DIGITAL_ATR_REQ_MIN_SIZE 16
- #define DIGITAL_ATR_REQ_MAX_SIZE 64
- #define DIGITAL_ATR_RES_TO_WT(s) ((s) & 0xF)
- #define DIGITAL_DID_MAX 14
- #define DIGITAL_PAYLOAD_SIZE_MAX 254
- #define DIGITAL_PAYLOAD_BITS_TO_PP(s) (((s) & 0x3) << 4)
- #define DIGITAL_PAYLOAD_PP_TO_BITS(s) (((s) >> 4) & 0x3)
- #define DIGITAL_PAYLOAD_BITS_TO_FSL(s) ((s) & 0x3)
- #define DIGITAL_PAYLOAD_FSL_TO_BITS(s) ((s) & 0x3)
- #define DIGITAL_GB_BIT 0x02
- #define DIGITAL_NFC_DEP_REQ_RES_HEADROOM 2 /* SoD: [SB (NFC-A)] + LEN */
- #define DIGITAL_NFC_DEP_REQ_RES_TAILROOM 2 /* EoD: 2-byte CRC */
- #define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
- #define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
- #define DIGITAL_NFC_DEP_PFB_MI_BIT 0x10
- #define DIGITAL_NFC_DEP_PFB_NACK_BIT 0x10
- #define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04
- #define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
- ((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
- #define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_MI_BIT)
- #define DIGITAL_NFC_DEP_NACK_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_NACK_BIT)
- #define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
- #define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
- #define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
- #define DIGITAL_NFC_DEP_RTOX_VALUE(data) ((data) & 0x3F)
- #define DIGITAL_NFC_DEP_RTOX_MAX 59
- #define DIGITAL_NFC_DEP_PFB_I_PDU 0x00
- #define DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU 0x40
- #define DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU 0x80
- struct digital_atr_req {
- u8 dir;
- u8 cmd;
- u8 nfcid3[10];
- u8 did;
- u8 bs;
- u8 br;
- u8 pp;
- u8 gb[0];
- } __packed;
- struct digital_atr_res {
- u8 dir;
- u8 cmd;
- u8 nfcid3[10];
- u8 did;
- u8 bs;
- u8 br;
- u8 to;
- u8 pp;
- u8 gb[0];
- } __packed;
- struct digital_psl_req {
- u8 dir;
- u8 cmd;
- u8 did;
- u8 brs;
- u8 fsl;
- } __packed;
- struct digital_psl_res {
- u8 dir;
- u8 cmd;
- u8 did;
- } __packed;
- struct digital_dep_req_res {
- u8 dir;
- u8 cmd;
- u8 pfb;
- } __packed;
- static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp);
- static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp);
- static const u8 digital_payload_bits_map[4] = {
- [0] = 64,
- [1] = 128,
- [2] = 192,
- [3] = 254
- };
- /* Response Waiting Time for ATR_RES PDU in ms
- *
- * RWT(ATR_RES) = RWT(nfcdep,activation) + dRWT(nfcdep) + dT(nfcdep,initiator)
- *
- * with:
- * RWT(nfcdep,activation) = 4096 * 2^12 / f(c) s
- * dRWT(nfcdep) = 16 / f(c) s
- * dT(nfcdep,initiator) = 100 ms
- * f(c) = 13560000 Hz
- */
- #define DIGITAL_ATR_RES_RWT 1337
- /* Response Waiting Time for other DEP PDUs in ms
- *
- * max_rwt = rwt + dRWT(nfcdep) + dT(nfcdep,initiator)
- *
- * with:
- * rwt = (256 * 16 / f(c)) * 2^wt s
- * dRWT(nfcdep) = 16 / f(c) s
- * dT(nfcdep,initiator) = 100 ms
- * f(c) = 13560000 Hz
- * 0 <= wt <= 14 (given by the target by the TO field of ATR_RES response)
- */
- #define DIGITAL_NFC_DEP_IN_MAX_WT 14
- #define DIGITAL_NFC_DEP_TG_MAX_WT 14
- static const u16 digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT + 1] = {
- 100, 101, 101, 102, 105,
- 110, 119, 139, 177, 255,
- 409, 719, 1337, 2575, 5049,
- };
- static u8 digital_payload_bits_to_size(u8 payload_bits)
- {
- if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map))
- return 0;
- return digital_payload_bits_map[payload_bits];
- }
- static u8 digital_payload_size_to_bits(u8 payload_size)
- {
- int i;
- for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++)
- if (digital_payload_bits_map[i] == payload_size)
- return i;
- return 0xff;
- }
- static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
- struct sk_buff *skb)
- {
- skb_push(skb, sizeof(u8));
- skb->data[0] = skb->len;
- if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
- *(u8 *)skb_push(skb, sizeof(u8)) = DIGITAL_NFC_DEP_NFCA_SOD_SB;
- }
- static int digital_skb_pull_dep_sod(struct nfc_digital_dev *ddev,
- struct sk_buff *skb)
- {
- u8 size;
- if (skb->len < 2)
- return -EIO;
- if (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)
- skb_pull(skb, sizeof(u8));
- size = skb->data[0];
- if (size != skb->len)
- return -EIO;
- skb_pull(skb, sizeof(u8));
- return 0;
- }
- static struct sk_buff *
- digital_send_dep_data_prep(struct nfc_digital_dev *ddev, struct sk_buff *skb,
- struct digital_dep_req_res *dep_req_res,
- struct digital_data_exch *data_exch)
- {
- struct sk_buff *new_skb;
- if (skb->len > ddev->remote_payload_max) {
- dep_req_res->pfb |= DIGITAL_NFC_DEP_PFB_MI_BIT;
- new_skb = digital_skb_alloc(ddev, ddev->remote_payload_max);
- if (!new_skb) {
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
- return ERR_PTR(-ENOMEM);
- }
- skb_put_data(new_skb, skb->data, ddev->remote_payload_max);
- skb_pull(skb, ddev->remote_payload_max);
- ddev->chaining_skb = skb;
- ddev->data_exch = data_exch;
- } else {
- ddev->chaining_skb = NULL;
- new_skb = skb;
- }
- return new_skb;
- }
- static struct sk_buff *
- digital_recv_dep_data_gather(struct nfc_digital_dev *ddev, u8 pfb,
- struct sk_buff *resp,
- int (*send_ack)(struct nfc_digital_dev *ddev,
- struct digital_data_exch
- *data_exch),
- struct digital_data_exch *data_exch)
- {
- struct sk_buff *new_skb;
- int rc;
- if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb) && (!ddev->chaining_skb)) {
- ddev->chaining_skb =
- nfc_alloc_recv_skb(8 * ddev->local_payload_max,
- GFP_KERNEL);
- if (!ddev->chaining_skb) {
- rc = -ENOMEM;
- goto error;
- }
- }
- if (ddev->chaining_skb) {
- if (resp->len > skb_tailroom(ddev->chaining_skb)) {
- new_skb = skb_copy_expand(ddev->chaining_skb,
- skb_headroom(
- ddev->chaining_skb),
- 8 * ddev->local_payload_max,
- GFP_KERNEL);
- if (!new_skb) {
- rc = -ENOMEM;
- goto error;
- }
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = new_skb;
- }
- skb_put_data(ddev->chaining_skb, resp->data, resp->len);
- kfree_skb(resp);
- resp = NULL;
- if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
- rc = send_ack(ddev, data_exch);
- if (rc)
- goto error;
- return NULL;
- }
- resp = ddev->chaining_skb;
- ddev->chaining_skb = NULL;
- }
- return resp;
- error:
- kfree_skb(resp);
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
- return ERR_PTR(rc);
- }
- static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp)
- {
- struct nfc_target *target = arg;
- struct digital_psl_res *psl_res;
- int rc;
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto exit;
- }
- rc = ddev->skb_check_crc(resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.6");
- goto exit;
- }
- rc = digital_skb_pull_dep_sod(ddev, resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.2");
- goto exit;
- }
- psl_res = (struct digital_psl_res *)resp->data;
- if ((resp->len != sizeof(*psl_res)) ||
- (psl_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN) ||
- (psl_res->cmd != DIGITAL_CMD_PSL_RES)) {
- rc = -EIO;
- goto exit;
- }
- rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH,
- NFC_DIGITAL_RF_TECH_424F);
- if (rc)
- goto exit;
- rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
- NFC_DIGITAL_FRAMING_NFCF_NFC_DEP);
- if (rc)
- goto exit;
- if (!DIGITAL_DRV_CAPS_IN_CRC(ddev) &&
- (ddev->curr_rf_tech == NFC_DIGITAL_RF_TECH_106A)) {
- ddev->skb_add_crc = digital_skb_add_crc_f;
- ddev->skb_check_crc = digital_skb_check_crc_f;
- }
- ddev->curr_rf_tech = NFC_DIGITAL_RF_TECH_424F;
- nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
- NFC_RF_INITIATOR);
- ddev->curr_nfc_dep_pni = 0;
- exit:
- dev_kfree_skb(resp);
- if (rc)
- ddev->curr_protocol = 0;
- }
- static int digital_in_send_psl_req(struct nfc_digital_dev *ddev,
- struct nfc_target *target)
- {
- struct sk_buff *skb;
- struct digital_psl_req *psl_req;
- int rc;
- u8 payload_size, payload_bits;
- skb = digital_skb_alloc(ddev, sizeof(*psl_req));
- if (!skb)
- return -ENOMEM;
- skb_put(skb, sizeof(*psl_req));
- psl_req = (struct digital_psl_req *)skb->data;
- psl_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- psl_req->cmd = DIGITAL_CMD_PSL_REQ;
- psl_req->did = 0;
- psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
- payload_size = min(ddev->local_payload_max, ddev->remote_payload_max);
- payload_bits = digital_payload_size_to_bits(payload_size);
- psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits);
- ddev->local_payload_max = payload_size;
- ddev->remote_payload_max = payload_size;
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
- digital_in_recv_psl_res, target);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp)
- {
- struct nfc_target *target = arg;
- struct digital_atr_res *atr_res;
- u8 gb_len, payload_bits;
- u8 wt;
- int rc;
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto exit;
- }
- rc = ddev->skb_check_crc(resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.6");
- goto exit;
- }
- rc = digital_skb_pull_dep_sod(ddev, resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.2");
- goto exit;
- }
- if (resp->len < sizeof(struct digital_atr_res)) {
- rc = -EIO;
- goto exit;
- }
- gb_len = resp->len - sizeof(struct digital_atr_res);
- atr_res = (struct digital_atr_res *)resp->data;
- wt = DIGITAL_ATR_RES_TO_WT(atr_res->to);
- if (wt > DIGITAL_NFC_DEP_IN_MAX_WT)
- wt = DIGITAL_NFC_DEP_IN_MAX_WT;
- ddev->dep_rwt = digital_rwt_map[wt];
- payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp);
- ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
- if (!ddev->remote_payload_max) {
- rc = -EINVAL;
- goto exit;
- }
- rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
- if (rc)
- goto exit;
- if ((ddev->protocols & NFC_PROTO_FELICA_MASK) &&
- (ddev->curr_rf_tech != NFC_DIGITAL_RF_TECH_424F)) {
- rc = digital_in_send_psl_req(ddev, target);
- if (!rc)
- goto exit;
- }
- rc = nfc_dep_link_is_up(ddev->nfc_dev, target->idx, NFC_COMM_ACTIVE,
- NFC_RF_INITIATOR);
- ddev->curr_nfc_dep_pni = 0;
- exit:
- dev_kfree_skb(resp);
- if (rc)
- ddev->curr_protocol = 0;
- }
- int digital_in_send_atr_req(struct nfc_digital_dev *ddev,
- struct nfc_target *target, __u8 comm_mode, __u8 *gb,
- size_t gb_len)
- {
- struct sk_buff *skb;
- struct digital_atr_req *atr_req;
- uint size;
- int rc;
- u8 payload_bits;
- size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
- if (size > DIGITAL_ATR_REQ_MAX_SIZE) {
- PROTOCOL_ERR("14.6.1.1");
- return -EINVAL;
- }
- skb = digital_skb_alloc(ddev, size);
- if (!skb)
- return -ENOMEM;
- skb_put(skb, sizeof(struct digital_atr_req));
- atr_req = (struct digital_atr_req *)skb->data;
- memset(atr_req, 0, sizeof(struct digital_atr_req));
- atr_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- atr_req->cmd = DIGITAL_CMD_ATR_REQ;
- if (target->nfcid2_len)
- memcpy(atr_req->nfcid3, target->nfcid2, NFC_NFCID2_MAXSIZE);
- else
- get_random_bytes(atr_req->nfcid3, NFC_NFCID3_MAXSIZE);
- atr_req->did = 0;
- atr_req->bs = 0;
- atr_req->br = 0;
- ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
- payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
- atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
- if (gb_len) {
- atr_req->pp |= DIGITAL_GB_BIT;
- skb_put_data(skb, gb, gb_len);
- }
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- rc = digital_in_send_cmd(ddev, skb, DIGITAL_ATR_RES_RWT,
- digital_in_recv_atr_res, target);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- static int digital_in_send_ack(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
- {
- struct digital_dep_req_res *dep_req;
- struct sk_buff *skb;
- int rc;
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_req = (struct digital_dep_req_res *)skb->data;
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
- ddev->curr_nfc_dep_pni;
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- ddev->saved_skb = pskb_copy(skb, GFP_KERNEL);
- rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
- digital_in_recv_dep_res, data_exch);
- if (rc) {
- kfree_skb(skb);
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
- return rc;
- }
- static int digital_in_send_nack(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
- {
- struct digital_dep_req_res *dep_req;
- struct sk_buff *skb;
- int rc;
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_req = (struct digital_dep_req_res *)skb->data;
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
- DIGITAL_NFC_DEP_PFB_NACK_BIT | ddev->curr_nfc_dep_pni;
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
- digital_in_recv_dep_res, data_exch);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- static int digital_in_send_atn(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
- {
- struct digital_dep_req_res *dep_req;
- struct sk_buff *skb;
- int rc;
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_req = (struct digital_dep_req_res *)skb->data;
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- rc = digital_in_send_cmd(ddev, skb, ddev->dep_rwt,
- digital_in_recv_dep_res, data_exch);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch, u8 rtox)
- {
- struct digital_dep_req_res *dep_req;
- struct sk_buff *skb;
- int rc;
- u16 rwt_int;
- rwt_int = ddev->dep_rwt * rtox;
- if (rwt_int > digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT])
- rwt_int = digital_rwt_map[DIGITAL_NFC_DEP_IN_MAX_WT];
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
- skb_put_u8(skb, rtox);
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_req = (struct digital_dep_req_res *)skb->data;
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU |
- DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT;
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- rc = digital_in_send_cmd(ddev, skb, rwt_int,
- digital_in_recv_dep_res, data_exch);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
- {
- int rc;
- if (!ddev->saved_skb)
- return -EINVAL;
- skb_get(ddev->saved_skb);
- rc = digital_in_send_cmd(ddev, ddev->saved_skb, ddev->dep_rwt,
- digital_in_recv_dep_res, data_exch);
- if (rc)
- kfree_skb(ddev->saved_skb);
- return rc;
- }
- static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp)
- {
- struct digital_data_exch *data_exch = arg;
- struct digital_dep_req_res *dep_res;
- u8 pfb;
- uint size;
- int rc;
- u8 rtox;
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- if ((rc == -EIO || (rc == -ETIMEDOUT && ddev->nack_count)) &&
- (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
- ddev->atn_count = 0;
- rc = digital_in_send_nack(ddev, data_exch);
- if (rc)
- goto error;
- return;
- } else if ((rc == -ETIMEDOUT) &&
- (ddev->atn_count++ < DIGITAL_NFC_DEP_N_RETRY_ATN)) {
- ddev->nack_count = 0;
- rc = digital_in_send_atn(ddev, data_exch);
- if (rc)
- goto error;
- return;
- }
- goto exit;
- }
- rc = digital_skb_pull_dep_sod(ddev, resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.2");
- goto exit;
- }
- rc = ddev->skb_check_crc(resp);
- if (rc) {
- if ((resp->len >= 4) &&
- (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
- ddev->atn_count = 0;
- rc = digital_in_send_nack(ddev, data_exch);
- if (rc)
- goto error;
- kfree_skb(resp);
- return;
- }
- PROTOCOL_ERR("14.4.1.6");
- goto error;
- }
- ddev->atn_count = 0;
- ddev->nack_count = 0;
- if (resp->len > ddev->local_payload_max) {
- rc = -EMSGSIZE;
- goto exit;
- }
- size = sizeof(struct digital_dep_req_res);
- dep_res = (struct digital_dep_req_res *)resp->data;
- if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
- dep_res->cmd != DIGITAL_CMD_DEP_RES) {
- rc = -EIO;
- goto error;
- }
- pfb = dep_res->pfb;
- if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
- PROTOCOL_ERR("14.8.2.1");
- rc = -EIO;
- goto error;
- }
- if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
- rc = -EIO;
- goto exit;
- }
- if (size > resp->len) {
- rc = -EIO;
- goto error;
- }
- skb_pull(resp, size);
- switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
- case DIGITAL_NFC_DEP_PFB_I_PDU:
- if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
- PROTOCOL_ERR("14.12.3.3");
- rc = -EIO;
- goto error;
- }
- ddev->curr_nfc_dep_pni =
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- resp = digital_recv_dep_data_gather(ddev, pfb, resp,
- digital_in_send_ack,
- data_exch);
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto error;
- }
- /* If resp is NULL then we're still chaining so return and
- * wait for the next part of the PDU. Else, the PDU is
- * complete so pass it up.
- */
- if (!resp)
- return;
- rc = 0;
- break;
- case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
- if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
- PROTOCOL_ERR("14.12.4.5");
- rc = -EIO;
- goto exit;
- }
- if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
- PROTOCOL_ERR("14.12.3.3");
- rc = -EIO;
- goto exit;
- }
- ddev->curr_nfc_dep_pni =
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
- if (!ddev->chaining_skb) {
- PROTOCOL_ERR("14.12.4.3");
- rc = -EIO;
- goto exit;
- }
- /* The initiator has received a valid ACK. Free the last sent
- * PDU and keep on sending chained skb.
- */
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- rc = digital_in_send_dep_req(ddev, NULL,
- ddev->chaining_skb,
- ddev->data_exch);
- if (rc)
- goto error;
- goto free_resp;
- case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
- if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */
- rc = digital_in_send_saved_skb(ddev, data_exch);
- if (rc)
- goto error;
- goto free_resp;
- }
- if (ddev->atn_count || ddev->nack_count) {
- PROTOCOL_ERR("14.12.4.4");
- rc = -EIO;
- goto error;
- }
- rtox = DIGITAL_NFC_DEP_RTOX_VALUE(resp->data[0]);
- if (!rtox || rtox > DIGITAL_NFC_DEP_RTOX_MAX) {
- PROTOCOL_ERR("14.8.4.1");
- rc = -EIO;
- goto error;
- }
- rc = digital_in_send_rtox(ddev, data_exch, rtox);
- if (rc)
- goto error;
- goto free_resp;
- }
- exit:
- data_exch->cb(data_exch->cb_context, resp, rc);
- error:
- kfree(data_exch);
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- if (rc)
- kfree_skb(resp);
- return;
- free_resp:
- dev_kfree_skb(resp);
- }
- int digital_in_send_dep_req(struct nfc_digital_dev *ddev,
- struct nfc_target *target, struct sk_buff *skb,
- struct digital_data_exch *data_exch)
- {
- struct digital_dep_req_res *dep_req;
- struct sk_buff *chaining_skb, *tmp_skb;
- int rc;
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_req = (struct digital_dep_req_res *)skb->data;
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = ddev->curr_nfc_dep_pni;
- ddev->atn_count = 0;
- ddev->nack_count = 0;
- chaining_skb = ddev->chaining_skb;
- tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_req, data_exch);
- if (IS_ERR(tmp_skb))
- return PTR_ERR(tmp_skb);
- digital_skb_push_dep_sod(ddev, tmp_skb);
- ddev->skb_add_crc(tmp_skb);
- ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL);
- rc = digital_in_send_cmd(ddev, tmp_skb, ddev->dep_rwt,
- digital_in_recv_dep_res, data_exch);
- if (rc) {
- if (tmp_skb != skb)
- kfree_skb(tmp_skb);
- kfree_skb(chaining_skb);
- ddev->chaining_skb = NULL;
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
- return rc;
- }
- static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
- {
- ddev->curr_rf_tech = rf_tech;
- ddev->skb_add_crc = digital_skb_add_crc_none;
- ddev->skb_check_crc = digital_skb_check_crc_none;
- if (DIGITAL_DRV_CAPS_TG_CRC(ddev))
- return;
- switch (ddev->curr_rf_tech) {
- case NFC_DIGITAL_RF_TECH_106A:
- ddev->skb_add_crc = digital_skb_add_crc_a;
- ddev->skb_check_crc = digital_skb_check_crc_a;
- break;
- case NFC_DIGITAL_RF_TECH_212F:
- case NFC_DIGITAL_RF_TECH_424F:
- ddev->skb_add_crc = digital_skb_add_crc_f;
- ddev->skb_check_crc = digital_skb_check_crc_f;
- break;
- default:
- break;
- }
- }
- static int digital_tg_send_ack(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
- {
- struct digital_dep_req_res *dep_res;
- struct sk_buff *skb;
- int rc;
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_res = (struct digital_dep_req_res *)skb->data;
- dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
- dep_res->cmd = DIGITAL_CMD_DEP_RES;
- dep_res->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
- ddev->curr_nfc_dep_pni;
- if (ddev->did) {
- dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
- skb_put_data(skb, &ddev->did, sizeof(ddev->did));
- }
- ddev->curr_nfc_dep_pni =
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- ddev->saved_skb = pskb_copy(skb, GFP_KERNEL);
- rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
- data_exch);
- if (rc) {
- kfree_skb(skb);
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
- return rc;
- }
- static int digital_tg_send_atn(struct nfc_digital_dev *ddev)
- {
- struct digital_dep_req_res *dep_res;
- struct sk_buff *skb;
- int rc;
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_res = (struct digital_dep_req_res *)skb->data;
- dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
- dep_res->cmd = DIGITAL_CMD_DEP_RES;
- dep_res->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
- if (ddev->did) {
- dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
- skb_put_data(skb, &ddev->did, sizeof(ddev->did));
- }
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
- NULL);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- static int digital_tg_send_saved_skb(struct nfc_digital_dev *ddev)
- {
- int rc;
- if (!ddev->saved_skb)
- return -EINVAL;
- skb_get(ddev->saved_skb);
- rc = digital_tg_send_cmd(ddev, ddev->saved_skb, 1500,
- digital_tg_recv_dep_req, NULL);
- if (rc)
- kfree_skb(ddev->saved_skb);
- return rc;
- }
- static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp)
- {
- int rc;
- struct digital_dep_req_res *dep_req;
- u8 pfb;
- size_t size;
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto exit;
- }
- rc = ddev->skb_check_crc(resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.6");
- goto exit;
- }
- rc = digital_skb_pull_dep_sod(ddev, resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.2");
- goto exit;
- }
- if (resp->len > ddev->local_payload_max) {
- rc = -EMSGSIZE;
- goto exit;
- }
- size = sizeof(struct digital_dep_req_res);
- dep_req = (struct digital_dep_req_res *)resp->data;
- if (resp->len < size || dep_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
- dep_req->cmd != DIGITAL_CMD_DEP_REQ) {
- rc = -EIO;
- goto exit;
- }
- pfb = dep_req->pfb;
- if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
- if (ddev->did && (ddev->did == resp->data[3])) {
- size++;
- } else {
- rc = -EIO;
- goto exit;
- }
- } else if (ddev->did) {
- rc = -EIO;
- goto exit;
- }
- if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
- rc = -EIO;
- goto exit;
- }
- if (size > resp->len) {
- rc = -EIO;
- goto exit;
- }
- skb_pull(resp, size);
- switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
- case DIGITAL_NFC_DEP_PFB_I_PDU:
- pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
- if (ddev->atn_count) {
- /* The target has received (and replied to) at least one
- * ATN DEP_REQ.
- */
- ddev->atn_count = 0;
- /* pni of resp PDU equal to the target current pni - 1
- * means resp is the previous DEP_REQ PDU received from
- * the initiator so the target replies with saved_skb
- * which is the previous DEP_RES saved in
- * digital_tg_send_dep_res().
- */
- if (DIGITAL_NFC_DEP_PFB_PNI(pfb) ==
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni - 1)) {
- rc = digital_tg_send_saved_skb(ddev);
- if (rc)
- goto exit;
- goto free_resp;
- }
- /* atn_count > 0 and PDU pni != curr_nfc_dep_pni - 1
- * means the target probably did not received the last
- * DEP_REQ PDU sent by the initiator. The target
- * fallbacks to normal processing then.
- */
- }
- if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
- PROTOCOL_ERR("14.12.3.4");
- rc = -EIO;
- goto exit;
- }
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- resp = digital_recv_dep_data_gather(ddev, pfb, resp,
- digital_tg_send_ack, NULL);
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto exit;
- }
- /* If resp is NULL then we're still chaining so return and
- * wait for the next part of the PDU. Else, the PDU is
- * complete so pass it up.
- */
- if (!resp)
- return;
- rc = 0;
- break;
- case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
- if (DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { /* NACK */
- if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) !=
- ddev->curr_nfc_dep_pni) {
- rc = -EIO;
- goto exit;
- }
- ddev->atn_count = 0;
- rc = digital_tg_send_saved_skb(ddev);
- if (rc)
- goto exit;
- goto free_resp;
- }
- /* ACK */
- if (ddev->atn_count) {
- /* The target has previously recevied one or more ATN
- * PDUs.
- */
- ddev->atn_count = 0;
- /* If the ACK PNI is equal to the target PNI - 1 means
- * that the initiator did not receive the previous PDU
- * sent by the target so re-send it.
- */
- if (DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) ==
- ddev->curr_nfc_dep_pni) {
- rc = digital_tg_send_saved_skb(ddev);
- if (rc)
- goto exit;
- goto free_resp;
- }
- /* Otherwise, the target did not receive the previous
- * ACK PDU from the initiator. Fallback to normal
- * processing of chained PDU then.
- */
- }
- /* Keep on sending chained PDU */
- if (!ddev->chaining_skb ||
- DIGITAL_NFC_DEP_PFB_PNI(pfb) !=
- ddev->curr_nfc_dep_pni) {
- rc = -EIO;
- goto exit;
- }
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- rc = digital_tg_send_dep_res(ddev, ddev->chaining_skb);
- if (rc)
- goto exit;
- goto free_resp;
- case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
- if (DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
- rc = -EINVAL;
- goto exit;
- }
- rc = digital_tg_send_atn(ddev);
- if (rc)
- goto exit;
- ddev->atn_count++;
- goto free_resp;
- }
- rc = nfc_tm_data_received(ddev->nfc_dev, resp);
- if (rc)
- resp = NULL;
- exit:
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
- ddev->atn_count = 0;
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- if (rc)
- kfree_skb(resp);
- return;
- free_resp:
- dev_kfree_skb(resp);
- }
- int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
- {
- struct digital_dep_req_res *dep_res;
- struct sk_buff *chaining_skb, *tmp_skb;
- int rc;
- skb_push(skb, sizeof(struct digital_dep_req_res));
- dep_res = (struct digital_dep_req_res *)skb->data;
- dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
- dep_res->cmd = DIGITAL_CMD_DEP_RES;
- dep_res->pfb = ddev->curr_nfc_dep_pni;
- if (ddev->did) {
- dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
- skb_put_data(skb, &ddev->did, sizeof(ddev->did));
- }
- ddev->curr_nfc_dep_pni =
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
- chaining_skb = ddev->chaining_skb;
- tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_res, NULL);
- if (IS_ERR(tmp_skb))
- return PTR_ERR(tmp_skb);
- digital_skb_push_dep_sod(ddev, tmp_skb);
- ddev->skb_add_crc(tmp_skb);
- ddev->saved_skb = pskb_copy(tmp_skb, GFP_KERNEL);
- rc = digital_tg_send_cmd(ddev, tmp_skb, 1500, digital_tg_recv_dep_req,
- NULL);
- if (rc) {
- if (tmp_skb != skb)
- kfree_skb(tmp_skb);
- kfree_skb(chaining_skb);
- ddev->chaining_skb = NULL;
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
- return rc;
- }
- static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
- void *arg, struct sk_buff *resp)
- {
- u8 rf_tech = (unsigned long)arg;
- if (IS_ERR(resp))
- return;
- digital_tg_set_rf_tech(ddev, rf_tech);
- digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech);
- digital_tg_listen(ddev, 1500, digital_tg_recv_dep_req, NULL);
- dev_kfree_skb(resp);
- }
- static int digital_tg_send_psl_res(struct nfc_digital_dev *ddev, u8 did,
- u8 rf_tech)
- {
- struct digital_psl_res *psl_res;
- struct sk_buff *skb;
- int rc;
- skb = digital_skb_alloc(ddev, sizeof(struct digital_psl_res));
- if (!skb)
- return -ENOMEM;
- skb_put(skb, sizeof(struct digital_psl_res));
- psl_res = (struct digital_psl_res *)skb->data;
- psl_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
- psl_res->cmd = DIGITAL_CMD_PSL_RES;
- psl_res->did = did;
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- ddev->curr_nfc_dep_pni = 0;
- rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
- (void *)(unsigned long)rf_tech);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- static void digital_tg_recv_psl_req(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp)
- {
- int rc;
- struct digital_psl_req *psl_req;
- u8 rf_tech;
- u8 dsi, payload_size, payload_bits;
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto exit;
- }
- rc = ddev->skb_check_crc(resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.6");
- goto exit;
- }
- rc = digital_skb_pull_dep_sod(ddev, resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.2");
- goto exit;
- }
- psl_req = (struct digital_psl_req *)resp->data;
- if (resp->len != sizeof(struct digital_psl_req) ||
- psl_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
- psl_req->cmd != DIGITAL_CMD_PSL_REQ) {
- rc = -EIO;
- goto exit;
- }
- dsi = (psl_req->brs >> 3) & 0x07;
- switch (dsi) {
- case 0:
- rf_tech = NFC_DIGITAL_RF_TECH_106A;
- break;
- case 1:
- rf_tech = NFC_DIGITAL_RF_TECH_212F;
- break;
- case 2:
- rf_tech = NFC_DIGITAL_RF_TECH_424F;
- break;
- default:
- pr_err("Unsupported dsi value %d\n", dsi);
- goto exit;
- }
- payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl);
- payload_size = digital_payload_bits_to_size(payload_bits);
- if (!payload_size || (payload_size > min(ddev->local_payload_max,
- ddev->remote_payload_max))) {
- rc = -EINVAL;
- goto exit;
- }
- ddev->local_payload_max = payload_size;
- ddev->remote_payload_max = payload_size;
- rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
- exit:
- kfree_skb(resp);
- }
- static void digital_tg_send_atr_res_complete(struct nfc_digital_dev *ddev,
- void *arg, struct sk_buff *resp)
- {
- int offset;
- if (IS_ERR(resp)) {
- digital_poll_next_tech(ddev);
- return;
- }
- offset = 2;
- if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
- offset++;
- ddev->atn_count = 0;
- if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
- digital_tg_recv_psl_req(ddev, arg, resp);
- else
- digital_tg_recv_dep_req(ddev, arg, resp);
- }
- static int digital_tg_send_atr_res(struct nfc_digital_dev *ddev,
- struct digital_atr_req *atr_req)
- {
- struct digital_atr_res *atr_res;
- struct sk_buff *skb;
- u8 *gb, payload_bits;
- size_t gb_len;
- int rc;
- gb = nfc_get_local_general_bytes(ddev->nfc_dev, &gb_len);
- if (!gb)
- gb_len = 0;
- skb = digital_skb_alloc(ddev, sizeof(struct digital_atr_res) + gb_len);
- if (!skb)
- return -ENOMEM;
- skb_put(skb, sizeof(struct digital_atr_res));
- atr_res = (struct digital_atr_res *)skb->data;
- memset(atr_res, 0, sizeof(struct digital_atr_res));
- atr_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
- atr_res->cmd = DIGITAL_CMD_ATR_RES;
- memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
- atr_res->to = DIGITAL_NFC_DEP_TG_MAX_WT;
- ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
- payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
- atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
- if (gb_len) {
- skb_put(skb, gb_len);
- atr_res->pp |= DIGITAL_GB_BIT;
- memcpy(atr_res->gb, gb, gb_len);
- }
- digital_skb_push_dep_sod(ddev, skb);
- ddev->skb_add_crc(skb);
- ddev->curr_nfc_dep_pni = 0;
- rc = digital_tg_send_cmd(ddev, skb, 999,
- digital_tg_send_atr_res_complete, NULL);
- if (rc)
- kfree_skb(skb);
- return rc;
- }
- void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp)
- {
- int rc;
- struct digital_atr_req *atr_req;
- size_t gb_len, min_size;
- u8 poll_tech_count, payload_bits;
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto exit;
- }
- if (!resp->len) {
- rc = -EIO;
- goto exit;
- }
- if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB) {
- min_size = DIGITAL_ATR_REQ_MIN_SIZE + 2;
- digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_106A);
- } else {
- min_size = DIGITAL_ATR_REQ_MIN_SIZE + 1;
- digital_tg_set_rf_tech(ddev, NFC_DIGITAL_RF_TECH_212F);
- }
- if (resp->len < min_size) {
- rc = -EIO;
- goto exit;
- }
- ddev->curr_protocol = NFC_PROTO_NFC_DEP_MASK;
- rc = ddev->skb_check_crc(resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.6");
- goto exit;
- }
- rc = digital_skb_pull_dep_sod(ddev, resp);
- if (rc) {
- PROTOCOL_ERR("14.4.1.2");
- goto exit;
- }
- atr_req = (struct digital_atr_req *)resp->data;
- if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
- atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
- atr_req->did > DIGITAL_DID_MAX) {
- rc = -EINVAL;
- goto exit;
- }
- payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp);
- ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
- if (!ddev->remote_payload_max) {
- rc = -EINVAL;
- goto exit;
- }
- ddev->did = atr_req->did;
- rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
- NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
- if (rc)
- goto exit;
- rc = digital_tg_send_atr_res(ddev, atr_req);
- if (rc)
- goto exit;
- gb_len = resp->len - sizeof(struct digital_atr_req);
- poll_tech_count = ddev->poll_tech_count;
- ddev->poll_tech_count = 0;
- rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK,
- NFC_COMM_PASSIVE, atr_req->gb, gb_len);
- if (rc) {
- ddev->poll_tech_count = poll_tech_count;
- goto exit;
- }
- rc = 0;
- exit:
- if (rc)
- digital_poll_next_tech(ddev);
- dev_kfree_skb(resp);
- }
|