On October 15, 2026, Linux developer Christian Fredrik Kalager Schaller reported that he had used Anthropic's AI coding tool Claude Code to develop a Linux scanner driver, and that the same approach had substantially improved the image quality of a laptop's built-in camera. His analysis of the scanner had been stuck for months. It moved forward quickly once he set up an environment in which he could record the manufacturer's Windows driver working correctly and compare that behavior with Linux. He got the first image scan working within a few hours, and infrared scanning followed a few days later. He has generalized the approach so it can be applied to other devices and released it on GitHub as "hw-harness." The result suggests that the efficiency of driver development depends not only on an AI's coding ability, but also on having an environment where real hardware behavior can be observed and hypotheses tested.
Recording Windows' correct behavior breaks the deadlock in AI-assisted driver development
The project began when Schaller found a large number of photo negatives among his late mother's belongings. To digitize the memories, he bought a Plustek "OpticFilm 8200i" film scanner, believing it would work on Linux. In reality, the control chip inside had been changed, and his unit was not supported by Linux. He tried to use Claude Code to develop a driver for SANE, Linux's common scanner interface, but made little progress and set the work aside for several months.
The turning point was a post by developer Tom Crider, who had used AI to fix a mouse driver. Crider described having the AI operate a Windows environment and record how the device behaved, and Schaller decided to build a similar setup. He prepared a Windows virtual machine on KVM, connected the physical scanner, and ran a scan with the manufacturer's software. During that scan, he recorded the communication using "usbmon," the USB monitoring feature on the Linux host. He then returned the same device to Linux, performed the same operation with his in-development driver, and recorded that traffic as well.
The advantage of this method is that the behavior of the working Windows driver and the in-development Linux driver can be compared using the same mechanism. In his October 15 blog post, Schaller explains that this environment, combined with improvements in Claude Code's capabilities, drove major progress. A few hours later, the first scan succeeded on Linux. Image quality still had problems at first, but the negative could be made out. Over several more days of work, he completed a driver that also supports infrared scanning.
The analysis covers more than the scanned images. USB traffic contains information needed to understand how a driver works, including the device's initialization sequence, register writes, checks that confirm the device is ready, and data transfer sizes and timing. For example, if only the scan resolution is changed between two captures, the control values that change accordingly may reveal which register sets the resolution. Claude Code searches large traffic logs for differences and repeating patterns, forms hypotheses about what they mean, and writes programs to test them. The developer runs those programs on the real device, checks the results, and feeds what is learned into the next round of analysis.
In the hw-harness methodology document, Schaller recommends using each capture to test a single question rather than recording a large amount of traffic at once. For example, it is easier to isolate a cause by splitting the work into small operations, such as turning on the lamp, moving the read head to its home position, or reading one line at 300 dpi, than by recording an entire 120-second scan. By recording Windows and Linux traffic under identical conditions and examining the first significant difference, he works out where the driver has a problem.
Note that what usbmon records are requests and responses between the Linux kernel and the USB host controller, not a direct measurement of the signals on the physical USB bus. The official Linux kernel documentation also explains that, for example when the host controller has a defect, the recorded content may not exactly match the actual traffic on the bus. Even so, recording Windows and Linux behavior at the same layer makes it easier to trace the differences between them.
The newly published hw-harness GitHub repository collects tools that support operating the Windows virtual machine, recording USB traffic, switching which side a device is attached to, and debugging on the Linux side. It was developed and tested on Fedora, and the published instructions assume a setup using libvirt/KVM and Windows 11 Pro. However, when Schaller actually fixed the scanner and camera, he used scripts written for each case; the published hw-harness was generalized afterward. Whether it achieves the same results on many different devices has not yet been adequately verified.
Scanner driver succeeds, but SANE itself had also gained support
The Plustek OpticFilm 8200i has variants that carry different control chips under the same product name. The earlier model uses the Genesys GL845, which SANE already supported on Linux. The unit Schaller bought has a Genesys GL128 and USB ID "07b3:1825," and initially could not be used from Linux. Even when the product name is the same, an existing driver may not work as is if the internal hardware differs.
Schaller developed his own SANE backend that supports color, grayscale, infrared, and combined color-plus-infrared scanning. It supports resolutions from 300 to 7200 dpi and bit depths of 8 and 16 bits per channel, and includes dust and scratch removal that uses the infrared data. He also added an exposure multiplier adjustment to handle dense negatives. The driver is distributed as an RPM package for Fedora and is built automatically whenever GitHub is updated.
However, while Schaller's work was on hold, support for the same scanner had also been added to SANE itself. According to Schaller, the support was added in September 2026, and SANE's development-version compatibility list also lists the GL128 model as "Basic." It supports 16-bit color and grayscale scanning of transparent originals, but not infrared scanning. Note also that support in the development version does not necessarily mean the change has reached the stable packages of each Linux distribution.
On October 9, Schaller published comparison results for his own driver versus the development version of SANE itself. Scan times measured with the same scanner and negative were as follows.
| Scan resolution | Schaller's own driver | SANE development version |
|---|---|---|
| 600dpi | 16.7 seconds | 16.4 seconds |
| 3600dpi | 34.6 seconds | 54.4 seconds |
At 600 dpi, the SANE development version was 0.3 seconds faster, while at 3600 dpi Schaller's own driver was 19.8 seconds faster. His driver is therefore not faster under every condition. In addition, the output image sizes at 3600 dpi differed in this comparison: 5184×3877 pixels for his own driver and 5184×3519 pixels for SANE itself. Because the scan areas were not exactly identical, this cannot be called a strict performance test of equal workloads.
The test used one scanner and one frame of negative film, and the SANE side used master branch commit "415217c5." The film holder position was aligned, and the 16-bit raw data from both drivers was run through the same negative conversion process. The film base color was estimated from each output, and dust removal was not used. However, no measurement error from repeated runs is shown, so the results are a comparison under limited conditions. Schaller himself judges the fine detail obtained at 3600 dpi to be about the same for both drivers.
Another advantage of his own driver is its support for infrared scanning. In film scanners, infrared can be used to detect the positions of dust and scratches on an image so that they can be corrected through image processing. To take advantage of this, Schaller also developed a GNOME app called "Negative Vibes" in Rust. It is designed to hold the 16-bit linear image data obtained from the scanner, along with infrared data when available, and to perform color adjustments, negative-to-positive conversion, and other edits non-destructively.
According to the Negative Vibes GitHub repository, the app supports color and black-and-white negatives and slide film, and can export to TIFF, JPEG, PNG, DNG, and other formats. However, the only device verified on real hardware is the OpticFilm 8200i, and the same features may not work with other film scanners. In particular, because infrared data is handled differently by each SANE backend, the app currently has to carry model-specific information. Making infrared dust removal available on a wide range of scanners will require a common interface on the SANE side.
A laptop's built-in camera also improves, with five issues found in the kernel and libcamera
Having succeeded with the scanner driver, Schaller applied the same approach to improving a laptop's built-in camera. The target was the camera in the Lenovo "ThinkPad X1 Carbon Gen 14 Aura Edition." This model pairs a Sony IMX471 image sensor with an Intel IPU7, but on Linux the captured images were dark, with heavy vignetting that darkened the corners of the frame and a strong yellow-green color cast.
However, a built-in MIPI camera cannot have its traffic recorded the same way as a USB scanner. Schaller therefore switched to investigating Windows driver configuration files (INF), the registry, ACPI tables that describe the hardware configuration, and similar sources, and comparing them with Linux behavior. He also extracted vignetting correction values and a color conversion matrix from model-specific tuning data included in Intel's Windows camera driver package. Rather than analyzing or porting the manufacturer driver's executable code, this approach proceeds from configuration information and observations of the real device.
According to the published findings, five problems were found: three in the Linux kernel's sensor driver and two in the libcamera image-processing library. On the kernel side, a bug in the code that returns the sensor's imaging area meant libcamera could not correctly recognize the actual readout area. In addition, the register that controls the test pattern was defined as 8 bits rather than the correct 16 bits, so switching test patterns did not work properly.
A further problem was that the upper limit of the analog gain was set too low. The IMX471 sensor supports analog gain of up to 16x, but the Linux driver could only set about 4.57x. Analog gain amplifies the signal the sensor receives, and if the limit is too low, sufficient brightness cannot be obtained in dark environments. With this fix, the amplification capability the sensor originally has became usable.
On the libcamera side, there was no vignetting correction, so the corners of the image were much darker than the center. With this camera, the periphery was about 2.7 stops darker than the center. Based on tuning data obtained from the Windows driver package, Schaller added software vignetting correction.
Another problem was in how white balance was calculated. In this model's Linux environment, the IPU7's hardware image processing is not used; the raw sensor output is processed by libcamera's software ISP (image signal processor). However, the white balance statistics were calculated at the sensor's native bit depth, while the value subtracted as the black level was still based on 8 bits.
The black level is the baseline output value that occurs even when no light reaches the sensor, and it must be subtracted to calculate colors and brightness correctly. For example, if an 8-bit-based value is used as is on 10-bit data, the black level correction amounts to only one quarter of what it should be. Extra value then remains in each color signal, and the white balance correction gains come closer to 1, so the color cast is not corrected sufficiently.
Schaller explains that this bug affects not only the IMX471 in this case but also RAW10 and RAW12 sensors that use libcamera's software ISP. If the fix is merged upstream, similar problems on other devices could therefore be improved. At present, however, it has not been confirmed on real hardware that other cameras would see the same effect.
Camera brightness improves about 2.9x; getting the patches upstream is the next challenge
To confirm the effect of the fixes, Schaller compared camera captures under the same seating position and lighting conditions. He did not move the laptop, and for the pre-fix state he reinstalled the standard kernel and libcamera 0.7.1 and shot again. In both cases, he waited 400 frames for auto exposure and white balance to stabilize before measuring. As a result, the measured value for overall image brightness rose from 31.1 before the fixes to 90.9, an improvement of about 2.9x.
Color reproduction also improved. Before the fixes, the red-to-green ratio was 0.890 and the blue-to-green ratio was 0.672; after the fixes they were 1.047 and 0.823, respectively. A comparison USB camera had a red-to-green ratio of 1.052 and a blue-to-green ratio of 0.989, so red moved closer to the reference, while blue remained about 17% short. Vignetting also improved, but color reproduction in low light remains a challenge.
According to Schaller, the color conversion matrix used this time was validated through mathematical consistency and actual captured results, but no colorimetric tests using a color chart have been performed. The lighting conditions tested were also limited to a single room, and evaluation under various light sources and brightness levels remains for the future. As for image processing, only the GPU-based path was actually tested; the CPU-based path was not covered.
A feature that lowers the frame rate to lengthen exposure time in dark environments also remains unresolved. In libcamera's current processing, the frame rate is maintained even in the dark, which limits exposure time. Although this fix raised the analog gain ceiling, that alone does not bring out the camera's full low-light performance. Schaller himself explains that image quality has improved significantly but has not reached a perfect state.
As of the October 15 report, the kernel patches had been submitted to Kate Hsuan, and the libcamera fixes were being reviewed by Wim Taymans with a view to submitting them upstream. In neither case can it be confirmed that they have been formally adopted into the common implementations, and further review and verification will be needed. As for the scanner, Schaller says that once SANE's own features catch up with his driver, many users, including himself, will probably use the SANE implementation.
What this effort shows is the importance of not merely having AI write driver code, but of preparing an environment in which the behavior of correctly working hardware can be observed and compared with the implementation under development. Claude Code made it more efficient to analyze large traffic logs, form hypotheses, and write verification programs, but it was the developer with the real hardware who ultimately confirmed the behavior. Schaller also stresses that checking on real hardware is essential for judging how hardware behaves.
If the released hw-harness proves effective on other devices, and the resulting fixes are merged into common implementations such as the Linux kernel, SANE, and libcamera, it could become a means of advancing driver development for hardware that has been difficult to support. However, working in one individual's development environment is not the same as working reliably on different units and in different environments. Going forward, verification of reproducibility and upstream adoption of the fixes will determine whether this result benefits Linux users broadly.
