lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CANn+LW+PkAcZ2ZVSUpAQwYhDucruiiN90cAakDMXnayRPW0jUQ@mail.gmail.com>
Date: Tue, 13 Jan 2026 15:42:09 +0600
From: Sirat <email@...at.me>
To: Andy Shevchenko <andy.shevchenko@...il.com>
Cc: andy@...nel.org, geert@...ux-m68k.org, robh@...nel.org, krzk+dt@...nel.org, 
	conor+dt@...nel.org, linux-kernel@...r.kernel.org, devicetree@...r.kernel.org
Subject: Re: [PATCH 3/4] auxdisplay: tm1637: Add driver for TM1637

Hi Andy,

Thanks for the review. appreciate the mentorship on the coding style.

On the I2C point: I did check, but the TM1637 is incompatible with
standard I2C adapters. It expects LSB-first data and there's no slave
address so bit-banging is the only option here.

I'll handle the rest in v2:
- Switching to `linedisp`.
- Fixing the struct alignment and locking with `guard()`.
- Cleaning up the headers (IWYU), units, and version numbers.

Thanks,
Sirat

On Tue, Jan 13, 2026 at 1:53 PM Andy Shevchenko
<andy.shevchenko@...il.com> wrote:
>
> On Tue, Jan 13, 2026 at 6:03 AM Siratul Islam <email@...at.me> wrote:
> >
> > Add a driver for the Titanmec TM1637 7-segment display controller.
> >
> > The TM1637 uses a custom two-wire protocol (similar to I2C but without
> > a slave address) which requires bit-banging via GPIOs. This driver
> > implements the protocol manually as it does not fit the standard I2C
> > subsystem.
> >
> > The driver exposes a character device interface via sysfs:
> > - 'message': Write a string to display (supports alphanumeric & dots).
> > - 'brightness': Control intensity (0-8).
> >
> > Standard 7-segment mapping is handled using the kernel's map_to_7segment
> > utility.
>
> Thanks for your contribution. I believe in the current form (design
> wise) this is no go (we want linedisp and better understanding of the
> protocol here), but below is just a shallow review to get you an idea
> about some common mistakes people make (usually style related) to
> avoid similar problems in the future. It means a free review for
> making your code better in the future.
>
> ...
>
> > +Date:          January 2026
> > +KernelVersion: 6.19
>
> At bare minimum this could be material for 6.21. Use
> https://hansen.beer/~dave/phb/ prediction machine for this.
>
> ...
>
> > +config TM1637
> > +       tristate "Shenzhen Titan Micro Electronics TM1637 7-Segment Display"
> > +       depends on GPIOLIB || COMPILE_TEST
> > +       select AUXDISPLAY
> > +       help
> > +         This driver provides support for the Titanmec TM1637 7-segment
> > +         display controller connected via GPIO bit-banging.
> > +
> > +         This driver exposes a character interface for controlling the
> > +         display content and brightness via sysfs.
>
> We also expect the name of the module being mentioned if the user chooses M.
>
> ...
>
> The below block doesn't follow the IWYU (Include What You Use)
> principle. E.g., bits.h is missing.
>
> > +#include <linux/delay.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/module.h>
> > +#include <linux/mod_devicetable.h>
> > +#include <linux/mutex.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/property.h>
> > +#include <linux/slab.h>
>
> + blank line
>
> > +#include <linux/map_to_7segment.h>
>
> ...
>
> > +/* Protocol timing */
> > +#define TM1637_BIT_DELAY_MIN 100
> > +#define TM1637_BIT_DELAY_MAX 120
>
> What units are these? We do suffixes like _MS for milliseconds, for example.
>
> ...
>
> > +struct tm1637 {
> > +       struct device *dev;
> > +       struct gpio_desc *clk;
> > +       struct gpio_desc *dio;
> > +       struct mutex lock; /* Protects display buffer and brightness */
> > +       u8 brightness;
> > +       u8 buf[TM1637_DIGITS];
>
> Always think about alignment in the data types.  Definitely we want a
> possibility for the code to use one assembly instruction to get a full
> buffer to the register. With this layout it becomes impossible on
> (some) 32-bit architectures. Also `pahole` should be your tool to
> check structure layouts.
>
> > +};
>
> ...
>
> > +static void tm1637_delay(void)
> > +{
> > +       usleep_range(TM1637_BIT_DELAY_MIN, TM1637_BIT_DELAY_MAX);
> > +}
>
> Unneeded wrapper, just use fsleep() directly in the code with the
> comment above on each case.
>
> ...
>
> > +static void tm1637_start(struct tm1637 *tm)
> > +{
> > +       gpiod_direction_output(tm->dio, 1);
> > +       gpiod_set_value(tm->clk, 1);
> > +       tm1637_delay();
> > +       gpiod_set_value(tm->dio, 0);
> > +       tm1637_delay();
> > +       gpiod_set_value(tm->clk, 0);
> > +       tm1637_delay();
> > +}
> > +
> > +static void tm1637_stop(struct tm1637 *tm)
> > +{
> > +       gpiod_direction_output(tm->dio, 0);
> > +       gpiod_set_value(tm->clk, 1);
> > +       tm1637_delay();
> > +       gpiod_set_value(tm->dio, 1);
> > +       tm1637_delay();
> > +}
> > +
> > +static bool tm1637_write_byte(struct tm1637 *tm, u8 data)
> > +{
> > +       bool ack;
> > +       int i;
> > +
> > +       for (i = 0; i < 8; i++) {
> > +               gpiod_set_value(tm->clk, 0);
> > +               tm1637_delay();
> > +
> > +               if (data & BIT(i))
> > +                       gpiod_direction_input(tm->dio);
> > +               else
> > +                       gpiod_direction_output(tm->dio, 0);
> > +
> > +               tm1637_delay();
> > +               gpiod_set_value(tm->clk, 1);
> > +               tm1637_delay();
> > +       }
> > +
> > +       gpiod_set_value(tm->clk, 0);
> > +       gpiod_direction_input(tm->dio);
> > +       tm1637_delay();
> > +
> > +       gpiod_set_value(tm->clk, 1);
> > +       tm1637_delay();
> > +
> > +       ack = !gpiod_get_value(tm->dio);
> > +
> > +       if (!ack)
> > +               gpiod_direction_output(tm->dio, 0);
> > +
> > +       tm1637_delay();
> > +       gpiod_set_value(tm->clk, 0);
> > +
> > +       return ack;
> > +}
>
> This looks like the I2C bitbanging protocol. Have you checked that
> one? And why I2C with raw transfers can't be used? I doubt this can't
> be proper i2c peripheral driver.
>
> ...
>
> > +       if (brightness > TM1637_BRIGHTNESS_MAX + 1)
> > +               brightness = TM1637_BRIGHTNESS_MAX + 1;
>
> min() / max()  (from minmax.h)?
>
> ...
>
> > +       mutex_lock(&tm->lock);
>
> > +       mutex_unlock(&tm->lock);
>
> Use guard()() or scoped_guard() from cleanup.h.
>
> ...
>
> > +static struct attribute *tm1637_attrs[] = {
> > +       &dev_attr_message.attr,
> > +       &dev_attr_brightness.attr,
> > +       NULL};
>
> Two lines on a single one. Split.
>
> ...
>
> > +static int tm1637_probe(struct platform_device *pdev)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct tm1637 *tm;
> > +
> > +       tm = devm_kzalloc(dev, sizeof(*tm), GFP_KERNEL);
> > +       if (!tm)
> > +               return -ENOMEM;
> > +
> > +       tm->dev = dev;
> > +
> > +       tm->clk = devm_gpiod_get(dev, "clk", GPIOD_OUT_LOW);
> > +       if (IS_ERR(tm->clk))
> > +               return dev_err_probe(dev, PTR_ERR(tm->clk), "Failed to get clk GPIO\n");
> > +
> > +       tm->dio = devm_gpiod_get(dev, "dio", GPIOD_OUT_LOW);
> > +       if (IS_ERR(tm->dio))
> > +               return dev_err_probe(dev, PTR_ERR(tm->dio), "Failed to get dio GPIO\n");
>
> > +       mutex_init(&tm->lock);
>
> Use devm_mutex_init().
>
> > +       tm->brightness = TM1637_BRIGHTNESS_MAX + 1;
> > +
> > +       platform_set_drvdata(pdev, tm);
> > +       tm1637_update_display(tm);
> > +
> > +       return 0;
> > +}
>
> ...
>
> > +       mutex_destroy(&tm->lock);
>
> Will be gone per above.
>
> ...
>
> > +static const struct of_device_id tm1637_of_match[] = {
> > +       {.compatible = "titanmec,tm1637"},
>
> Missing spaces inside {}.
>
> > +       {}};
>
> Two lines on a single one. Please, split.
>
> --
> With Best Regards,
> Andy Shevchenko
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