Lenovo ThinkPad X1 Carbon (Gen 2)

This article or section does not follow the
Laptop page guidelines
.
Reason:
Needs an accessibility and function keys sections. (Discuss in
Talk:Lenovo ThinkPad X1 Carbon (Gen 2)
)
Hardware
PCI/USB ID
Working?
GPU
8086:0a16
Yes
Audio
8086:9c20
Yes
Wi-Fi
8086:08b2
Yes
Ethernet
8086:155a
Yes
WWAN
1199:a001
Yes
GPS
Untested
Bluetooth
8087:07dc
Yes
Webcam
04ca:7036
Yes
Fingerprint reader
138a:0017
Yes
Trackpad
Yes
Touchscreen
Yes
Almost everything works out of the box. Most of the hardware is based on the Intel Lynx Point reference design.
Power management
The
kernel module
thinkpad_acpi
picks up most of the sensors. The kernel module
tp_smapi
is not currently supported. PCIe ASPM does not currently work.
Udev
does not not notify whenever battery discharges by 1%, but it does notify at 80%, 20%, 5%, 4% and 0%.  To take advantage of this, see (Suspend On Low Battery
Laptop#Hibernate on low battery level
)
Wake from suspend
Wake from suspend can be buggy with earlier versions of the bios, see:
[1]
This can be solved by flashing the bios to a version >=1.13. Look here for Lenovo's bios versions:
[2]
A guide how to make a bootable BIOS key drive can be found here:
[3]
And some fairly old help from Lenovo here:
[4]
If the function keys fail to wake after suspend, ensure you have a kernel version >=3.15.
If you build your own kernels, make sure to either enable
TPM
(Trusted Platform Module) drivers or disable the Security Chip in the BIOS.
Keyboard
On kernel 3.14 and lower the adaptive panel at the top of the keyboard is locked to function mode.
From kernel 3.15, Home mode is also available which allows access to screen brightness and other controls.
If you wish to remap keys to get back to a sane keyboard layout, you can use either
xmodmap
or other
input remap utilities
.
Automatically turn on keyboard backlight when typing
The keyboard backlight works out of the box and there is a button on the soft keyboard to toggle it between off, low, and high brightness. Using a C program that continuously checks for keyboard input, it is possible to only activate the backlight for a certain time.
This article or section is out of date.
Reason:
See
Special:Diff/764472/764600
. (Discuss in
Talk:Lenovo ThinkPad X1 Carbon (Gen 2)
)
The program source is as a follows
kbdbacklight.c
/* Original Author: Howard Chu <hyc@symas.com> 2013-01-15
 *
 * compile as "gcc -O2 -o kbdbacklight kbdbacklight.c" and run it in the background, or arrange to have it run at bootup.
 *
 * adapted by gabtub@gmail.com 2017-01-22
 * using https://gist.github.com/hadess/6847281
 * based on http://askubuntu.com/questions/383501/enable-the-keyboard-backlights-on-supported-lenovo-e-g-carbon-x1-with-command
 * original code found at  http://forum.notebookreview.com/threads/asus-keyboard-backlight-controller.703985/
 * sigterm catching done as shown in https://airtower.wordpress.com/2010/06/16/catch-sigterm-exit-gracefully/
 *
 * fixed by sva 2022-10-08
 * refactored the whole code out of boredom. keyboard should now be detected automatically using libudev.h 2023-06-25
 * uses /sys/class/leds/, s.t. ec_sys is not necessary
 *
 * monitor keyboard activity and toggle keyboard backlight
 */
#include <stdio.h> // fprintf(), snprintf(), stderr
#include <unistd.h> // write(), close(), read()
#include <string.h> // strlen(), strncpy()
#include <fcntl.h> // open(), O_RDONLY, O_WRONLY
#include <limits.h> // PATH_MAX
#include <poll.h> // poll()

#include <linux/input.h> // struct input_event, EV_KEY
#include <libudev.h> // udev stuff

#define IDLE_MSEC 1000
#define BRGHT_OFF 0
#define BRGHT_MED 128
#define BRGHT_HI 255

static volatile int running = 1;

static int find_keyboard(char* devnode, size_t size) {
  struct udev* udev = udev_new();
  if (!udev) {
    fprintf(stderr, "Failed to create udev context\n");
    return -1;
  }

  struct udev_enumerate* enumerate = udev_enumerate_new(udev);
  if (!enumerate) {
    fprintf(stderr, "Failed to create udev enumerate\n");
    udev_unref(udev);
    return -1;
  }

  udev_enumerate_add_match_subsystem(enumerate, "input");
  udev_enumerate_add_match_property(enumerate, "ID_INPUT_KEYBOARD", "1");
  udev_enumerate_scan_devices(enumerate);

  struct udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);
  struct udev_list_entry* entry;
  int found = 0;

  udev_list_entry_foreach(entry, devices) {
    const char* path = udev_list_entry_get_name(entry);
    struct udev_device* dev = udev_device_new_from_syspath(udev, path);
    if (!dev) {
      fprintf(stderr, "Failed to create udev device\n");
      continue;
    }

    const char* devnode_path = udev_device_get_devnode(dev);
    if (devnode_path) {
      if (strlen(devnode_path) < size) {
        strncpy(devnode, devnode_path, size);
        found = 1;
        break;
      } else {
        fprintf(stderr, "Device node path is too long\n");
      }
    }

    udev_device_unref(dev);
  }

  udev_enumerate_unref(enumerate);
  udev_unref(udev);

  return found ? 0 : -1;
}

static int set_backlight(int brightness) {
  char buf[16];
  snprintf(buf, sizeof(buf), "%d", brightness);
  int fd = open("/sys/class/leds/tpacpi::kbd_backlight/brightness", O_WRONLY);
  if (fd < 0) {
    fprintf(stderr, "Failed to open keyboard backlight file\n");
    return -1;
  }
  if (write(fd, buf, strlen(buf)) != strlen(buf)) {
    fprintf(stderr, "Failed to set keyboard backlight\n");
    close(fd);
    return -1;
  }
  close(fd);
  return 0;
}

static void handle_input(int fd, int* brightness) {
  struct input_event ev;
  int rc = read(fd, &ev, sizeof(ev));
  if (rc > 0) {
    if (ev.type == EV_KEY && ev.value == 1) {
      set_backlight(BRGHT_HI);
      *brightness = BRGHT_HI;
    }
  }
}

static void handle_timeout(int fd, int* brightness) {
  set_backlight(BRGHT_OFF);
  *brightness = BRGHT_OFF;
}

static void handle_poll(int fd, int* brightness) {
  struct pollfd pfd;
  pfd.fd = fd;
  pfd.events = POLLIN;
  int timeout = IDLE_MSEC;
  while (running) {
    int rc = poll(&pfd, 1, timeout);
    if (rc > 0) {
      handle_input(fd, brightness);
      timeout = IDLE_MSEC;
    } else if (rc == 0) {
      handle_timeout(fd, brightness);
      timeout = -1;
    }
  }
}

int main(int argc, char** argv) {
  char devnode[PATH_MAX];
  if (find_keyboard(devnode, sizeof(devnode)) < 0) {
    fprintf(stderr, "Failed to find keyboard device\n");
    return 1;
  }

  int fd = open(devnode, O_RDONLY);
  if (fd < 0) {
    fprintf(stderr, "Failed to open keyboard device\n");
    return 1;
  }

  int brightness = BRGHT_OFF;
  set_backlight(brightness);
  handle_poll(fd, &brightness);
  close(fd);
  return 0;
}
This file can be compiled with:
$ gcc -O2 -o kbdbacklight kbdbacklight.c -ludev
and must be executed as root.
It would be possible to autostart this by creating a systemd service as follows:
Create a folder /usr/local/customscripts/kbdbacklight/
Save the compiled c program to /usr/local/customscripts/kbdbacklight/kbdbacklight
Create the following bash script in the same folder:
/usr/local/customscripts/kbdbacklight/kbdbacklight.sh
#!/bin/bash
# must be executed as root
./kbdbacklight &
RETVAL=$?
PID=$!
[ $RETVAL -eq 0 ] && echo $PID > /usr/local/customscripts/kbdbacklight/pid
Create the following systemd service and place it in /etc/systemd/system/kbdbacklight.service
/etc/systemd/system/kbdbacklight.service
[Unit]
Description=starts a daemon monitoring keyboard usage. will turn on keyboard backlight until no key is pressed for a TIMEOUT period
Requires=
After=

[Service]
Type=forking
User=root
WorkingDirectory=/usr/local/customscripts/kbdbacklight/
ExecStart=/usr/local/customscripts/kbdbacklight/kbdbacklight.sh &
PIDFile=/usr/local/customscripts/kbdbacklight/pid

[Install]
WantedBy=multi-user.target
start/enable
kbdbacklight.service
Note
Specify the amount timeout for turning the backlight off again by adjusting the constant IDLE_MSEC in the C program (and recompiling it again).
Trackpad
The factual accuracy of this article or section is disputed.
Reason:
When both
xf86-input-synaptics
and
xf86-input-libinput
are installed, the trackpoint (red thingy) uses libinput by default, so it does not cooperate with the trackpad (which by default is driven by synaptics), and as a result you cannot scroll with middle button + trackpoint. Keeping only
xf86-input-libinput
gets everything working. (Discuss in
Talk:Lenovo ThinkPad X1 Carbon (Gen 2)
)
To enable Trackpad support you need to install
xf86-input-synaptics
.
Lock-ups on click
There are significant issues with the trackpad locking up on click. This is due to the trackpad operating in buggy PS/2 mode.
One alternative is to abandon the trackpad completely and use the trackpoint.  Make sure xf86-input-synaptics is not installed - the trackpad will still register button one mouse clicks.  Using xbindkeys
Xbindkeys
and
xdotool
, right button clicks can be mapped to some other event.  For example:
~/.xbindkeysrc
# Emit a right click on Alt + trackpad click
"xdotool click 3"
  Mod1 + b:1 + Release
Tweaking trackpad behavior
The behavior of the trackpad by default can be contrary to your expectations, particularly if you are coming from an OS X style trackpad. The following settings can help significantly:
/etc/X11/xorg.conf.d/99-x1carbon.conf
# Copy this to /etc/X11/xorg.conf.d/99-x1carbon.conf
 Section "InputClass"
     Identifier "X1 carbon stuff"
     MatchIsTouchpad "on"
     MatchDevicePath "/dev/input/event*"
     Driver "synaptics"

     # Enable two finger scrolling vertically, disable horizontally
     Option "VertTwoFingerScroll" "1"
     Option "HorizTwoFingerScroll" "0"

     # No scrolling along the edge
     Option "VertEdgeScroll" "0"
     Option "HorizEdgeScroll" "0"

     Option "LockedDrags" "0"
     Option "FingerPress" "1"

     # Turn off the blasted corners as buttons
     Option "RTCornerButton" "0"
     Option "RBCornerButton" "0"
     Option "LTCornerButton" "0"
     Option "LBCornerButton" "0"

     # Ignore "taps" and listen for "clicks"
     Option "TapButton1" "0"
     Option "TapButton2" "0"
     Option "TapButton3" "0"
     Option "ClickFinger1" "1" # Left click one finger
     Option "ClickFinger2" "3" # Right click two fingers
     Option "ClickFinger3" "0" # Three finger click disabled

     Option "TapAndDragGesture" "0"

     # No circular scrolling
     Option "CircularScrolling" "0"
 EndSection
If you are using gnome-shell, you may need to tell the settings app not to overwrite our changes:
$ gsettings set org.gnome.settings-daemon.plugins.mouse active false
Touchpad not working after wake up from sleep
See
Touchpad Synaptics#Touchpad does not work after resuming from hibernate/suspend
.
Audio
You may need to add a default sound card options to its
kernel module parameter
:
/etc/modprobe.d/alsa-base.conf
options snd_hda_intel index=1
ALSA-Preamplifier
It is a common problem on laptops running linux that the sound, even on maximum, is not loud enough. This can be fixed by adding an ALSA preamplifier.
Install
alsa-utils
.
Change the config in /etc/asound.conf to the following ( you might have to adjust the cardnumber):
# Set your DEFAULT device to the softvol plug-in
# NOT to a hardware card device
#
# The "!" means completely override the previous default
# Not just changing/adding to it.
pcm.!default {
  type plug
  slave.pcm "softvol"
}

# Configure softvol
pcm.softvol {
  type softvol

  # Send softvol's output to dmix
  slave {
    pcm "dmix"
    # If you wanted to you could send the output to a card directly
    # But in most cases it's better to send it to dmix and let
    # dmix handle where to send it. You can add a whole extra section
    # to configure dmix and where it sends output, but I'm
    # not covering that here.

    ## Use Card 0 Device 0 instead of dmix
    # pcm "hw:0,0"
    ## Use Card 2 Device 0 instead of dmix
    # pcm "hw:2,0"
  }

  # Add a control slider in your mixer interfaces
  # i.e. KMix and alsamixer
  control {
    name "Pre-Amp"
    card 0 #<CardNumberYouWantControlToShowOn> i.e. card 0 or card 2
  }

  # Minimum dB when slider is at 0%
  min_dB -5.0

  # Maximum DB when slider is at 100%
  max_dB 40.0

  # How many levels the slider should go through
  # i.e. how granular do you want your control to be
  resolution 12
}
Taken from
here
.
Warning
It is possible to permanently damage your loudspeakers if you turn it up too much!
Processor
See
Microcode
how to update to processor's microcode.
BIOS update
To install a BIOS update from linux, download the bootable iso
from here
Since there is no CD drive,
this method
can be used (German).
Network
Wired
There is a small port on the right side for Ethernet. An adapter is required. In case of loss of the adapter, the part number for ordering is 04X6435.
Wireless
Works out of the box. The module
iwlwifi
should be automatically loaded by
udev
.
$ lspci
Network controller: Intel Corporation Wireless 7260 (rev 83)
Display
Touchscreen
Works out of the box as single touch. The hardware is multi-touch, but current stable drivers only support left-click mouse emulation. Seems to work with
Touchegg
.
HiDPI
Since the display has such a high pixel density, you might encounter problems. See here:
HiDPI
See also
ThinkWiki