· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
SetHHK InXUsing Hotplug

Hotplug를 이용해서 HappyHacking Keyboard 키맵 지정하기

이 글은 리눅스의 Hotplug 기능을 이용해서 X Window에서 사용자가 지정한 키맵, Xmodmap 설정파일,해피해킹 키보드의 키맵을 적용시키는 방법을 설명합니다. 제가 사용하는 데비안 시드 Debian Sid를 기준으로 설명합니다.

저는 Thinkpad T42 노트북에 HHK를 사용하고 있습니다. HHK의 원래 키맵에 익숙해지질 않아서 부득이 tilde(~)키와 Esc키를 아예 키캡을 바꿔끼우고, Caps_Lock 자리에 있는 HHK의 Control키를 Escape키로 배정해서 사용하고 있습니다. Alt키와 그 옆의 사각형키도 바꿔서 다른 키보드들처럼 Control, Alt 순서로 배정해서 사용하고 있습니다. HHK를 붙일 때마다 변경된 키맵을 설정하기가 번거로워서 Hotplug를 이용해서 자동으로 인식되도록 설정해봤습니다.

(아래에 설명하는 방법이 hotplug를 제대로 사용하는 것인지 잘 모르겠네요. 보충해야 될 부분은 지적해주세요.)

Hotplug에 대한 구체적인 설명은 LinuxHotplug 페이지를 참고하세요.


2. 먼저,

  • 시스템이 hotplug기능을 사용하고 있어야 합니다.
  • python이 설치되어 있어야 합니다.
  • 물론 HHK는 준비해야 겠죠.

Hotplug가 사용하는 디렉토리들은,
  • /etc/hotplug
  • /etc/hotplug.d

3. 스크립트를 작성합니다.

/etc/hotplug_device.d 디렉토리를 만듭니다.
shell > mkdir /etc/hotplug_device.d

다음 스크립트를 작성합니다.

/etc/hotplug.d/usb/usbhid.hotplug
#!/usr/bin/env python

import os, glob, sys, sre

DIR_HOTPLUG_DEVICE = "/etc/hotplug_device.d"

if not os.path.isdir(DIR_HOTPLUG_DEVICE) : sys.exit(1)
sys.path.append(DIR_HOTPLUG_DEVICE)

for i in glob.glob("%s/*_usb.py" % DIR_HOTPLUG_DEVICE) :
   __device_filename = sre.compile(".py$").sub("", os.path.basename(i))
   __module = __import__(__device_filename, globals(), locals(), [__device_filename,])

   DEVICE = getattr(__module, "device")

   DEVICE().do()

/etc/hotplug_device.d/BASIC_USB.py
import os, sys, pickle

class device :

   LOG_HOTPLUG_DEVICE = "/var/run/hotplug_device.pkl"
   ACTION = ""
   DEVPATH_REMOVE = ""
   DEVPATH = ""
   PRODUCT = ""
   MANUFACTURER = ""

   def __init__ (self) :
      self.get_info()

   def get_info (self) :
      self.ACTION = os.getenv("ACTION")
      self.DEVPATH = "/sys%s" % os.getenv("DEVPATH")
      self.DEVPATH_REMOVE = os.sep.join(self.DEVPATH.split(os.sep)[:-2])

      if not os.path.isdir(self.DEVPATH) :
         raise RuntimeError, "devpath, %s does not exists" % self.DEVPATH

      # get PRODUCT name and get MANUFACTURER name
      __file_product = "%s/product" % os.sep.join(self.DEVPATH.split(os.sep)[:-1])
      __file_manufacture = "%s/manufacturer" % os.sep.join(self.DEVPATH.split(os.sep)[:-1])
      if os.path.isfile(__file_product) :
         self.PRODUCT = "".join(open(__file_product, "r").readlines()).strip()
      if os.path.isfile(__file_manufacture) :
         self.MANUFACTURER = "".join(open(__file_manufacture, "r").readlines()).strip()

   def check_add (self) : pass
   def check_remove (self) : pass

   def do (self) :
      data = self.get_data()
      if self.ACTION == "add" :
         if self.check_add() :
            self.add()
            data[self.DEVPATH_REMOVE] = \
               (self.PRODUCT, self.MANUFACTURER, self.ACTION,)

            self.store_data(data)

            return True
      elif self.ACTION == "remove" :
         if self.check_remove() :
            self.remove()

            del(data[self.DEVPATH])
            self.store_data()

            return True

      return False

   def add (self) :
      self.store_data()

   def remove (self) :
      pass

   def store_data (self, data) :
      """
         store information for removing this devices.
      """
      __fd_pk = open(self.LOG_HOTPLUG_DEVICE, "w")
      pickle.dump(data, __fd_pk)
      __fd_pk.close()

   def get_data (self) :
      if not os.path.isfile(self.LOG_HOTPLUG_DEVICE) :
         __data = dict()
      else :
         __fd_pk = open(self.LOG_HOTPLUG_DEVICE, "r")
         try :
            __data = pickle.load(__fd_pk)
         except :
            __data = dict()

      return __data

   def run_external_command (self, cmd) :
      pi, po, pe = os.popen3(cmd)

      return (pi, po, pe,)

