Yuki Nakata's Blog

天才 中ちゃん♪

カテゴリ: Linux

lubuntu 16.10にGPU版tensorflowをインストールしてみました。ようやくできました。

NVIDIA GeForce 950M搭載PCにubuntuをインストールしてみた。

前回ubuntu16.04をインストールしました。

ところがnvidiaドライバを入れたところ、ログインループ問題に引っかかり解決できませんでした。w

永久にログインすらできなくなる糞仕様。

ubuntu16.04に見切りをつけて、最新のlubuntu16.10英語版をインストールしたところ大正解。

最新の環境をあっさり一発でセットアップできました。今までの苦労は何だったんだ。

軽量lubuntuにすると起動も軽快です。

環境構築だけで苦戦している人が多いようですが、tensorflowやディープラーニングを構築するならlubuntu16.10です。

一つずつ確認しながら進んで行きましょう。

環境 lubuntu16.10
GPU: GEFORCE 950M

lubuntuのダウンロード

$sudo apt-get update

$sudo apt-get upgrade

nvidiaドライバのインストール 
nvidiaの最新ドライババージョンは375です。

nvidia ドライバ
GPUを検索にかけるとバージョンがでてきます。恐らくみんな375なはずです。
ダウンロードボタンが出てきますが、クリックしません。apt-get からインストールします。

$sudo add-apt-repository ppa:graphics-drivers/ppa

$sudo apt-get update

$sudo apt install nvidia-375 nvidia-settings

$sudo apt install mesa-utils

再起動するとNVIDIA X Server Settingsがインストールされています。

GPUの使用状況を確認してみます。
$nvidia-smi
Fri Dec  9 10:08:43 2016      
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 375.20                 Driver Version: 375.20                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 950M    Off  | 0000:01:00.0     Off |                  N/A |
| N/A   40C    P0    N/A /  N/A |      0MiB /  2034MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                              
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

Cudaインストール
$sudo apt-get install nvidia-cuda-toolkit

Cuda 8.0がインストールされています。
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2016 NVIDIA Corporation
Built on Sun_Sep__4_22:14:01_CDT_2016
Cuda compilation tools, release 8.0, V8.0.44

cuDNNインストール
cuDNNとはディープラーニング用のライブラリです。

