Skip to content

Commit

Permalink
v0.2.2-beta: Danish layout, fix for USB injection, programming compan…
Browse files Browse the repository at this point in the history
…ion script
  • Loading branch information
mame82 committed Nov 20, 2019
1 parent 0a65f2b commit f44c0c1
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 15 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# LOGITacker v0.2.2-beta

**For updates from older LOGITacker versions the command `erase_flash` has to be ran once, to re-initialize
the flash data storage for the changed data structures. Not doing so likely causes errors during LOGITacker
operation**

- fix: malformed keyboard reports when USB injection is used, because Logitech checksum was injected
- added Danish keyboard layout `da`
- added python companion script to program, which creates a script with Danish unicode character on LOGITacker
(programming using USB HID interface)

# LOGITacker v0.2.1-beta

**For updates from older LOGITacker versions the command `erase_flash` has to be ran once, to re-initialize
Expand Down
2 changes: 1 addition & 1 deletion apr-dongle/blank/config/sdk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,7 @@
// <i> Note: This value is not editable in Configuration Wizard.
// <i> Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER.
#ifndef APP_USBD_STRING_SERIAL
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.1-beta")
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.2-beta")
#endif

// </e>
Expand Down
2 changes: 1 addition & 1 deletion logitacker/logitacker.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extern "C" {
#include "logitacker_keyboard_map.h"
#include "logitacker_processor_covert_channel.h"

#define VERSION_STRING "v0.2.1-beta"
#define VERSION_STRING "v0.2.2-beta"

//#define PAIRING_REQ_MARKER_BYTE 0xee // byte used as device ID in pairing requests
#define ACTIVE_ENUM_INNER_LOOP_MAX 20 //how many CAPS presses / key releases get send
Expand Down
2 changes: 1 addition & 1 deletion logitacker/logitacker_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ static void cmd_options_inject_lang(nrf_cli_t const *p_cli, size_t argc, char **

return;
} else {
nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "need language layout name as first argument (f.e. us, de)\r\n");
nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "need language layout name as first argument (f.e. us, de, da)\r\n");

return;

