/********************************************************************** * COPYRIGHT 2020 MULTI-TECH SYSTEMS, INC. * * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF * MULTI-TECH SYSTEMS, INC. * * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY * INFORMATION AND/OR TRADE SECRET. * * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. * ***********************************************************************/ #include "Device.h" Device::Lora15Card::Lora15Card(Device& d, const std::string productId, const std::string port) : LoraCard(d, productId, port) { int ret; fpgaVersion = 255; if ((productId.find("MTCDT3-") == 0) && (port.back() == '2')) { spiPath = "/dev/spidev1.0"; } else if (productId.find("MTAC-LORA-") == 0) { if (port.back() == '2') { spiPath = "/dev/spidev32765.2"; } else { spiPath = "/dev/spidev32766.2"; } } ret = spiOpen(spiPath.c_str()); if (ret != 0) { printf("Could not open SPI port %s", spiPath.c_str()); return; } /* detect if the gateway has an FPGA with SPI mux header support */ ret = spiRead(MTAC_FPGA_ADDRESS, &fpgaVersion); if (ret != 0) { printf("Could not read FPGA version"); } spiClose(); spi_target_ptr = NULL; device.accessoryCard.AddMember("fpgaVersion", fpgaVersion, device.accessoryCardsAlloc); } int Device::Lora15Card::spiOpen(const char *spidev) { int *spi_device = NULL; int dev; int a = 0, b = 0; int i; /* allocate memory for the device descriptor */ spi_device = (int *)malloc(sizeof(int)); if (spi_device == NULL) { printf("ERROR: MALLOC FAIL\n"); return -1; } /* open SPI device */ dev = open(spidev, O_RDWR); if (dev < 0) { printf("ERROR: failed to open SPI device %s\n", spidev); return -1; } /* setting SPI mode to 'mode 0' */ i = SPI_MODE_3; a = ioctl(dev, SPI_IOC_WR_MODE, &i); b = ioctl(dev, SPI_IOC_RD_MODE, &i); if ((a < 0) || (b < 0)) { printf("ERROR: SPI PORT FAIL TO SET IN MODE 0\n"); close(dev); free(spi_device); return -1; } /* setting SPI max clk (in Hz) */ i = SPI_SPEED; a = ioctl(dev, SPI_IOC_WR_MAX_SPEED_HZ, &i); b = ioctl(dev, SPI_IOC_RD_MAX_SPEED_HZ, &i); if ((a < 0) || (b < 0)) { printf("ERROR: SPI PORT FAIL TO SET MAX SPEED\n"); close(dev); free(spi_device); return -1; } /* setting SPI to MSB first */ i = 0; a = ioctl(dev, SPI_IOC_WR_LSB_FIRST, &i); b = ioctl(dev, SPI_IOC_RD_LSB_FIRST, &i); if ((a < 0) || (b < 0)) { printf("ERROR: SPI PORT FAIL TO SET MSB FIRST\n"); close(dev); free(spi_device); return -1; } /* setting SPI to 8 bits per word */ i = 0; a = ioctl(dev, SPI_IOC_WR_BITS_PER_WORD, &i); b = ioctl(dev, SPI_IOC_RD_BITS_PER_WORD, &i); if ((a < 0) || (b < 0)) { printf("ERROR: SPI PORT FAIL TO SET 8 BITS-PER-WORD\n"); close(dev); return -1; } *spi_device = dev; spi_target_ptr = (void *)spi_device; return 0; } int Device::Lora15Card::spiRead(uint8_t address, uint8_t *data) { int spi_device; uint8_t out_buf[3]; uint8_t in_buf[ARRAY_SIZE(out_buf)]; uint8_t command_size; struct spi_ioc_transfer k; int a; spi_device = *(int *)spi_target_ptr; /* spi_target cannot be null beforehand */ /* prepare frame to be sent */ out_buf[0] = MTAC_FPGA; out_buf[1] = READ_ACCESS | (address & 0x7F); out_buf[2] = 0x00; command_size = 3; /* I/O transaction */ memset(&k, 0, sizeof(k)); /* clear k */ k.tx_buf = (unsigned long)out_buf; k.rx_buf = (unsigned long)in_buf; k.len = command_size; k.cs_change = 1; a = ioctl(spi_device, SPI_IOC_MESSAGE(1), &k); /* determine return code */ if (a != (int)k.len) { printf("ERROR: SPI READ FAILURE\n"); return -1; } else { *data = in_buf[command_size - 1]; return 0; } } int Device::Lora15Card::spiClose() { int spi_device; int a; /* close file & deallocate file descriptor */ spi_device = *(int *)spi_target_ptr; /* check that spi_target is not null */ a = close(spi_device); free(spi_target_ptr); /* determine return code */ if (a < 0) { printf("ERROR: SPI PORT FAILED TO CLOSE\n"); return -1; } else { return 0; } }