yumetodoの旅とプログラミングとかの記録

旅や登山の記録やプログラミング関連の話とかフリーソフト紹介とか

NKT(長く苦しい戦い)であったデュアルブート環境でbluetoothマウスを動くようにすることに成功ス!

はじめに

yumetodo.hateblo.jp

yumetodo.hateblo.jp

yumetodo.hateblo.jp

yumetodo.hateblo.jp

2018年、家のあまりにも操作性の良くない有線マウスをリストラするべく購入したBluetooth接続のマウス。

ところがデュアルブート環境である我が家では安定的に接続することができずにいた。

Ubuntuのバージョンは16.04から18.04を経て20.04にまでなった。

転機

2020年8月23日、GolangVim界隈で知らない人はいない@mattn_jp氏のふとしたツイートがきっかけとなった。

紹介の合った記事がこちら。

orumin.blogspot.com

試す

このころは別件で忙しく、またcovid19研究加速のためにrosetta homeを回してるのであんま再起動したくないとか理由をつけて先延ばしにしていたが、重い腰を上げてついに試してみることにした。

Ubuntuにて

まずchntpwを導入する。レジストリを閲覧するのに必要だ。

$sudo apt install chntpw

BluetoothマウスをGUIなどからペアリングする

Windowsにて

PC再起動してWindowsを起動する

BluetoothマウスをGUIなどからペアリングする

管理者権限powershellを立ち上げてハイバネーションを切る

powercfg.exe /hibernate off
再びUbuntuにて

PC再起動してUbuntuを立ち上げる

nautilusなどからWindowのCドライブをマウントする

Bluetoothインターフェイス(ようはPCについたチップ)のIDを調べる

$bluetoothctl
Agent registered
[CHG] Controller A4:C3:F0:88:90:45 Pairable: yes
[ELECOM BlueLED Mouse]# exit

A4:C3:F0:88:90:45だった。

次のようにしてレジストリを閲覧する

$chntpw -e /media/yumetodo/4C7E6CE87E6CCC70/Windows/System32/config/SYSTEM
chntpw version 1.00 140201, (c) Petter N Hagen
Hive </media/yumetodo/4C7E6CE87E6CCC70/Windows/System32/config/SYSTEM> name (from header): <SYSTEM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 686c <lh>
File size 24379392 [1740000] bytes, containing 5276 pages (+ 1 headerpage)
Used for data: 372635/23536872 blocks/bytes, unused: 87/38808 blocks/bytes.

Simple registry editor. ? for help.

>          

> ls 
Node has 17 subkeys and 0 values
  key name
  <ActivationBroker>
  <ControlSet001>
  <DriverDatabase>
  <HardwareConfig>
  <Input>
  <Keyboard Layout>
  <Maps>
  <MountedDevices>
  <ResourceManager>
  <ResourcePolicyStore>
  <RNG>
  <Select>
  <Setup>
  <Software>
  <State>
  <WaaS>
  <WPA>      

> cd ControlSet001

\ControlSet001> cd Service\BTHPORT

\ControlSet001\Services\BTHPORT> cd Parameters\Keys

(...)\Services\BTHPORT\Parameters\Keys> ls
Node has 2 subkeys and 0 values
  key name
  <001bdc0f6618>
  <a4c3f0889045>

(...)\Services\BTHPORT\Parameters\Keys> cd a4c3f0889045

(...)\BTHPORT\Parameters\Keys\a4c3f0889045> ls
Node has 0 subkeys and 1 values
  size     type              value name             [value if type DWORD]
    16  3 REG_BINARY         <c8478227da53>

(...)\BTHPORT\Parameters\Keys\a4c3f0889045> hex c8478227da5.
cat_vk: No such value <c8478227da5.>

(...)\BTHPORT\Parameters\Keys\a4c3f0889045> hex c8478227da53
Value <c8478227da53> of type REG_BINARY (3), data length 16 [0x10]
:00000  08 57 94 6B D5 43 8B 13 30 0E 90 A8 1B 43 ED C7 .W.k.C..0....C..

ControlSet001ControlSet002の中をみる。大抵はControlSet001らしい。そこから\Services\BTHPORT\Parameters\Keysと辿るとbluetoothインターフェイスのIDが列挙されている。目的のIDの中にはマウスのIDの値があるので、hexでバイナリデータを閲覧する。今回は0857946BD5438B13300E90A81B43EDC7であった。

あとはUbuntu側のbluetoothの設定を書き換える。

$sudo nano "/var/lib/bluetooth/A4:C3:F0:88:90:45/C8:47:82:27:DA:53"/info
[General]
Name=ELECOM BlueLED Mouse
Class=0x000580
SupportedTechnologies=BR/EDR;
Trusted=true
Blocked=false
Services=00001000-0000-1000-8000-00805f9b34fb;00001124-0000-1000-8000-00805f9b34fb;00001200-0000-1000-8000-00805f9b34fb;