NVIDIA cuDNN
ログインして、cuDNN v5.1 Library for Linuxをダウンロードします。
$tar xzvf cudnn-8.0-linux-x64-v5.1.tgz
$ sudo cp -a cuda/lib64/* /usr/local/lib/
$ sudo cp -a cuda/include/* /usr/local/include/
$ sudo ldconfig

tensorflowのインストール
pythonはバージョン2.7と3.5の2つが入っています。2と3で互換性がないので両方入っています。
$python -V
Python 2.7.12+

$python3 -V
Python 3.5.2+

$sudo apt-get install python3-pip

$sudo pip3 install --upgrade pip

$export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-0.12.0rc0-cp35-cp35m-linux_x86_64.whl

$sudo pip3 install --upgrade $TF_BINARY_URL

exportの一行ですが、下のtensorflow.orgから貼り付けました。ubuntu64 bit, GPU enabled, python3.5
Download and Setup - TensorFlow

$ python3

>>> import tensorflow as tf
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcudnn.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:128] successfully opened CUDA library libcurand.so locally


>>> hello = tf.constant('hello tensorFlow!')
>>> sess = tf.Session()
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:936] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_device.cc:885] Found device 0 with properties:
name: GeForce GTX 950M
major: 5 minor: 0 memoryClockRate (GHz) 1.124
pciBusID 0000:01:00.0
Total memory: 1.99GiB
Free memory: 1.95GiB
I tensorflow/core/common_runtime/gpu/gpu_device.cc:906] DMA: 0
I tensorflow/core/common_runtime/gpu/gpu_device.cc:916] 0:   Y
I tensorflow/core/common_runtime/gpu/gpu_device.cc:975] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 950M, pci bus id: 0000:01:00.0)

これでGPU版tensorflowをインストールできました。

厳選リンク 参考にさせていただきました。
TensorFlow r0.9 (GPU版)を ubuntu16.04 にインストール


ついでに初期設定をしておきましょう。
google chromeのインストール

$wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

$sudo dpkg -i google-chrome*.deb

$sudo apt-get install -f

$google-chrome

windowsとubuntu マルチブートにしていると時刻がずれるのを直す

$sudo timedatectl set-local-rtc 1

lubuntuの日本語化

昔私が書いたブログ
Elementary OS 初期設定2 日本語入力 Japanese Input

変更点が一つあります。
zenityというパッケージを追加インストールします。
$sudo apt-get install zenity

パッケージをインストールし終わったらスタートメニューからSettings(設定) -> Language Support(言語サポート)
日本語を一番下から一番上に引っ張ります。

$fcitx-setup-helper

ログアウトし直すと半角/全角キーを押すと日本語入力できるようになります。

product_img_mbk630
3カ月くらい前にマウスコンピュータでノートPCを買いました。

MB-K670XN-SH2というモデルです。

グラフィックスカードGeForce® GTX 950M(2GB)を搭載しています。

CUDAに対応していて、GPU版tensorFlowが利用できるということでやってみようとなったんですが、とてつもなく大変でした。

GPUのCUDAサポート CUDA | Supported GPUs | GeForce 

どハマリしたポイントを書いていきます。
 
まずlinuxを直接インストールしなければいけません。

virtualBoxのようなバーチャルではnvidiaのドライバがインストールできません。

MBRをイジリたくはないんだけれど、しょうがない。

参考サイト
Ubuntu16.04 + Windows10 のデュアルブート環境を構築する

Windows10とUbuntuのデュアルブートをやってみた話

この2つのサイトが役に立ちました。まずは正しい情報なのでやってみましょう。

私の場合はうまくいきませんでした。笑

ここから先はうまくいかなかった人向けです。

USBメモリーからubuntuをインストールできましたが、再起動するとlinuxが起動しません。

ディスプレイが真っ黒なまま停止します。

おかしいな、と思い一旦linuxの全領域を削除。

再インストールしようとしたのですが、今度はインストールができなくなりました。

ubuntuのロゴ表示で停止します。

途方に暮れていて見つけたのが次のサイト。

nVidiaのGPU搭載PCにUbuntuを入れようとしてハマった 

ここで原因が判明しました。

nVidiaのGPUを搭載しているとlinuxが起動しない、という問題があるようです。

解決方法はgrubでカーネルに渡すパロメータを変更します。

grubの画面で「e」を押し、編集モードに入り、

「quiet splash」を 「nomodeset」へ変更します。これで解決!。

オプションの意味は
nomodeset 起動時にいわゆるdmesgをディスプレイに表示。これが正解。

quiet splash dmesgを非表示にして、ubuntuのロゴを表示、見栄えを良くする。

良くわからんが、quiet splashにするとnvidiaのgpuに引っ掛かるようです。



インストールし終わったら、/etc/default/grubを直接編集します。

同じように「quiet splash」を 「nomodeset」へ変更し、

#sudo update-grub

でgrubを更新することができます。 

これで無事ubuntu16.04をインストールできるようになりました。 

マウスをカスタマイズしよう linux編の続きです。

実はゲームパッド Elecom F310についてずっと考えていました。笑

マウス同様ジョイパッドをカスタマイズしましょう。なんとかプログラムもできました。

ゲームパッドをマウスみたいにします。

前回同様にUSB接続を調べます。
$ cat /proc/bus/input/devices
I: Bus=0003 Vendor=1bcf Product=0005 Version=0110
N: Name="USB Optical Mouse"
P: Phys=usb-3f980000.usb-1.2/input0
S: Sysfs=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/0003:1BCF:0005.0001/input/input0
U: Uniq=
H: Handlers=mouse0 event0 
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0 0 0 0 0
B: REL=143
B: MSC=10

I: Bus=0003 Vendor=0d62 Product=8070 Version=0111
N: Name="ELECOM Wired Keyboard"
P: Phys=usb-3f980000.usb-1.4/input0
S: Sysfs=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:0D62:8070.0002/input/input1
U: Uniq=
H: Handlers=sysrq kbd leds event1 
B: PROP=0
B: EV=120013
B: KEY=10000 7 ff9f207a c14057ff febeffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=1f

I: Bus=0003 Vendor=046d Product=c21d Version=4014
N: Name="Logitech Gamepad F310"
P: Phys=usb-3f980000.usb-1.3/input0
S: Sysfs=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/input/input3
U: Uniq=
H: Handlers=event3 js0 
B: PROP=0
B: EV=20000b
B: KEY=7cdb0000 0 0 0 0 0 0 0 0 0
B: ABS=3003f
B: FF=1 7030000 0 0

私の環境ではマウスがevent0 キーボードがevent1, ゲームパッドがevent3です。
マウスが/dev/input/event0,
キーボードが /dev/input/event1
ゲームパッドが/dev/input/event3 となります。

次にゲームパッドのボタンの割り当てを調べます。

//input2.c
//ゲームパッド入力を調べるプログラム
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define GAMEPAD_EVENT "/dev/input/event3"
#define MOUSE_EVENT "/dev/input/event0"

int gamepadfd;
int mousefd;

int main(void)
{
gamepadfd = open(GAMEPAD_EVENT, O_RDWR);
mousefd = open(MOUSE_EVENT, O_RDWR);
  for (;;) {
    struct input_event event;

    if (read(gamepadfd, &event, sizeof(event)) != sizeof(event)) {
      exit(EXIT_FAILURE);
    }
    switch(event.type) {
      case EV_KEY:
printf("type:%x  code:%x value:%x\n", event.type, event.code, event.value);
        break;
      case EV_REL:
printf("type:%x  code:%x value:%x\n", event.type, event.code, event.value);
break;
case EV_ABS:
printf("type:%x  code:%x value:%x\n", event.type, event.code, event.value);
break;
      default:
 
        break;
    }
    fflush(stdout);
  }
  
  close(gamepadfd);
  close(mousefd);
}
ゲームパッドを適当に押すと数字が表示されますので、/usr/include/linux/input.hとにらめっこして調べます。

chrome用にゲームパッドを次のようにカスタマイズします。


プログラムの説明
前回のプログラムと同じような仕組みです。
十字キーと十字スティックはシグナルを使ってポーリングしています。つまり毎回入力されていないかデータを取得しにいっています。ぶさいくですがそれしかできませんでした。

要するにゲームパッドからマウスやキーボードにデータ変換しているだけです。変換する箇所が多いのでごちゃごちゃしています。だいぶ試行錯誤しました。

//gamepad.c
//ゲームパッドをchromeブラウザ用にカスタマイズするプログラム
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <string.h>
#include <signal.h>

//ここでマウスとキーボードとゲームパッドのイベントを設定してください。
#define MOUSE_EVENT "/dev/input/event0"
#define KEYBOARD_EVENT "/dev/input/event1"
#define GAMEPAD_EVENT "/dev/input/event3"

#define die(str, args...) do { perror(str); exit(EXIT_FAILURE); } while(0)

typedef struct _GamepadMouseState GamepadMouseState;
struct _GamepadMouseState 
{
  __s32 vx, vy;
  int wheelvalue;
  int wheeldirection;
};

static GamepadMouseState state;
static struct itimerval itimerval;
static struct itimerval old_itimerval;
static struct itimerval htimerval;
static struct itimerval old_htimerval;

int keyboardfd;
int gamepadfd;
int virtualfd;
int mousefd;
int i;



//イベントを発生させる関数
void send_event(int output, int type, int code, int value)
{
  struct input_event event;
  if (mousefd < 0) {
    return;
  }

  event.type = type;
  event.code = code;
  event.value = value;
  gettimeofday(&event.time, NULL);
write(output, &event, sizeof(event));
}

//ゲームパッドのホイール移動
void wheel_handler()
{
//printf("wheel :%x  \n", state.wheelvalue);
if(state.wheeldirection == 0)
return;
send_event(mousefd, EV_REL, ABS_WHEEL, state.wheeldirection);
send_event(mousefd, EV_SYN, SYN_REPORT, 0);
}

//ゲームパッドの十字キーの状態を取得し、マウス移動させる
void alarm_handler(int signum)
{
if((i % 25) == 0) {
wheel_handler();
}
i++;
if(i > 5000)
i = 0;
  if (state.vx == 0 && state.vy == 0 ) {
    return;
  }
  if (state.vx!= 0) {
    send_event(mousefd, EV_REL, REL_X, state.vx);
  }

  if (state.vy!= 0) {
    send_event(mousefd, EV_REL, REL_Y, state.vy);
  }
}



//シグナルを設定する 2000マイクロ秒毎にalarm_handlerを実行する
void init_event_handler()
{
  itimerval.it_value.tv_sec = 0;
  itimerval.it_value.tv_usec = 2000;
  itimerval.it_interval.tv_sec = 0;
  itimerval.it_interval.tv_usec = 2000;
  signal(SIGALRM, alarm_handler);
  setitimer(ITIMER_REAL, &itimerval, &old_itimerval);
}


int main(void)
{
mousefd = open(MOUSE_EVENT, O_RDWR);
gamepadfd = open(GAMEPAD_EVENT, O_RDWR);
keyboardfd = open(KEYBOARD_EVENT, O_RDWR);
init_event_handler();
//ゲームパッドを無効化
ioctl(gamepadfd, EVIOCGRAB, 1);
  for (;;) {
    struct input_event event;

    if (read(gamepadfd, &event, sizeof(event)) != sizeof(event)) {
      exit(EXIT_FAILURE);
    }
    //printf("type:%x  code:%x value:%x\n", event.type, event.code, event.value);
    switch(event.type) {
case EV_KEY:
if(event.code == BTN_X) {
send_event(mousefd, EV_KEY, BTN_MOUSE, event.value);
send_event(mousefd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_Y) {
send_event(mousefd, EV_KEY, BTN_MIDDLE, event.value);
send_event(mousefd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_A) {
send_event(keyboardfd, EV_KEY, KEY_LEFTCTRL, event.value);
send_event(keyboardfd, EV_KEY, KEY_W, event.value);
send_event(keyboardfd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_B) {
send_event(mousefd, EV_KEY, BTN_RIGHT, event.value);
send_event(mousefd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_TL) {
send_event(keyboardfd, event.type, KEY_LEFTCTRL, event.value);
send_event(keyboardfd, event.type, KEY_T, event.value);
send_event(keyboardfd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_TR) {
send_event(keyboardfd, event.type, KEY_LEFTCTRL, event.value);
send_event(keyboardfd, event.type, KEY_TAB, event.value);
send_event(keyboardfd, EV_SYN, SYN_REPORT, 0);
}
break;
      case EV_ABS:
//printf("type:%x  code:%x value:%x\n", event.type, event.code, event.value);
if(event.code == ABS_HAT0Y) {//上下ボタンを押したとき
state.vy = event.value;
}else if(event.code == ABS_HAT0X) {//左右ボタンを離したとき
state.vx = event.value;
}else if(event.code == ABS_RY) {//ホイール上下
//printf("type:%x  code:%x value:%d\n", event.type, event.code, event.value);
if(event.value > 10000) {
state.wheeldirection = 0xffffffff;
} else if(-8000 < event.value && event.value < 8000){
state.wheeldirection = 0;
}else {
state.wheeldirection = 1;
}
state.wheelvalue = event.value;
//send_event(mousefd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == ABS_RX) {
}else {
}
        break;
      case EV_REL:
break;
 
      default:
        break;
    }
    fflush(stdout);
  }
  
  //ゲームパッドを有効に戻す
  ioctl(gamepadfd, EVIOCGRAB, 0);
  
  close(keyboardfd);
  close(gamepadfd);
  close(virtualfd);
}


$ gcc -o gamepad gamepad.c
$ sudo ./gamepad

 

windowsの次はlinuxでマウスをカスタマイズします。

プログラムを作って、マウスを乗っ取ります。 

仕組みが分かれば簡単にプログラムで作ることができます。

なぜならlinuxはすべてファイル扱いで、 マウスもキーボードもゲームパッドもファイルだからです。

openして、readしてwriteすればいいわけです。

自由自在にカスタマイズできてしまいます。

たとえば、マウスを左クリックするとキーボードのAと入力させることもできます。

ですからゲームパッドをマウス替わりにカスタマイズすることもでてきしまうわけです。

この仕組みがわかればキーロガーも作れてしまいます。

まずはUSBに接続されているデバイスを調べます。
pi@raspberrypi:~ $ cat /proc/bus/input/devices
 
I: Bus=0003 Vendor=1bcf Product=0005 Version=0110
N: Name="USB Optical Mouse"
P: Phys=usb-3f980000.usb-1.2/input0
S: Sysfs=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/0003:1BCF:0005.0001/input/input0
U: Uniq=
H: Handlers=mouse0 event0 
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0 0 0 0 0
B: REL=143
B: MSC=10

I: Bus=0003 Vendor=0d62 Product=8070 Version=0111
N: Name="ELECOM Wired Keyboard"
P: Phys=usb-3f980000.usb-1.4/input0
S: Sysfs=/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:0D62:8070.0002/input/input1
U: Uniq=
H: Handlers=sysrq kbd leds event1 
B: PROP=0
B: EV=120013
B: KEY=10000 7 ff9f207a c14057ff febeffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=1f

私の場合はこんなかんじ。

マウスとキーボードが認識されています。重要なのはHandlersのeventです。マウスがevent0, キーボードがevent1です。これを記憶しておきます。先ほどのファイルというのがこれです。

マウスは/dev/input/event0, キーボードは/dev/input/event1に対応しています。

試しにマウスを監視してみましょう。
$hexdump /dev/input/event0

同様にキーボード
$hexdump /dev/input/event1

マウスやキーボードの定義は/usr/include/linux/input.hにされています。ここを開いてみてください。

キーボード系
#define KEY_Q                   16 キーボードのQ
#define KEY_W                   17 キーボードのW
#define KEY_E                   18
#define KEY_R                   19
#define KEY_T                   20

マウス系
#define BTN_LEFT                0x110 マウスの左クリック
#define BTN_RIGHT               0x111 マウスの右クリック 
#define BTN_MIDDLE              0x112 マウスのホイールクリック
こんなかんじでずらっと登録されています。

マウスやキーボードの入力があるとイベントが発生します。その構造体も定義されています。
struct input_event {
        struct timeval time;
        __u16 type;
        __u16 code;
        __s32 value;
};

event.type
  EV_KEY マウスやキーボードがクリックされたとき
  EV_REL マウスの位置移動、ホイールが回転したとき
event.code
  左クリックやらキーボードの入力キー
event.value
 1: キーを押したとき、 0: キーを離したとき
 他の数字 移動量

では早速マウスボタンを調べてみましょう。
input.c
//マウス入力を調べるプログラム
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int keyboardfd;
int mousefd;

int main(void)
{
  mousefd = open("/dev/input/event0", O_RDWR);
  keyboardfd = open("/dev/input/event1", O_RDWR);
  for (;;) {
    struct input_event event;

    if (read(mousefd, &event, sizeof(event)) != sizeof(event)) {
      exit(EXIT_FAILURE);
    }
    switch(event.type) {
      case EV_KEY:
printf("code:%x  value:%x\n", event.code, event.value);
        break;
      case EV_REL:
//printf("rel:%x  ", event.code);
break;
  case EV_ABS:
//printf("abs:%x  ", event.code);
break;
      default:
 
        break;
    }
    fflush(stdout);
  }
  
  close(keyboardfd);
  close(mousefd);
}
$gcc -o input input.c
 
pi@raspberrypi:~/Documents $ sudo ./input
code:110  value:0
code:112  value:1
code:110  value:1
code:112  value:0
code:114  value:1
code:114  value:0
code:113  value:1
code:113  value:0
code:110  value:1
code:110  value:0

110だから左クリックだなとか、value 1は押したとき、value 0は離したとき。
判明したのが次のとおり。カスタマイズの内容も書いておきました。


 で、ここからが少しやっかい。
BTN_EXTRAをCTRL + Wにすると、
BTN_EXTRA + CTRL + Wになってしまいます。 
つまり、BTN_EXTRAとBTN_SIDEの機能を無効にしたいのです。

結論を書くとマウスを無効にし、User Inputという仮想デバイスでマウス機能を再登録します。

ちなみにマウスを無効にするのはたった1行
ioctl(マウスちゃん, EVIOCGRAB, 1);

マウスを元に戻すのも1行
ioctl(マウスちゃん, EVIOCGRAB, 0);

あとはUser Inputでマウス機能を登録すればできあがりです!
コメントを書いておくのでプログラムを読んでください。

5mouse.c
//マウスをchromeブラウザ用にカスタマイズするプログラム
//サイドボタンを
//現在のタブを閉じる Ctrl+w
//開いている次のタブに移動する Ctrl+Tab 
//に設定する
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <string.h>

//ここでマウスとキーボードのイベントを設定してください。
#define MOUSE_EVENT "/dev/input/event0"
#define KEYBOARD_EVENT "/dev/input/event1"


#define die(str, args...) do { perror(str); exit(EXIT_FAILURE); } while(0)

int keyboardfd;
int mousefd;
int virtualfd;

void create_uinput_device (int fd) {
  struct uinput_user_dev uidev;
  memset(&uidev, 0, sizeof(uidev));

  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "YUKIMOUSE");
  uidev.id.bustype = BUS_USB;
  uidev.id.vendor  = 0xAAAA;
  uidev.id.product = 0xBBBB;
  uidev.id.version = 1;

  if (write(fd, &uidev, sizeof(uidev)) < 0)
    die("create_uinput_device: write");

  if (ioctl(fd, UI_DEV_CREATE) < 0)
    die("create_uinput_device: ioctl");
}

void send_event(int output, int type, int code, int value)
{
  struct input_event event;

  event.type = type;
  event.code = code;
  event.value = value;
  gettimeofday(&event.time, NULL);
write(output, &event, sizeof(event));
}

int main(void)
{
mousefd = open(MOUSE_EVENT, O_RDWR);
keyboardfd = open(KEYBOARD_EVENT, O_RDWR);
virtualfd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
//マウス機能を登録し、User Inputデバイスを作成する
//ここで左クリックを有効にするよーとか、マウス動かすよーとか登録
ioctl(virtualfd, UI_SET_EVBIT, EV_REL);
ioctl(virtualfd, UI_SET_RELBIT, REL_X);
ioctl(virtualfd, UI_SET_RELBIT, REL_Y);
ioctl(virtualfd, UI_SET_RELBIT, REL_WHEEL);
ioctl(virtualfd, UI_SET_EVBIT, EV_KEY);
ioctl(virtualfd, UI_SET_KEYBIT, BTN_LEFT);
ioctl(virtualfd, UI_SET_KEYBIT, BTN_RIGHT);
ioctl(virtualfd, UI_SET_KEYBIT, BTN_MIDDLE);
create_uinput_device(virtualfd);
//マウスを無効化
ioctl(mousefd, EVIOCGRAB, 1);
  for (;;) {
    struct input_event event;

    if (read(mousefd, &event, sizeof(event)) != sizeof(event)) {
      exit(EXIT_FAILURE);
    }
    switch(event.type) {
      case EV_KEY:
if(event.code == BTN_EXTRA && event.value == 1) {//EXTRAボタンを押したときCTRL + W
send_event(keyboardfd, event.type, KEY_LEFTCTRL, 1);
send_event(keyboardfd, event.type, KEY_W, 1);
send_event(keyboardfd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_EXTRA && event.value == 0) {//EXTRAボタンを離したとき
send_event(keyboardfd, event.type, KEY_W, 0);
send_event(keyboardfd, event.type, KEY_LEFTCTRL, 0);
send_event(keyboardfd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_SIDE && event.value == 1) {//SIDEボタンを押したとき CTRL + TAB
send_event(keyboardfd, event.type, KEY_LEFTCTRL, 1);
send_event(keyboardfd, event.type, KEY_TAB, 1);
send_event(keyboardfd, EV_SYN, SYN_REPORT, 0);
}else if(event.code == BTN_SIDE && event.value == 0) {//SIDEボタンを離したとき
send_event(keyboardfd, event.type, KEY_TAB, 0);
send_event(keyboardfd, event.type, KEY_LEFTCTRL, 0);
send_event(keyboardfd, EV_SYN, SYN_REPORT, 0);
}else {
send_event(mousefd, event.type, event.code, event.value);
}
        break;
      case EV_REL:
//printf("%x  ", event.code);
send_event(mousefd, event.type, event.code, event.value);
break;
case EV_ABS:
send_event(mousefd, event.type, event.code, event.value);
break;
      default:
send_event(mousefd, event.type, event.code, event.value);
//printf("0");
        break;
    }
    fflush(stdout);
  }
  
  //マウスを有効に戻す
  ioctl(mousefd, EVIOCGRAB, 0);
  
  close(keyboardfd);
  close(mousefd);
  close(virtualfd);
}


一応マウスを無効にするので注意が必要かと
$gcc -o 5mouse 5mouse.c 
$sudo ./5mouse

思っていたようにマウスをカスタマイズすることができました。
あとはスクリプトを作るなり、起動時に自動実行すればいいかと思います。

参考サイト 超絶素晴らしいサイトです。
Linux Input Subsystemの使い方

特定のキーボードを ESC 入力のためのフットペダルにする 
サンプルプログラムが分かりやすいです。 

ゲームパッドをカスタマイズしよう linux編 に続きます。

linuxにプログラマー用のフォントM+をインストールしよう

M+はシンプルで見やすい。これでいいです。

もう面倒くさいのでそのままそっくりコピペしておきます。


$sudo mkdir -p /usr/share/fonts/truetype/mplusipa

$wget http://jaist.dl.sourceforge.jp/mix-mplus-ipa/25997/mixfont-mplus-ipa-TrueType-20060520p1.tar.bz2

$tar jvxf mixfont-mplus-ipa-TrueType-20060520p1.tar.bz2

$cd mixfont-mplus-ipa-TrueType-20060520p1/opfc-ModuleHP-1.1.1_withIPAFonts_and_Mplus/fonts

$sudo cp *.ttf /usr/share/fonts/truetype/mplusipa

$sudo fc-cache -v  *.ttf

$sudo mkfontdir

$xset xp rehash

$fc-list


これでフォントのインストールの仕方も理解できました。

/usr/share/fonts/ 以下にttfをぶっこんで、登録すればいいんですね。


参考サイト
Ubuntu Linux 8.04 

Cub Linuxをインストールしました。

chrome + ubuntu でcub linuxです。

cub linux
 ここからダウンロードできます。
Screenshot from 2016-02-05 11:21:41
マウスポインタが指しているアイコンをクリックでインストール。

後はUbuntuのインストールと同じです。Englishでインストールします。
Screenshot from 2016-02-05 20:48:45
インストール後に日本語にします。

Elementary OS 初期設定2 日本語入力 Japanese Input  <-- 全く同じ方法で日本語になります。ご参考に

デフォルトでChromeやFlashが入っていますので、いきなりYoutubeが利用できます。

あとguest additionsをインストールしなくてもフルスクリーンになります。

Linuxのデスクトップも魅力的になってきたと思います。

非常に気に入りました。アイコンもフラットデザインでスマホっぽいです。

Elementary OS やlubuntuからcub linuxへと乗り換えました。

2016年はこれで行きます。

↑このページのトップヘ