mirror of
https://github.com/d0k3/GodMode9.git
synced 2026-05-31 14:56:55 +00:00
* Add i2c read support to lua * Add i2c write support to lua With memory permissions before write * Adjust i2c write * Fix inverted id check, better permissions * Change write to not return anything on success * Add some documentation for lua i2c * Change write length from 1024 to 64 * Add whitelist for i2c writing * Move i2c module into preload * Add registers and bitmasks for mcu Add documentation to lua-doc * Fix missing column divider in lua-doc * Add ~= 0 then to lua example * Add some more registers
148 lines
4.0 KiB
C
148 lines
4.0 KiB
C
#ifndef NO_LUA
|
|
#include "gm9internali2c.h"
|
|
#include "fsperm.h"
|
|
#include "system/i2c.h"
|
|
|
|
typedef struct {
|
|
uint8_t dev_id;
|
|
uint8_t reg_addr_start;
|
|
uint8_t reg_addr_end;
|
|
} WhiteListPair;
|
|
|
|
static const WhiteListPair WriteWhitelist[] = {
|
|
// Device_id, Register_address, Register_address_end
|
|
{ I2C_DEV_MCU, 0x15, 0x17 },
|
|
{ I2C_DEV_MCU, 0x1c, 0x1f },
|
|
{ I2C_DEV_MCU, 0x28, 0x29 },
|
|
{ I2C_DEV_MCU, 0x2a, 0x2d },
|
|
};
|
|
|
|
static bool IsWriteAllowed(uint8_t dev_id, uint8_t reg_addr)
|
|
{
|
|
for (unsigned i = 0; i < sizeof(WriteWhitelist)/sizeof(WriteWhitelist[0]); i++) {
|
|
if (WriteWhitelist[i].dev_id == dev_id &&
|
|
reg_addr >= WriteWhitelist[i].reg_addr_start &&
|
|
reg_addr <= WriteWhitelist[i].reg_addr_end)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static int i2c_read(lua_State *L) {
|
|
int dev_id = luaL_checkinteger(L, 1);
|
|
int reg_addr = luaL_checkinteger(L, 2);
|
|
int length = luaL_checkinteger(L, 3);
|
|
|
|
if (dev_id < 0 || dev_id > 17) {
|
|
return luaL_error(L, "Invalid device ID: %d (must be 0-17)", dev_id);
|
|
}
|
|
|
|
if (length <= 0 || length > 64) {
|
|
return luaL_error(L, "Invalid length: %d (must be 1-64)", length);
|
|
}
|
|
|
|
if (reg_addr < 0 || reg_addr > 255) {
|
|
return luaL_error(L, "Invalid register address: %d (must be 0-255)", reg_addr);
|
|
}
|
|
|
|
// Create a buffer for the read data
|
|
u8 *buffer = malloc(length);
|
|
if (!buffer) {
|
|
return luaL_error(L, "Memory allocation failed");
|
|
}
|
|
bool success = I2C_readRegBuf((I2cDevice)dev_id, (u8)reg_addr, buffer, (u32)length);
|
|
|
|
if (success) {
|
|
// Create a Lua table to hold the byte values
|
|
lua_createtable(L, length, 0);
|
|
|
|
// Fill the table with byte values as integers
|
|
for (int i = 0; i < length; i++) {
|
|
lua_pushinteger(L, buffer[i]); // Push byte value as integer
|
|
lua_rawseti(L, -2, i + 1); // Set table[i+1] = byte
|
|
}
|
|
|
|
free(buffer);
|
|
return 1;
|
|
} else {
|
|
free(buffer);
|
|
return luaL_error(L, "I2C read failed");
|
|
}
|
|
}
|
|
|
|
static int i2c_write(lua_State *L) {
|
|
SetWritePermissionsLuaError(L, PERM_MEMORY);
|
|
|
|
int dev_id = luaL_checkinteger(L, 1);
|
|
int reg_addr = luaL_checkinteger(L, 2);
|
|
|
|
if (!lua_istable(L, 3)) {
|
|
return luaL_error(L, "Third parameter must be a table of byte values");
|
|
}
|
|
|
|
int length = lua_rawlen(L, 3);
|
|
|
|
if (dev_id < 0 || dev_id > 17) {
|
|
return luaL_error(L, "Invalid device ID: %d (must be 0-17)", dev_id);
|
|
}
|
|
|
|
if (length <= 0 || length > 64) {
|
|
return luaL_error(L, "Invalid data length: %d (must be 1-64)", length);
|
|
}
|
|
|
|
if (reg_addr < 0 || reg_addr > 255) {
|
|
return luaL_error(L, "Invalid register address: %d (must be 0-255)", reg_addr);
|
|
}
|
|
|
|
if (!IsWriteAllowed(dev_id, reg_addr)) {
|
|
return luaL_error(L, "Write to device %d, register %d is not allowed", dev_id, reg_addr);
|
|
}
|
|
|
|
// Create a buffer for the write data
|
|
u8 *buffer = malloc(length);
|
|
if (!buffer) {
|
|
return luaL_error(L, "Memory allocation failed");
|
|
}
|
|
|
|
// Extract byte values from Lua table
|
|
for (int i = 0; i < length; i++) {
|
|
lua_rawgeti(L, 3, i + 1); // Get table[i+1]
|
|
|
|
if (!lua_isinteger(L, -1)) {
|
|
free(buffer);
|
|
return luaL_error(L, "Table element %d is not an integer", i + 1);
|
|
}
|
|
|
|
int value = lua_tointeger(L, -1);
|
|
if (value < 0 || value > 255) {
|
|
free(buffer);
|
|
return luaL_error(L, "Table element %d is out of range: %d (must be 0-255)", i + 1, value);
|
|
}
|
|
|
|
buffer[i] = (u8)value;
|
|
lua_pop(L, 1); // Remove the value from stack
|
|
}
|
|
|
|
bool success = I2C_writeRegBuf((I2cDevice)dev_id, (u8)reg_addr, buffer, (u32)length);
|
|
|
|
free(buffer);
|
|
|
|
if (success) {
|
|
return 0;
|
|
} else {
|
|
return luaL_error(L, "I2C write failed");
|
|
}
|
|
}
|
|
|
|
static const luaL_Reg i2c[] = {
|
|
{"read", i2c_read},
|
|
{"write", i2c_write},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
int gm9lua_open_internali2c(lua_State* L) {
|
|
luaL_newlib(L, i2c);
|
|
return 1;
|
|
}
|
|
#endif
|