My First Contribution to the Linux Kernel

The story of submitting a first patch to the Linux kernel — adding media key support for a 20-year-old Fujitsu Lifebook S2110, from debugging the driver to getting the patch merged into Linux 6.15 and backported to all LTS versions.

This article describes the experience of submitting my first patch to the Linux kernel. The project focused on adding media key support for an old Fujitsu Lifebook S2110 laptop from 2005.

Fujitsu Lifebook S2110

Background

I own a Fujitsu Lifebook S2110 from 2005, now 20 years old. Despite its age, it runs well with the latest Arch Linux, with 2GB of RAM and a hard drive. Once the cache warms up, the system is responsive enough for C programming.

Above the main keyboard sits a block of media keys: A, B, Internet, and E-mail. On the right is a hardware switch between "Application" and "Player" modes. I became curious why these keys didn't fully work in Player mode, even though they functioned correctly in Application mode.

How Media Keys Work in Linux

Using the xev(1) utility to analyze input events, I discovered that in Application mode all four keys generate events:

  • A: XF86Launch1
  • B: XF86Launch2
  • Internet: XF86Launch3
  • E-mail: XF86Launch4

In Player mode, no events fired, but the kernel log showed error messages: "Unknown GIRB result [40000414]", "Unknown GIRB result [40000415]", and so on. Each key press generated such a message.

Media keys on the laptop

Finding the Right Driver

Using the lsmod command, I found the fujitsu_laptop module, which likely handled these keys. Searching the kernel source code confirmed that the file drivers/platform/x86/fujitsu-laptop.c contained the relevant code.

Studying the fujitsu-laptop Driver

Analyzing the driver source code, I identified the following structure:

Module initialization — the fujitsu_init() function registers several components:

  • acpi_fujitsu_bl_driver — backlight control
  • fujitsu_pf_driver — platform driver
  • acpi_fujitsu_laptop_driver — laptop event handling

Input device setup — the acpi_fujitsu_laptop_input_setup() function creates an input device and selects a keymap based on the DMI table.

DMI system — the table contains information about specific laptop models and their corresponding keymaps. If the model isn't found, keymap_default is used.

Event handling — the acpi_fujitsu_laptop_notify() function receives key codes from firmware, masks the necessary bits to obtain the scancode, and checks whether it exists in the current keymap. Unknown codes trigger the error message.

Modifying the Driver

I determined that the key codes in Player mode were simply offset by 4 from Application mode:

#define KEY1_CODE  0x410
#define KEY2_CODE  0x411
#define KEY3_CODE  0x412
#define KEY4_CODE  0x413
#define KEY5_CODE  0x414    // was 0x420
#define KEY6_CODE  0x415    // new
#define KEY7_CODE  0x416    // new
#define KEY8_CODE  0x417    // new
#define KEY9_CODE  0x420    // renamed from KEY5_CODE

I created a new keymap for the S2110:

static const struct key_entry keymap_s2110[] = {
    { KE_KEY, KEY1_CODE, { KEY_PROG1 } },      /* "A" */
    { KE_KEY, KEY2_CODE, { KEY_PROG2 } },      /* "B" */
    { KE_KEY, KEY3_CODE, { KEY_WWW } },         /* "Internet" */
    { KE_KEY, KEY4_CODE, { KEY_EMAIL } },       /* "E-mail" */
    { KE_KEY, KEY5_CODE, { KEY_STOPCD } },
    { KE_KEY, KEY6_CODE, { KEY_PLAYPAUSE } },
    { KE_KEY, KEY7_CODE, { KEY_PREVIOUSSONG } },
    { KE_KEY, KEY8_CODE, { KEY_NEXTSONG } },
    { KE_END, 0 }
};

And added a DMI table entry to identify the device:

{
    .callback = fujitsu_laptop_dmi_keymap_override,
    .ident = "Fujitsu LifeBook S2110",
    .matches = {
        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S2110"),
    },
    .driver_data = (void *)keymap_s2110
}
Working media keys

Testing the Changes

I built a new kernel using the Arch build system. After installation and reboot, the kernel log showed: "fujitsu_laptop: Identified laptop model 'Fujitsu LifeBook S2110'".

The keys now worked correctly in Player mode:

  • KEY5: XF86AudioStop
  • KEY6: XF86AudioPlay
  • KEY7: XF86AudioPrev
  • KEY8: XF86AudioNext

I added keybindings to my i3 configuration:

bindsym XF86AudioStop exec --no-startup-id playerctl stop
bindsym XF86AudioPlay exec --no-startup-id playerctl play-pause
bindsym XF86AudioPrev exec --no-startup-id playerctl previous
bindsym XF86AudioNext exec --no-startup-id playerctl next

Submitting Upstream

After a local commit, I checked the code with checkpatch.pl, which found no style errors. I used get_maintainer.pl to determine the patch recipients.

I sent the patch via email using git send-email.

Project Timeline

  • May 9, 2025 — patch sent to the mailing list
  • May 11 — driver maintainer acknowledged the patch (Acked-by)
  • May 15 — included in the platform drivers review branch
  • May 23 — sent to the main branch (Linux 6.15)
  • May 23 — Linus Torvalds accepted the pull request into the main repository
  • May 25 — version 6.15 released with the author mentioned in the changelog
  • May 27 — Sasha Levin selected the patch for backporting to all supported LTS versions (6.14, 6.12, 6.6, 6.1, 5.15, 5.10, 5.4)
  • June 14 — Arch update on the S2110 included the new kernel with key support

Conclusion

The process turned out to be much simpler than expected. The guide for beginning kernel developers was very helpful in properly preparing the patch. The mailing list mechanism made it possible to find precedents and solutions through Git archives and project history.

I have additional patches ready that fix network card issues on this model, but they require changes to core kernel code in kernel/dma/, so I want to make sure they're correct before submitting.