/etc/hotplug_device.d/HHK_usb.py
import os, sys, pickle
import __BASIC_USB__

XMODMAP = "/usr/bin/X11/xmodmap"
MAPFILE_BASIC = "/usr/local/etc/xmodmap/basic"
MAPFILE_HHK = "/usr/local/etc/xmodmap/HHK"
MAPFILE_TP = "/usr/local/etc/xmodmap/TP"

class device (__BASIC_USB__.device) :

   KEY_PRODUCT = "PFU-65 USB Keyboard"
   KEY_MANUFACTURER = "Chicony"

   def check_add (self) :
      # if this attached device is keyboard and is HHK.
      if not self.PRODUCT == self.KEY_PRODUCT or \
            not self.MANUFACTURER == self.KEY_MANUFACTURER :
         return False

      return True

   def check_remove (self) :
      if not os.path.isfile(self.LOG_HOTPLUG_DEVICE) :
         return False

      __data = self.get_data()

      return self.DEVPATH in __data

   def add (self) :
      self.xmodmap(MAPFILE_BASIC)
      self.xmodmap(MAPFILE_HHK)

   def remove (self) :
      self.xmodmap(MAPFILE_BASIC)
      self.xmodmap(MAPFILE_TP)

   def xmodmap (self, mapfile) :
      self.run_external_command("/bin/su spike -c '%s -display :0.0 %s'" % (XMODMAP, mapfile))

위에서
MAPFILE_BASIC = "/usr/local/etc/xmodmap/basic"
MAPFILE_HHK = "/usr/local/etc/xmodmap/HHK"
MAPFILE_TP = "/usr/local/etc/xmodmap/TP"
라고 정의되어 있는 부분에서 MAPFILE_HHK은 HHK의 xmodmap을, MAPFILE_TP는 HHK를 사용하지 않을 경우 사용할 xmodmap 파일을, MAPFILE_BASIC은 두가지 모두 필요로 하는 부분을 넣도록 합니다. 위 스크립트에 나와있는 대로, MAPFILE_BASIC이 먼저 읽어들이기 때문에 MAPFILE_BASIC에는 MAPFILE_HHK, MAPFILE_TP가 모두 미리 읽어들이는 공통적인 설정을 지정하면 됩니다.

그리고 /etc/hotplug_device.d/HHK_usb.py의 마지막 부분
   def xmodmap (self, mapfile) :
      self.run_external_command("/bin/su spike -c '%s -display :0.0 %s'" % (XMODMAP, mapfile))
에서 spike를 X Window를 사용하는 사용자 id로 바꿔주면 됩니다. (사용자를 지정하지 않고 xmodmap을 지정할 수 있는 방법이 있으면 알려주세요.)

마지막으로
shell > chmod 700 /etc/hotplug.d/usb/usbhid.hotplug

4. 테스트,

위의 스크립트를 모두 제 위치에 갖다놓고, 이제 시험을 해봅니다. HHK를 usb에 붙이고 빼고를 반복하면서 원하는 키맵이 제대로 지정되는지 테스트해봅니다. 스크립트를 디버깅하기가 마뜩치 않긴 하지만, 문제가 될 만한 부분을 조금씩 수정해가면서 테스트해봅니다.

5. 파일들

@usbhid.hotplug.gz (392 Bytes)

@HHK_usb.py.gz (492 Bytes)

attachment:BASIC_USB.py.gz

@HHK.gz (210 Bytes)

@TP.gz (163 Bytes)

@basic.gz (56 Bytes)





sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-02-03 17:35:04
Processing time 0.0107 sec