<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/13681">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add sim-atr command<br><br>the sim-atr command resets the card and read the resulting<br>answer to reset.<br><br>Change-Id: I30b284cab60a50d4cd3080f46f4d332193bbf1ee<br>---<br>M sysmoOCTSIM/main.c<br>1 file changed, 91 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/sysmoOCTSIM/main.c b/sysmoOCTSIM/main.c</span><br><span>index 369e3ef..5b10c5f 100644</span><br><span>--- a/sysmoOCTSIM/main.c</span><br><span>+++ b/sysmoOCTSIM/main.c</span><br><span>@@ -31,6 +31,13 @@</span><br><span> </span><br><span> #include "command.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+// TODO put declaration in more global file</span><br><span style="color: hsl(120, 100%, 40%);">+// TODO for now SIM7 is not present because used for debug</span><br><span style="color: hsl(120, 100%, 40%);">+static struct usart_async_descriptor* SIM_peripheral_descriptors[] = {&SIM0, &SIM1, &SIM2, &SIM3, &SIM4, &SIM5, &SIM6, NULL};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void SIM_rx_cb(const struct usart_async_descriptor *const io_descr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> static void board_init()</span><br><span> {</span><br><span>@@ -48,6 +55,15 @@</span><br><span>      /* increase drive strength of 20Mhz SIM clock output to 8mA</span><br><span>   * (there are 8 inputs + traces to drive!) */</span><br><span>        hri_port_set_PINCFG_DRVSTR_bit(PORT, 0, 11);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        // enable SIM interfaces</span><br><span style="color: hsl(120, 100%, 40%);">+      for (uint8_t i = 0; i < ARRAY_SIZE(SIM_peripheral_descriptors); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (NULL == SIM_peripheral_descriptors[i]) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             usart_async_register_callback(SIM_peripheral_descriptors[i], USART_ASYNC_RXC_CB, SIM_rx_cb); // required for RX to work, even if the callback does nothing</span><br><span style="color: hsl(120, 100%, 40%);">+            usart_async_enable(SIM_peripheral_descriptors[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span> }</span><br><span> </span><br><span> static int validate_slotnr(int argc, char **argv, int idx)</span><br><span>@@ -203,7 +219,81 @@</span><br><span>      ncn8025_set(slotnr, &settings);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(sim_atr, cmd_sim_atr, "sim-atr", "Read ATR from SIM card")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ncn8025_settings settings;</span><br><span style="color: hsl(120, 100%, 40%);">+     int slotnr = validate_slotnr(argc, argv, 1);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      if (slotnr < 0 || slotnr >= ARRAY_SIZE(SIM_peripheral_descriptors) || NULL == SIM_peripheral_descriptors[slotnr]) {</span><br><span style="color: hsl(120, 100%, 40%);">+             return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // check if card is present (and read current settings)</span><br><span style="color: hsl(120, 100%, 40%);">+       ncn8025_get(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!settings.simpres) {</span><br><span style="color: hsl(120, 100%, 40%);">+              printf("no card present in slot %d, aborting\r\n", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+         return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // switch card off (assert reset and disable power)</span><br><span style="color: hsl(120, 100%, 40%);">+   // note: ISO/IEC 7816-3:2006 section 6.4 provides the deactivation sequence, but not the minimum corresponding times</span><br><span style="color: hsl(120, 100%, 40%);">+  settings.rstin = true;</span><br><span style="color: hsl(120, 100%, 40%);">+        settings.cmdvcc = false;</span><br><span style="color: hsl(120, 100%, 40%);">+      ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // TODO wait some time for card to be completely deactivated</span><br><span style="color: hsl(120, 100%, 40%);">+  usart_async_flush_rx_buffer(SIM_peripheral_descriptors[slotnr]); // flush RX buffer to start from scratch</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   //usart_async_set_baud_rate(SIM_peripheral_descriptors[slotnr], 2500000 / (372 / 1)); // set USART baud rate to match the interface (f = 2.5 MHz) and card default settings (Fd = 372, Dd = 1)</span><br><span style="color: hsl(120, 100%, 40%);">+        // set clock to lowest frequency (20 MHz / 8 = 2.5 MHz)</span><br><span style="color: hsl(120, 100%, 40%);">+       // note: according to ISO/IEC 7816-3:2006 section 5.2.3 the minimum value is 1 MHz, and maximum is 5 MHz during activation</span><br><span style="color: hsl(120, 100%, 40%);">+    settings.clkdiv = SIM_CLKDIV_8;</span><br><span style="color: hsl(120, 100%, 40%);">+       // set card voltage to 3.0 V (the most supported)</span><br><span style="color: hsl(120, 100%, 40%);">+     // note: according to ISO/IEC 7816-3:2006 no voltage should damage the card, and you should cycle from low to high</span><br><span style="color: hsl(120, 100%, 40%);">+    settings.vsel = SIM_VOLT_3V0;</span><br><span style="color: hsl(120, 100%, 40%);">+ // provide power (the NCN8025 should perform the activation according to spec)</span><br><span style="color: hsl(120, 100%, 40%);">+        // note: activation sequence is documented in ISO/IEC 7816-3:2006 section 6.2</span><br><span style="color: hsl(120, 100%, 40%);">+ settings.cmdvcc = true;</span><br><span style="color: hsl(120, 100%, 40%);">+       ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // wait for Tb=400 cycles before re-asserting reset</span><br><span style="color: hsl(120, 100%, 40%);">+   delay_us(400 * 10000 / 2500); // 400 cycles * 1000 for us, 2.5 MHz / 1000 for us</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    // de-assert reset to switch card back on</span><br><span style="color: hsl(120, 100%, 40%);">+     settings.rstin = false;</span><br><span style="color: hsl(120, 100%, 40%);">+       ncn8025_set(slotnr, &settings);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // wait for Tc=40000 cycles for transmission to start</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t cycles = 40000;</span><br><span style="color: hsl(120, 100%, 40%);">+      while (cycles && !usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+          delay_us(10);</span><br><span style="color: hsl(120, 100%, 40%);">+         cycles -= 25; // 10 us = 25 cycles at 2.5 MHz</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+               delay_us(12 * 372 / 1 / 2); // wait more than one byte (approximate freq down to 2 MHz)</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     // verify if one byte has been received</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("card in slot %d is not responding, aborting\r\n", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // read ATR (just do it until there is no traffic anymore)</span><br><span style="color: hsl(120, 100%, 40%);">+    // TODO the ATR should be parsed to read the right number of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("ATR: ");</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t atr_byte;</span><br><span style="color: hsl(120, 100%, 40%);">+     while (usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (1 == io_read(&SIM_peripheral_descriptors[slotnr]->io, &atr_byte, 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 printf("%02x ", atr_byte);</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             uint16_t wt = 9600; // waiting time in ETU</span><br><span style="color: hsl(120, 100%, 40%);">+            while (wt && !usart_async_is_rx_not_empty(SIM_peripheral_descriptors[slotnr])) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(120, 100%, 40%);">+                       wt--;</span><br><span style="color: hsl(120, 100%, 40%);">+         }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> extern void testmode_init(void);</span><br><span> </span><br><span>@@ -223,6 +313,7 @@</span><br><span>       command_register(&cmd_sim_clkdiv);</span><br><span>       command_register(&cmd_sim_voltage);</span><br><span>      command_register(&cmd_sim_led);</span><br><span style="color: hsl(120, 100%, 40%);">+   command_register(&cmd_sim_atr);</span><br><span>  testmode_init();</span><br><span> </span><br><span>         printf("\r\n\r\nsysmocom sysmoOCTSIM\r\n");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13681">change 13681</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13681"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-ccid-firmware </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I30b284cab60a50d4cd3080f46f4d332193bbf1ee </div>
<div style="display:none"> Gerrit-Change-Number: 13681 </div>
<div style="display:none"> Gerrit-PatchSet: 9 </div>
<div style="display:none"> Gerrit-Owner: Kévin Redon <kredon@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>