[LinkKey]
Key=0857946BD5438B13300E90A81B43EDC7
Type=4
PINLength=0

[DeviceID]
Source=2
Vendor=1390
Product=229
Version=297

LinkKeyの中のKeyをさっきのhexで調べた値に書き換える。

終わったらbluetoothを再起動する

$sudo systemctl restart bluetooth
再びWindowsにて

管理者権限powershellを立ち上げてハイバネーションを有効に。切りっぱなしはスリープ周りの挙動への影響が無視できないのでね。

powercfg.exe /hibernate on

まとめ

マウスがうごく!すばらしい!

#covid19 への政治的対応に思うこと

はじめに

この記事は別に政府・都に物申す!みたいな意識高そうなことを目的とはしていない。今自分がどう思っていたかを後で振り返られるように記録する記事だ。

3.11原発事故と今回の政府の対応にみる共通点

3.11原発事故では、原子力発電に対する規制を担うブレーキ役たる原子力保安院と、原子力発電推進を担うアクセル役の資源エネルギー庁が並列どころかアクセル役の傘下にブレーキ役がいるという状態になっていた。これが原発事故時に指摘された問題で、後に原子力規制庁として独立して一応の解決をみた。

今回、新型コロナウィルス感染症対応はどうだったか。当初こそ厚生労働省や政府の専門家会議を中心として進んだが、経済的打撃が現実味を帯びるやいなや、専門家会議は解散、感染症対策はなぜか経済再生担当相が旗をふるという状態になった。アクセル役がブレーキ役を期待されるという点において原子力保安院よりさらにひどいと言える。

彼らは3.11から何を学んだのだろうか。

リーダーシップを取れない菅総理

president.jp

やたらと「思います」と強調することが指摘されているが別にそんなことがリーダーシップのなさの根本要因ではない。野党あたりは春の緊急事態宣言くらいから言っていたような必要な対策ができず、挙句の果てに与野党間の調整などと言っていることに、リーダーシップのなさが透けているのだ。

責任の押し付け合いをする都と国

bunshun.jp

すかさず文集砲がでているが、責任を取りたがらない菅総理小池都知事は迷走し続けている。まあ小池都知事の成立過程からして政府与党との関係性が良かろうはずもないといえばそうだが、この緊急時においてもまだ派閥次元の政治抗争をやってるのかとあきれてしまう。

準備不足の緊急事態宣言

1度目の緊急事態宣言からあれだけ時間があったのに、準備不足とはどういうことなのか。休業要請をする店舗・関係企業への保証は1度目からほんの少しだけ改善したが、不十分にすぎる。休業要請と保証はセットという言葉を1度目は無視できたが、2度めは無視しきれないのか時短でもいいという中途半端な中身に後退してしまった。

人の動きを止めれば感染は止まることは明確にわかっているのに、1度目より後退してどうするんだ。人の動きを止めれば経済がとまる?それは正しい。だから政府が、お金をその気になれば(信用が創造できる範囲において)作ることができる政府が、切れ目のない保証をする。そうしなければならなかったのに。各店舗の営業規模であるとかを把握しなければならない細かな対策は、1度目のあの時期に間に合わないのは仕方がないかもしれない。でもあれから何ヶ月たったのだろう。仕方ないと養護する余地はない。

Go to キャンペーン

経済対策という観点だけみれば非常にいい政策といえる。国が直接お金を配るよりも人を動かしてお金を使わせるほうがはるかに効率的な経済対策となる。そういう対策がリーマン・ショックのときに欲しかった。

しかし人が動くというのはそれだけで感染症対策と逆行する。時期尚早にすぎる。後に『65歳以上の高齢者と基礎疾患のある人に利用自粛を呼びかける』と後退したが、キャリアーとなり二次感染させるのは高齢者ではなかった。この的はずれな対策は現在の感染者数となって現れている。

今後の感染症対策

済んだ話はもういい。過去には戻れない。我が国は医療従事者のみなさんが感染者が少なかった秋に必死に稼いだ余力を早々にただただ無策に使い果たした。すでに医療現場は崩壊していて救急搬送は3時間を超えることある。崩壊してからでた緊急事態宣言、どうにか中身を強化し人の動きを止めなければならない。今日も両親は普通に出勤していくがそれは普通に考えておかしい。リモートワークできる業種が出勤をやめないでどうするのだ。

C++erらしくRAIIしつつmmap

teratail.com

に回答するために、mmapを調べていたら

nnabeyang.hatenablog.com

という記事を見つけたのだが、これはCで書かれているのでC++から使うためにラップした。

どうもWindowsの場合は上述ブログ中のget_filecontentで開いてclose_mapで閉じるらしい。このときget_filecontentで得たmap領域へのポインタとハンドル両方いるのだそう。
unixではget_filecontentで開いてmunmapで閉じるらしい。このときget_filecontentで得たmap領域へのポインタとサイズがいるらしい。

