Ты!!! Мне удалось написать скрипт на Python, который возвращает мне нагрузку на новое виртуальное устройство :-D Теперь я могу использовать его с Gimp/Krita/... Осталось только написать правильный драйвер C и загрузить прямо в ядре... Если у вас есть идеи, дайте мне знать!
Доказательство:
Таким образом, идея скрипта состоит в том, чтобы прочитать ввод из файла событий графического планшета, а затем создать хорошие события (не более BTN_LEFT
, а BTN_TOUCH
вместо этого... см. мой другой вопрос/ответ здесь для более подробной информации ).
Чтобы запустить скрипт (, см. ниже ), сохраните его в папке combine_both.py
и сделайте его исполняемым/установите deps:
$ chmod +x combine_both.py
$ sudo pip3 install libevdev
Затем проверьте доступные устройства ввода:
$ xinput list
Это должно дать вам несколько записей, среди них одна запись типа
VEIKK.INC A30 Mouse id=12 [slave pointer (2)]
Обратите внимание на идентификатор (, отмеченный как
позже ), а также идентификатор указателя виртуального ядра
:
Virtual core pointer id=2 [master pointer (3)]
Затем вам нужно знать, какой /dev/input/eventX
файл выбрать, проще всего запустить sudo evtest
и прочитать имя файла, соответствующего VEIKK.INC A30 Mouse
. Затем запустите скрипт с этим файлом в качестве аргумента, как в:
sudo./combine_both.py /dev/input/event7
Этот скрипт должен выводить информацию, когда вы пытаетесь щелкнуть или переместить устройство. Кроме того, в xinput list
также должно быть указано это устройство с именем Tablet alone Pen (0)
и идентификатором
, а xinput test
должно дать вам что-то вроде (обратите внимание на 3 столбца для x/y/давления):
$ xinput test 21
[...]
motion a[0]=4151295 a[1]=4151295 a[2]=241
motion a[0]=4060671 a[1]=4060671 a[2]=226
motion a[0]=3969535 a[1]=3969535 a[2]=211
motion a[0]=3878399 a[1]=3878399 a[2]=196
motion a[0]=3787775 a[1]=3787775 a[2]=181
motion a[0]=3696639 a[1]=3696639 a[2]=166
motion a[0]=3605503 a[1]=3605503 a[2]=151
motion a[0]=3514879 a[1]=3514879 a[2]=137
motion a[0]=3423743 a[1]=3423743 a[2]=122
motion a[0]=3332607 a[1]=3332607 a[2]=107
motion a[0]=3241983 a[1]=3241983 a[2]=92
motion a[0]=3150847 a[1]=3150847 a[2]=77
motion a[0]=3059711 a[1]=3059711 a[2]=62
motion a[0]=2969087 a[1]=2969087 a[2]=47
motion a[0]=2877951 a[1]=2877951 a[2]=32
motion a[0]=2650623 a[1]=2650623 a[2]=17
button release 1
Теперь, чтобы заставить его работать с Gimp/Krita, вы хотите отключить настоящую мышь (, иначе у вас будут конфликты между настоящим и поддельным планшетом ), с
xinput float
и когда вы закончите, вы можете снова подключить реальное устройство с помощью
xinput reattach
В gimp не забудьте настроить Tablet alone Pen (0)
на mode=screen
в Edit/input devices
и убедитесь, что реальный планшет VEIKK.INC A30 Mouse
отключен. Наконец, выбрал хорошую динамику, например Pencil Generic
для теста!
Наслаждайтесь!(и я дам вам знать, если в какой-то момент напишу драйвер C)
Скрипт:
#!/usr/bin/env python3
import sys
import libevdev
import datetime
import time
def print_capabilities(l):
v = l.driver_version
print("Input driver version is {}.{}.{}".format(v >> 16, (v >> 8) & 0xff, v & 0xff))
id = l.id
print("Input device ID: bus {:#x} vendor {:#x} product {:#x} version {:#x}".format(
id["bustype"],
id["vendor"],
id["product"],
id["version"],
))
print("Input device name: {}".format(l.name))
print("Supported events:")
for t, cs in l.evbits.items():
print(" Event type {} ({})".format(t.value, t.name))
for c in cs:
if t in [libevdev.EV_LED, libevdev.EV_SND, libevdev.EV_SW]:
v = l.value[c]
print(" Event code {} ({}) state {}".format(c.value, c.name, v))
else:
print(" Event code {} ({})".format(c.value, c.name))
if t == libevdev.EV_ABS:
a = l.absinfo[c]
print(" {:10s} {:6d}".format('Value', a.value))
print(" {:10s} {:6d}".format('Minimum', a.minimum))
print(" {:10s} {:6d}".format('Maximum', a.maximum))
print(" {:10s} {:6d}".format('Fuzz', a.fuzz))
print(" {:10s} {:6d}".format('Flat', a.flat))
print(" {:10s} {:6d}".format('Resolution', a.resolution))
print("Properties:")
for p in l.properties:
print(" Property type {} ({})".format(p.value, p.name))
def print_event(e):
print("Event: time {}.{:06d}, ".format(e.sec, e.usec), end='')
if e.matches(libevdev.EV_SYN):
if e.matches(libevdev.EV_SYN.SYN_MT_REPORT):
print("++++++++++++++ {} ++++++++++++".format(e.code.name))
elif e.matches(libevdev.EV_SYN.SYN_DROPPED):
print(">>>>>>>>>>>>>> {} >>>>>>>>>>>>".format(e.code.name))
else:
print("-------------- {} ------------".format(e.code.name))
else:
print("type {:02x} {} code {:03x} {:20s} value {:4d}".format(e.type.value, e.type.name, e.code.value, e.code.name, e.value))
class Tablet():
def __init__(self, tablet_name):
self.tablet_name = tablet_name
def __enter__(self):
self.dev = libevdev.Device()
self.dev.name = "Tablet alone"
### NB: all the following information needs to be enabled
### in order to recognize the device as a tablet.
# Say that the device will send "absolute" values
self.dev.enable(libevdev.INPUT_PROP_DIRECT)
# Say that we are using the pen (not the erasor), and should be set to 1 when we are at proximity to the device.
# See http://www.infradead.org/~mchehab/kernel_docs_pdf/linux-input.pdf page 9 (=13) and guidelines page 12 (=16), or the https://github.com/linuxwacom/input-wacom/blob/master/4.5/wacom_w8001.c (rdy=proximity)
self.dev.enable(libevdev.EV_KEY.BTN_TOOL_PEN)
self.dev.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER)
# Click
self.dev.enable(libevdev.EV_KEY.BTN_TOUCH)
# Press button 1 on pen
self.dev.enable(libevdev.EV_KEY.BTN_STYLUS)
# Press button 2 on pen, see great doc
self.dev.enable(libevdev.EV_KEY.BTN_STYLUS2)
# Send absolute X coordinate
self.dev.enable(libevdev.EV_ABS.ABS_X,
libevdev.InputAbsInfo(minimum=0, maximum=32767, resolution=100))
# Send absolute Y coordinate
self.dev.enable(libevdev.EV_ABS.ABS_Y,
libevdev.InputAbsInfo(minimum=0, maximum=32767, resolution=100))
# Send absolute pressure
self.dev.enable(libevdev.EV_ABS.ABS_PRESSURE,
libevdev.InputAbsInfo(minimum=0, maximum=8191))
# Use to confirm that we finished to send the informations
# (to be sent after every burst of information, otherwise
# the kernel does not proceed the information)
self.dev.enable(libevdev.EV_SYN.SYN_REPORT)
# Report buffer overflow
self.dev.enable(libevdev.EV_SYN.SYN_DROPPED)
self.uinput = self.dev.create_uinput_device()
print("New device at {} ({})".format(self.uinput.devnode, self.uinput.syspath))
# Sleep for a bit so udev, libinput, Xorg, Wayland,...
# all have had a chance to see the device and initialize
# it. Otherwise the event will be sent by the kernel but
# nothing is ready to listen to the device yet. And it
# will never be detected in the futur ;-)
time.sleep(1)
# self.simulate_first_click()
self.reset_state()
return self
def __exit__(self, type, value, traceback):
pass
def reset_state(self):
self.is_away = True
self.is_touching = False
self.pressed_button_1 = False
self.pressed_button_2 = False
self.lastmodif = datetime.datetime.now()
def send_events(self, events, is_away=False):
self.lastmodif = datetime.datetime.now()
self.is_away = is_away
self.uinput.send_events(events)
def simulate_first_click(self):
"""Useful only the first time to make sure
xinput detected the input"""
# Reports that the PEN is close to the surface
# Important to make sure xinput can detect (and list)
# the pen. Otherwise, it won't write anything in gimp.
self.uinput.send_events([
libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
value=0),
libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
value=1),
libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
value=0),
])
# Says that the pen it out of range of the tablet. Useful
# to make sure you can move your mouse, and to avoid
# strange things during the first draw.
self.uinput.send_events([
libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
value=0),
libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
value=0),
libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
value=0),
])
def send_state_no_pos(self, is_away=False):
self.lastmodif = datetime.datetime.now()
self.is_away = is_away
print("Away: {}, Touching: {}".format(self.is_away, self.is_touching))
self.uinput.send_events([
libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH,
value=1 if self.is_touching else 0),
libevdev.InputEvent(libevdev.EV_KEY.BTN_TOOL_PEN,
value=1 if not self.is_away else 0),
libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS,
value=1 if self.pressed_button_1 else 0),
libevdev.InputEvent(libevdev.EV_KEY.BTN_STYLUS2,
value=1 if self.pressed_button_2 else 0),
libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
value=0),
])
def touch_press(self):
self.is_touching = True
self.send_state_no_pos()
def touch_release(self):
self.is_touching = False
self.send_state_no_pos()
def button_1_press(self):
self.pressed_button_1 = True
self.send_state_no_pos()
def button_1_release(self):
self.pressed_button_1 = False
self.send_state_no_pos()
def button_2_press(self):
self.pressed_button_2 = True
self.send_state_no_pos()
def button_2_release(self):
self.pressed_button_2 = False
self.send_state_no_pos()
def move_x(self, abs_x):
self.send_events([
libevdev.InputEvent(libevdev.EV_ABS.ABS_X,
value=abs_x),
libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
value=0),
])
def move_y(self, abs_y):
self.send_events([
libevdev.InputEvent(libevdev.EV_ABS.ABS_Y,
value=abs_y),
libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
value=0),
])
def change_pressure(self, pressure):
self.send_events([
libevdev.InputEvent(libevdev.EV_ABS.ABS_PRESSURE,
value=pressure),
libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT,
value=0),
])
def handle_event(self, e):
if e.matches(libevdev.EV_ABS.ABS_PRESSURE):
self.change_pressure(e.value)
elif e.matches(libevdev.EV_ABS.ABS_X):
self.move_x(e.value)
elif e.matches(libevdev.EV_ABS.ABS_Y):
self.move_y(e.value)
elif e.matches(libevdev.EV_KEY.BTN_LEFT):
if e.value == 1:
self.touch_press()
else:
self.touch_release()
elif e.matches(libevdev.EV_SYN.SYN_REPORT):
pass
else:
print("Unkown event:")
print_event(e)
def main(args):
path = args[1]
try:
with Tablet("Tablet alone") as tablet:
### Read the events from real graphics tablet
with open(path, "rb") as fd:
l = libevdev.Device(fd)
print_capabilities(l)
print("################################\n"
"# Waiting for events #\n"
"################################")
while True:
try:
ev = l.events()
for e in ev:
print_event(e)
tablet.handle_event(e)
except libevdev.EventsDroppedException:
for e in l.sync():
print_event(e)
tablet.handle_event(e)
except KeyboardInterrupt:
pass
except IOError as e:
import errno
if e.errno == errno.EACCES:
print("Insufficient permissions to access {}".format(path))
elif e.errno == errno.ENOENT:
print("Device {} does not exist".format(path))
else:
raise e
except OSError as e:
print(e)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: sudo {} /dev/input/eventX".format(sys.argv[0]))
print(" $ sudo evtest")
print("can help you to know which file to use.")
sys.exit(1)
main(sys.argv)
Вы не сможете получить доступ ко всему пространству SSD, так как у вас есть файловая система поверх него, которая, в свою очередь, может иметь ограничения на пространство, доступное для файлов. Вам нужно будет посмотреть на фактическое доступное пространство с помощью чего-то вроде df
и работать с этим числом (, и даже некоторые из них могут быть недоступны, поэтому вам может потребоваться использовать что-то меньшее ).
Если вам на самом деле не нужны четыре задания, вы можете обойтись созданием одного файла с помощью fill_fs=1
, а затем использовать loops=2
...
Предупреждение:Из этого следует, что запуск вашей основной файловой системы (, которая используется для журналов и т. д. )из-за нехватки места, плохо влияет на работоспособность вашей системы...