<commit_before>//
//
//

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#include <algorithm>

#include "unix/constant.h"
#include "unix/final-action.hpp"
#include "unix/log.hpp"

#include "mcu-msg.hpp"
#include "spi-dev.hpp"

namespace
{
  constexpr const char* path = "/dev/spidev0.0";
  constexpr uint8_t mode = SPI_MODE_0;
  constexpr uint8_t word_size = 8;      // 8 bits per word
  constexpr uint32_t speed = 1000;       // 1kHz ?
  //constexpr uint32_t speed = 20;       // 1kHz ?
  //constexpr uint16_t delay = 1000;      // 1 millisecond ?
  constexpr uint16_t delay = 65535;      // 65 ms?
}

namespace led_d
{

  spi_dev_t::spi_dev_t ()
    : m_device (0)
  {
  }

  spi_dev_t::~spi_dev_t ()
  {
  }

  void spi_dev_t::start ()
  {
    m_device = open (path, O_RDWR);
    if (m_device < 0)
      throw std::runtime_error ("Failed to open spi device");

    uint8_t ioc_mode = mode;
    if (ioctl (m_device, SPI_IOC_WR_MODE, &ioc_mode) < 0)
      throw std::runtime_error ("Failed to set spi write mode");
    if (ioctl (m_device, SPI_IOC_RD_MODE, &ioc_mode) < 0)
      throw std::runtime_error ("Failed to set spi read mode");

    uint8_t ioc_bits = word_size;
    if (ioctl (m_device, SPI_IOC_WR_BITS_PER_WORD, &ioc_bits) < 0)
      throw std::runtime_error ("Failed to set spi write bits");
    if (ioctl (m_device, SPI_IOC_RD_BITS_PER_WORD, &ioc_bits) < 0)
      throw std::runtime_error ("Failed to set spi read bits");

    uint32_t ioc_speed = speed;
    if (ioctl (m_device, SPI_IOC_WR_MAX_SPEED_HZ, &ioc_speed) < 0)
      throw std::runtime_error ("Failed to set spi write speed");
    if (ioctl (m_device, SPI_IOC_RD_MAX_SPEED_HZ, &ioc_speed) < 0)
      throw std::runtime_error ("Failed to set spi read speed");

    drain ();
  }

  void spi_dev_t::stop ()
  {
    if (m_device > 0)
      close (m_device);
    m_device = 0;
  }

  void spi_dev_t::transfer (const mcu_msg_t &out, mcu_msg_t &in)
  {
    static uint8_t *write_buf = nullptr;
    static uint8_t *read_buf = nullptr;
    static std::size_t buf_size = 0;

    // the only purpose of this object is to free memory
    // allocated for the r/w buffers at the end of app execution
    static auto remove_buf = unix::make_final_action
      ([&] ()
       {
         delete [] write_buf;
         delete [] read_buf;
       });

    auto realloc = [] (uint8_t *&space, std::size_t new_size) {
      delete [] space;
      space = new uint8_t [new_size];
    };

    if (out.size () > buf_size) {
      // it is ok to call delete with null pointer
      realloc (write_buf, out.size ());
      realloc (read_buf, out.size ());
    }

    std::size_t i = 0;
    for (auto info : out)
      write_buf[i++] = info;

    struct spi_ioc_transfer buf;
    memset (&buf, 0, sizeof (buf));
    
    buf.tx_buf =  (unsigned long) write_buf;<commit_msg>pi: Wrong memory usage in spi_dev::transfer<commit_after>//
//
//

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#include <algorithm>

#include "unix/constant.h"
#include "unix/final-action.hpp"
#include "unix/log.hpp"

#include "mcu-msg.hpp"
#include "spi-dev.hpp"

namespace
{
  constexpr const char* path = "/dev/spidev0.0";
  constexpr uint8_t mode = SPI_MODE_0;
  constexpr uint8_t word_size = 8;      // 8 bits per word
  constexpr uint32_t speed = 1000;       // 1kHz ?
  //constexpr uint32_t speed = 20;       // 1kHz ?
  //constexpr uint16_t delay = 1000;      // 1 millisecond ?
  constexpr uint16_t delay = 65535;      // 65 ms?
}

namespace led_d
{

  spi_dev_t::spi_dev_t ()
    : m_device (0)
  {
  }

  spi_dev_t::~spi_dev_t ()
  {
  }

  void spi_dev_t::start ()
  {
    m_device = open (path, O_RDWR);
    if (m_device < 0)
      throw std::runtime_error ("Failed to open spi device");

    uint8_t ioc_mode = mode;
    if (ioctl (m_device, SPI_IOC_WR_MODE, &ioc_mode) < 0)
      throw std::runtime_error ("Failed to set spi write mode");
    if (ioctl (m_device, SPI_IOC_RD_MODE, &ioc_mode) < 0)
      throw std::runtime_error ("Failed to set spi read mode");

    uint8_t ioc_bits = word_size;
    if (ioctl (m_device, SPI_IOC_WR_BITS_PER_WORD, &ioc_bits) < 0)
      throw std::runtime_error ("Failed to set spi write bits");
    if (ioctl (m_device, SPI_IOC_RD_BITS_PER_WORD, &ioc_bits) < 0)
      throw std::runtime_error ("Failed to set spi read bits");

    uint32_t ioc_speed = speed;
    if (ioctl (m_device, SPI_IOC_WR_MAX_SPEED_HZ, &ioc_speed) < 0)
      throw std::runtime_error ("Failed to set spi write speed");
    if (ioctl (m_device, SPI_IOC_RD_MAX_SPEED_HZ, &ioc_speed) < 0)
      throw std::runtime_error ("Failed to set spi read speed");

    drain ();
  }

  void spi_dev_t::stop ()
  {
    if (m_device > 0)
      close (m_device);
    m_device = 0;
  }

  void spi_dev_t::transfer (const mcu_msg_t &out, mcu_msg_t &in)
  {
    static uint8_t *write_buf = nullptr;
    static uint8_t *read_buf = nullptr;
    static std::size_t buf_size = 0;

    // the only purpose of this object is to free memory
    // allocated for the r/w buffers at the end of app execution
    static auto remove_buf = unix::make_final_action
      ([&] ()
       {
         delete [] write_buf;
         delete [] read_buf;
       });

    auto realloc = [] (uint8_t *&space, std::size_t new_size) {
      delete [] space;
      space = new uint8_t [new_size];
    };

    if (out.size () > buf_size) {
      // it is ok to call delete with null pointer
      buf_size = out.size ();
      realloc (write_buf, buf_size);
      realloc (read_buf, buf_size);
    }

    std::size_t i = 0;
    for (auto info : out)
      write_buf[i++] = info;

    struct spi_ioc_transfer buf;
    memset (&buf, 0, sizeof (buf));
    
    buf.tx_buf =  (unsigned long) write_buf;
{'fraction_non_alphanumeric': 0.12818814176879761, 'fraction_numerical': 0.018549188473004307, 'mean_word_length': 2.893617021276596, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5173040', 'n_tokens_mistral': 2393, 'n_tokens_neox': 2308, 'n_words': 600}