Created
April 28, 2021 16:22
-
-
Save pabloko/2cc22e9275bf63438e4c7caeb8127f19 to your computer and use it in GitHub Desktop.
Lua 5.1 / luajit - Usb HID library (hidapi) [win/mac/linux]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//using hidapi library: https://github.com/signal11/hidapi/ by Alan Ott | |
#include <stdio.h> | |
#include <malloc.h> | |
#include "hidapi.h" | |
#pragma comment(lib, "setupapi.lib") | |
#pragma comment(lib, "hidapi.lib") | |
#include <Windows.h> | |
#include <lua.hpp> | |
#pragma comment(lib, "lua5.1.lib") | |
unsigned char buffer[0xFFF] = { 0 }; | |
//utf8->wide helper (libcurl) | |
wchar_t *_convert_UTF8_to_wchar (const char *str_utf8) | |
{ | |
wchar_t *str_w = NULL; | |
if ( str_utf8 ) | |
{ | |
int str_w_len = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, | |
str_utf8, -1, NULL, 0); | |
if ( str_w_len > 0 ) | |
{ | |
str_w = ( wchar_t * )malloc (str_w_len * sizeof (wchar_t)); | |
if ( str_w ) | |
{ | |
if ( MultiByteToWideChar (CP_UTF8, 0, str_utf8, -1, str_w, | |
str_w_len) == 0 ) | |
{ | |
free (str_w); | |
return NULL; | |
} | |
} | |
} | |
} | |
return str_w; | |
} | |
//wide->utf8 helper (libcurl) | |
char *_convert_wchar_to_UTF8 (const wchar_t *str_w) | |
{ | |
char *str_utf8 = NULL; | |
if ( str_w ) | |
{ | |
int str_utf8_len = WideCharToMultiByte (CP_UTF8, 0, str_w, -1, NULL, | |
0, NULL, NULL); | |
if ( str_utf8_len > 0 ) | |
{ | |
str_utf8 = ( char * )malloc (str_utf8_len * sizeof (wchar_t)); | |
if ( str_utf8 ) | |
{ | |
if ( WideCharToMultiByte (CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len, | |
NULL, FALSE) == 0 ) | |
{ | |
free (str_utf8); | |
return NULL; | |
} | |
} | |
} | |
} | |
return str_utf8; | |
} | |
BOOL luaopen_usbhid (lua_State* L) | |
{ | |
#define LUA_TB(x) x, [] (lua_State *L) -> int | |
const luaL_reg tab_funcs_hid[] = { | |
{ LUA_TB ("Enumerate") { | |
hid_enumerate (0,0); | |
hid_device_info *dinfo = hid_enumerate (lua_tonumber(L, 1), lua_tonumber (L, 2)); | |
hid_device_info *diterator = dinfo; | |
int _count = 0; | |
while ( diterator != NULL ) | |
{ | |
_count++; | |
diterator = diterator->next; | |
} | |
lua_createtable (L, _count, 0); | |
int _step = 1; //lua starts on 1 :P | |
while ( dinfo != NULL ) | |
{ | |
lua_pushnumber (L, _step); | |
_step++; | |
lua_createtable (L, 0, 10); | |
lua_pushstring (L, dinfo->path); | |
lua_setfield (L, -2, "path"); | |
lua_pushnumber (L, dinfo->vendor_id); | |
lua_setfield (L, -2, "vid"); | |
lua_pushnumber (L, dinfo->product_id); | |
lua_setfield (L, -2, "pid"); | |
char *str = _convert_wchar_to_UTF8 (dinfo->serial_number); | |
lua_pushstring (L, str); | |
lua_setfield (L, -2, "serial"); | |
free (str); | |
lua_pushnumber (L, dinfo->release_number); | |
lua_setfield (L, -2, "release_number"); | |
str = _convert_wchar_to_UTF8 (dinfo->manufacturer_string); | |
lua_pushstring (L, str); | |
lua_setfield (L, -2, "manufacturer_string"); | |
free (str); | |
str = _convert_wchar_to_UTF8 (dinfo->product_string); | |
lua_pushstring (L, str); | |
lua_setfield (L, -2, "product_string"); | |
free (str); | |
lua_pushnumber (L, dinfo->usage_page); | |
lua_setfield (L, -2, "usage_page"); | |
lua_pushnumber (L, dinfo->usage); | |
lua_setfield (L, -2, "usage"); | |
lua_pushnumber (L, dinfo->interface_number); | |
lua_setfield (L, -2, "interface_number"); | |
lua_settable (L, -3); | |
dinfo = dinfo->next; | |
} | |
hid_free_enumeration (dinfo); | |
return 1; | |
}}, | |
{ LUA_TB ("Open") { | |
wchar_t *_serial = _convert_UTF8_to_wchar (lua_tostring (L, 3)); | |
hid_device *hid = hid_open (lua_tonumber(L, 1),lua_tonumber(L, 2), _serial); | |
free (_serial); | |
if ( hid != NULL ) | |
lua_pushlightuserdata (L, hid); | |
else | |
lua_pushnil (L); | |
return 1; | |
}}, | |
{ LUA_TB ("OpenPath") { | |
hid_device *hid = hid_open_path (lua_tostring (L, 1)); | |
if ( hid != NULL ) | |
lua_pushlightuserdata (L, hid); | |
else | |
lua_pushnil (L); | |
return 1; | |
}}, | |
{ LUA_TB ("Write") { | |
hid_device *hid = (hid_device*)lua_touserdata (L, 1); | |
size_t _size = 0; | |
const unsigned char *_buf = (const unsigned char*)lua_tolstring (L, 2, &_size); | |
size_t _written = hid_write (hid, _buf, _size); | |
lua_pushnumber (L, _written); | |
return 1; | |
}}, | |
{ LUA_TB ("ReadTimeout") { | |
hid_device *hid = ( hid_device * )lua_touserdata (L, 1); | |
size_t _read = hid_read_timeout (hid, buffer, sizeof (buffer), lua_tonumber (L, 2)); | |
lua_pushlstring (L, (const char*)buffer, _read); | |
return 1; | |
}}, | |
{ LUA_TB ("Read") { | |
hid_device *hid = ( hid_device * )lua_touserdata (L, 1); | |
size_t _read = hid_read (hid, buffer, sizeof (buffer)); | |
lua_pushlstring (L, ( const char * )buffer, _read); | |
return 1; | |
}}, | |
{ LUA_TB ("SetNonBlocking") { | |
hid_device *hid = ( hid_device * )lua_touserdata (L, 1); | |
lua_pushnumber (L, hid_set_nonblocking (hid, lua_tonumber (L, 2))); | |
return 1; | |
}}, | |
{ LUA_TB ("SendFeatureReport") { | |
hid_device *hid = ( hid_device * )lua_touserdata (L, 1); | |
size_t _size = 0; | |
const unsigned char *_buf = ( const unsigned char * )lua_tolstring (L, 2, &_size); | |
size_t _written = hid_send_feature_report (hid, _buf, _size); | |
lua_pushnumber (L, _written); | |
return 1; | |
}}, | |
{ LUA_TB ("GetFeatureReport") { | |
hid_device *hid = ( hid_device * )lua_touserdata (L, 1); | |
size_t _read = hid_get_feature_report (hid, buffer, sizeof (buffer)); | |
lua_pushlstring (L, ( const char * )buffer, _read); | |
return 1; | |
}}, | |
{ LUA_TB ("Close") { | |
hid_device *hid = ( hid_device * )lua_touserdata (L, 1); | |
hid_close (hid); | |
return 0; | |
}}, | |
{ LUA_TB ("Error") { | |
hid_device *hid = ( hid_device * )lua_touserdata (L, 1); | |
lua_pushnumber (L, 1); | |
char *err = _convert_wchar_to_UTF8(hid_error (hid)); | |
lua_pushstring (L, err); | |
free (err); | |
return 1; | |
}}, | |
{ LUA_TB ("Init") { | |
lua_pushnumber (L, hid_init ()); | |
return 1; | |
}}, | |
{ LUA_TB ("Exit") { | |
lua_pushnumber (L, hid_exit ()); | |
return 1; | |
}}, | |
{ NULL, NULL } | |
}; | |
luaL_openlib (L, "HID", tab_funcs_hid, NULL); | |
return TRUE; | |
} | |
BOOL APIENTRY DllMain( HMODULE hModule, | |
DWORD ul_reason_for_call, | |
LPVOID lpReserved | |
) | |
{ | |
switch (ul_reason_for_call) | |
{ | |
case DLL_PROCESS_ATTACH: | |
hid_init (); | |
break; | |
case DLL_THREAD_ATTACH: | |
break; | |
case DLL_THREAD_DETACH: | |
break; | |
case DLL_PROCESS_DETACH: | |
hid_exit (); | |
break; | |
} | |
return TRUE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment