From 2b86b4f49d71f01df9f102b58b86e51edfc60d46 Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 25 Oct 2016 21:23:46 +0200 Subject: [PATCH 01/13] Log error code of ioctl --- src/init-headphone | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 src/init-headphone diff --git a/src/init-headphone b/src/init-headphone old mode 100755 new mode 100644 index e307221..3c3a288 --- a/src/init-headphone +++ b/src/init-headphone @@ -116,7 +116,7 @@ class SMBus(object): err = self.__libc.ioctl(self.__fd, I2C_SLAVE, address) if err != 0: self.__logger.error("Can't set I2C slave address") - raise RuntimeError("Can't set I2C slave address") + raise OSError(err, os.strerror(err)) self.__address = address def __access(self, read_write, device_cmd, size, data): @@ -131,7 +131,7 @@ class SMBus(object): err = self.__libc.ioctl(self.__fd, I2C_SMBUS, ctypes.byref(args)) if err != 0: self.__logger.error("Can't transfer data on I2C bus") - raise RuntimeError("Can't transfer data on I2C bus") + raise OSError(err, os.strerror(err)) def write_byte_data(self, device_cmd, value): self.__logger.info("Writing byte data on I2C bus: " From 2790b36ec8c3b25bf6ff43c4ba85d6d79d7c836e Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 25 Oct 2016 21:24:29 +0200 Subject: [PATCH 02/13] Add color to logging output --- src/init-headphone | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/init-headphone b/src/init-headphone index 3c3a288..7a765e1 100644 --- a/src/init-headphone +++ b/src/init-headphone @@ -20,6 +20,7 @@ import ctypes import logging import os import subprocess +import sys import traceback __all__ = ["init", "set_mute", "set_effect", "recovery"] @@ -317,7 +318,35 @@ def main(): recovery() +class ColorStreamHandler(logging.StreamHandler): + def emit(self, record): + try: + FORMAT_SEQ = "\033[%dm" + fmt = 0 # reset + if record.levelno >= logging.ERROR: + fmt = 31 # red + elif record.levelno >= logging.WARNING: + fmt = 33 # yellow + msg = self.format(record) + if hasattr(self.stream, 'isatty') and self.stream.isatty(): + fs = (FORMAT_SEQ + "%s" + FORMAT_SEQ + "\n") % (fmt, msg, 0) + else: + fs = "%s\n" % msg + self.stream.write(fs) + self.flush() + except Exception: + self.handleError(record) + + +def setup_logging(): + ch = ColorStreamHandler(sys.stderr) + fmt = logging.Formatter('%(levelname)s:%(message)s') + ch.setFormatter(fmt) + logging.getLogger().addHandler(ch) + + if __name__ == "__main__": + setup_logging() try: main() except Exception: From 6d9914b38f239a2f8fe5c291cc551b56464a513e Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 25 Oct 2016 21:25:43 +0200 Subject: [PATCH 03/13] Bump version number to 0.12 --- src/init-headphone | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init-headphone b/src/init-headphone index 7a765e1..41e1633 100644 --- a/src/init-headphone +++ b/src/init-headphone @@ -25,7 +25,7 @@ import traceback __all__ = ["init", "set_mute", "set_effect", "recovery"] -VERSION = "0.11" +VERSION = "0.12" SUPPORTED_I2C_BUS_NAMES = ["SMBus I801 adapter"] I2C_CLASS_PATH = "/sys/class/i2c-dev" DEV_PATH = "/dev" From 00e2175c0e3143c48d4882e20c26b93ce5c9da69 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 2 Nov 2016 00:40:16 +0100 Subject: [PATCH 04/13] Add troubleshoot information --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index d1d8ac8..7443c41 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,15 @@ available commands: recovery ``` +## Troubleshoot + + * Run **init-headphone** with the ``--verbose`` argument. + * Use ``dmesg | grep i801`` to check for problems with the SMBus driver. + * List all i2c busses with ``i2cdetect -l`` to find the full name of the bus + **SMBus I801 adapter...**. Use that name as a argument for **i2cdetect** + like ``i2cdetect "SMBus I801 adapter at f040"``. This should show the + headphone amplifier at address 0x73. + ## Supported models This list is subject to change. If the headphone jack is not working after suspend, the model is probably supported. From fa69da8c2174a52082aefa57deecda1bde9ac4db Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 2 Nov 2016 00:44:51 +0100 Subject: [PATCH 05/13] Add information about the Windows driver --- README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/README.md b/README.md index 7443c41..ba070fe 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,74 @@ available commands: like ``i2cdetect "SMBus I801 adapter at f040"``. This should show the headphone amplifier at address 0x73. +## Information about the Windows Driver + +The Windows driver consists of a kernel space component **SvThANSP.sys** and a +user space component **hp.dll**. +The kernel driver is simple and only supports a few commands that allow access +to I/O ports. +**hp.dll** uses [DeviceIoControl](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363216%28v=vs.85%29.aspx) +to communicates via the device file ``\\.\SvANSPDo`` with the driver. +It talks directly to the SMBus controller. + +**hp.dll** exports the functions ``InitHeadphone()``, ``Set_Mute(bool)`` and +``Set_effect(int)`` to control the headphone amplifier which is connected to the +SMBus. + +### Supported ``dwIoControlCode``s for [DeviceIoControl](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363216%28v=vs.85%29.aspx) + +#### 0x9C402494: Enumerate PCI device + +``lpInBuffer`` amd ``lpOutBuffer`` look something like: + +```c +struct { + int bus, + int device, + int func, + int pcireg, + int result, + int unused +} +``` + +The driver reads a word from the register ``pcireg`` of the with +``bus``, ``device`` and ``func`` specified PCI device. +The result is returned in ``result``. If the register doesn't exist, the +returned result is 0xffff. It's used to find the SMBus controller by **hp.dll**. + +#### 0x9C4024D0: Read byte + +``lpInBuffer`` amd ``lpOutBuffer`` look something like: + +```c +struct { + int address, + int data_read, + int data_write +} +``` + +The driver reads one byte from ``address``. The result is returned in +``data_read``. + +#### 0x9C4024C4: Write byte + +``lpInBuffer`` amd ``lpOutBuffer`` are the same as above. + +The driver writes one byte ``data_write`` to ``address``. + +### SMBus controller + +A detailed description of the controller is available in the [chipset datasheet](https://www-ssl.intel.com/content/dam/www/public/us/en/documents/datasheets/8-series-chipset-pch-datasheet.pdf). + +The important registers are: + + * **Transmit Slave Address Register**: Bit 0 indicates direction, the other 7 Bits + are the device address (Offset: 0x4) + * **Host Command Register**: Command (Offset: 0x3) + * **Host Data 0 Register**: Data (Offset: 0x5) + ## Supported models This list is subject to change. If the headphone jack is not working after suspend, the model is probably supported. From 40a4678c13b001ef4f5637a60a4fc6984a61cae5 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 2 Nov 2016 00:45:12 +0100 Subject: [PATCH 06/13] Add newline to end of file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ba070fe..daa7321 100644 --- a/README.md +++ b/README.md @@ -154,4 +154,4 @@ This list is subject to change. If the headphone jack is not working after suspe * W970TUQ * WA50SBQ * WA50SFQ Series -* WA50SJQ Series \ No newline at end of file +* WA50SJQ Series From 2b98b9ae83e9352aa8cbfaebb6b482335b84306f Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 2 Nov 2016 06:32:39 +0100 Subject: [PATCH 07/13] Fix spelling mistake --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index daa7321..6b06112 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ available commands: like ``i2cdetect "SMBus I801 adapter at f040"``. This should show the headphone amplifier at address 0x73. -## Information about the Windows Driver +## Information about the Windows driver The Windows driver consists of a kernel space component **SvThANSP.sys** and a user space component **hp.dll**. From ec63cef85a4112bdac5ed265ab013871fc9759f6 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 2 Nov 2016 06:34:52 +0100 Subject: [PATCH 08/13] Add link to tools --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 6b06112..0da244b 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,9 @@ It talks directly to the SMBus controller. ``Set_effect(int)`` to control the headphone amplifier which is connected to the SMBus. +If you are interested in analyzing or running the Windows driver on Linux +(with [Wine](https://winehq.org)) take a look at: https://github.com/Unrud/init-headphone-tools + ### Supported ``dwIoControlCode``s for [DeviceIoControl](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363216%28v=vs.85%29.aspx) #### 0x9C402494: Enumerate PCI device From 8c6742bfd0f1b217d1088f0586a13012b1cca43f Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 22 Mar 2017 15:08:50 +0100 Subject: [PATCH 09/13] Format README --- README.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0da244b..b80a084 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,14 @@ Manage the headphone amplifier found in some Clevo laptops. Can initialize the device if headphones are not working after suspend. -**There are packages for [Arch Linux](https://aur.archlinux.org/packages/init-headphone/), [Fedora](https://github.com/letitz/init-headphone/releases) and [Ubuntu](https://github.com/Unrud/init-headphone-ubuntu/releases)** +**There are packages for +[Arch Linux](https://aur.archlinux.org/packages/init-headphone/), +[Fedora](https://github.com/letitz/init-headphone/releases) and +[Ubuntu](https://github.com/Unrud/init-headphone-ubuntu/releases)** ## Usage ``` -$ init-headphone --help +init-headphone --help usage: init-headphone [-h] [--version] [-v] [command] Manage the headphone amplifier found in some Clevo laptops @@ -54,8 +57,8 @@ to communicates via the device file ``\\.\SvANSPDo`` with the driver. It talks directly to the SMBus controller. **hp.dll** exports the functions ``InitHeadphone()``, ``Set_Mute(bool)`` and -``Set_effect(int)`` to control the headphone amplifier which is connected to the -SMBus. +``Set_effect(int)`` to control the headphone amplifier which is connected to +the SMBus. If you are interested in analyzing or running the Windows driver on Linux (with [Wine](https://winehq.org)) take a look at: https://github.com/Unrud/init-headphone-tools @@ -80,7 +83,8 @@ struct { The driver reads a word from the register ``pcireg`` of the with ``bus``, ``device`` and ``func`` specified PCI device. The result is returned in ``result``. If the register doesn't exist, the -returned result is 0xffff. It's used to find the SMBus controller by **hp.dll**. +returned result is 0xffff. It's used to find the SMBus controller by +**hp.dll**. #### 0x9C4024D0: Read byte @@ -105,17 +109,19 @@ The driver writes one byte ``data_write`` to ``address``. ### SMBus controller -A detailed description of the controller is available in the [chipset datasheet](https://www-ssl.intel.com/content/dam/www/public/us/en/documents/datasheets/8-series-chipset-pch-datasheet.pdf). +A detailed description of the controller is available in the +[chipset datasheet](https://www-ssl.intel.com/content/dam/www/public/us/en/documents/datasheets/8-series-chipset-pch-datasheet.pdf). The important registers are: - * **Transmit Slave Address Register**: Bit 0 indicates direction, the other 7 Bits - are the device address (Offset: 0x4) + * **Transmit Slave Address Register**: Bit 0 indicates direction, the other + 7 Bits are the device address (Offset: 0x4) * **Host Command Register**: Command (Offset: 0x3) * **Host Data 0 Register**: Data (Offset: 0x5) ## Supported models -This list is subject to change. If the headphone jack is not working after suspend, the model is probably supported. +This list is subject to change. If the headphone jack is not working after +suspend, the model is probably supported. ```x is used as wildcard``` * N151SD/N155SD/N170SD/N150SC/N151SC/N155SC From 9dd54b0234e119f82de67b80b926fadcee1fa35d Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 22 Mar 2017 15:21:45 +0100 Subject: [PATCH 10/13] add Autotools for installation --- Makefile.am | 14 ++++++++++++++ autogen.sh | 8 ++++++++ configure.ac | 23 +++++++++++++++++++++++ init-headphone.service.in | 15 +++++++++++++++ src/init-headphone | 0 5 files changed, 60 insertions(+) create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 init-headphone.service.in mode change 100644 => 100755 src/init-headphone diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..cb68e3c --- /dev/null +++ b/Makefile.am @@ -0,0 +1,14 @@ +DISTCHECK_CONFIGURE_FLAGS = \ + --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) + +if HAVE_SYSTEMD +systemdsystemunit_DATA = \ + init-headphone.service +endif + +sbin_SCRIPTS = src/init-headphone + +CLEANFILES = init-headphone.service + +init-headphone.service: init-headphone.service.in Makefile + sed -e 's,$${sbindir},${sbindir},g' init-headphone.service.in > init-headphone.service diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..f409ade --- /dev/null +++ b/autogen.sh @@ -0,0 +1,8 @@ +#!/bin/sh +AUTORECONF="$(which autoreconf)" +if test -z "$AUTORECONF" +then + echo "*** Error: autoreconf not found" + exit 1 +fi +"$AUTORECONF" --force --install --verbose || exit $? diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..3e4b1c8 --- /dev/null +++ b/configure.ac @@ -0,0 +1,23 @@ +AC_INIT([init-headphone], [0.12]) + +PKG_PROG_PKG_CONFIG +AC_ARG_WITH([systemdsystemunitdir], + [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],, + [with_systemdsystemunitdir=auto]) +AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [ + def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) + + AS_IF([test "x$def_systemdsystemunitdir" = "x"], + [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"], + [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])]) + with_systemdsystemunitdir=no], + [with_systemdsystemunitdir="$def_systemdsystemunitdir"])]) +AS_IF([test "x$with_systemdsystemunitdir" != "xno"], + [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])]) +AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"]) + +AM_INIT_AUTOMAKE([foreign]) + +AC_CONFIG_FILES([Makefile]) + +AC_OUTPUT diff --git a/init-headphone.service.in b/init-headphone.service.in new file mode 100644 index 0000000..96289e2 --- /dev/null +++ b/init-headphone.service.in @@ -0,0 +1,15 @@ +[Unit] +Description=Initialize headphone amplifier found in some Clevo laptops +After=suspend.target +After=hibernate.target +After=hybrid-sleep.target + +[Service] +Type=oneshot +ExecStart=${sbindir}/init-headphone + +[Install] +WantedBy=suspend.target +WantedBy=hibernate.target +WantedBy=hybrid-sleep.target +WantedBy=multi-user.target diff --git a/src/init-headphone b/src/init-headphone old mode 100644 new mode 100755 From c1a2fa3fae573577e5a90865eefef99c101c12cd Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 22 Mar 2017 15:22:22 +0100 Subject: [PATCH 11/13] add installation instructions --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index b80a084..41dfb84 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,27 @@ Can initialize the device if headphones are not working after suspend. [Fedora](https://github.com/letitz/init-headphone/releases) and [Ubuntu](https://github.com/Unrud/init-headphone-ubuntu/releases)** +## Installation + +To install just run: + + ./autogen.sh + ./configure + make + make install + +If **systemd** is available, a unit file that starts the program automatically +gets installed. To enable it run: + + systemctl enable init-headphone + +If you are not using **systemd**, take a look at the *etc/* folder. It +includes example configuration for **pm-utils** and **upstart** to start the +program automatically. + +On older Linux versions you might have to add the kernel parameter +``acpi_enforce_resources=lax`` to make the i2c driver work. + ## Usage ``` init-headphone --help From 411109d7da51bda0e770736f4f53cabf84a979c8 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 22 Mar 2017 15:23:28 +0100 Subject: [PATCH 12/13] add NEWS --- NEWS.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 NEWS.md diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..322d22c --- /dev/null +++ b/NEWS.md @@ -0,0 +1,58 @@ +# Changes in 0.12 + + * add Autotools + * improve logging + +# Changes in 0.11 + + * remove list of supported models + * show error message if library not found + * improve logging + * show active default effect in help + * hide --force argument + * try to load missing kernel modules + * add configuration examples + +# Changes in 0.10 + + * recognize more i2c bus names + * add license + +# Changes in 0.9 + + * remove model check + +# Changes in 0.8 + + * add ability to skip model check + * only print exception in verbose mode + +# Changes in 0.7 + + * use baseboard product name instead of system product name to identify model + * model communication with device after newer versions of the Windows driver + * add lots of supposedly supported models + * improved help + * improved logging + +# Changes in 0.6 + + * add Eurocom M4 to supported systems + +# Changes in 0.5 + + * add W230SD to supported systems + +# Changes in 0.4 + + * add support for Python 3 (still works with Python 2) + * python-smbus is no longer required + * better error handling + +# Changes in 0.3 + + * add "Mythlogic Chaos 1313-A" and "HUMA H3" to supported products + * add mute/unmute and some effects + +# Changes in 0.2 +Initial release From 6d2c6e0b75bd7438e722003a91fac18507b16f34 Mon Sep 17 00:00:00 2001 From: Unrud Date: Wed, 22 Mar 2017 17:02:39 +0100 Subject: [PATCH 13/13] shorten description in systemd unit file --- etc/linux-systemd/init-headphone.service | 2 +- init-headphone.service.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/linux-systemd/init-headphone.service b/etc/linux-systemd/init-headphone.service index c982ec6..e14d051 100644 --- a/etc/linux-systemd/init-headphone.service +++ b/etc/linux-systemd/init-headphone.service @@ -1,5 +1,5 @@ [Unit] -Description=Initialize headphone amplifier found in some Clevo laptops +Description=Initialize headphone amplifier After=suspend.target After=hibernate.target After=hybrid-sleep.target diff --git a/init-headphone.service.in b/init-headphone.service.in index 96289e2..04ff85e 100644 --- a/init-headphone.service.in +++ b/init-headphone.service.in @@ -1,5 +1,5 @@ [Unit] -Description=Initialize headphone amplifier found in some Clevo laptops +Description=Initialize headphone amplifier After=suspend.target After=hibernate.target After=hybrid-sleep.target