というわけでこれをRAII技法を使ってラップした。

なおついでに

  • C++にはvoid*から任意のポインタへの暗黙変換はないのでキャストが必要
  • キャストはstatic_castを使う

などした。

#ifndef YUMETODO_MMAP_HPP_
#define YUMETODO_MMAP_HPP_
// ref: http://nnabeyang.hatenablog.com/entry/20110620/1308560702
#include <cstdint>
#include <cassert>
#ifdef OS_WINDOWS
#include <stdio.h>
#include <windows.h>
#else

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>

#endif

#ifdef OS_WINDOWS
namespace impl{
std::size_t get_filecontent(char** buf, const char* fpath, HANDLE* map_handle) noexcept {
  unsigned int mode1, mode2, mode3, mode4;
  mode1 = GENERIC_READ;
  //assert(0x80000000 == mode1);
  mode2 = PAGE_READONLY;
  mode3 = FILE_MAP_READ;
  mode4 = FILE_SHARE_READ;
  wchar_t fname[80];
  int len;
  char* p = fpath;
  int i = 0;
  while(*p != '\0')  {
    mbtowc(&fname[i++], p, MB_CUR_MAX);
    p++;
  }
  fname[i] = '\0';
  HANDLE handle = CreateFileW(fname, mode1, mode4, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if(handle == INVALID_HANDLE_VALUE) {
    fprintf(stderr, "file open failed\n");
    exit(1);
  }
  auto size = GetFileSize(handle, 0);
  assert(size >= 0);
  *map_handle = CreateFileMapping(handle, 0, mode2, 0, 0, 0);
  *buf = static_cast<char*>(MapViewOfFile(*map_handle, mode3, 0, 0, 0));
  if(handle != INVALID_HANDLE_VALUE) {
    CloseHandle(handle);
    handle = INVALID_HANDLE_VALUE;
  }
  return std::size_t(size);
}

void close_map(char** inp, HANDLE* map_handle) noexcept {
  UnmapViewOfFile(*inp);
  if(*map_handle != INVALID_HANDLE_VALUE) {
    CloseHandle(*map_handle);
    *map_handle = INVALID_HANDLE_VALUE;
  }
  *inp_ = NULL;
}
}
class mmap_handle {
  char *inp_;
  std::size_t size_;
  HANDLE map_handle_;
public:
  mmap_handle(const char* fpath) noexcept {
    this->size_ = impl::get_filecontent(&inp_, fpath, &map_handle_);
  }
  ~mmap_handle() noexcept {
    impl::close_map(&inp_, &map_handle_);
  }
  char* get() noexcept;
  const char* get() const noexcept;
  std::size_t size() const noexcept;
  char* begin() noexcept;
  const char* begin() const noexcept;
  const char* cbegin() const noexcept;
  char* end() noexcept;
  const char* end() const noexcept;
  const char* cend() const noexcept;
};
#else
namespace impl{
std::size_t get_filecontent(char** buf, const char* fpath) noexcept {
  int fd = open(fpath, O_RDONLY);
  assert(fd > 0);
  struct stat st;
  assert(fstat(fd, &st) >= 0 && st.st_size >= 0);
  const auto re = std::size_t(st.st_size);
  *buf = static_cast<char*>(mmap(NULL, re, PROT_READ, MAP_PRIVATE, fd, 0));
  close(fd);
  return re;
}
}
class mmap_handle {
  char *inp_;
  std::size_t size_;
public:
  mmap_handle(const char* fpath) noexcept {
    this->size_ = impl::get_filecontent(&inp_, fpath);
  }
  ~mmap_handle() noexcept {
    munmap(inp_, size_);
  }
  char* get() noexcept;
  const char* get() const noexcept;
  std::size_t size() const noexcept;
  char* begin() noexcept;
  const char* begin() const noexcept;
  const char* cbegin() const noexcept;
  char* end() noexcept;
  const char* end() const noexcept;
  const char* cend() const noexcept;
};
#endif
inline char* mmap_handle::get() noexcept { return this->inp_; }
inline const char* mmap_handle::get() const noexcept { return this->inp_; }
inline std::size_t mmap_handle::size() const noexcept { return this->size_; }
inline char* mmap_handle::begin() noexcept { return this->inp_; }
inline const char* mmap_handle::begin() const noexcept { return this->inp_; }
inline const char* mmap_handle::cbegin() const noexcept { return this->inp_; }
inline char* mmap_handle::end() noexcept { return this->inp_ + this->size_; }
inline const char* mmap_handle::end() const noexcept { return this->inp_ + this->size_; }
inline const char* mmap_handle::cend() const noexcept { return this->inp_ + this->size_; }
#endif //YUMETODO_MMAP_HPP_

使用例は

wandbox.org