Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ obj-$(CONFIG_LUNATIK_FIFO) += lib/luafifo.o
obj-$(CONFIG_LUNATIK_XTABLE) += lib/luaxtable.o
obj-$(CONFIG_LUNATIK_NETFILTER) += lib/luanetfilter.o
obj-$(CONFIG_LUNATIK_COMPLETION) += lib/luacompletion.o
obj-$(CONFIG_LUNATIK_HID) += lib/luahid.o

3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ all: lunatik_sym.h
CONFIG_LUNATIK_RCU=m CONFIG_LUNATIK_THREAD=m CONFIG_LUNATIK_FIB=m \
CONFIG_LUNATIK_DATA=m CONFIG_LUNATIK_PROBE=m CONFIG_LUNATIK_SYSCALL=m \
CONFIG_LUNATIK_XDP=m CONFIG_LUNATIK_FIFO=m CONFIG_LUNATIK_XTABLE=m \
CONFIG_LUNATIK_NETFILTER=m CONFIG_LUNATIK_COMPLETION=m
CONFIG_LUNATIK_NETFILTER=m CONFIG_LUNATIK_COMPLETION=m \
CONFIG_LUNATIK_HID=m

clean:
${MAKE} -C ${MODULES_BUILD_PATH} M=${PWD} clean
Expand Down
2 changes: 1 addition & 1 deletion bin/lunatik
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ local lunatik = {
device = "/dev/lunatik",
modules = {"lunatik", "luadevice", "lualinux", "luanotifier", "luasocket", "luarcu",
"luathread", "luafib", "luadata", "luaprobe", "luasyscall", "luaxdp", "luafifo", "luaxtable",
"luanetfilter", "luacompletion", "lunatik_run"}
"luanetfilter", "luacompletion", "luahid", "lunatik_run"}
}

function lunatik.prompt()
Expand Down
122 changes: 122 additions & 0 deletions lib/luahid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: (c) 2025 Jieming Zhou <[email protected]>
* SPDX-License-Identifier: MIT OR GPL-2.0-only
*/

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/limits.h>
#include <asm/byteorder.h>

#include <linux/hid.h>

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#include <lunatik.h>

typedef struct luahid_s {
lunatik_object_t *runtime;
struct hid_driver driver;
} luahid_t;

/*
* kernel codes copied from drivers/hid/hid-generic.c
* links: https://elixir.bootlin.com/linux/v6.13.7/source/drivers/hid/hid-generic.c
*/
static int hid_generic_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
int ret;

hdev->quirks |= HID_QUIRK_INPUT_PER_APP;

ret = hid_parse(hdev);
if (ret)
return ret;

return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
}
static const struct hid_device_id hid_table[] = {
{ HID_USB_DEVICE(0x046D, 0xC542) },
{ }
};
MODULE_DEVICE_TABLE(hid, hid_table);


static void luahid_release(void *private)
{
luahid_t *hid = (luahid_t *)private;
if (hid) {
hid_unregister_driver(&hid->driver);
lunatik_putobject(hid->runtime);
}
}

static int luahid_register(lua_State *L);

static const luaL_Reg luahid_lib[] = {
{"register", luahid_register},
{NULL, NULL}
};

static const luaL_Reg luahid_mt[] = {
{"__gc", lunatik_deleteobject},
{NULL, NULL}
};

static const lunatik_class_t luahid_class = {
.name = "hid",
.methods = luahid_mt,
.release = luahid_release,
.sleep = true,
};

static int luahid_register(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE); /* assure that is a driver */

lunatik_object_t *object = lunatik_newobject(L, &luahid_class, sizeof(luahid_t));
luahid_t *hid = (luahid_t *)object->private;

/*
* configure the driver's properties & callbacks
*/
struct hid_driver *user_driver = &(hid->driver);
user_driver -> name = lunatik_checkalloc(L, NAME_MAX);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please mind our code style.. when in doubt, use Linux's code style.. no space around ->

lunatik_setstring(L, 1, user_driver, name, NAME_MAX);
user_driver -> id_table = hid_table;
user_driver -> probe = hid_generic_probe;

lunatik_registerobject(L, 1, object);

int ret = __hid_register_driver(user_driver, THIS_MODULE, KBUILD_MODNAME);
if (ret) {
lunatik_unregisterobject(L, object);
luaL_error(L, "failed to register hid driver: %s", user_driver->name);
}
lunatik_setruntime(L, hid, hid);
lunatik_getobject(hid->runtime);
return 1; /* object */
}

LUNATIK_NEWLIB(hid, luahid_lib, &luahid_class, NULL);

static int __init luahid_init(void)
{
return 0;
}

static void __exit luahid_exit(void)
{
}

module_init(luahid_init);
module_exit(luahid_exit);
MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Jieming Zhou <[email protected]>");

11 changes: 0 additions & 11 deletions lib/luanetfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,6 @@ do { \
lua_pop(L, 1); \
} while (0)

#define lunatik_setstring(L, idx, hook, field, maxlen) \
do { \
size_t len; \
lunatik_checkfield(L, idx, #field, LUA_TSTRING); \
const char *str = lua_tolstring(L, -1, &len); \
if (len > maxlen) \
luaL_error(L, "'%s' is too long", #field); \
strncpy((char *)hook->field, str, maxlen); \
lua_pop(L, 1); \
} while (0)

const lunatik_reg_t luanetfilter_family[] = {
{"UNSPEC", NFPROTO_UNSPEC},
{"INET", NFPROTO_INET},
Expand Down
11 changes: 11 additions & 0 deletions lunatik.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,17 @@ static inline T checker(lua_State *L, int ix) \

#define lunatik_getregistry(L, key) lua_rawgetp((L), LUA_REGISTRYINDEX, (key))

#define lunatik_setstring(L, idx, hook, field, maxlen) \
do { \
size_t len; \
lunatik_checkfield(L, idx, #field, LUA_TSTRING); \
const char *str = lua_tolstring(L, -1, &len); \
if (len > maxlen) \
luaL_error(L, "'%s' is too long", #field); \
strncpy((char *)hook->field, str, maxlen); \
lua_pop(L, 1); \
} while (0)

static inline void lunatik_setregistry(lua_State *L, int ix, void *key)
{
lua_pushvalue(L, ix);
Expand Down