initial
This commit is contained in:
commit
fb1e31fd19
5 changed files with 214 additions and 0 deletions
18
Makefile
Normal file
18
Makefile
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
huawei-sound-fix:
|
||||||
|
@gcc huawei_matebook14s_codec_fix.cpp -o huawei-sound-fix
|
||||||
|
@echo "Now run sudo make install"
|
||||||
|
|
||||||
|
.PHONY:
|
||||||
|
install: huawei-sound-fix
|
||||||
|
@cp huawei-sound-fix /usr/local/bin/
|
||||||
|
@chmod +x /usr/local/bin/huawei-sound-fix
|
||||||
|
@cp *.service /etc/systemd/system/
|
||||||
|
@systemctl daemon-reload
|
||||||
|
@systemctl enable huawei-codec-fix.service
|
||||||
|
@systemctl enable restart-huawei-codec-fix.service
|
||||||
|
@systemctl start huawei-codec-fix.service
|
||||||
|
@echo "Now reboot required"
|
||||||
|
|
||||||
|
.PHONY:
|
||||||
|
clear:
|
||||||
|
@rm huawei-sound-fix
|
10
README.md
Normal file
10
README.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Fix sound on Huawei laptops on modern linux
|
||||||
|
|
||||||
|
Recipe from https://github.com/thesofproject/linux/issues/3350#issuecomment-1399427143
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/neonxp/fix-huawei-sound.git
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
reboot
|
||||||
|
```
|
12
huawei-codec-fix.service
Normal file
12
huawei-codec-fix.service
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=huawei-codec-fix
|
||||||
|
Before=sleep.target
|
||||||
|
StopWhenUnneeded=yes
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=idle
|
||||||
|
ExecStart=/usr/local/bin/huawei-sound-fix
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target suspend.target hibernate.target hybrid-sleep.target sleep.target
|
164
huawei_matebook14s_codec_fix.cpp
Normal file
164
huawei_matebook14s_codec_fix.cpp
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* File: huawei_matebook14s_codec_fix.cpp
|
||||||
|
* Author: ursul_polar
|
||||||
|
*
|
||||||
|
* Created on Jan 22, 2023, 5:34 AM
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/io.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
typedef uint64_t u64;
|
||||||
|
|
||||||
|
#define HDA_VERB(nid,verb,param) ((nid)<<24 | (verb)<<8 | (param))
|
||||||
|
#define HDA_IOCTL_VERB_WRITE _IOWR('H', 0x11, struct hda_verb_ioctl)
|
||||||
|
#define GET_VARIABLE_NAME(Variable) (void(Variable),#Variable)
|
||||||
|
|
||||||
|
// Struct to contain HDA_VERBS properties
|
||||||
|
struct hda_verb_ioctl {
|
||||||
|
u32 verb; /* HDA_VERB() */
|
||||||
|
u32 res; /* response */
|
||||||
|
}state_check;
|
||||||
|
|
||||||
|
// Derivate struct to handle conn and EAPD separately
|
||||||
|
struct verbs_enable{
|
||||||
|
struct hda_verb_ioctl conn;
|
||||||
|
struct hda_verb_ioctl eapd;
|
||||||
|
}speaker_enable, headphone_enable;
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
// If TERM Signal is sent will cause the loop to exit
|
||||||
|
void trpsig(int)
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_conn_state(int fd){
|
||||||
|
// Set standard verb to get status for HP connection
|
||||||
|
state_check.verb = HDA_VERB(0x16, 0x0f09, 0x0);
|
||||||
|
|
||||||
|
// Check connection status
|
||||||
|
if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &state_check) < 0)
|
||||||
|
syslog(LOG_ERR, "Failed to read connection state verb.");
|
||||||
|
return state_check.res >> 28;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_snd_device(){
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
// Check that we can RW with regards to the sound card
|
||||||
|
fd = open("/dev/snd/hwC0D0", O_RDWR|O_NOCTTY);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
syslog(LOG_ERR, "Failed to open snd device.");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_pin(int fd, const char* type){
|
||||||
|
struct hda_verb_ioctl clear_pins;
|
||||||
|
|
||||||
|
int array[]={0x715, 0x716, 0x717};
|
||||||
|
|
||||||
|
for(int i=0; i<3; i++){
|
||||||
|
|
||||||
|
if(type == "headphone" && array[i] != 0x715)
|
||||||
|
clear_pins.verb = HDA_VERB(0x1, array[i], 0x2);
|
||||||
|
else if( type =="headphone" && array[i] == 0x715)
|
||||||
|
clear_pins.verb = HDA_VERB(0x1, array[i], 0x0);
|
||||||
|
|
||||||
|
if(type == "spkr" && array[i] == 0x715)
|
||||||
|
clear_pins.verb = HDA_VERB(0x1, array[i], 0x2);
|
||||||
|
else if( type =="spkr" && array[i] != 0x715)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (clear_pins.verb > 0){
|
||||||
|
if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &clear_pins) < 0)
|
||||||
|
syslog(LOG_ERR, "Failed to write clear pin hda verb.");
|
||||||
|
else
|
||||||
|
syslog(LOG_INFO, "Written data to hda verb %.8x", clear_pins.verb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_verb(int fd, struct hda_verb_ioctl conn, struct hda_verb_ioctl eapd, const char* type){
|
||||||
|
|
||||||
|
// Enable speakers with hda verbs
|
||||||
|
if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &conn) < 0)
|
||||||
|
syslog(LOG_ERR, "Failed to write connection slector hda verb.");
|
||||||
|
if (ioctl(fd, HDA_IOCTL_VERB_WRITE, &eapd) < 0)
|
||||||
|
syslog(LOG_ERR, "Failed to write EAPD hda verb.");
|
||||||
|
|
||||||
|
clear_pin(fd, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
// TERM Signal check
|
||||||
|
signal(SIGTERM, &trpsig);
|
||||||
|
|
||||||
|
// Sound card file descriptor and connection state vars
|
||||||
|
int fd, state;
|
||||||
|
|
||||||
|
// Check connection status
|
||||||
|
state = 0;
|
||||||
|
|
||||||
|
// Set standard verbs to enable connections and EAPD for speaker
|
||||||
|
speaker_enable.conn.verb = HDA_VERB(0x16, 0x701, 0x0001);
|
||||||
|
speaker_enable.eapd.verb = HDA_VERB(0x17, 0x70c, 0x0002);
|
||||||
|
|
||||||
|
// Set standard verbs to enable connections and EAPD for headphones
|
||||||
|
headphone_enable.conn.verb = HDA_VERB(0x16, 0x701, 0x0000);
|
||||||
|
headphone_enable.eapd.verb = HDA_VERB(0x17, 0x70c, 0x0000);
|
||||||
|
|
||||||
|
// Write to syslog
|
||||||
|
syslog(LOG_INFO, "Daemon started.");
|
||||||
|
|
||||||
|
// Check that we can RW with regards to the sound card
|
||||||
|
fd = get_snd_device();
|
||||||
|
|
||||||
|
// Enable Speaker on startup so that there's no need to have a audio jack inserted
|
||||||
|
// to trigger the switch
|
||||||
|
enable_verb(fd, speaker_enable.conn, speaker_enable.eapd, "spkr");
|
||||||
|
syslog(LOG_INFO, "Enabled speaker output");
|
||||||
|
|
||||||
|
// Enter loop to detect connection changes
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
if (state != get_conn_state(fd) && state == 8){
|
||||||
|
//Enable speaker
|
||||||
|
enable_verb(fd, speaker_enable.conn, speaker_enable.eapd, "spkr");
|
||||||
|
syslog(LOG_INFO, "Enabled speaker output");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state != get_conn_state(fd) && state == 0){
|
||||||
|
//Enable headphones
|
||||||
|
enable_verb(fd, headphone_enable.conn, headphone_enable.eapd, "headphone");
|
||||||
|
syslog(LOG_INFO, "Enabled headphone output");
|
||||||
|
}
|
||||||
|
|
||||||
|
state = get_conn_state(fd);
|
||||||
|
}
|
||||||
|
// Close and exit
|
||||||
|
close(fd);
|
||||||
|
syslog(LOG_INFO, "Daemon stopped.");
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
10
restart-huawei-codec-fix.service
Normal file
10
restart-huawei-codec-fix.service
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Restart huawei codec fix after resume
|
||||||
|
After=suspend.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/systemctl --no-block restart huawei-codec-fix.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=suspend.target
|
Loading…
Reference in a new issue