From 0b99c6028deeebe94c8eddeb3274bc14f8e3985a Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Tue, 18 Dec 2018 21:47:30 +0100 Subject: [PATCH] Working communication and keys --- Makefile | 17 ++++-- build/skiller-sgk3.pdf | Bin 6754 -> 0 bytes doc/random.txt | 111 ++++++++++++++++++++++++++++++++++++++ doc/skiller-sgk3.tex | 3 ++ "src/\\" | 50 +++++++++++++++++ src/keys.c | 30 +++++++++++ src/keys.h | 118 +++++++++++++++++++++++++++++++++++++++++ src/skiller.c | 84 +++++++++++++++++++++++++++++ src/skiller.h | 46 ++++++++++++++++ src/skillerctl.c | 58 ++++++++++++++++++++ src/sniffer.c | 108 +++++++++++++++++++++++++++++++++++++ src/usb.c | 42 +++++++++++++++ src/usb.h | 18 +++++++ src/utils.c | 17 ++++++ src/utils.h | 8 +++ 15 files changed, 706 insertions(+), 4 deletions(-) delete mode 100644 build/skiller-sgk3.pdf create mode 100644 doc/random.txt create mode 100644 "src/\\" create mode 100644 src/keys.c create mode 100644 src/keys.h create mode 100644 src/skiller.c create mode 100644 src/skiller.h create mode 100644 src/skillerctl.c create mode 100644 src/sniffer.c create mode 100644 src/usb.c create mode 100644 src/usb.h create mode 100644 src/utils.c create mode 100644 src/utils.h diff --git a/Makefile b/Makefile index b2accb6..a90e7ce 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,26 @@ CC=gcc CFLAGS=-Wall -O0 -g -LDFLAGS=-lm +LDFLAGS=-lm -lusb-1.0 TEX=xelatex TEXFLAGS=-file-line-error -interaction nonstopmode -all: doc +all: doc build/sniffer build/skillerctl + +-include $(wildcard build/*.d) + +build/sniffer: build/sniffer.o build/utils.o build/usb.o build/skiller.o + $(CC) $^ -o $@ $(LDFLAGS) + +build/skillerctl: build/skillerctl.o build/utils.o build/usb.o build/skiller.o + $(CC) $^ -o $@ $(LDFLAGS) + doc: doc/skiller-sgk3.pdf %.pdf: %.tex $(TEX) $(TEXFLAGS) -output-directory build $< -.c.o: - $(CC) $(CFLAGS) -MMD -c ./src/$< -o ./build/$@ +build/%.o: src/%.c + $(CC) $(CFLAGS) -MMD -c $< -o $@ clean: rm build/* diff --git a/build/skiller-sgk3.pdf b/build/skiller-sgk3.pdf deleted file mode 100644 index 4f79bae9a059d5aa1266d7d30178c24594f6dbe1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6754 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 TfZGCu1x3IBc6LQ=CBT0HYMR*G diff --git a/doc/random.txt b/doc/random.txt new file mode 100644 index 0000000..144407a --- /dev/null +++ b/doc/random.txt @@ -0,0 +1,111 @@ +?? ?? ?? ???? ?? ?? rrggbb +04 79 01 1103 65 0100 ff0000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +04 fa 00 1103 65 0100 008000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +04 7c 01 1103 68 0100 ff0000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +?? ???? com? keyc ?? rrggbb +04 0100 0100 0000 00 000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +04 be03 1103 c000 00 fffbf0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ; a +04 0200 0200 0000 00 000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +04 0d03 11 03 0e01 00 fffbf0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ; b +04 0703 11 03 0801 00 fffbf0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ; c +04 c403 11 03 c600 00 fffbf0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ; d +04 9703 11 03 9900 00 fffbf0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ; o +04 d202 11 03 c000 00 ffff00 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ; a +04 5401 11 03 c000 00 000080 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +04 9700 11 03 0201 00 000080 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +04 5701 11 03 c300 00 000080 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +04 d000 11 03 3b01 00 000080 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +04 9400 11 03 0000 00 000080 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +04 4409 11 36 0000 00 0000fe 00800000800000800000800000800000800000800000800000800000800000800000800000000000800000800000ff000000000000 + +04 1800 06 01 0f00 00 020000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +04 4402 04 2c 0000 00 aa5502150000000000000050000000000102030405060708090a0b0c0d0e0f00101214000000000000000000000000000000000000000000 + +esc == 00, left to right, top to bottom. + +Magic Number: 0x04 +Control sum: Sum of all the other bytes +Some kind of command: 0x0311 +Some kind of address: 0x0000 +Some kind of 0x00: 0x00 + +Payload: + bbggrr: 0x800000 + + +Command types: + - 0x01 - lights off + - 0x02 - lights on + - 0x06 - change settings + - 0x00 - mode + - 0x01 - brightness + - 0x02 - pulse speed + - 0x03 - direction + - 0x04 - Is RGB + - 0x05 - color (3 bytes) + + - 0x11 - change color + +02 // number of repetitions +03 // a chuj wie + +delay ?? ?? Key code +05 A0 02 0F +05 20 02 0F +05 A0 02 12 +05 20 02 12 +05 A0 02 0F +00 20 02 0F + +6D 00 65 00 68 00 // meh + +0000 AA 55 34 00 01 00 01 00 00 00 00 00 00 00 00 00 +0010 12 00 06 00 01 03 05 A0 02 0F 05 20 02 0F 05 A0 +0020 02 12 05 20 02 12 05 A0 02 0F 00 20 02 0F 6D 00 +0030 65 00 68 00 + +0000 AA 55 +60 00 // długość +02 00 // ilość wpisów ? +01 00 +0E 00 +00 0E +32 76 +03 00 +14 00 +36 00 +06 00 + +06 00 // number of keystrokes +02 // number of repetitions +03 // ?? + +05 A0 02 0F +05 20 02 0F +05 A0 02 12 +05 20 02 12 +05 A0 02 0F +00 20 02 0F + +6D 00 65 00 68 00 // name: meh + +08 00 +01 +03 +05 A0 01 20 // 05 = delay, 05*10ms A0 - press, 0x01 - modifier 0x20 - keycode +05 A0 02 0F +05 20 02 0F +05 A0 02 12 +05 20 02 12 +05 A0 02 0F +05 20 02 0F +00 20 01 20 + +6B 00 65 00 6B 00 + diff --git a/doc/skiller-sgk3.tex b/doc/skiller-sgk3.tex index 8df389c..11c80fe 100644 --- a/doc/skiller-sgk3.tex +++ b/doc/skiller-sgk3.tex @@ -20,4 +20,7 @@ \begin{document} {\huge \noindent \textbf{\thetitle} \vspace{5mm}} \\ {\large \theauthor} \\ + + \section{Basic hardware information} + Port: USB, ID \texttt{0c45:8513} \end{document} diff --git "a/src/\\" "b/src/\\" new file mode 100644 index 0000000..efe5286 --- /dev/null +++ "b/src/\\" @@ -0,0 +1,50 @@ +#ifndef KEYS_H +#define KEYS_H + +#include + +#define SK_KEY_BAD 0xffff +#define SK_KEY_ESC 0x0000 +#define SK_KEY_F1 0x0003 +#define SK_KEY_F2 0x0006 +#define SK_KEY_F3 0x0009 +#define SK_KEY_F4 0x000C +#define SK_KEY_F5 0x000F +#define SK_KEY_F6 0x0012 +#define SK_KEY_F7 0x0015 +#define SK_KEY_F8 0x0018 +#define SK_KEY_F9 0x001B +#define SK_KEY_F10 0x001E +#define SK_KEY_F11 0x0021 +#define SK_KEY_F12 0x0024 +#define SK_KEY_PRTSC 0x002a +#define SK_KEY_SCROLL_LOCK 0x002d +#define SK_KEY_BREAK 0x0030 +#define SK_KEY_TILDE 0x003f +#define SK_KEY_1 0x003f +#define SK_KEY_2 0x003f +#define SK_KEY_3 0x003f +#define SK_KEY_4 0x003f +#define SK_KEY_5 0x003f +#define SK_KEY_6 0x003f +#define SK_KEY_7 0x003f +#define SK_KEY_8 0x003f +#define SK_KEY_9 0x003f +#define SK_KEY_0 0x003f +#define SK_KEY_MINUS 0x003f +#define SK_KEY_EQUALS 0x003f +#define SK_KEY_BACKSPACE 0x003f +#define SK_KEY_INSERT 0x003f +#define SK_KEY_HOME 0x003f +#define SK_KEY_PGUP 0x003f +#define SK_KEY_NUMLOCK 0x003f +#define SK_KEY_NUMDIV 0x003f +#define SK_KEY_NUMASTERIX 0x003f +#define SK_KEY_NUMMINUS 0x003f + +typedef uint16_t skillerctl_keyaddr_t; + +skillerctl_keyaddr_t skillerctl_keyaddr(const char* name); + +#endif /* KEYS_H */ + diff --git a/src/keys.c b/src/keys.c new file mode 100644 index 0000000..39ce8b5 --- /dev/null +++ b/src/keys.c @@ -0,0 +1,30 @@ +#include "keys.h" +#include +#include + +typedef struct { + skillerctl_keyaddr_t addr; + char* name; +} keyaddr_name_pair; + +keyaddr_name_pair keycodeLUT[] = { + SK_KEY_ESC, "esc", + SK_KEY_F1, "f1", + SK_KEY_F2, "f2", +}; + +skillerctl_keyaddr_t skillerctl_keyaddr(const char* name) +{ + size_t n = sizeof(keycodeLUT) / sizeof(keyaddr_name_pair); + keyaddr_name_pair *current; + + for (int i = 0; i < n; i++) { + current = keycodeLUT + i; + + if (strcmp(current->name, name) == 0) { + return current->addr; + } + } + + return SK_KEY_BAD; +} diff --git a/src/keys.h b/src/keys.h new file mode 100644 index 0000000..42c606b --- /dev/null +++ b/src/keys.h @@ -0,0 +1,118 @@ +#ifndef KEYS_H +#define KEYS_H + +#include + +#define SK_KEY_BAD 0xffff +#define SK_KEY_ESC 0x0000 +#define SK_KEY_F1 0x0003 +#define SK_KEY_F2 0x0006 +#define SK_KEY_F3 0x0009 +#define SK_KEY_F4 0x000C +#define SK_KEY_F5 0x000F +#define SK_KEY_F6 0x0012 +#define SK_KEY_F7 0x0015 +#define SK_KEY_F8 0x0018 +#define SK_KEY_F9 0x001B +#define SK_KEY_F10 0x001E +#define SK_KEY_F11 0x0021 +#define SK_KEY_F12 0x0024 +#define SK_KEY_PRTSC 0x002a +#define SK_KEY_SCROLL_LOCK 0x002d +#define SK_KEY_BREAK 0x0030 +#define SK_KEY_TILDE 0x003f +#define SK_KEY_1 0x0042 +#define SK_KEY_2 0x0045 +#define SK_KEY_3 0x0048 +#define SK_KEY_4 0x004b +#define SK_KEY_5 0x004e +#define SK_KEY_6 0x0051 +#define SK_KEY_7 0x0054 +#define SK_KEY_8 0x0057 +#define SK_KEY_9 0x005A +#define SK_KEY_0 0x005D +#define SK_KEY_MINUS 0x0060 +#define SK_KEY_EQUALS 0x0063 +#define SK_KEY_BACKSPACE 0x0066 +#define SK_KEY_INSERT 0x0069 +#define SK_KEY_HOME 0x006c +#define SK_KEY_PGUP 0x006f +#define SK_KEY_NUMLOCK 0x0072 +#define SK_KEY_NUMDIV 0x0075 +#define SK_KEY_NUMASTERIX 0x0078 +#define SK_KEY_NUMMINUS 0x007A +#define SK_KEY_TAB 0x007E +#define SK_KEY_Q 0x0081 +#define SK_KEY_W 0x0084 +#define SK_KEY_E 0x0087 +#define SK_KEY_R 0x008A +#define SK_KEY_T 0x008D +#define SK_KEY_Y 0x0090 +#define SK_KEY_U 0x0093 +#define SK_KEY_I 0x0096 +#define SK_KEY_O 0x0099 +#define SK_KEY_P 0x009C +#define SK_KEY_OPEN_BRACKET 0x009F +#define SK_KEY_CLOSE_BRACKET 0x00A2 +#define SK_KEY_BACKSLASH 0x00A5 +#define SK_KEY_DELETE 0x00A8 +#define SK_KEY_END 0x00AB +#define SK_KEY_PGDOWN 0x00AE +#define SK_KEY_NUM7 0x00B1 +#define SK_KEY_NUM8 0x00B4 +#define SK_KEY_NUM9 0x00B7 +#define SK_KEY_NUMPLUS 0x00BA +#define SK_KEY_CAPSLOCK 0x00BD +#define SK_KEY_A 0x00C0 +#define SK_KEY_S 0x00C3 +#define SK_KEY_D 0x00C6 +#define SK_KEY_F 0x00C9 +#define SK_KEY_G 0x00CC +#define SK_KEY_H 0x00CF +#define SK_KEY_J 0x00D2 +#define SK_KEY_K 0x00D5 +#define SK_KEY_L 0x00D8 +#define SK_KEY_COLON 0x00DB +#define SK_KEY_QUOTE 0x00DE +#define SK_KEY_ENTER 0x00E4 +#define SK_KEY_NUM4 0x00F0 +#define SK_KEY_NUM5 0x00F3 +#define SK_KEY_NUM6 0x00F6 +#define SK_KEY_LSHIFT 0x00FC +#define SK_KEY_Z 0x0102 +#define SK_KEY_X 0x0105 +#define SK_KEY_C 0x0108 +#define SK_KEY_V 0x010b +#define SK_KEY_B 0x010e +#define SK_KEY_N 0x0111 +#define SK_KEY_M 0x0114 +#define SK_KEY_COMMA 0x0117 +#define SK_KEY_DOT 0x011a +#define SK_KEY_SLASH 0x011d +#define SK_KEY_RSHIFT 0x0123 +#define SK_KEY_UP 0x0129 +#define SK_KEY_NUM1 0x012f +#define SK_KEY_NUM2 0x0132 +#define SK_KEY_NUM3 0x0135 +#define SK_KEY_NUMENTER 0x0138 +#define SK_KEY_LCTRL 0x013b +#define SK_KEY_LWIN 0x013e +#define SK_KEY_LALT 0x0141 +#define SK_KEY_SPACE 0x0144 +#define SK_KEY_ALTGR 0x0147 +#define SK_KEY_SHARKOON 0x014a +#define SK_KEY_MENU 0x014d +#define SK_KEY_RCTRL 0x0153 +#define SK_KEY_LEFT 0x0165 +#define SK_KEY_DOWN 0x0168 +#define SK_KEY_RIGHT 0x016b +#define SK_KEY_NUM0 0x0171 +#define SK_KEY_NUMDEL 0x0174 + +typedef uint16_t skillerctl_keyaddr_t; + +skillerctl_keyaddr_t skillerctl_keyaddr(const char* name); +char* skillerctl_keystr(skillerctl_keyaddr_t key); + +#endif /* KEYS_H */ + diff --git a/src/skiller.c b/src/skiller.c new file mode 100644 index 0000000..d07aeff --- /dev/null +++ b/src/skiller.c @@ -0,0 +1,84 @@ +#include "skiller.h" +#include + +skillerctl_packet_t* skillerctl_unpack(skillerctl_packet_t *packet, uint8_t *data, size_t length) { + if (*(unsigned char*)data != 0x04 || length < 1) { + return NULL; + } + + packet->magic = *(uint8_t*)(data); + packet->checksum = *(uint16_t*)(data + 1); + packet->command = *(uint8_t*)(data + 3); + packet->length = *(uint8_t*)(data + 4); + packet->address = *(uint8_t*)(data + 5); + // 1 null byte + memcpy(packet->payload, data + 8, packet->length); + + return packet; +} + +void* skillerctl_pack(skillerctl_packet_t *packet, uint8_t *data) { + memcpy(data, &packet->magic, 1); + memcpy(data + 1, &packet->checksum, 2); + memcpy(data + 3, &packet->command, 1); + memcpy(data + 4, &packet->length, 1); + memcpy(data + 5, &packet->address, 2); + // 1 null byte + memcpy(data + 8, packet->payload, SK_MAX_PAYLOAD); + + return packet; +} + +void skillerctl_make_packet(skillerctl_packet_t *packet, uint8_t command, uint16_t address, void* payload, uint8_t size) +{ + packet->magic = SK_MAGIC; + packet->address = address; + packet->command = command; + packet->length = size; + + memset(packet->payload, 0, SK_MAX_PAYLOAD); + + if (payload && size) + memcpy(packet->payload, payload, size); + + packet->checksum = skillectl_packet_checksum(packet); +} + +uint16_t skillectl_packet_checksum(skillerctl_packet_t *packet) +{ + uint16_t checksum = 0; + + checksum += (packet->command) & 0xFF; + checksum += (packet->address) & 0xFF; + checksum += (packet->address >> 8) & 0xFF; + checksum += (packet->length) & 0xFF; + + for (int i = 0; i < packet->length; i++) { + checksum += packet->payload[i]; + } + + return checksum; +} + +void skillerctl_color_command(skillerctl_packet_t *packet, skillerctl_keyaddr_t address, uint32_t color) +{ + skillerctl_payload_color_t payload; + + payload.color[0].r = (color >> 16) & 0xFF; + payload.color[0].g = (color >> 8) & 0xFF; + payload.color[0].b = color & 0xFF; + + skillerctl_make_packet(packet, SK_CMD_COLOR, address, &payload, 3); +} + +void skillerctl_enable_command(skillerctl_packet_t *packet) +{ + skillerctl_payload_color_t payload; + skillerctl_make_packet(packet, SK_CMD_ENABLE, 0x0000, NULL, 0); +} + +void skillerctl_disable_command(skillerctl_packet_t *packet) +{ + skillerctl_payload_color_t payload; + skillerctl_make_packet(packet, SK_CMD_DISABLE, 0x0000, NULL, 0); +} diff --git a/src/skiller.h b/src/skiller.h new file mode 100644 index 0000000..f246137 --- /dev/null +++ b/src/skiller.h @@ -0,0 +1,46 @@ +#ifndef SKILLER_H +#define SKILLER_H + +#include +#include +#include "keys.h" + +#define SK_MAX_PAYLOAD 56 +#define SK_PACKET_SIZE 64 + +#define SK_MAGIC 0x04 + +#define SK_CMD_COLOR 0x11 +#define SK_CMD_ENABLE 0x01 +#define SK_CMD_DISABLE 0x02 + +typedef struct { + uint8_t magic; + uint16_t checksum; + uint8_t command; + uint16_t address; + uint8_t length; + uint8_t payload[SK_MAX_PAYLOAD]; +} skillerctl_packet_t; + +typedef struct { + struct { + uint8_t r; + uint8_t g; + uint8_t b; + } color[SK_MAX_PAYLOAD / 3]; +} skillerctl_payload_color_t; + +void skillerctl_make_packet(skillerctl_packet_t *packet, uint8_t command, uint16_t address, void* payload, uint8_t size); + +void skillerctl_color_command(skillerctl_packet_t *packet, skillerctl_keyaddr_t address, uint32_t color); +void skillerctl_enable_command(skillerctl_packet_t *packet); +void skillerctl_disable_command(skillerctl_packet_t *packet); + +skillerctl_packet_t* skillerctl_unpack(skillerctl_packet_t *packet, uint8_t *data, size_t length); +void* skillerctl_pack(skillerctl_packet_t *packet, uint8_t *data); + +uint16_t skillectl_packet_checksum(skillerctl_packet_t *packet); + +#endif /* SKILLER_H */ + diff --git a/src/skillerctl.c b/src/skillerctl.c new file mode 100644 index 0000000..83e65f6 --- /dev/null +++ b/src/skillerctl.c @@ -0,0 +1,58 @@ +#include +#include +#include "skiller.h" +#include "usb.h" +#include "utils.h" + +void stuff(libusb_device *skiller) +{ + libusb_device_handle *handle; + skillerctl_packet_t packet; + + if (skiller == NULL) { + printf("Device not found kurwa.\n"); + return; + } + + + if (libusb_open(skiller, &handle) != LIBUSB_SUCCESS) { + printf("Nie udało się nawiązać połączenia kurwa..\n"); + return; + } + + printf("Hura kurwa.\n"); + + libusb_detach_kernel_driver(handle, 1); + libusb_claim_interface(handle, 1); + +/* skillerctl_enable_command(&packet); */ +/* skillerctl_send_command(handle, &packet); */ + + skillerctl_color_command(&packet, SK_KEY_ESC, 0xFF0000); + skillerctl_send_command(handle, &packet); + skillerctl_color_command(&packet, SK_KEY_F1, 0x00FF00); + skillerctl_send_command(handle, &packet); + skillerctl_color_command(&packet, SK_KEY_F2, 0x0000FF); + skillerctl_send_command(handle, &packet); + + /* skillerctl_disable_command(&packet); */ + /* skillerctl_send_command(handle, &packet); */ + + libusb_release_interface(handle, 1); + libusb_attach_kernel_driver(handle, 1); + libusb_close(handle); +} + +int main() +{ + libusb_device **list; + + libusb_init(NULL); + size_t count = libusb_get_device_list(NULL, &list); + libusb_device *skiller = skillerctl_find_device(list, count); + + stuff(skiller); + + libusb_free_device_list(list, 1); + libusb_exit(NULL); +} diff --git a/src/sniffer.c b/src/sniffer.c new file mode 100644 index 0000000..f3e6447 --- /dev/null +++ b/src/sniffer.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include + +#include "../lib/optparse.h" +#include "utils.h" +#include "skiller.h" +#include "usb.h" + +#define USBMON_IOC_MAGIC 0x92 +#define USBMON_IOCX_GET _IOW(USBMON_IOC_MAGIC, 10, usbmon_get_t) + +typedef struct usbmon_packet { + uint64_t id; /* 0: URB ID - from submission to callback */ + uint8_t type; /* 8: Same as text; extensible. */ + uint8_t xfer_type; /* ISO (0), Intr, Control, Bulk (3) */ + uint8_t epnum; /* Endpoint number and transfer direction */ + uint8_t devnum; /* Device address */ + uint16_t busnum; /* 12: Bus number */ + char flag_setup; /* 14: Same as text */ + char flag_data; /* 15: Same as text; Binary zero is OK. */ + int64_t ts_sec; /* 16: gettimeofday */ + uint64_t ts_usec; /* 24: gettimeofday */ + int status; /* 28: */ + unsigned int length; /* 32: Length of data (submitted or actual) */ + unsigned int len_cap; /* 36: Delivered length */ + union { /* 40: */ + unsigned char setup[8]; /* Only for Control S-type */ + struct iso_rec { /* Only for ISO */ + int error_count; + int numdesc; + } iso; + } s; + int interval; /* 48: Only for Interrupt and ISO */ + int start_frame; /* 52: For ISO */ + unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */ + unsigned int ndesc; /* 60: Actual number of ISO descriptors */ +} usbmon_packet_t; /* 64 total length */ + +typedef struct usbmon_get { + usbmon_packet_t *packet; + void *data; + size_t alloc; +} usbmon_get_t; + +const char types[4] = "SICB"; + +uint8_t buffer[4096]; +usbmon_packet_t packet; + +int main(int argc, char** argv) +{ + libusb_device **list; + + libusb_init(NULL); + size_t count = libusb_get_device_list(NULL, &list); + libusb_device *skiller = skillerctl_find_device(list, count); + + if (skiller != NULL) { + uint8_t bus = libusb_get_bus_number(skiller); + uint8_t dev = libusb_get_device_address(skiller); + + printf("Keyboard found on bus %03d, device: %d\n", bus, dev); + + char* device = "/dev/usbmon0"; + + usbmon_get_t get = { + .packet = &packet, + .data = &buffer, + .alloc = sizeof buffer + }; + + int fd = open(device, O_RDONLY); + + if (fd < 0) { + printf("Cannot open device %s, maybe usbmon module is not loaded corectly?\n", device); + return 1; + } + + while (1) { + if (ioctl(fd, USBMON_IOCX_GET, &get) < 0) { + break; + } + + if (packet.devnum != dev || packet.busnum != bus) { + continue; + } + + printf("%s dev %d [%c] len: %d \n", packet.type == 'S' ? "->" : "<-", packet.devnum, types[packet.xfer_type], packet.length); + + skillerctl_packet_t ctl; + if (skillerctl_unpack(&ctl, buffer, packet.length)) { + printf("Command: 0x%02X, checksum: 0x%04X, payload length: %d, addr: 0x%04X \n", ctl.command, ctl.checksum, ctl.length, ctl.address); + hexdump(ctl.payload, ctl.length); + } else if (packet.length > 0) { + printf("Unknown packet kind! \n"); + hexdump(buffer, packet.length); + } + } + } + + + libusb_free_device_list(list, 1); + libusb_exit(NULL); +} diff --git a/src/usb.c b/src/usb.c new file mode 100644 index 0000000..8b798d2 --- /dev/null +++ b/src/usb.c @@ -0,0 +1,42 @@ +#include "usb.h" +#include "utils.h" +#include +#include +#include + +libusb_device* skillerctl_find_device(libusb_device **devices, size_t count) +{ + libusb_device *device; + struct libusb_device_descriptor descriptor; + + for (unsigned i = 0; i < count; i++) { + device = devices[i]; + + libusb_get_device_descriptor(device, &descriptor); + if (descriptor.idVendor == SK_VID && descriptor.idProduct == SK_PID) { + return device; + } + } + + return NULL; +} + +void skillerctl_send_command(libusb_device_handle *handle, skillerctl_packet_t *packet) +{ + // buffer for storing packed packet + uint8_t buffer[SK_PACKET_SIZE]; + int length; + + skillerctl_pack(packet, buffer); + printf("Sending packet to keyboard: \n"); + hexdump(buffer, SK_PACKET_SIZE); + + libusb_control_transfer(handle, 0x21, 9, 0x0204, 0x0001, buffer, SK_PACKET_SIZE, 250); + libusb_interrupt_transfer(handle, SK_PORT_STATE, buffer, sizeof(buffer), &length, 250); + + printf("State from keyboard: \n"); + hexdump(buffer, SK_PACKET_SIZE); + + // we need to pretend that we're doing important stuff + usleep(100000); +} diff --git a/src/usb.h b/src/usb.h new file mode 100644 index 0000000..c0fc658 --- /dev/null +++ b/src/usb.h @@ -0,0 +1,18 @@ +#ifndef USB_H +#define USB_H + +#include "skiller.h" +#include + +#define SK_VID 0x0C45 +#define SK_PID 0x8513 + +#define SK_PORT_STATE 0x82 +#define SK_PORT_HID 0x81 + +libusb_device* skillerctl_find_device(libusb_device **devices, size_t count); + +void skillerctl_send_command(libusb_device_handle *handle, skillerctl_packet_t *packet); + +#endif /* USB_H */ + diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..93563e0 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,17 @@ +#include "utils.h" +#include + +void hexdump(void* data, size_t length) +{ + for (size_t read = 0; read < length; read += 16) { + printf("%04zx", read); + + size_t to_read = length - read > 16 ? 16 : length - read; + for (size_t byte = 0; byte < to_read; byte++) { + printf(" %02X", ((unsigned char*)data)[read + byte]); + } + + printf("\n"); + } +} + diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..aaffe17 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,8 @@ +#ifndef UTILS_H_ +#define UTILS_H_ + +#include + +void hexdump(void* bytes, size_t length); + +#endif