firmware/br-ext-chip-allwinner/board/v83x/kernel/patches/00000-drivers_char_sunxi-sc...

330 lines
6.7 KiB
Diff

diff -drupN a/drivers/char/sunxi-scr/smartcard.c b/drivers/char/sunxi-scr/smartcard.c
--- a/drivers/char/sunxi-scr/smartcard.c 1970-01-01 03:00:00.000000000 +0300
+++ b/drivers/char/sunxi-scr/smartcard.c 2022-06-12 05:28:14.000000000 +0300
@@ -0,0 +1,325 @@
+/*
+ * drivers/char/sunxi-scr/smartcard.c
+ *
+ * Copyright (C) 2016 Allwinner.
+ * fuzhaoke <fuzhaoke@allwinnertech.com>
+ *
+ * Decode for ISO7816 smart card
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include "smartcard.h"
+
+void smartcard_ta1_decode(struct smc_atr_para *psmc_atr, uint8_t ta1)
+{
+ pr_debug("%s: enter!!\n", __func__);
+
+ switch ((ta1>>4)&0xf) {
+ case 0x0:
+ psmc_atr->FMAX = 4;
+ psmc_atr->F = 372;
+ break;
+ case 0x1:
+ psmc_atr->FMAX = 5;
+ psmc_atr->F = 372;
+ break;
+ case 0x2:
+ psmc_atr->FMAX = 6;
+ psmc_atr->F = 558;
+ break;
+ case 0x3:
+ psmc_atr->FMAX = 8;
+ psmc_atr->F = 744;
+ break;
+ case 0x4:
+ psmc_atr->FMAX = 12;
+ psmc_atr->F = 1116;
+ break;
+ case 0x5:
+ psmc_atr->FMAX = 16;
+ psmc_atr->F = 1488;
+ break;
+ case 0x6:
+ psmc_atr->FMAX = 20;
+ psmc_atr->F = 1860;
+ break;
+ case 0x9:
+ psmc_atr->FMAX = 5;
+ psmc_atr->F = 512;
+ break;
+ case 0xA:
+ psmc_atr->FMAX = 7;
+ psmc_atr->F = 768;
+ break;
+ case 0xB:
+ psmc_atr->FMAX = 10;
+ psmc_atr->F = 1024;
+ break;
+ case 0xC:
+ psmc_atr->FMAX = 15;
+ psmc_atr->F = 1536;
+ break;
+ case 0xD:
+ psmc_atr->FMAX = 20;
+ psmc_atr->F = 2048;
+ break;
+ default: /* 0x7/0x8/0xE/0xF */
+ psmc_atr->FMAX = 4;
+ psmc_atr->F = 372;
+ pr_err("Unsupport ta1 = 0x%x\n", ta1);
+ break;
+ }
+
+ switch (ta1&0xf) {
+ case 0x1:
+ psmc_atr->D = 1;
+ break;
+ case 0x2:
+ psmc_atr->D = 2;
+ break;
+ case 0x3:
+ psmc_atr->D = 4;
+ break;
+ case 0x4:
+ psmc_atr->D = 8;
+ break;
+ case 0x5:
+ psmc_atr->D = 16;
+ break;
+ case 0x6:
+ psmc_atr->D = 32;
+ break;
+ case 0x8:
+ psmc_atr->D = 12;
+ break;
+ case 0x9:
+ psmc_atr->D = 20;
+ break;
+ default: /* 0x0/0x7/0xA/0xB/0xC/0xD/0xE/0xF */
+ psmc_atr->D = 1;
+ pr_err("Unsupport ta1 = 0x%x\n", ta1);
+ break;
+ }
+}
+
+void smartcard_tb1_decode(struct smc_atr_para *psmc_atr, uint8_t tb1)
+{
+ pr_debug("%s: enter!!\n", __func__);
+
+ switch ((tb1>>5)&0x3) {
+ case 0:
+ psmc_atr->I = 25;
+ break;
+ case 1:
+ psmc_atr->I = 50;
+ break;
+ case 2:
+ psmc_atr->I = 100;
+ break;
+ default:
+ psmc_atr->I = 50;
+ }
+
+ if (((tb1&0x1f) > 4) && ((tb1&0x1f) < 26))
+ psmc_atr->P = (tb1&0x1f); /* 5~25 in Volts */
+ else if (0 == (tb1&0x1f))
+ psmc_atr->P = 0;
+ else
+ psmc_atr->P = 5;
+}
+
+/* ATR data format: max 33 byte(include TS)
+ * [TS|T0|TA1|TB1|TC1|TD1|TA2|TB2|TC2|TD2|...|T1|T2|........|TK|TCK]
+ * |-------- max 16 byte --------------|-- max 15 byte --|verify
+ * |--------------------- max 33 byte -------------------------|
+ * TS: Initial character
+ * 0x3b:direct convention, 0x3f:inverse convention
+ * T0: Format character
+ * [bit7|bit6|bit5|bit4|bit3|bit2|bit1|bit0]
+ * |------- Y1 --------|-------- K --------|
+ * Y1: indicator for the presence of the interface character
+ * TA1 is transmitted when bit[4] = 1
+ * TB1 is transmitted when bit[5] = 1
+ * TC1 is transmitted when bit[6] = 1
+ * TD1 is transmitted when bit[7] = 1
+ * K: history number
+ * TAi: Interface character
+ * code FI,DI
+ * TBi: Interface character
+ * code II,PI
+ * TCi: Interface character
+ * code N
+ * TDi: Interface character
+ * code Yi+1, T
+ * [bit7|bit6|bit5|bit4|bit3|bit2|bit1|bit0]
+ * |------ Yi + 1 -----|-------- T --------|
+ * Yi + 1: indicator for the presence of the interface character
+ * TAi+1 is transmitted when bit[4] = 1
+ * TBi+1 is transmitted when bit[5] = 1
+ * TCi+1 is transmitted when bit[6] = 1
+ * TDi+1 is transmitted when bit[7] = 1
+ * T: Protocol type for subsequent transmission
+ * T=0: character transmit
+ * T=1: block transmit
+ * T=other: reserved
+ * T1~TK: history byte, information of the card like manufacture name
+ * TCK: verify character, make sure the data is correctly
+*/
+void smartcard_atr_decode(struct smc_atr_para *psmc_atr, struct smc_pps_para *psmc_pps,
+ uint8_t *pdata, uint8_t with_ts)
+{
+ uint8_t index = 0;
+ uint8_t temp;
+ uint8_t i;
+
+ pr_debug("%s: Enter...\n", __func__);
+
+ psmc_pps->ppss = 0xff;
+ psmc_pps->pps0 = 0;
+
+ if (with_ts) {
+ psmc_atr->TS = pdata[0]; /* TS */
+ index++;
+ }
+ temp = pdata[index]; /* T0 */
+ index++;
+ psmc_atr->TK_NUM = temp & 0xf;
+
+ /* TA1 */
+ if (temp & 0x10) {
+ smartcard_ta1_decode(psmc_atr, pdata[index]);
+ psmc_pps->pps0 |= 0x1<<4;
+ psmc_pps->pps1 = pdata[index];
+ index++;
+ }
+
+ /* TB1 */
+ if (temp & 0x20) {
+ smartcard_tb1_decode(psmc_atr, pdata[index]);
+ index++;
+ }
+
+ /* TC1 */
+ if (temp & 0x40) {
+ psmc_atr->N = pdata[index] & 0xff;
+ index++;
+ }
+
+ /* TD1 */
+ if (temp & 0x80) {
+ pr_debug("%s: TD1 parse 0x%x !!\n", __func__, pdata[index]);
+ temp = pdata[index];
+ psmc_atr->T = temp & 0xf;
+ psmc_pps->pps0 |= temp & 0xf;
+
+ /* Adjust Guard Time */
+ if (psmc_atr->N == 0xff) {
+ if (psmc_atr->T == 1)
+ psmc_atr->N = 1;
+ else
+ psmc_atr->N = 2;
+ }
+ index++;
+ } else {
+ if (psmc_atr->N == 0xff)
+ psmc_atr->N = 2;
+ goto rx_tk;
+ }
+
+ /* TA2 */
+ if (temp & 0x10) {
+ pr_debug("TA2 Exist!!\n");
+ index++;
+ }
+
+ /* TB2 */
+ if (temp & 0x20) {
+ pr_debug("TB2 Exist!!\n");
+ index++;
+ }
+
+ /* TC2 */
+ if (temp & 0x40) {
+ pr_debug("TC2 Exist!!\n");
+ index++;
+ }
+
+ /* TD2 */
+ if (temp & 0x80) {
+ pr_debug("TD2 Exist!!\n");
+ temp = pdata[index];
+ index++;
+ } else {
+ goto rx_tk;
+ }
+
+ /* TA3 */
+ if (temp & 0x10) {
+ pr_debug("TA3 Exist!!\n");
+ index++;
+ }
+
+ /* TB3 */
+ if (temp & 0x20) {
+ pr_debug("TB3 Exist!!\n");
+ index++;
+ }
+
+ /* TC3 */
+ if (temp & 0x40) {
+ pr_debug("TC3 Exist!!\n");
+ index++;
+ }
+
+ /* TD3 */
+ if (temp & 0x80) {
+ pr_debug("TD3 Exist!!\n");
+ temp = pdata[index];
+ index++;
+ } else {
+ goto rx_tk;
+ }
+
+ /* TA4 */
+ if (temp & 0x10) {
+ pr_debug("TA4 Exist!!\n");
+ index++;
+ }
+
+ /* TB4 */
+ if (temp & 0x20) {
+ pr_debug("TB4 Exist!!\n");
+ index++;
+ }
+
+ /* TC4 */
+ if (temp & 0x40) {
+ pr_debug("TC4 Exist!!\n");
+ index++;
+ }
+
+ /* TD4 */
+ if (temp & 0x80) {
+ pr_debug("TD4 Exist!!\n");
+ temp = pdata[index];
+ index++;
+ }
+
+rx_tk:
+ for (i = 0; i < (psmc_atr->TK_NUM); i++)
+ psmc_atr->TK[i] = pdata[index++];
+
+ psmc_pps->pck = psmc_pps->ppss;
+ psmc_pps->pck ^= psmc_pps->pps0;
+ if (psmc_pps->pps0&(0x1<<4))
+ psmc_pps->pck ^= psmc_pps->pps1;
+ if (psmc_pps->pps0&(0x1<<5))
+ psmc_pps->pck ^= psmc_pps->pps2;
+ if (psmc_pps->pps0&(0x1<<6))
+ psmc_pps->pck ^= psmc_pps->pps3;
+}