text: /*******************************************************************************
   * This file is part of the ARK Ledger App.
   *
   * Copyright (c) ARK Ecosystem <info@ark.io>
   *
   * The MIT License (MIT)
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to
   * deal in the Software without restriction, including without limitation the
   * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   * sell copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   * SOFTWARE.
   * 
   * -----
   * 
   * Parts of this software are based on Ledger Nano SDK
   * 
   * (c) 2017 Ledger
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   ******************************************************************************/
  
  #include "io.h"
  
  #include <os.h>
  #include <ux.h>
  #include <os_io_seproxyhal.h>
  
  ////////////////////////////////////////////////////////////////////////////////
  uint8_t G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
  
  ////////////////////////////////////////////////////////////////////////////////
  uint8_t io_event(unsigned char channel) {
      // nothing done with the event
      // throw an error on the transport layer if needed.
  
      // can't have more than one tag in the reply, not supported yet.
      switch (G_io_seproxyhal_spi_buffer[0]) {
          case SEPROXYHAL_TAG_FINGER_EVENT:
              UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
              break;
  
          case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
              UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
              break;
  
          case SEPROXYHAL_TAG_STATUS_EVENT:
              if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID &&
                  !(U4BE(G_io_seproxyhal_spi_buffer, 3U) &
                  SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
                  THROW(EXCEPTION_IO_RESET);
              }
  
          case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
              UX_DISPLAYED_EVENT({});
              break;
  
          case SEPROXYHAL_TAG_TICKER_EVENT:
              UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {
                  if (UX_ALLOWED) {
                      UX_REDISPLAY();
                  }
              });
              break;
  
          // no break is intentional
          default: UX_DEFAULT_EVENT(); break;
      }
  
      // close the event if not done previously (such as by a display)
      if (!io_seproxyhal_spi_is_status_sent()) {
          io_seproxyhal_general_status();
      }
  
      // Command has been processed,
      // DO NOT reset the current APDU transport.
      return 1U;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  uint16_t io_exchange_al(unsigned char channel, unsigned short tx_len) {
      switch (channel & ~(IO_FLAGS)) {
          case CHANNEL_KEYBOARD: break;
  
          case CHANNEL_SPI:
              // Multiplexed I/O exchange.
              // done over SPI channel and TLV encapsulated protocol.
              if (tx_len) {
                  io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
          
                  if (channel & IO_RESET_AFTER_REPLIED) {
                      reset();
                  }
  
                  // Nothing received from the master so far.
                  // (it's a tx transaction)
                  return 0U;
              }
              else {
                  return io_seproxyhal_spi_recv(G_io_apdu_buffer,
                                                sizeof(G_io_apdu_buffer),
                                                0U);
              }
  
          default: THROW(INVALID_PARAMETER);
      }
      return 0UL;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // override point, but nothing more to do
  void io_seproxyhal_display(const bagl_element_t *element) {
      io_seproxyhal_display_default((bagl_element_t *)element);
  }
  