Rename our allwpilib (which is now 2020) to not have 2019 in the name

Change-Id: I3c07f85ed32ab8b97db765a9b43f2a6ce7da964a
diff --git a/hal/src/main/native/athena/I2C.cpp b/hal/src/main/native/athena/I2C.cpp
new file mode 100644
index 0000000..b72e25e
--- /dev/null
+++ b/hal/src/main/native/athena/I2C.cpp
@@ -0,0 +1,192 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) 2016-2019 FIRST. All Rights Reserved.                        */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in the root directory of */
+/* the project.                                                               */
+/*----------------------------------------------------------------------------*/
+
+#include "hal/I2C.h"
+
+#include <fcntl.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <cstring>
+
+#include "DigitalInternal.h"
+#include "HALInitializer.h"
+#include "hal/DIO.h"
+#include "hal/HAL.h"
+
+using namespace hal;
+
+static wpi::mutex digitalI2COnBoardMutex;
+static wpi::mutex digitalI2CMXPMutex;
+
+static uint8_t i2COnboardObjCount{0};
+static uint8_t i2CMXPObjCount{0};
+static int i2COnBoardHandle{-1};
+static int i2CMXPHandle{-1};
+
+static HAL_DigitalHandle i2CMXPDigitalHandle1{HAL_kInvalidHandle};
+static HAL_DigitalHandle i2CMXPDigitalHandle2{HAL_kInvalidHandle};
+
+namespace hal {
+namespace init {
+void InitializeI2C() {}
+}  // namespace init
+}  // namespace hal
+
+extern "C" {
+
+void HAL_InitializeI2C(HAL_I2CPort port, int32_t* status) {
+  hal::init::CheckInit();
+  initializeDigital(status);
+  if (*status != 0) return;
+
+  if (port < 0 || port > 1) {
+    // Set port out of range error here
+    return;
+  }
+
+  if (port == HAL_I2C_kOnboard) {
+    std::scoped_lock lock(digitalI2COnBoardMutex);
+    i2COnboardObjCount++;
+    if (i2COnboardObjCount > 1) return;
+    int handle = open("/dev/i2c-2", O_RDWR);
+    if (handle < 0) {
+      std::printf("Failed to open onboard i2c bus: %s\n", std::strerror(errno));
+      return;
+    }
+    i2COnBoardHandle = handle;
+  } else {
+    std::scoped_lock lock(digitalI2CMXPMutex);
+    i2CMXPObjCount++;
+    if (i2CMXPObjCount > 1) return;
+    if ((i2CMXPDigitalHandle1 = HAL_InitializeDIOPort(
+             HAL_GetPort(24), false, status)) == HAL_kInvalidHandle) {
+      return;
+    }
+    if ((i2CMXPDigitalHandle2 = HAL_InitializeDIOPort(
+             HAL_GetPort(25), false, status)) == HAL_kInvalidHandle) {
+      HAL_FreeDIOPort(i2CMXPDigitalHandle1);  // free the first port allocated
+      return;
+    }
+    digitalSystem->writeEnableMXPSpecialFunction(
+        digitalSystem->readEnableMXPSpecialFunction(status) | 0xC000, status);
+    int handle = open("/dev/i2c-1", O_RDWR);
+    if (handle < 0) {
+      std::printf("Failed to open MXP i2c bus: %s\n", std::strerror(errno));
+      return;
+    }
+    i2CMXPHandle = handle;
+  }
+}
+
+int32_t HAL_TransactionI2C(HAL_I2CPort port, int32_t deviceAddress,
+                           const uint8_t* dataToSend, int32_t sendSize,
+                           uint8_t* dataReceived, int32_t receiveSize) {
+  if (port < 0 || port > 1) {
+    // Set port out of range error here
+    return -1;
+  }
+
+  struct i2c_msg msgs[2];
+  msgs[0].addr = deviceAddress;
+  msgs[0].flags = 0;
+  msgs[0].len = sendSize;
+  msgs[0].buf = const_cast<uint8_t*>(dataToSend);
+  msgs[1].addr = deviceAddress;
+  msgs[1].flags = I2C_M_RD;
+  msgs[1].len = receiveSize;
+  msgs[1].buf = dataReceived;
+
+  struct i2c_rdwr_ioctl_data rdwr;
+  rdwr.msgs = msgs;
+  rdwr.nmsgs = 2;
+
+  if (port == HAL_I2C_kOnboard) {
+    std::scoped_lock lock(digitalI2COnBoardMutex);
+    return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
+  } else {
+    std::scoped_lock lock(digitalI2CMXPMutex);
+    return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
+  }
+}
+
+int32_t HAL_WriteI2C(HAL_I2CPort port, int32_t deviceAddress,
+                     const uint8_t* dataToSend, int32_t sendSize) {
+  if (port < 0 || port > 1) {
+    // Set port out of range error here
+    return -1;
+  }
+
+  struct i2c_msg msg;
+  msg.addr = deviceAddress;
+  msg.flags = 0;
+  msg.len = sendSize;
+  msg.buf = const_cast<uint8_t*>(dataToSend);
+
+  struct i2c_rdwr_ioctl_data rdwr;
+  rdwr.msgs = &msg;
+  rdwr.nmsgs = 1;
+
+  if (port == HAL_I2C_kOnboard) {
+    std::scoped_lock lock(digitalI2COnBoardMutex);
+    return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
+  } else {
+    std::scoped_lock lock(digitalI2CMXPMutex);
+    return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
+  }
+}
+
+int32_t HAL_ReadI2C(HAL_I2CPort port, int32_t deviceAddress, uint8_t* buffer,
+                    int32_t count) {
+  if (port < 0 || port > 1) {
+    // Set port out of range error here
+    return -1;
+  }
+
+  struct i2c_msg msg;
+  msg.addr = deviceAddress;
+  msg.flags = I2C_M_RD;
+  msg.len = count;
+  msg.buf = buffer;
+
+  struct i2c_rdwr_ioctl_data rdwr;
+  rdwr.msgs = &msg;
+  rdwr.nmsgs = 1;
+
+  if (port == HAL_I2C_kOnboard) {
+    std::scoped_lock lock(digitalI2COnBoardMutex);
+    return ioctl(i2COnBoardHandle, I2C_RDWR, &rdwr);
+  } else {
+    std::scoped_lock lock(digitalI2CMXPMutex);
+    return ioctl(i2CMXPHandle, I2C_RDWR, &rdwr);
+  }
+}
+
+void HAL_CloseI2C(HAL_I2CPort port) {
+  if (port < 0 || port > 1) {
+    // Set port out of range error here
+    return;
+  }
+
+  if (port == HAL_I2C_kOnboard) {
+    std::scoped_lock lock(digitalI2COnBoardMutex);
+    if (i2COnboardObjCount-- == 0) {
+      close(i2COnBoardHandle);
+    }
+  } else {
+    std::scoped_lock lock(digitalI2CMXPMutex);
+    if (i2CMXPObjCount-- == 0) {
+      close(i2CMXPHandle);
+    }
+    HAL_FreeDIOPort(i2CMXPDigitalHandle1);
+    HAL_FreeDIOPort(i2CMXPDigitalHandle2);
+  }
+}
+
+}  // extern "C"