<p>Kévin Redon has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13949">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add function to transfer TPDU<br><br>this function takes care of reading and writing the complete TPDU<br>to the card.<br><br>note: the sim-iccid command uses this function, but still only to<br>select MF.<br><br>Change-Id: I50c90f3697580a4c93220a3e09cc33ec85889814<br>---<br>M sysmoOCTSIM/main.c<br>1 file changed, 184 insertions(+), 83 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/49/13949/1</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 11849c7..327ac6d 100644</span><br><span>--- a/sysmoOCTSIM/main.c</span><br><span>+++ b/sysmoOCTSIM/main.c</span><br><span>@@ -226,7 +226,183 @@</span><br><span> </span><br><span>       // set baud rate</span><br><span>     uint32_t baudrate = (freq * d) / f; // calculate actual baud rate</span><br><span style="color: hsl(0, 100%, 40%);">-       return slot_set_baudrate(slotnr, baudrate); // // set baud rate</span><br><span style="color: hsl(120, 100%, 40%);">+       return slot_set_baudrate(slotnr, baudrate); // set baud rate</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%);">+/** write data to card</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] slotnr slot number on which to send data</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] data data to be transmitted</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] length length of data to be transmitted</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @return error code</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int slot_card_write(uint8_t slotnr, const uint8_t* data, uint16_t length)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+       ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (0 == length || NULL == data) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_INVALID_ARG;</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%);">+   struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr];</span><br><span style="color: hsl(120, 100%, 40%);">+      ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 0; // disable receive (to avoid the echo back)</span><br><span style="color: hsl(120, 100%, 40%);">+       SIM_tx_count[slotnr] = false; // reset TX complete</span><br><span style="color: hsl(120, 100%, 40%);">+    for (uint16_t i = 0; i < length; i++) { // transmit data</span><br><span style="color: hsl(120, 100%, 40%);">+           while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING blocking)</span><br><span style="color: hsl(120, 100%, 40%);">+          if (1 != io_write(&sim->io, &data[i], 1)) { // put but in transmit buffer</span><br><span style="color: hsl(120, 100%, 40%);">+                  return ERR_IO;</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%);">+     while (!SIM_tx_count[slotnr]); // wait until transmission is complete (WARNING blocking)</span><br><span style="color: hsl(120, 100%, 40%);">+      ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // enable receive again</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return ERR_NONE;</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 data from card</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] slotnr slot number on which to send data</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[out] data buffer for read data to be stored</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] length length of data to be read</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] wt Waiting Time in ETU</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @return error code</span><br><span style="color: hsl(120, 100%, 40%);">+ *  TODO fix WT/ETU duration</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int slot_card_read(uint8_t slotnr, uint8_t* data, uint16_t length, uint32_t wt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+       ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (0 == length || NULL == data) {</span><br><span style="color: hsl(120, 100%, 40%);">+            return ERR_INVALID_ARG;</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%);">+   struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1; // ensure RX is enabled</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t timeout = wt; // reset waiting time</span><br><span style="color: hsl(120, 100%, 40%);">+  for (uint16_t i = 0; i < length; i++) { // read all data</span><br><span style="color: hsl(120, 100%, 40%);">+           while (timeout && !usart_async_is_rx_not_empty(sim)) { // verify if data is present</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%);">+                       timeout--;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             if (0 == timeout) { // timeout reached</span><br><span style="color: hsl(120, 100%, 40%);">+                        return ERR_TIMEOUT;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             timeout = wt; // reset waiting time</span><br><span style="color: hsl(120, 100%, 40%);">+           if (1 != io_read(&sim->io, &data[i], 1)) { // read one byte</span><br><span style="color: hsl(120, 100%, 40%);">+                        return ERR_IO;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return ERR_NONE;</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%);">+/** transfer TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] slotnr slot number on which to transfer the TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] header TPDU header to send</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[io] data TPDU data to transfer</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] data_length length of TPDU data to transfer</span><br><span style="color: hsl(120, 100%, 40%);">+ *  @param[in] write if the data should be written (true) or read (false)</span><br><span style="color: hsl(120, 100%, 40%);">+ * TODO fix WT</span><br><span style="color: hsl(120, 100%, 40%);">+ * TODO the data length can be deduce from the header</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int slot_tpdu_xfer(uint8_t slotnr, const uint8_t* header, uint8_t* data, uint16_t data_length, bool write)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      // input checks</span><br><span style="color: hsl(120, 100%, 40%);">+       ASSERT(slotnr < ARRAY_SIZE(SIM_peripheral_descriptors));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (NULL == header || (data_length > 0 && NULL == data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return ERR_INVALID_ARG;</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%);">+   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr]; // get USART peripheral</span><br><span style="color: hsl(120, 100%, 40%);">+      usart_async_flush_rx_buffer(sim); // 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%);">+  // send command header</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("(%d) TPDU: ", slotnr);</span><br><span style="color: hsl(120, 100%, 40%);">+      for (uint8_t i = 0; i < 5; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          printf("%02x ", header[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = slot_card_write(slotnr, header, 5); // transmit header</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("error in command header transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+            return rc;</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 procedure byte, and handle data</span><br><span style="color: hsl(120, 100%, 40%);">+       uint8_t pb = 0x60; // wait more procedure byte</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t data_i = 0; // progress in the data transfer</span><br><span style="color: hsl(120, 100%, 40%);">+ while (0x60 == pb) { // wait for SW</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = slot_card_read(slotnr, &pb, 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 printf("error while receiving PB/SW1 (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             printf("%02x ", pb);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (0x60 == pb) { // NULL byte</span><br><span style="color: hsl(120, 100%, 40%);">+                        // just wait more time</span><br><span style="color: hsl(120, 100%, 40%);">+                } else if ((0x60 == (pb & 0xf0)) || (0x90 == (pb & 0xf0))) { // SW1 byte</span><br><span style="color: hsl(120, 100%, 40%);">+                      // left the rest of the code handle it</span><br><span style="color: hsl(120, 100%, 40%);">+                } else if (header[1] == pb) { // ACK byte</span><br><span style="color: hsl(120, 100%, 40%);">+                     // transfer rest of the data</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (data_i >= data_length) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               printf("error no more data to transfer\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               return ERR_INVALID_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (write) { // transmit remaining command data</span><br><span style="color: hsl(120, 100%, 40%);">+                               rc = slot_card_write(slotnr, &data[data_i], data_length - data_i); // transmit command data</span><br><span style="color: hsl(120, 100%, 40%);">+                               if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 printf("error in command data transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                                      return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+                            }</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else { // receive remaining command data</span><br><span style="color: hsl(120, 100%, 40%);">+                            rc = slot_card_read(slotnr, &data[data_i], data_length - data_i, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+                           if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 printf("error in command data receive (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                                       return rc;</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%);">+                     for (uint16_t i = data_i; i < data_length; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          printf("%02x ", data[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+                   }</span><br><span style="color: hsl(120, 100%, 40%);">+                     data_i = data_length; // remember we transferred the data</span><br><span style="color: hsl(120, 100%, 40%);">+                     pb = 0x60; // wait for SW1</span><br><span style="color: hsl(120, 100%, 40%);">+            } else if (header[1] == (pb ^ 0xff)) { // ACK byte</span><br><span style="color: hsl(120, 100%, 40%);">+                    // transfer only one byte</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (data_i >= data_length) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               printf("error no more data to transfer\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                               return ERR_INVALID_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (write) { // transmit command data byte</span><br><span style="color: hsl(120, 100%, 40%);">+                            rc = slot_card_write(slotnr, &data[data_i], 1); // transmit command data</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 printf("error in command data transmit (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                                      return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+                            }</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else { // receive command data byte</span><br><span style="color: hsl(120, 100%, 40%);">+                         rc = slot_card_read(slotnr, &data[data_i], 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+                              if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                 printf("error in command data receive (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+                                       return rc;</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("%02x ", data[data_i]);</span><br><span style="color: hsl(120, 100%, 40%);">+                      data_i += 1; // remember we transferred one data byte</span><br><span style="color: hsl(120, 100%, 40%);">+                 pb = 0x60; // wait for SW1</span><br><span style="color: hsl(120, 100%, 40%);">+            } else { // invalid byte</span><br><span style="color: hsl(120, 100%, 40%);">+                      return ERR_INVALID_DATA;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   // read SW2</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t sw2;</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = slot_card_read(slotnr, &sw2, 1, ISO7816_3_DEFAULT_WT);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("error in receiving SW2 (errno = %d)\r\n", rc);</span><br><span style="color: hsl(120, 100%, 40%);">+              return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("%02x", sw2);</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%);">+     return ERR_NONE;</span><br><span> }</span><br><span> </span><br><span> DEFUN(sim_status, cmd_sim_status, "sim-status", "Get state of specified NCN8025")</span><br><span>@@ -480,90 +656,15 @@</span><br><span>           ncn8025_set(slotnr, &settings);</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   // read MF</span><br><span style="color: hsl(0, 100%, 40%);">-      printf("(%d) SELECT MF: ", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-   struct usart_async_descriptor* sim = SIM_peripheral_descriptors[slotnr];</span><br><span style="color: hsl(0, 100%, 40%);">-        ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch</span><br><span style="color: hsl(120, 100%, 40%);">+    // select MF</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("(%d) SELECT MF\r\n", slotnr);</span><br><span>      // write SELECT MF APDU</span><br><span style="color: hsl(0, 100%, 40%);">- const uint8_t select_mf[] = {0xa0, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00};</span><br><span style="color: hsl(0, 100%, 40%);">- SIM_tx_count[slotnr] = false; // reset TX complete</span><br><span style="color: hsl(0, 100%, 40%);">-      for (uint8_t i = 0; i < 5; i++) { // transmit command header</span><br><span style="color: hsl(0, 100%, 40%);">-         printf("%02x ", select_mf[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-                while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING could block)</span><br><span style="color: hsl(0, 100%, 40%);">-         if (1 != io_write(&sim->io, &select_mf[i], 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     printf("(%d) error: could not send command header\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-                      return;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(120, 100%, 40%);">+     const uint8_t select_mf_header[] = {0xa0, 0xa4, 0x00, 0x00, 0x02};</span><br><span style="color: hsl(120, 100%, 40%);">+    const uint8_t select_mf_data[] = {0x3f, 0x00};</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc = slot_tpdu_xfer(slotnr, select_mf_header, (uint8_t*)select_mf_data, ARRAY_SIZE(select_mf_data), true); // transfer TPDU</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ERR_NONE != rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("error while SELECT MF (errno = %d)\r\n", rc);</span><br><span>      }</span><br><span style="color: hsl(0, 100%, 40%);">-       uint16_t wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU (actually it can be a lot more after the ATR, but we use the default)</span><br><span style="color: hsl(0, 100%, 40%);">-        while (wt && !SIM_tx_count[slotnr]) { // wait until transmission is complete</span><br><span style="color: hsl(0, 100%, 40%);">-            delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(0, 100%, 40%);">-         wt--;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (0 == wt) { // timeout reached</span><br><span style="color: hsl(0, 100%, 40%);">-               printf("(%d) error: could not transmit data\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-            return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       ((Sercom *)sim->device.hw)->USART.CTRLB.bit.RXEN = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-     //usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch</span><br><span style="color: hsl(0, 100%, 40%);">-    wt = ISO7816_3_DEFAULT_WT; // reset waiting time</span><br><span style="color: hsl(0, 100%, 40%);">-        while (wt && !usart_async_is_rx_not_empty(sim)) { // wait for procedure byte</span><br><span style="color: hsl(0, 100%, 40%);">-            delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(0, 100%, 40%);">-         wt--;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (0 == wt) { // timeout reached</span><br><span style="color: hsl(0, 100%, 40%);">-               printf("(%d) error: card not responsive\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-                return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t pb;</span><br><span style="color: hsl(0, 100%, 40%);">-     if (1 != io_read(&sim->io, &pb, 1)) { // read procedure byte</span><br><span style="color: hsl(0, 100%, 40%);">-         printf("(%d) error: could not read data\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-                return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (select_mf[1] != pb) { // the header is ACKed when the procedure by is equal to the instruction byte</span><br><span style="color: hsl(0, 100%, 40%);">-         printf("(%d) error: header NACKed\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-              return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       SIM_tx_count[slotnr] = false; // reset TX complete</span><br><span style="color: hsl(0, 100%, 40%);">-      for (uint8_t i = 5; i < 7; i++) { // transmit command data</span><br><span style="color: hsl(0, 100%, 40%);">-           printf("%02x ", select_mf[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-                while(!usart_async_is_tx_empty(sim)); // wait for previous byte to be transmitted (WARNING could block)</span><br><span style="color: hsl(0, 100%, 40%);">-         if (1 != io_write(&sim->io, &select_mf[i], 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     printf("(%d) error: could not send command data\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-                        return;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU (actually it can be a lot more after the ATR, but we use the default)</span><br><span style="color: hsl(0, 100%, 40%);">- while (wt && !SIM_tx_count[slotnr]) { // wait until transmission is complete</span><br><span style="color: hsl(0, 100%, 40%);">-            delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(0, 100%, 40%);">-         wt--;</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (0 == wt) { // timeout reached</span><br><span style="color: hsl(0, 100%, 40%);">-               printf("(%d) error: could not transmit data\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-            return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       usart_async_flush_rx_buffer(sim); // flush RX buffer to start from scratch</span><br><span style="color: hsl(0, 100%, 40%);">-      // read SW</span><br><span style="color: hsl(0, 100%, 40%);">-      uint8_t sw[2]; // to read the status words</span><br><span style="color: hsl(0, 100%, 40%);">-      wt = ISO7816_3_DEFAULT_WT; // waiting time in ETU (actually it can be a lot more after the ATR, but we use the default)</span><br><span style="color: hsl(0, 100%, 40%);">- for (uint8_t i = 0; i < ARRAY_SIZE(sw); i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-               while (wt && !usart_async_is_rx_not_empty(sim)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       delay_us(149); // wait for 1 ETU (372 / 1 / 2.5 MHz = 148.8 us)</span><br><span style="color: hsl(0, 100%, 40%);">-                 wt--;</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (0 == wt) { // timeout reached</span><br><span style="color: hsl(0, 100%, 40%);">-                       printf("(%d) error: card not responsive\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-                } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        if (1 != io_read(&sim->io, &sw[i], 1)) { // read SW</span><br><span style="color: hsl(0, 100%, 40%);">-                          printf("(%d) error: could not read data\r\n", slotnr);</span><br><span style="color: hsl(0, 100%, 40%);">-                                return;</span><br><span style="color: hsl(0, 100%, 40%);">-                 }</span><br><span style="color: hsl(0, 100%, 40%);">-                       printf("%02x ", sw[i]);</span><br><span style="color: hsl(0, 100%, 40%);">-                       wt = ISO7816_3_DEFAULT_WT; // reset WT</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       printf("\r\n");</span><br><span> </span><br><span>        // disable LED</span><br><span>       settings.led = false;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13949">change 13949</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/13949"/><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: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I50c90f3697580a4c93220a3e09cc33ec85889814 </div>
<div style="display:none"> Gerrit-Change-Number: 13949 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Kévin Redon <kredon@sysmocom.de> </div>