Expand Down
8 changes: 7 additions & 1 deletion logitacker/logitacker_keyboard_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,18 @@ uint32_t logitacker_keyboard_map_wc_to_hid_reports(hid_keyboard_report_t **p_out
default:
return NRF_ERROR_INVALID_PARAM;
}

} else if (in_layout == LANGUAGE_LAYOUT_DE) {
switch (in_rune) {
LAYOUT_DE(LAYOUT_SWITCH_CASE)
default:
return NRF_ERROR_INVALID_PARAM;
}
} else if (in_layout == LANGUAGE_LAYOUT_DA) {
switch (in_rune) {
LAYOUT_DA(LAYOUT_SWITCH_CASE)
default:
return NRF_ERROR_INVALID_PARAM;
}
} else {
return NRF_ERROR_INVALID_PARAM;
}
Expand Down Expand Up @@ -307,6 +312,7 @@ logitacker_keyboard_map_lang_t logitacker_keyboard_map_lang_from_str(char * lang

if (strcmp(lang_str, "de") == 0 || strcmp(lang_str, "DE") == 0 ) return LANGUAGE_LAYOUT_DE;
if (strcmp(lang_str, "us") == 0 || strcmp(lang_str, "US") == 0 ) return LANGUAGE_LAYOUT_US;
if (strcmp(lang_str, "da") == 0 || strcmp(lang_str, "DA") == 0 ) return LANGUAGE_LAYOUT_DA;

lab_default:
NRF_LOG_WARNING("unknown language layout '%s' ... using 'us' as default", nrf_log_push(lang_str));
Expand Down
114 changes: 114 additions & 0 deletions logitacker/logitacker_keyboard_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,11 @@ DEF_REPORT_SEQUENCE_NAMED(GRAVE_FOLLOWED_BY_SPACE, DEF_REPORT(HID_MOD_KE
// German '`' as deadkey
DEF_REPORT_SEQUENCE_NAMED(SHIFT_AND_EQUAL_FOLLOWED_BY_SPACE, DEF_REPORT(HID_MOD_KEY_LEFT_SHIFT, HID_KEY_EQUAL), DEF_REPORT(HID_MOD_KEY_NONE, HID_KEY_NONE), DEF_REPORT(HID_MOD_KEY_NONE, HID_KEY_SPACE));

// for DA
DEF_REPORT_SEQUENCE_NAMED(US_RALT_AND_4, DEF_REPORT(HID_MOD_KEY_RIGHT_ALT, HID_KEY_4));
DEF_REPORT_SEQUENCE_NAMED(US_RALT_AND_EQUAL, DEF_REPORT(HID_MOD_KEY_RIGHT_ALT, HID_KEY_EQUAL));
DEF_REPORT_SEQUENCE_NAMED(SHIFT_AND_RIGHTBRACE_FOLLOWED_BY_SPACE, DEF_REPORT(HID_MOD_KEY_LEFT_SHIFT, HID_KEY_RIGHTBRACE), DEF_REPORT(HID_MOD_KEY_NONE, HID_KEY_NONE), DEF_REPORT(HID_MOD_KEY_NONE, HID_KEY_SPACE));
DEF_REPORT_SEQUENCE_NAMED(RALT_AND_RIGHTBRACE_FOLLOWED_BY_SPACE, DEF_REPORT(HID_MOD_KEY_LEFT_SHIFT, HID_KEY_RIGHTBRACE), DEF_REPORT(HID_MOD_KEY_NONE, HID_KEY_NONE), DEF_REPORT(HID_MOD_KEY_NONE, HID_KEY_SPACE));

#define LAYOUT_US(PROC_FUNC) \
PROC_FUNC(L'\t', HID_REPORT_SEQUENCE_US_TAB) \
Expand Down Expand Up @@ -598,6 +603,114 @@ DEF_REPORT_SEQUENCE_NAMED(SHIFT_AND_EQUAL_FOLLOWED_BY_SPACE, DEF_REPORT(
PROC_FUNC(L'€', HID_REPORT_SEQUENCE_RALT_AND_E) \
PROC_FUNC(L'µ', HID_REPORT_SEQUENCE_RALT_AND_M) \

#define LAYOUT_DA(PROC_FUNC) \
PROC_FUNC(L'\t', HID_REPORT_SEQUENCE_US_TAB) \
PROC_FUNC(L'\n', HID_REPORT_SEQUENCE_US_ENTER) \
PROC_FUNC(L' ', HID_REPORT_SEQUENCE_US_SPACE) \
PROC_FUNC(L'!', HID_REPORT_SEQUENCE_US_SHIFT_AND_1) \
PROC_FUNC(L'\"', HID_REPORT_SEQUENCE_US_SHIFT_AND_2) \
PROC_FUNC(L'#', HID_REPORT_SEQUENCE_US_SHIFT_AND_3) \
PROC_FUNC(L'$', HID_REPORT_SEQUENCE_US_RALT_AND_4) \
PROC_FUNC(L'%', HID_REPORT_SEQUENCE_US_SHIFT_AND_5) \
PROC_FUNC(L'&', HID_REPORT_SEQUENCE_US_SHIFT_AND_6) \
PROC_FUNC(L'\'', HID_REPORT_SEQUENCE_US_BACKSLASH) \
PROC_FUNC(L'(', HID_REPORT_SEQUENCE_US_SHIFT_AND_8) \
PROC_FUNC(L')', HID_REPORT_SEQUENCE_US_SHIFT_AND_9) \
PROC_FUNC(L'*', HID_REPORT_SEQUENCE_US_SHIFT_AND_BACKSLASH) \
PROC_FUNC(L'+', HID_REPORT_SEQUENCE_US_MINUS) \
PROC_FUNC(L',', HID_REPORT_SEQUENCE_US_COMMA) \
PROC_FUNC(L'-', HID_REPORT_SEQUENCE_US_SLASH) \
PROC_FUNC(L'.', HID_REPORT_SEQUENCE_US_DOT) \
PROC_FUNC(L'/', HID_REPORT_SEQUENCE_US_SHIFT_AND_7) \
PROC_FUNC(L'0', HID_REPORT_SEQUENCE_US_0) \
PROC_FUNC(L'1', HID_REPORT_SEQUENCE_US_1) \
PROC_FUNC(L'2', HID_REPORT_SEQUENCE_US_2) \
PROC_FUNC(L'3', HID_REPORT_SEQUENCE_US_3) \
PROC_FUNC(L'4', HID_REPORT_SEQUENCE_US_4) \
PROC_FUNC(L'5', HID_REPORT_SEQUENCE_US_5) \
PROC_FUNC(L'6', HID_REPORT_SEQUENCE_US_6) \
PROC_FUNC(L'7', HID_REPORT_SEQUENCE_US_7) \
PROC_FUNC(L'8', HID_REPORT_SEQUENCE_US_8) \
PROC_FUNC(L'9', HID_REPORT_SEQUENCE_US_9) \
PROC_FUNC(L':', HID_REPORT_SEQUENCE_US_SHIFT_AND_DOT) \
PROC_FUNC(L';', HID_REPORT_SEQUENCE_US_SHIFT_AND_COMMA) \
PROC_FUNC(L'<', HID_REPORT_SEQUENCE_102ND) \
PROC_FUNC(L'=', HID_REPORT_SEQUENCE_US_SHIFT_AND_0) \
PROC_FUNC(L'>', HID_REPORT_SEQUENCE_SHIFT_AND_102ND) \
PROC_FUNC(L'?', HID_REPORT_SEQUENCE_US_SHIFT_AND_MINUS) \
PROC_FUNC(L'@', HID_REPORT_SEQUENCE_RALT_AND_Q) \
PROC_FUNC(L'A', HID_REPORT_SEQUENCE_US_SHIFT_AND_A) \
PROC_FUNC(L'B', HID_REPORT_SEQUENCE_US_SHIFT_AND_B) \
PROC_FUNC(L'C', HID_REPORT_SEQUENCE_US_SHIFT_AND_C) \
PROC_FUNC(L'D', HID_REPORT_SEQUENCE_US_SHIFT_AND_D) \
PROC_FUNC(L'E', HID_REPORT_SEQUENCE_US_SHIFT_AND_E) \
PROC_FUNC(L'F', HID_REPORT_SEQUENCE_US_SHIFT_AND_F) \
PROC_FUNC(L'G', HID_REPORT_SEQUENCE_US_SHIFT_AND_G) \
PROC_FUNC(L'H', HID_REPORT_SEQUENCE_US_SHIFT_AND_H) \
PROC_FUNC(L'I', HID_REPORT_SEQUENCE_US_SHIFT_AND_I) \
PROC_FUNC(L'J', HID_REPORT_SEQUENCE_US_SHIFT_AND_J) \
PROC_FUNC(L'K', HID_REPORT_SEQUENCE_US_SHIFT_AND_K) \
PROC_FUNC(L'L', HID_REPORT_SEQUENCE_US_SHIFT_AND_L) \
PROC_FUNC(L'M', HID_REPORT_SEQUENCE_US_SHIFT_AND_M) \
PROC_FUNC(L'N', HID_REPORT_SEQUENCE_US_SHIFT_AND_N) \
PROC_FUNC(L'O', HID_REPORT_SEQUENCE_US_SHIFT_AND_O) \
PROC_FUNC(L'P', HID_REPORT_SEQUENCE_US_SHIFT_AND_P) \
PROC_FUNC(L'Q', HID_REPORT_SEQUENCE_US_SHIFT_AND_Q) \
PROC_FUNC(L'R', HID_REPORT_SEQUENCE_US_SHIFT_AND_R) \
PROC_FUNC(L'S', HID_REPORT_SEQUENCE_US_SHIFT_AND_S) \
PROC_FUNC(L'T', HID_REPORT_SEQUENCE_US_SHIFT_AND_T) \
PROC_FUNC(L'U', HID_REPORT_SEQUENCE_US_SHIFT_AND_U) \
PROC_FUNC(L'V', HID_REPORT_SEQUENCE_US_SHIFT_AND_V) \
PROC_FUNC(L'W', HID_REPORT_SEQUENCE_US_SHIFT_AND_W) \
PROC_FUNC(L'X', HID_REPORT_SEQUENCE_US_SHIFT_AND_X) \
PROC_FUNC(L'Y', HID_REPORT_SEQUENCE_US_SHIFT_AND_Y) \
PROC_FUNC(L'Z', HID_REPORT_SEQUENCE_US_SHIFT_AND_Z) \
PROC_FUNC(L'[', HID_REPORT_SEQUENCE_RALT_AND_8) \
PROC_FUNC(L'\\', HID_REPORT_SEQUENCE_RALT_AND_102ND) \
PROC_FUNC(L']', HID_REPORT_SEQUENCE_RALT_AND_9) \
PROC_FUNC(L'^', HID_REPORT_SEQUENCE_SHIFT_AND_RIGHTBRACE_FOLLOWED_BY_SPACE) \
PROC_FUNC(L'_', HID_REPORT_SEQUENCE_US_SHIFT_AND_SLASH) \
PROC_FUNC(L'`', HID_REPORT_SEQUENCE_SHIFT_AND_EQUAL_FOLLOWED_BY_SPACE) \
PROC_FUNC(L'a', HID_REPORT_SEQUENCE_US_A) \
PROC_FUNC(L'b', HID_REPORT_SEQUENCE_US_B) \
PROC_FUNC(L'c', HID_REPORT_SEQUENCE_US_C) \
PROC_FUNC(L'd', HID_REPORT_SEQUENCE_US_D) \
PROC_FUNC(L'e', HID_REPORT_SEQUENCE_US_E) \
PROC_FUNC(L'f', HID_REPORT_SEQUENCE_US_F) \
PROC_FUNC(L'g', HID_REPORT_SEQUENCE_US_G) \
PROC_FUNC(L'h', HID_REPORT_SEQUENCE_US_H) \
PROC_FUNC(L'i', HID_REPORT_SEQUENCE_US_I) \
PROC_FUNC(L'j', HID_REPORT_SEQUENCE_US_J) \
PROC_FUNC(L'k', HID_REPORT_SEQUENCE_US_K) \
PROC_FUNC(L'l', HID_REPORT_SEQUENCE_US_L) \
PROC_FUNC(L'm', HID_REPORT_SEQUENCE_US_M) \
PROC_FUNC(L'n', HID_REPORT_SEQUENCE_US_N) \
PROC_FUNC(L'o', HID_REPORT_SEQUENCE_US_O) \
PROC_FUNC(L'p', HID_REPORT_SEQUENCE_US_P) \
PROC_FUNC(L'q', HID_REPORT_SEQUENCE_US_Q) \
PROC_FUNC(L'r', HID_REPORT_SEQUENCE_US_R) \
PROC_FUNC(L's', HID_REPORT_SEQUENCE_US_S) \
PROC_FUNC(L't', HID_REPORT_SEQUENCE_US_T) \
PROC_FUNC(L'u', HID_REPORT_SEQUENCE_US_U) \
PROC_FUNC(L'v', HID_REPORT_SEQUENCE_US_V) \
PROC_FUNC(L'w', HID_REPORT_SEQUENCE_US_W) \
PROC_FUNC(L'x', HID_REPORT_SEQUENCE_US_X) \
PROC_FUNC(L'y', HID_REPORT_SEQUENCE_US_Y) \
PROC_FUNC(L'z', HID_REPORT_SEQUENCE_US_Z) \
PROC_FUNC(L'{', HID_REPORT_SEQUENCE_RALT_AND_7) \
PROC_FUNC(L'|', HID_REPORT_SEQUENCE_US_RALT_AND_EQUAL) \
PROC_FUNC(L'}', HID_REPORT_SEQUENCE_RALT_AND_0) \
PROC_FUNC(L'~', HID_REPORT_SEQUENCE_RALT_AND_RIGHTBRACE_FOLLOWED_BY_SPACE) \
PROC_FUNC(L'§', HID_REPORT_SEQUENCE_US_SHIFT_AND_GRAVE) \
PROC_FUNC(L'å', HID_REPORT_SEQUENCE_US_LEFTBRACE) \
PROC_FUNC(L'Å', HID_REPORT_SEQUENCE_US_SHIFT_AND_LEFTBRACE) \
PROC_FUNC(L'æ', HID_REPORT_SEQUENCE_US_SEMICOLON) \
PROC_FUNC(L'Æ', HID_REPORT_SEQUENCE_US_SHIFT_AND_SEMICOLON) \
PROC_FUNC(L'ø', HID_REPORT_SEQUENCE_US_APOSTROPHE) \
PROC_FUNC(L'Ø', HID_REPORT_SEQUENCE_US_SHIFT_AND_APOSTROPHE) \
PROC_FUNC(L'€', HID_REPORT_SEQUENCE_RALT_AND_E) \
PROC_FUNC(L'µ', HID_REPORT_SEQUENCE_RALT_AND_M) \


#define LAYOUT_SWITCH_CASE(nameval, val) case nameval: {*p_out_report_seq=(void*)val; *out_rep_seq_len=sizeof(val) ;return NRF_SUCCESS; }

Expand All @@ -606,6 +719,7 @@ DEF_REPORT_SEQUENCE_NAMED(SHIFT_AND_EQUAL_FOLLOWED_BY_SPACE, DEF_REPORT(
typedef enum {
LANGUAGE_LAYOUT_DE,
LANGUAGE_LAYOUT_US,
LANGUAGE_LAYOUT_DA,
} logitacker_keyboard_map_lang_t;

typedef struct {
Expand Down
3 changes: 3 additions & 0 deletions logitacker/logitacker_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ void logitacker_options_print(nrf_cli_t const * p_cli)
case LANGUAGE_LAYOUT_US:
injection_lan_str = "us";
break;
case LANGUAGE_LAYOUT_DA:
injection_lan_str = "da";
break;
}

char * workmode_str = "unknown";
Expand Down
8 changes: 4 additions & 4 deletions logitacker/logitacker_processor_inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,17 @@ void processor_inject_timer_handler_func_(logitacker_processor_inject_ctx_t *sel
case INJECT_TASK_TYPE_PRESS_KEYS:
case INJECT_TASK_TYPE_TYPE_STRING:
case INJECT_TASK_TYPE_TYPE_ALTSTRING: {
// if timer is called, write (and auto transmit) current ESB payload
logitacker_unifying_payload_update_checksum(self->tmp_tx_payload.data, self->tmp_tx_payload.length);

// if timer is called, write (and auto transmit) current payload
if (self->usb_inject) {
//write USB HID report
if (logitacker_usb_write_keyboard_input_report(self->tmp_tx_payload.data) != NRF_SUCCESS) {
NRF_LOG_WARNING("Failed to write keyboard report, busy with old report");
} else {
NRF_LOG_DEBUG("keyboard report sent to USB");
NRF_LOG_INFO("keyboard report sent to USB");
}
} else {
// fix: only append checksum to report if ESB is used
logitacker_unifying_payload_update_checksum(self->tmp_tx_payload.data, self->tmp_tx_payload.length);
if (nrf_esb_write_payload(&self->tmp_tx_payload) != NRF_SUCCESS) {
NRF_LOG_INFO("Error writing payload");
} else {
Expand Down
2 changes: 1 addition & 1 deletion mdk-dongle/blank/config/sdk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,7 @@
// <i> Note: This value is not editable in Configuration Wizard.
// <i> Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER.
#ifndef APP_USBD_STRING_SERIAL
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.1-beta")
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.2-beta")
#endif

// </e>
Expand Down
7 changes: 3 additions & 4 deletions mdk/blank/armgcc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,11 @@ $(foreach target, $(TARGETS), $(call define_target, $(target)))

# Flash the program
flash: default
@echo Flashing: $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex
nrfjprog -f nrf52 --program $(OUTPUT_DIRECTORY)/nrf52840_xxaa.hex --sectorerase
nrfjprog -f nrf52 --reset
@echo Flashing: $(OUTPUT_DIRECTORY)/logitacker_mdk.hex
pyocd flash -t nrf52840 $(OUTPUT_DIRECTORY)/logitacker_mdk.hex

erase:
nrfjprog -f nrf52 --eraseall
pyocd erase -t nrf52840 --chip

SDK_CONFIG_FILE := ../config/sdk_config.h
CMSIS_CONFIG_TOOL := $(SDK_ROOT)/external_tools/cmsisconfig/CMSIS_Configuration_Wizard.jar
Expand Down
2 changes: 1 addition & 1 deletion mdk/blank/config/sdk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,7 @@
// <i> Note: This value is not editable in Configuration Wizard.
// <i> Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER.
#ifndef APP_USBD_STRING_SERIAL
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.1-beta")
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.2-beta")
#endif

// </e>
Expand Down
2 changes: 1 addition & 1 deletion pca10059/blank/config/sdk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,7 @@
// <i> Note: This value is not editable in Configuration Wizard.
// <i> Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER.
#ifndef APP_USBD_STRING_SERIAL
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.1-beta")
#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("v0.2.2-beta")
#endif

// </e>
Expand Down
91 changes: 91 additions & 0 deletions python_tests/create_utf8_script_DA.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import struct

'''
Important: This is a test script for LOGITacker's HID based programming interface.
The script assumes the raw HID interface accessible on /dev/hidraw1 and writes data to
this dev-file. There is no proper implementation to directly interface with LOGITacker on
the USB HID layer, neither is the protocol finalized.
The python script demos how to create injection scripts, which include Unicode and thus
can't be entered using the serial CLI (ASCII based input).
LOGITacker supports ONLY UTF-8 encoding (see 2nd line of this script). Support for Unicode
characters depends on chosen language layout and respective keymapping. The characters in
this script are supported with 'da' layout.
'''

# report types
REPORT_TYPE_COMMAND = 0x02

# commands
COMMAND_SCRIPT_STRING = 0x10
COMMAND_SCRIPT_ALTSTRING = 0x11
COMMAND_SCRIPT_PRESS = 0x12
COMMAND_SCRIPT_DELAY = 0x13
COMMAND_SCRIPT_CLEAR = 0x14

def build_report(cmd, args=""):
report = chr(REPORT_TYPE_COMMAND) + chr(cmd) + args
report = report + (64 - len(report)) * '\x00'
return report

def cmd_string(str=""):
l = len(str)
if l > 60:
l = 60

return build_report(COMMAND_SCRIPT_STRING, chr(l) + str[:l])

def cmd_altstring(str=""):
l = len(str)
if l > 60:
l = 60

return build_report(COMMAND_SCRIPT_ALTSTRING, chr(l) + str[:l])

def cmd_press(str=""):
l = len(str)
if l > 60:
l = 60

return build_report(COMMAND_SCRIPT_PRESS, chr(l) + str[:l])

def cmd_delay(delay=1):
d_str = struct.pack('<I',delay)
return build_report(COMMAND_SCRIPT_DELAY, d_str)

def cmd_clear():
return build_report(COMMAND_SCRIPT_CLEAR, "")

def split_string(n, st):
lst = [""]
for i in str(st):
l = len(lst) - 1
if len(lst[l]) < n:
lst[l] += i
else:
lst += [i]
return lst

file = "/dev/hidraw1" # has to be adjusted to LOGITacker's raw HID interface

with open(file, 'wb') as of:
of.write(cmd_clear())
of.flush()

of.write(cmd_delay(3000))
of.flush()


unicode = "ÆØÅæø倵 Københaven"
# caution: the following loop splits the string into chunks based on single bytes, not UTF8 codepoints
# it has to be assured that multibyte characters don't get split
for chunk in split_string(60,unicode):

of.write(cmd_string(chunk))
of.flush()

of.write(cmd_press("RETURN"))
of.flush()

0 comments on commit f44c0c1

Please sign in to comment.