参照: Ubuntu 日本語フォーラム - サスペンドから復帰後キーボードが認識されません
Ubuntuに限らず、Arch Linuxなどの他ディストリビューションでもこの問題が発生します。 (i8042に関する問題ですが、他のi8042搭載マシンでは問題ないらしく、CF-S10シリーズのみ発生します。)
カーネルのドライバを書き換えてビルドしなおせば対策できますが、アップデートの度に自分で書き換えるのはあまりにも面倒です。
(ちなみに先日、東京で学会発表する機会があって CF-S10を持っていったのですが、何日か前にカーネルのアップデートをしてから再起動せずにサスペンドして使っていたところ、この問題の影響で一部デバイスが認識されなくなり焦りましたw)
...ということで...ちょっと今更ですが、
Arch Linux環境向けにカーネルを自動で書き換えてビルドしなおすスクリプトを書きました。
行っている内容としては...
- Arch Linuxの公式リポジトリからPKGBUILDやpatchを取得。
- makepkgを用いてPKGBUILDから最新カーネルのソースコードを取得。
- 上記参照ページと同様に drivers/input/serio/i8042.c を書き換え。
- makepkgでビルドを実行してパッケージ化し、システムに上書きインストール。
(尚、ビルドは4コア使うように設定してありますが、数十分を要します。)
となっています。
今後、Linuxカーネルがアップデートされたときにもこのスクリプトを実行すれば、不具合対策済みカーネルで上書きできます(...できるはずです)。
尚、このスクリプトは特に自己責任でご利用ください。
また間違いやもっと良い方法がありましたら、ご指摘をお待ちしております m(_ _)m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# Arch Linux - Linux kernel rebuild script for Let's note CF-S10 series | |
# https://gist.github.com/mugifly/9582654/ | |
# Required: perl 5.x | |
use strict; | |
use warnings; | |
use utf8; | |
use Cwd; | |
use File::Path; | |
print <<EOF; | |
------------------------------------------------------- | |
Arch Linux - Linux kernel rebuild script for Let's note CF-S10 series | |
https://gist.github.com/mugifly/9582654/ | |
--PLEASE USE THIS SCRIPT AT YOUR OWN RISK-- | |
About kernel problem on CF-S10 series (Resume process of i8042 device): | |
https://forums.ubuntulinux.jp/viewtopic.php?pid=78318 | |
------------------------------------------------------- | |
EOF | |
our $DEFAULT_REPO_TYPE = 'core'; # core or testing | |
our $WORK_DIR = "/tmp"; | |
our $REPO_URL = 'https://projects.archlinux.org/svntogit/packages.git/snapshot/packages-packages/linux.tar.gz'; | |
our $BUILD_OPTION = 'MAKEFLAGS="-j4" '; | |
# Check a temporary directory | |
check_temp_dir($WORK_DIR); | |
# Read parameters | |
our $options = check_parameters(); | |
# Fetch a repository | |
my $arch = check_arch(); | |
my ($repo_dir_path, $linux_ver) = fetch_repo($REPO_URL, $WORK_DIR, $arch); | |
# Fetch a source (using makepkg -o) | |
my $source_dir_path = fetch_source($repo_dir_path, $linux_ver); | |
# Apply of a patch | |
apply_patch_source($source_dir_path); | |
# Build process | |
my @package_files = build_repo($repo_dir_path, $BUILD_OPTION); | |
# Install process | |
install_packages(@package_files); | |
print "Done.\n"; | |
exit; | |
# ------------------------------ | |
sub check_temp_dir { | |
my $dir_path = shift; | |
if (!-d $dir_path) { | |
mkdir $dir_path || die "Can't make a directory: $dir_path"; | |
} | |
} | |
sub check_parameters { | |
my $options = { | |
confirm => 1, | |
repoType => $DEFAULT_REPO_TYPE, | |
}; | |
foreach (@ARGV) { | |
if ($_ eq "--noconfirm") { | |
$options->{confirm} = 0; | |
} elsif ($_ eq "--help" || $_ eq "-h") { | |
print_help(); | |
exit; | |
} elsif ($_ =~ /^--repo=(core|testing)/) { | |
$options->{repoType} = $1; | |
} | |
} | |
return $options; | |
} | |
sub print_help { | |
print <<'EOF'; | |
$ perl arch-cfs10-kernel-rebuild.pl [--noconfirm] [--repo=REPO] [--help|-h] | |
EOF | |
print <<EOF; | |
REPO: Choose the repository (Default: $DEFAULT_REPO_TYPE) | |
* core | |
* testing | |
EOF | |
} | |
sub check_arch { | |
print "-----Checking machine architecture-----\n"; | |
my $u = `uname -a`; | |
if ($u =~ /x86_64/) { | |
print "Detected :x86_64\n"; | |
return "x86_64"; | |
} | |
print "Detected :i686\n"; | |
return "i686"; | |
} | |
sub fetch_repo { | |
print "-----Fetching repository-----\n"; | |
my ($repo_url, $current_dir_path, $arch) = @_; | |
# Get a date | |
our $current_date = `date '+%F_%H%M%S'`; | |
chomp($current_date); | |
# Fetch a repository file | |
chdir($current_dir_path); | |
`wget -O "linux-${current_date}.tar.gz" "${repo_url}"`; | |
# Extract a repository file | |
`tar zxf "linux-${current_date}.tar.gz"`; | |
unlink "linux-${current_date}.tar.gz"; | |
# Parse a pkgbuild file | |
my ($pkgver, $linux_ver); | |
my $pkgbuild_path = "packages-packages/linux/repos/$options->{repoType}-${arch}/PKGBUILD"; | |
open(my $fh, "<", $pkgbuild_path) || die "Can't open the PKGBUILD file: $!"; | |
while (my $line = <$fh>) { | |
if ($line =~ /^pkgver=(.+)/) { | |
$pkgver = $1; | |
} elsif ($line =~ /^_srcname=(.+)/) { | |
$linux_ver = $1; | |
} | |
if (defined $pkgver && defined $linux_ver) { | |
last; | |
} | |
} | |
close($fh); | |
if (!defined $pkgver || $pkgver eq '') { | |
die "Can't fetch the pkgver from PKGBUILD file."; | |
} | |
print "Fetched PKGBUILD: linux-${pkgver} (kernel: ${linux_ver})\n"; | |
if (-d "linux-${pkgver}") { | |
print "Already fetched PKGBUILD.\n"; | |
File::Path::rmtree(["packages-packages"]) or die "$!"; | |
} else { | |
`mv packages-packages/ linux-${pkgver}`; | |
} | |
return ($current_dir_path."/linux-${pkgver}/linux/repos/$options->{repoType}-${arch}/", $linux_ver); | |
} | |
sub fetch_source { | |
my ($repo_dir_path, $linux_ver) = @_; | |
print "-----Fetching source of kernel ${linux_ver}-----\n"; | |
print "Repo-dir: $repo_dir_path\n"; | |
# Fetch a source using makepkg | |
chdir($repo_dir_path); | |
`makepkg -o`; | |
my $current_dir_path = Cwd::getcwd(); | |
my $source_dir_path = $current_dir_path."/src/${linux_ver}"; | |
if (!-d $source_dir_path) { | |
die "Can't find a source directory: ${repo_dir_path}${source_dir_path}"; | |
} | |
return $source_dir_path; | |
} | |
sub apply_patch_source { | |
my $source_dir_path = shift; | |
print "-----Applying patch-----\n"; | |
chdir($source_dir_path); | |
# Patch for the resume suspend of the i8042 on Let's note CF-S10 series | |
my $ret = system('sed -i -e "s#.resume\s*=\s*i8042_pm_resume,#.resume = i8042_pm_restore,#g" drivers/input/serio/i8042.c'); | |
if ($ret != 0) { | |
die "Can't not applied the patch for i8042 driver."; | |
} | |
} | |
sub build_repo { | |
my ($repo_dir_path, $build_option) = @_; | |
print "-----Building source-----\n"; | |
print "$repo_dir_path"; | |
chdir($repo_dir_path); | |
# Build | |
print "Now processing...\n"; | |
my $ret = system($build_option.' makepkg -e'); | |
if ($ret != 0) { | |
die "Build has failed."; | |
} | |
# Check a package files | |
print "Checking package files...\n"; | |
my @package_files = (); | |
opendir(my $dirh, $repo_dir_path); | |
foreach (readdir($dirh)) { | |
next if /^\.{1,2}$/; | |
my $f = $_; | |
if ($f =~ /^linux-(.+).pkg\.tar\.xz$/) { | |
print "* ${f}\n"; | |
push(@package_files, "${repo_dir_path}${f}"); | |
} | |
} | |
if (@package_files <= 0) { | |
die "Can't find a generated package files."; | |
} | |
return @package_files; | |
} | |
sub install_packages { | |
my @package_files = @_; | |
print "-----Installing packages-----\n"; | |
my $package_num = @package_files; | |
foreach my $path (@package_files) { | |
print "$path\n"; | |
} | |
if ($options->{confirm}) { | |
print "Do you install these ${package_num} packages? [y/n]: "; | |
my $ans = <STDIN>; | |
chomp($ans); | |
if (!defined $ans || $ans !~ /y/i) { | |
print "Canceled.\n"; | |
exit; | |
} | |
} | |
print "Now installing...\n"; | |
foreach my $path (@package_files) { | |
print "* $path\n"; | |
my $ret = system("sudo pacman -U $path --noconfirm"); | |
if ($ret != 0) { | |
die "Install error: $path"; | |
} | |
} | |
} |
0 件のコメント:
コメントを投稿
お気軽にコメントをお寄せください m(_ _)m♪
"コメントの記入者"欄から[名前/URL]を選ぶと、登録なしでコメント投稿していただけます。