├── .gitignore ├── Android.mk ├── factory ├── Android.bp ├── openrc │ ├── me176c-factory.initd.in │ ├── udev │ │ ├── 99-me176c-factory.rules.in │ │ ├── meson.build │ │ └── setaddr.sh.in │ └── meson.build ├── systemd │ ├── udev │ │ ├── 99-me176c-factory.rules │ │ ├── me176c-factory-wifiaddr@.service.in │ │ ├── me176c-factory-bdaddr@.service.in │ │ └── meson.build │ ├── me176c-factory.service.in │ └── meson.build ├── meson_options.txt ├── meson.build ├── me176c-factory.h ├── README.md ├── me176c-factory.c └── service.c ├── thermal ├── Android.mk ├── thermald-me176c.service ├── README.md └── thermal-conf-me176c.xml ├── LICENSE ├── README.md └── porting.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | ifeq ($(TARGET_DEVICE), K013) 4 | include $(call all-makefiles-under, $(LOCAL_PATH)) 5 | endif 6 | -------------------------------------------------------------------------------- /factory/Android.bp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // Copyright (C) 2019 lambdadroid 3 | 4 | cc_library_static { 5 | name: "libme176c-factory", 6 | vendor: true, 7 | recovery_available: true, 8 | 9 | srcs: ["me176c-factory.c"], 10 | export_include_dirs: ["."], 11 | } 12 | -------------------------------------------------------------------------------- /thermal/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_MODULE := thermal-conf.xml 5 | LOCAL_VENDOR_MODULE := true 6 | LOCAL_SRC_FILES := thermal-conf-me176c.xml 7 | LOCAL_MODULE_CLASS := ETC 8 | LOCAL_MODULE_RELATIVE_PATH := thermald 9 | include $(BUILD_PREBUILT) 10 | -------------------------------------------------------------------------------- /factory/openrc/me176c-factory.initd.in: -------------------------------------------------------------------------------- 1 | #!/sbin/openrc-run 2 | # SPDX-License-Identifier: MIT 3 | # Copyright (C) 2019 lambdadroid 4 | 5 | name="ME176C Factory" 6 | 7 | start() { 8 | ebegin "Starting $name" 9 | @LIBRARY_DIRECTORY@/me176c-factory @BLOCK_DEVICE@ 10 | eend $? "Failed to start $name" 11 | } 12 | -------------------------------------------------------------------------------- /factory/openrc/udev/99-me176c-factory.rules.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | ACTION=="add", SUBSYSTEM=="net", KERNELS=="INT33BB:00", RUN+="@LIBRARY_DIRECTORY@/setaddr.sh wifi $name" 5 | ACTION=="add", SUBSYSTEM=="bluetooth", KERNELS=="80860F0A:01", RUN+="@LIBRARY_DIRECTORY@/setaddr.sh bd %k" 6 | -------------------------------------------------------------------------------- /factory/systemd/udev/99-me176c-factory.rules: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | ACTION=="add", SUBSYSTEM=="net", KERNELS=="INT33BB:00", ENV{SYSTEMD_WANTS}+="me176c-factory-wifiaddr@$name" 5 | ACTION=="add", SUBSYSTEM=="bluetooth", KERNELS=="80860F0A:01", ENV{SYSTEMD_WANTS}+="me176c-factory-bdaddr@%k" 6 | -------------------------------------------------------------------------------- /factory/systemd/me176c-factory.service.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | [Unit] 5 | Description=ME176C Factory Service 6 | 7 | [Service] 8 | Type=oneshot 9 | ExecStart=@LIBRARY_DIRECTORY@/me176c-factory @BLOCK_DEVICE@ 10 | RemainAfterExit=true 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /factory/openrc/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | configure_file(configuration: conf, 5 | input: 'me176c-factory.initd.in', 6 | output: 'me176c-factory', 7 | install_dir: join_paths(get_option('prefix'), get_option('sysconfdir'), 'init.d'), 8 | ) 9 | 10 | if get_option('udev') 11 | subdir('udev') 12 | endif 13 | -------------------------------------------------------------------------------- /factory/systemd/udev/me176c-factory-wifiaddr@.service.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | [Unit] 5 | Description=Set WiFi MAC Address (%I) 6 | Requires=me176c-factory.service 7 | After=me176c-factory.service 8 | 9 | Before=wpa_supplicant@%i.service 10 | 11 | [Service] 12 | Type=oneshot 13 | EnvironmentFile=@RUNTIME_DIRECTORY@/environment 14 | ExecStart=@BINARY_DIRECTORY@/ip link set dev %i address $WIFIADDR 15 | -------------------------------------------------------------------------------- /factory/systemd/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | systemd = dependency('systemd') 5 | systemdsystemunitdir = systemd.get_pkgconfig_variable('systemdsystemunitdir') 6 | 7 | configure_file(configuration: conf, 8 | input: 'me176c-factory.service.in', 9 | output: 'me176c-factory.service', 10 | install_dir: systemdsystemunitdir, 11 | ) 12 | 13 | if get_option('udev') 14 | subdir('udev') 15 | endif 16 | -------------------------------------------------------------------------------- /factory/systemd/udev/me176c-factory-bdaddr@.service.in: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | [Unit] 5 | Description=Set Bluetooth MAC Address (%I) 6 | Requires=me176c-factory.service 7 | After=me176c-factory.service 8 | 9 | ConditionPathExists=@BINARY_DIRECTORY@/btmgmt 10 | 11 | [Service] 12 | Type=oneshot 13 | EnvironmentFile=@RUNTIME_DIRECTORY@/environment 14 | ExecStart=@BINARY_DIRECTORY@/btmgmt -i %i public-addr $BDADDR 15 | -------------------------------------------------------------------------------- /factory/openrc/udev/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | udev = dependency('udev') 5 | 6 | configure_file(configuration: conf, 7 | input: '99-me176c-factory.rules.in', 8 | output: '99-me176c-factory.rules', 9 | install_dir: join_paths(udev.get_pkgconfig_variable('udevdir'), 'rules.d'), 10 | ) 11 | 12 | configure_file(configuration: conf, 13 | input: 'setaddr.sh.in', 14 | output: 'setaddr.sh', 15 | install_dir: me176c_libdir, 16 | ) 17 | -------------------------------------------------------------------------------- /factory/systemd/udev/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | udev = dependency('udev') 5 | 6 | configure_file(configuration: conf, 7 | input: 'me176c-factory-wifiaddr@.service.in', 8 | output: 'me176c-factory-wifiaddr@.service', 9 | install_dir: systemdsystemunitdir, 10 | ) 11 | 12 | configure_file(configuration: conf, 13 | input: 'me176c-factory-bdaddr@.service.in', 14 | output: 'me176c-factory-bdaddr@.service', 15 | install_dir: systemdsystemunitdir, 16 | ) 17 | 18 | install_data('99-me176c-factory.rules', 19 | install_dir: join_paths(udev.get_pkgconfig_variable('udevdir'), 'rules.d')) 20 | -------------------------------------------------------------------------------- /thermal/thermald-me176c.service: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0-or-later 2 | # Copyright (C) 2015 Intel Corporation 3 | # Modified from https://github.com/intel/thermal_daemon/blob/v1.8/data/thermald.service.in 4 | # to point to custom configuration for ME176C. 5 | 6 | [Unit] 7 | Description=Thermal Daemon Service (ME176C) 8 | 9 | [Service] 10 | Type=dbus 11 | SuccessExitStatus=1 12 | BusName=org.freedesktop.thermald 13 | ExecStart=/usr/bin/thermald --no-daemon --dbus-enable --ignore-cpuid-check --ignore-default-control --config-file=/etc/thermald/thermal-conf-me176c.xml 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | Alias=dbus-org.freedesktop.thermald.service 18 | -------------------------------------------------------------------------------- /factory/meson_options.txt: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | option('udev', type: 'boolean', value: true, 5 | description: 'Install udev rules to automatically set MAC addresses') 6 | option('systemd', type: 'boolean', value: true, 7 | description : 'Install systemd service file') 8 | option('openrc', type: 'boolean', value: false, 9 | description: 'Install OpenRC service file') 10 | 11 | option('blockdevice', type: 'string', value: '/dev/disk/by-partlabel/factory', 12 | description: 'Runtime location of factory partition block device') 13 | option('rundir', type: 'string', value: '/run', 14 | description: 'Runtime directory to store factory information') 15 | -------------------------------------------------------------------------------- /factory/openrc/udev/setaddr.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT 3 | # Copyright (C) 2019 lambdadroid 4 | 5 | rc-service me176c-factory start 6 | 7 | addr=$(cat "@RUNTIME_DIRECTORY@/${1}addr") 8 | [ -n "$addr" ] || exit 9 | 10 | case "$1" in 11 | wifi) 12 | ip link set dev "$2" address "$addr" 13 | ;; 14 | bd) 15 | # This tends to fail because the udev rule is trigged too early 16 | # Loop with 2 seconds timeout to have a better chance to succeed 17 | i=0 18 | while [ $i -lt 20 ]; do 19 | btmgmt -i "$2" public-addr "$addr" && exit 20 | sleep 0.1 21 | i=$((i + 1)) 22 | done 23 | exit 1 24 | ;; 25 | *) 26 | exit 1 27 | ;; 28 | esac 29 | -------------------------------------------------------------------------------- /thermal/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # thermald-me176c 4 | This directory contains a custom configuration for [thermald] 5 | for the ASUS MeMO Pad 7 (ME176C(X)). It is based on similar trip points that 6 | were used on the stock (Android) system of the tablet. They begin throttling 7 | quite early based on the device (not CPU) temperature. 8 | 9 | Feel free to contribute if you think these values can be improved. 10 | 11 | ## Usage 12 | Install [thermald]. Copy `thermal-conf-me176c.xml` to `/etc/thermald/thermal-conf.xml`. 13 | With the `--config-file=` parameter, it can also be copied to a non-generic location 14 | like `/etc/thermald/thermal-conf-me176c.xml`. An updated systemd service for this 15 | is provided in `thermald-me176c.service`. 16 | 17 | [thermald]: https://github.com/intel/thermal_daemon 18 | 19 | ## Packaging 20 | - **Arch Linux:** `thermald-me176c` AUR package 21 | -------------------------------------------------------------------------------- /factory/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # Copyright (C) 2019 lambdadroid 3 | 4 | project('me176c-factory', 'c', 5 | version: '0.1.0', 6 | license: 'MIT', 7 | default_options: [ 8 | 'c_std=c11', 9 | 'warning_level=3', 10 | 'werror=true' 11 | ] 12 | ) 13 | 14 | me176c_libdir = join_paths(get_option('libdir'), 'me176c') 15 | me176c_rundir = join_paths(get_option('rundir'), 'me176c') 16 | 17 | executable('me176c-factory', 18 | 'me176c-factory.c', 19 | 'service.c', 20 | c_args: ['-DRUNTIME_DIRECTORY="' + me176c_rundir + '"'], 21 | install: true, 22 | install_dir: me176c_libdir, 23 | ) 24 | 25 | conf = configuration_data() 26 | conf.set('BLOCK_DEVICE', get_option('blockdevice')) 27 | conf.set('BINARY_DIRECTORY', join_paths(get_option('prefix'), get_option('bindir'))) 28 | conf.set('LIBRARY_DIRECTORY', join_paths(get_option('prefix'), me176c_libdir)) 29 | conf.set('RUNTIME_DIRECTORY', me176c_rundir) 30 | 31 | if get_option('systemd') 32 | subdir('systemd') 33 | endif 34 | if get_option('openrc') 35 | subdir('openrc') 36 | endif 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless otherwise noted, the source code and configuration files 2 | in this repository are licensed under: 3 | 4 | SPDX-License-Identifier: MIT 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | All documentation is licensed under: 25 | SPDX-License-Identifier: CC-BY-SA-4.0 OR GFDL-1.3-or-later 26 | -------------------------------------------------------------------------------- /factory/me176c-factory.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // Copyright (C) 2019 lambdadroid 3 | 4 | #ifndef ME176C_FACTORY_H 5 | #define ME176C_FACTORY_H 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | struct me176c_factory_info { 11 | /** The serial number of the device. */ 12 | char serialno[32]; 13 | /** The Bluetooth device address of the device (format XX:XX:XX:XX:XX:XX) */ 14 | char bdaddr[18]; 15 | /** The WiFi hardware address of the device (format XX:XX:XX:XX:XX:XX) */ 16 | char wifiaddr[18]; 17 | }; 18 | 19 | /** 20 | * Read the factory info from the mounted factory partition. 21 | * 22 | * @param mount The mount directory of the factory partition 23 | * @param info Pointer to the struct where the result is stored 24 | */ 25 | int me176c_factory_read(const char *mount, struct me176c_factory_info *info); 26 | 27 | /** 28 | * Load the factory info from the block device pointed by "source". 29 | * Mounts the block device at "target", reads the factory info and unmounts 30 | * the block device again. 31 | * 32 | * @param mount The path to the block device (of the factory partition) 33 | * @param target The path to mount to (temporarily) 34 | * @param info Pointer to the struct where the result is stored 35 | */ 36 | int me176c_factory_load(const char *source, const char *target, struct me176c_factory_info *info); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | #endif 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Linux on ASUS MeMO Pad 7 (ME176C(X)) 4 | This repository contains source code for using Linux on the ASUS MeMO Pad 7 (ME176C(X))), 5 | including a Linux kernel fork and userspace modules shared between different Linux distributions. 6 | 7 | **IMPORTANT NOTE:** Recent Linux versions (5.19+) work without the need for any device specific 8 | patches thanks to the new `x86-android-tablets` module with support for the ME176C. The Linux 9 | kernel fork is no longer maintained. Just use the standard Linux kernel as provided by your 10 | Linux distribution! 11 | 12 | The [me176c-factory](/factory) module is still maintained to allow setting the 13 | correct MAC addresses for WiFi and Bluetooth. 14 | 15 | ## Kernel branches 16 | - Archived: 17 | - [Linux 5.4](https://github.com/me176c-dev/linux-me176c/tree/5.4): `5.4` 18 | - [Android (Linux 4.19)](https://github.com/me176c-dev/linux-me176c/tree/android-4.19): `android-4.19` 19 | - [Linux 4.19](https://github.com/me176c-dev/linux-me176c/tree/4.19): `4.19` 20 | - [Linux 4.14](https://github.com/me176c-dev/linux-me176c/tree/4.14): `4.14` 21 | - [LineageOS 14.1 (Linux 4.14)](https://github.com/me176c-dev/linux-me176c/tree/cm-14.1): `cm-14.1` 22 | 23 | ## Userspace modules 24 | - [me176c-factory](/factory) 25 | - [thermald-me176c](/thermal) 26 | 27 | ## Documentation 28 | - [Porting - Using linux-me176c in other distributions](/porting.md) 29 | - [me176c-boot](https://github.com/me176c-dev/me176c-boot#readme) 30 | - [Dual/multi boot example (me176c-boot)](https://github.com/me176c-dev/me176c-boot/tree/master/examples/multi-boot) 31 | - [Tips and tricks (ArchWiki)](https://wiki.archlinux.org/index.php/ASUS_MeMO_Pad_7_(ME176C(X))#Tips_and_tricks) 32 | -------------------------------------------------------------------------------- /factory/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # me176c-factory 4 | A simple library, and optionally service to load the factory information 5 | (serial number, BT/WiFi mac address) from the `factory` partition on the 6 | ASUS MeMO Pad 7 (ME176C(X)). 7 | 8 | ## Library 9 | `me176c-factory.c/h` provides methods to load the factory information. 10 | See [`me176c-factory.h`](me176c-factory.h) for details. 11 | 12 | ## Service 13 | There is a simple service implementation suitable for most Linux distributions. 14 | It mounts the `factory` partition temporarily on boot, reads the data and stores 15 | it in the runtime directory `/run/me176c` (compile-time configurable). 16 | 17 | ### Building 18 | Using [Meson]: 19 | 20 | ``` 21 | meson . build 22 | ninja -C build 23 | ``` 24 | 25 | ### Usage 26 | Run `/usr/lib/me176c/me176c-factory `. In most cases, 27 | `` should be `/dev/disk/by-partlabel/factory`. 28 | 29 | The service then writes the information to: 30 | - `/run/me176c/serialno`: Serial number 31 | - `/run/me176c/wifiaddr`: WiFi hardware (MAC) address 32 | - `/run/me176c/bdaddr`: Bluetooth device (MAC) address 33 | - `/run/me176c/environment`: Above information as `KEY=VALUE` pairs 34 | 35 | ### systemd 36 | systemd and udev integration is enabled by default. It provides `me176c-factory.service` 37 | that starts the service on boot. Optionally, udev rules together with 38 | `me176c-factory-bdaddr@` and `me176c-factory-wifiaddr@` are provided 39 | to automatically set the WiFi/Bluetooth MAC address on boot. 40 | 41 | ### OpenRC 42 | OpenRC + udev integration can be enabled with `-Dsystemd=false -Dopenrc=true`. 43 | It provides the `me176c-factory` service. Optionally, udev rules are provided 44 | to automatically set the WiFi/Bluetooth MAC address on boot. 45 | 46 | ## Packaging 47 | - **Arch Linux:** `me176c-factory` AUR package 48 | 49 | [Meson]: http://mesonbuild.com 50 | -------------------------------------------------------------------------------- /factory/me176c-factory.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // Copyright (C) 2019 lambdadroid 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "me176c-factory.h" 12 | 13 | #define PHONE_INFO_FILE "PhoneInfodisk/PhoneInfo_inf" 14 | 15 | #define BDADDR_OFFSET 0x99 16 | #define WIFI_ADDR_OFFSET 0xcc 17 | 18 | static void format_addr(const char *buf, char *addr) { 19 | // Copy MAC address and add separators 20 | for (int i = 0; i < 12; i += 2) { 21 | if (i) 22 | *addr++ = ':'; 23 | *addr++ = buf[i]; 24 | *addr++ = buf[i+1]; 25 | } 26 | *addr = 0; 27 | } 28 | 29 | int me176c_factory_read(const char *mount, struct me176c_factory_info *info) { 30 | char buf[256]; 31 | int i = snprintf(buf, sizeof(buf), "%s/%s", mount, PHONE_INFO_FILE); 32 | if (i < 0 || i >= (int) sizeof(buf)) { 33 | errno = ENAMETOOLONG; 34 | return -1; 35 | } 36 | 37 | int fd = open(buf, O_RDONLY); 38 | if (fd < 0) 39 | return fd; 40 | 41 | i = read(fd, buf, sizeof(buf)); 42 | close(fd); 43 | if (i != sizeof(buf)) 44 | return i; 45 | 46 | memcpy(info->serialno, buf, sizeof(info->serialno)); 47 | info->serialno[sizeof(info->serialno)-1] = 0; 48 | 49 | format_addr(&buf[BDADDR_OFFSET], info->bdaddr); 50 | format_addr(&buf[WIFI_ADDR_OFFSET], info->wifiaddr); 51 | return 0; 52 | } 53 | 54 | int me176c_factory_load(const char *source, const char *target, struct me176c_factory_info *info) { 55 | int ret = mkdir(target, 0770); 56 | if (ret && errno != EEXIST) 57 | return ret; 58 | 59 | ret = mount(source, target, "ext4", MS_RDONLY | MS_NOSUID | MS_NODEV | MS_NOEXEC, ""); 60 | if (ret) 61 | return ret; 62 | 63 | ret = me176c_factory_read(target, info); 64 | 65 | umount(target); 66 | rmdir(target); 67 | return ret; 68 | } 69 | -------------------------------------------------------------------------------- /factory/service.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // Copyright (C) 2019 lambdadroid 3 | 4 | #define _POSIX_C_SOURCE 200809L 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "me176c-factory.h" 13 | 14 | #define MOUNT_PATH RUNTIME_DIRECTORY "/factory" 15 | #define SERIALNO_FILE RUNTIME_DIRECTORY "/serialno" 16 | #define BDADDR_FILE RUNTIME_DIRECTORY "/bdaddr" 17 | #define WIFIADDR_FILE RUNTIME_DIRECTORY "/wifiaddr" 18 | #define ENVIRONMENT_FILE RUNTIME_DIRECTORY "/environment" 19 | 20 | static int write_file(char *p, char *s) { 21 | int fd = creat(p, 0660); 22 | if (fd < 0) 23 | return 1; 24 | 25 | int len = strlen(s); 26 | s[len] = '\n'; 27 | len = write(fd, s, len + 1); 28 | close(fd); 29 | 30 | if (len < 0) { 31 | fprintf(stderr, "Failed to write to %s: %s\n", p, strerror(errno)); 32 | return 1; 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | static int write_environment(const struct me176c_factory_info *info) { 39 | int fd = creat(ENVIRONMENT_FILE, 0660); 40 | if (fd < 0) 41 | return 1; 42 | 43 | int written = dprintf(fd, "SERIALNO=%s\nBDADDR=%s\nWIFIADDR=%s\n", 44 | info->serialno, info->bdaddr, info->wifiaddr); 45 | close(fd); 46 | return written < 0; 47 | } 48 | 49 | int main(int argc, char *argv[]) { 50 | if (argc < 2) { 51 | fprintf(stderr, "Usage: me176c-factory \n"); 52 | return 1; 53 | } 54 | 55 | int ret = mkdir(RUNTIME_DIRECTORY, 0777); 56 | if (ret && errno != EEXIST) { 57 | perror("Failed to create runtime directory '" RUNTIME_DIRECTORY "'"); 58 | return 1; 59 | } 60 | 61 | const char *source = argv[1]; 62 | struct me176c_factory_info info; 63 | ret = me176c_factory_load(source, MOUNT_PATH, &info); 64 | if (ret) { 65 | fprintf(stderr, "Failed to load factory info from '%s': %s\n", 66 | source, strerror(errno)); 67 | return 1; 68 | } 69 | 70 | printf("Loaded factory info from '%s': serialno: %s, bdaddr: %s, wifiaddr: %s\n", 71 | source, info.serialno, info.bdaddr, info.wifiaddr); 72 | 73 | return write_environment(&info) 74 | | write_file(SERIALNO_FILE, info.serialno) 75 | | write_file(BDADDR_FILE, info.bdaddr) 76 | | write_file(WIFIADDR_FILE, info.wifiaddr); 77 | } 78 | -------------------------------------------------------------------------------- /porting.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Porting - Using linux-me176c in other distributions 4 | Most of the code in linux-me176c is not specific to one Linux distribution. 5 | In fact it is already being used for Android, Arch Linux and postmarketOS. 6 | This page explains how to apply it to an other Linux distribution. 7 | 8 | ### Linux kernel fork (linux-me176c) 9 | Most of the necessary patches for full functionality have been submitted upstream. 10 | However, the battery/charging drivers have been ported from the downstream stock 11 | (3.10) kernel. Even though they went through major cleanup already, they are not 12 | even closely in a state that is suitable for upstreaming. 13 | 14 | This is why it is necessary to run a Linux kernel fork ("linux-me176c") for 15 | full functionality. Compared to other downstream kernel it only carries a couple 16 | of patches that can be easily rebased on top of newer kernel versions. 17 | 18 | Usually, linux-me176c tracks the latest LTS kernel and is available from one 19 | of the branches in this repository. 20 | 21 | ### Dependencies 22 | Unfortunately, there are a few closed-source components required for full 23 | functionality. Some of them (e.g. me176c-acpi and CPU Microcode) will be running 24 | anyway through the BIOS. Therefore, replacing them with updated/fixed versions 25 | will not add new unfree code. 26 | 27 | - **[me176c-acpi]:** For full functionality (e.g. touchscreen, Bluetooth, ...) 28 | - **Firmware:** 29 | - [linux-firmware](https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/) 30 | (available as package for almost all distributions): 31 | - **WiFI:** `brcm/brcmfmac43362-sdio.bin` 32 | - **Sound:** `intel/fw_sst_0f28.bin` 33 | - Additional firmware from the ASUS stock ROM ([`UL-K013-WW-12.10.1.36-user.zip`](https://dlcdnets.asus.com/pub/ASUS/EeePAD/ME176C/UL-K013-WW-12.10.1.36-user.zip)): 34 | - **WiFI:** `/system/etc/nvram.txt` -> `brcm/brcmfmac43362-sdio.txt` 35 | - **Bluetooth:** `/system/etc/firmware/BCM2076B1_002.002.004.0132.0141_reduced_2dB.hcd` -> `brcm/BCM2076B1.hcd` 36 | - **Userspace:** 37 | - Battery Daemon (`/sbin/upi_ug31xx` in the `boot.img` ramdisk of the ASUS Stock ROM): 38 | May be needed for battery driver to work correctly. Appears to be used for calibration/backup purposes. 39 | - Running it avoids `User space daemon no response` spam in the kernel log. 40 | - Requires mounting the `config` partition at `/config`, although the mount point can be changed by using `sed` on the binary. 41 | - Example extraction: [Arch Linux (AUR) `me176c-firmware` package](https://github.com/me176c-dev/archlinux-me176c/tree/master/me176c-firmware) 42 | - Example systemd service: [Arch Linux (AUR) `me176c-battery` package](https://github.com/me176c-dev/archlinux-me176c/tree/master/me176c-battery) 43 | - **CPU Microcode Update:** Not included in Intel's Linux microcode update package. 44 | - **Download:** From [platomav/CPUMicrocodes](https://github.com/platomav/CPUMicrocodes/tree/master/Intel/cpu30678_plat02_ver00000837_2018-01-25_PRD_F0D56486.bin) 45 | - Pack it into an initrd for use with the Linux CPU microcode updater. 46 | - Example package: [Arch Linux (AUR) `intel-ucode-byt-t-c0` package](https://aur.archlinux.org/packages/intel-ucode-byt-t-c0/) 47 | 48 | ### Notes 49 | See also: [Tips and tricks (ArchWiki)](https://wiki.archlinux.org/index.php/ASUS_MeMO_Pad_7_(ME176C(X))#Tips_and_tricks) 50 | 51 | #### WiFi / Bluetooth 52 | - WiFi / Bluetooth do not use the same MAC address as the stock (ASUS) system by default 53 | - Bluetooth needs to be configured with an unique MAC address from userspace to make it work 54 | - [me176c-factory](/factory) can be used to apply the ASUS WiFi/BT MAC address from the factory partition 55 | 56 | #### Thermal 57 | Consider setting up a Thermal Daemon (e.g. [thermald](https://github.com/intel/thermal_daemon)) to monitor device 58 | temperature and to throttle the CPU performance early when the device gets too hot. 59 | - [Custom configuration for thermald](/thermal) is provided in this repository. 60 | 61 | [me176c-acpi]: https://github.com/me176c-dev/me176c-acpi 62 | -------------------------------------------------------------------------------- /thermal/thermal-conf-me176c.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 16 | ME176C 17 | ME176C 18 | 19 | 20 | 21 | CPU 22 | 23 | 24 | TCPU 25 | 95000 26 | passive 27 | SEQUENTIAL 28 | 29 | 30 | 1 31 | rapl_controller 32 | 33 | 34 | 2 35 | intel_pstate 36 | 37 | 38 | 3 39 | intel_powerclamp 40 | 41 | 42 | 4 43 | Processor 44 | 45 | 46 | 47 | 48 | 49 | 50 | SoC0 51 | 52 | 53 | soc_dts0 54 | 90000 55 | passive 56 | SEQUENTIAL 57 | 58 | 59 | 1 60 | rapl_controller 61 | 62 | 63 | 2 64 | intel_pstate 65 | 66 | 67 | 3 68 | intel_powerclamp 69 | 70 | 71 | 4 72 | Processor 73 | 74 | 75 | 76 | 77 | soc_dts0 78 | 100000 79 | critical 80 | 81 | 82 | 83 | 84 | 85 | SoC1 86 | 87 | 88 | soc_dts1 89 | 90000 90 | passive 91 | SEQUENTIAL 92 | 93 | 94 | 1 95 | rapl_controller 96 | 97 | 98 | 2 99 | intel_pstate 100 | 101 | 102 | 3 103 | intel_powerclamp 104 | 105 | 106 | 4 107 | Processor 108 | 109 | 110 | 111 | 112 | soc_dts1 113 | 100000 114 | critical 115 | 116 | 117 | 118 | 119 | 120 | STR1 121 | 122 | 123 | STR1 124 | 55000 125 | passive 126 | SEQUENTIAL 127 | 128 | 129 | 1 130 | rapl_controller 131 | 132 | 133 | 2 134 | intel_pstate 135 | 136 | 137 | 3 138 | intel_powerclamp 139 | 140 | 141 | 4 142 | Processor 143 | 144 | 145 | 146 | 147 | STR1 148 | 64000 149 | critical 150 | 151 | 152 | 153 | 154 | 155 | STR2 156 | 157 | 158 | STR2 159 | 55000 160 | passive 161 | SEQUENTIAL 162 | 163 | 164 | 1 165 | rapl_controller 166 | 167 | 168 | 2 169 | intel_pstate 170 | 171 | 172 | 3 173 | intel_powerclamp 174 | 175 | 176 | 4 177 | Processor 178 | 179 | 180 | 181 | 182 | STR2 183 | 64000 184 | critical 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | --------------------------------------------------------------------------------