Close
Showing results 1 to 2 of 2
  1. #1

    Default [Suggestion] Use raspberry pie as a smart KVM for boxing

    Ok, so i was thinking of using some rasberry pie as a smart kvm.
    I think it's a great idea and i didn't see anyone mention this, so it's probably worth a thread.

    I'm not a veteran coder, and actually i don't know python, so take any part of code with a grain of salt, it's more about the idea than my implementation.

    As some know, rasberry pie zero can act as a physical keyboard, using OTG USB. That mean you can connect via usb the rab to your computer and it will be recognize as an usb keyboard and it will be able to send hardware keys to your computer.
    You can find usefull info here : https://gndtovcc.home.blog/2020/04/1...-keyboard-hid/
    and here : https://mtlynch.io/key-mime-pi/

    I've got a rasberry pie zero and i made some tests.
    My initial plan was this :

    Broadcast a keyboard to all rasberry pie zero.
    The rasb capture the USB HUD input, and emulate a keyboard to all five computer.
    But on the contrary of an usual kvm broadcast, it only let selected few keys to be broadcast to slave, like key 1 to 9 for exemple.
    And you can add some hot key to switch the 'main computer' who get all the keys without filter.

    You can capture input USB HID commands using a python code like that :
    Code:
    import usb.core
    import usb.util
    import time
    
    
    USB_IF      = 0 # Interface
    USB_TIMEOUT = 5 # Timeout in MS
    
    
    USB_VENDOR  = 0x046d
    USB_PRODUCT = 0xc31c
    
    
    dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
    
    
    endpoint = dev[0][(0,0)][0]
    
    
    if dev.is_kernel_driver_active(USB_IF) is True:
      dev.detach_kernel_driver(USB_IF)
    
    
    usb.util.claim_interface(dev, USB_IF)
    
    
    while True:
      control = None
    
    
      try:
        control = dev.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize, USB_TIMEOUT)
        print control
      except:
        pass
    Sadly, after receiving my rasberry pie zero, i saw that my initial idea was not possible due to hardware limitation.
    Because the rasberry pie zero have only one usb, the other slot is only for power.
    Edit : A way of doing that could be using the bluetooth, there is some stuff about making a rasberry pie act as a BT keyboard here ( https://impythonist.wordpress.com/20...-raspberry-pi/ ) and here ( https://projects-raspberry.com/emula...-raspberry-pi/ ) but i didn't test it.

    It's not totally useless, thought, because you can still plug it to your computer and use wifi to receive command.
    I did just that as a POC, so i connected the rasb to my wifi and via usb to a second computer, put a php-nginx webserver on it and a simple php script like that :
    PHP Code:
    <?php$key = @$_GET['key'];$mod = @$_GET['mod']*1;$key = explode("x",$key);$z = chr(0);$cmd = chr($mod).$z;$nb=0;foreach($key as $k){    $nb++;    $cmd.=chr($k);}$left=6-$nb;if($left>0){    for($i=0;$i<$left;$i++) $cmd.= $z;}file_put_contents( "/dev/hidg0", $cmd );?>
    And on my my main computer i used a simple python script like that to capture key and send http requests :
    Code:
    # encoding=utf8
    from pynput import keyboard
    import requests
     
    def split(word):
        return [char for char in word]
    
    
    
    
    usbval = {3: 0x48,8: 0x2a,9: 0x2b,12: 0x53,13: 0x28,16: 0xe1,17: 0xe0,18: 0xe1,19: 0x48,20: 0x39,21: 0x90,25: 0x91,27: 0x29,32: 0x2c,33: 0x4b,34: 0x4e,35: 0x4d,36: 0x4a,37: 0x50,38: 0x52,39: 0x4f,40: 0x51,41: 0x77,43: 0x74,44: 0x46,45: 0x49,46: 0x4c,47: 0x75,48: 0x27,49: 0x1e,50: 0x1f,51: 0x20,52: 0x21,53: 0x22,54: 0x23,55: 0x24,56: 0x25,57: 0x26,59: 0x33,60: 0xc5,61: 0x2e,65: 0x04,66: 0x05,67: 0x06,68: 0x07,69: 0x08,70: 0x09,71: 0x0a,72: 0x0b,73: 0x0c,74: 0x0d,75: 0x0e,76: 0x0f,77: 0x10,78: 0x11,79: 0x12,80: 0x13,81: 0x14,82: 0x15,83: 0x16,84: 0x17,85: 0x18,86: 0x19,87: 0x1a,88: 0x1b,89: 0x1c,90: 0x1d,91: 0xe3,96: 0x62,97: 0x59,98: 0x5a,99: 0x5b,100: 0x5c,101: 0x5d,102: 0x5e,103: 0x5f,104: 0x60,105: 0x61,112: 0x3b,113: 0x3c,114: 0x3d,115: 0x3e,116: 0x3f,117: 0x40,118: 0x41,119: 0x42,120: 0x43,121: 0x44,122: 0x45,123: 0x46,124: 0x68,125: 0x69,126: 0x6a,127: 0x6b,128: 0x6c,129: 0x6d,130: 0x6e,131: 0x6f,132: 0x70,133: 0x71,134: 0x72,144: 0x53,145: 0x47,161: 0x1e,163: 0x32,173: 0x2d,179: 0xe8,168: 0xfa,186: 0x33,187: 0x2e,188: 0x36,189: 0x2d,190: 0x37,191: 0x38,192: 0x35,219: 0x2f,220: 0x31,221: 0x30,222: 0x34,223: 0x35,-1:''}
        
    allowed = [48,49,50,51,52,53,54,55,56,57]
    allowed_special = ['Key.f1','Key.f2','Key.f3','Key.f4','Key.f5','Key.f6','Key.f7','Key.f8','Key.f9','Key.f10','Key.f11','Key.f12']
    
    
    allowed_mod = ['Key.ctrl_l','Key.shift','Key.alt_l']
    #ctrl 1
    #shift 2
    #alt 4
    
    
    
    
    keyboardstate = []
    modstate = []
    previousstate = []
    previousmod = []
    
    
    def sendkey():
        global previousstate
        global previousmod
        global modstate
        print(previousstate)
        print(keyboardstate)
        print(modstate)
        nb=0
        key = ""
        if previousstate != keyboardstate or previousmod != modstate:
            modval = 0
            for i in modstate:
                modval = modval + i
            for i in keyboardstate:
                nb = nb+1
                key = key + str(usbval[i]) + "x"
            r =requests.get('http://192.168.1.27/write2.php?mod=' + str(modval) + '&key=' + key)
            #print('http://192.168.1.27/write2.php?mod=' + str(modval) + '&key=' + key)
        previousstate = keyboardstate[:]
        previousmod = modstate[:]
        return True
    
    
    class CaptureKeys:
        def __init__(self):
            pass
     
        def on_press(self, key):
            if hasattr(key, 'vk'):
                if key.vk in allowed and key.vk not in keyboardstate and len(keyboardstate)<6 :
                    keyboardstate.append(key.vk)
                    sendkey()
            else:
                print(key)
                if format(key) in allowed_mod :
                    if key == keyboard.Key.ctrl_l and 1 not in modstate:
                        modstate.append(1)
                    if key == keyboard.Key.shift and 2 not in modstate:
                        modstate.append(2)
                    if key == keyboard.Key.alt_l and 4 not in modstate:
                        modstate.append(4)
                    sendkey()
                    
        def on_release(self, key):
            if hasattr(key, 'vk'):
                if key.vk in allowed and key.vk in keyboardstate :
                    keyboardstate.remove(key.vk)
                    sendkey()
            else:
                if format(key) in allowed_mod :
                    if key == keyboard.Key.ctrl_l and 1 in modstate:
                        modstate.remove(1)
                    if key == keyboard.Key.shift and 2 in modstate:
                        modstate.remove(2)
                    if key == keyboard.Key.alt_l and 4 in modstate:
                        modstate.remove(4)
                    sendkey()
            
            if key == keyboard.Key.esc:
                # Stop listener
                return False
     
        # Collect events until released
        def main(self):
            with keyboard.Listener(
                    on_press=self.on_press,
                    on_release=self.on_release) as listener:
                listener.join()
     
        def start_listener(self):
            keyboard.Listener.start
            self.main()
     
    if __name__ == '__main__':
        ck = CaptureKeys()
        ck.start_listener()
    It works really well and with that if it only broadcast key 1 to 9 to my secondary computer.
    The downside is you have a software client side, so it's not pure hardware boxing.
    Of course, this could be improved (using a socks connection instead of a webserver to start)

    But i see that more as a POC than a practical solution.
    Now i read that others raspberry PIE have USB OTG enabled, and since they have 4 usb, i wonder if you can use that on all 4 USB.
    If that's the case, i will show you the setup i have in mind.


    End Goal : Having one keyboard and one mouse.
    Use Alt+F1, Alt+F2, Alf+F4, Alt+F5, Alt+F6 to switch between 'Active computer'.
    Active computer get all the keyboard key, slave only receive a custom range of key (like only 1 to 9).
    On switching the left rasb send a keyboard command to the mouse kvm to also switch mouse and send an ir command to the hdmi switch to make the slave fullscreen.
    By default all your keys go to your main but only a selected few (1 to 9) are broadcasted to slave.
    If you switch using let say Alf+F2, all your keys go to the second computers (and others get only 1-9), it send a command to the mouse kvm to also switch the mouse, and a ir command to the hdmi switch to full screen your slave on your left screen.

    Right now, i don't know if that's doable. But i think it definitely need some digging from the community.
    Attached Images Attached Images    

  2. #2

    Default

    It seems i have a problem to fufill my idea. If i'm not wrong, the raspberry 4 has only one UTG enabled port. And a setup with multiple rasberry 4 would be pricy.
    I don't drop the ball, i've got other idea. First, maybe we can use the "La Frite AML-S805X-AC" computer.
    https://www.kickstarter.com/projects...es/description
    There is only one UTG too, but with a 15$ price tag, that could do the trick.

    The second idea is to use 6 raspberry zero pi w, one as a server, and the 5 others as clients.
    And to communicate we can use UDP broadcast over wifi.
    It seems really easy to do : https://gist.github.com/ninedraft/7c...1e326fffb664b5
    As for the IR remote control for the HDMI Switch, there is a full guide here : https://www.instructables.com/Raspbe...versal-Remote/

    There is also maybe a way to do both keyboard and mouse ( https://github.com/stjeong/rasp_vusb )
    I would very much like it, but the amount of data to broadcast would be a lot more than keyboard. Worth a try.
    Last edited by Baltyre : 02-26-2021 at 06:20 PM

Posting Rules

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •