remove comma two support (#24248)
* remove comma two support
* cleanup release files
* little more
* more libs
* no more gralloc
* add snpe back
old-commit-hash: 5c48e7bc86
taco
parent
e8ad31f32b
commit
5a9644261f
361 changed files with 203 additions and 33559 deletions
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:2ca3679a8e9a066bccbf8cb27377a40bad65e348d668040adda37c27ff6bad4d |
||||
size 69 |
@ -1 +0,0 @@ |
||||
README.md |
File diff suppressed because it is too large
Load Diff
@ -1,106 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <atomic> |
||||
#include <cstdint> |
||||
#include <memory> |
||||
|
||||
#include "cereal/messaging/messaging.h" |
||||
#include "cereal/visionipc/visionbuf.h" |
||||
#include "selfdrive/camerad/cameras/camera_common.h" |
||||
#include "selfdrive/camerad/imgproc/utils.h" |
||||
#include "selfdrive/camerad/include/msm_cam_sensor.h" |
||||
#include "selfdrive/camerad/include/msmb_camera.h" |
||||
#include "selfdrive/camerad/include/msmb_isp.h" |
||||
#include "selfdrive/camerad/include/msmb_ispif.h" |
||||
#include "selfdrive/common/mat.h" |
||||
#include "selfdrive/common/util.h" |
||||
|
||||
#define FRAME_BUF_COUNT 4 |
||||
#define METADATA_BUF_COUNT 4 |
||||
|
||||
#define NUM_FOCUS 8 |
||||
|
||||
#define LP3_AF_DAC_DOWN 366 |
||||
#define LP3_AF_DAC_UP 634 |
||||
#define LP3_AF_DAC_M 440 |
||||
#define LP3_AF_DAC_3SIG 52 |
||||
|
||||
#define FOCUS_RECOVER_PATIENCE 50 // 2.5 seconds of complete blur
|
||||
#define FOCUS_RECOVER_STEPS 240 // 6 seconds
|
||||
|
||||
typedef struct CameraState CameraState; |
||||
|
||||
typedef int (*camera_apply_exposure_func)(CameraState *s, int gain, int integ_lines, uint32_t frame_length); |
||||
|
||||
typedef struct StreamState { |
||||
struct msm_isp_buf_request buf_request; |
||||
struct msm_vfe_axi_stream_request_cmd stream_req; |
||||
struct msm_isp_qbuf_info qbuf_info[FRAME_BUF_COUNT]; |
||||
VisionBuf *bufs; |
||||
} StreamState; |
||||
|
||||
typedef struct CameraState { |
||||
int camera_num; |
||||
int camera_id; |
||||
|
||||
int fps; |
||||
CameraInfo ci; |
||||
|
||||
unique_fd csid_fd; |
||||
unique_fd csiphy_fd; |
||||
unique_fd sensor_fd; |
||||
unique_fd isp_fd; |
||||
|
||||
struct msm_vfe_axi_stream_cfg_cmd stream_cfg; |
||||
|
||||
StreamState ss[3]; |
||||
CameraBuf buf; |
||||
|
||||
std::mutex frame_info_lock; |
||||
FrameMetadata frame_metadata[METADATA_BUF_COUNT]; |
||||
int frame_metadata_idx; |
||||
|
||||
// exposure
|
||||
uint32_t pixel_clock, line_length_pclk; |
||||
uint32_t frame_length; |
||||
unsigned int max_gain; |
||||
float cur_exposure_frac, cur_gain_frac; |
||||
int cur_gain, cur_integ_lines; |
||||
|
||||
float measured_grey_fraction; |
||||
float target_grey_fraction; |
||||
|
||||
std::atomic<float> digital_gain; |
||||
camera_apply_exposure_func apply_exposure; |
||||
|
||||
// rear camera only,used for focusing
|
||||
unique_fd actuator_fd; |
||||
std::atomic<float> focus_err; |
||||
std::atomic<float> lens_true_pos; |
||||
std::atomic<int> self_recover; // af recovery counter, neg is patience, pos is active
|
||||
uint16_t cur_step_pos; |
||||
uint16_t cur_lens_pos; |
||||
int16_t focus[NUM_FOCUS]; |
||||
uint8_t confidence[NUM_FOCUS]; |
||||
} CameraState; |
||||
|
||||
|
||||
typedef struct MultiCameraState { |
||||
unique_fd ispif_fd; |
||||
unique_fd msmcfg_fd; |
||||
unique_fd v4l_fd; |
||||
uint16_t lapres[(ROI_X_MAX-ROI_X_MIN+1)*(ROI_Y_MAX-ROI_Y_MIN+1)]; |
||||
|
||||
VisionBuf focus_bufs[FRAME_BUF_COUNT]; |
||||
VisionBuf stats_bufs[FRAME_BUF_COUNT]; |
||||
|
||||
CameraState road_cam; |
||||
CameraState driver_cam; |
||||
|
||||
SubMaster *sm; |
||||
PubMaster *pm; |
||||
LapConv *lap_conv; |
||||
} MultiCameraState; |
||||
|
||||
void actuator_move(CameraState *s, uint16_t target); |
||||
int sensor_write_regs(CameraState *s, struct msm_camera_i2c_reg_array* arr, size_t size, int data_type); |
@ -1,91 +0,0 @@ |
||||
#!/usr/bin/env python3 |
||||
import os |
||||
import time |
||||
import psutil |
||||
from typing import Optional |
||||
|
||||
import cereal.messaging as messaging |
||||
from common.realtime import set_core_affinity, set_realtime_priority |
||||
from selfdrive.swaglog import cloudlog |
||||
|
||||
|
||||
MAX_MODEM_CRASHES = 3 |
||||
MODEM_PATH = "/sys/devices/soc/2080000.qcom,mss/subsys5" |
||||
WATCHED_PROCS = ["zygote", "zygote64", "system_server", "/system/bin/servicemanager", "/system/bin/surfaceflinger"] |
||||
|
||||
|
||||
def get_modem_crash_count() -> Optional[int]: |
||||
try: |
||||
with open(os.path.join(MODEM_PATH, "crash_count")) as f: |
||||
return int(f.read()) |
||||
except Exception: |
||||
cloudlog.exception("Error reading modem crash count") |
||||
return None |
||||
|
||||
def get_modem_state() -> str: |
||||
try: |
||||
with open(os.path.join(MODEM_PATH, "state")) as f: |
||||
return f.read().strip() |
||||
except Exception: |
||||
cloudlog.exception("Error reading modem state") |
||||
return "" |
||||
|
||||
def main(): |
||||
set_core_affinity(1) |
||||
set_realtime_priority(1) |
||||
|
||||
procs = {} |
||||
crash_count = 0 |
||||
modem_killed = False |
||||
modem_state = "ONLINE" |
||||
androidLog = messaging.sub_sock('androidLog') |
||||
|
||||
while True: |
||||
# check critical android services |
||||
if any(p is None or not p.is_running() for p in procs.values()) or not len(procs): |
||||
cur = {p: None for p in WATCHED_PROCS} |
||||
for p in psutil.process_iter(attrs=['cmdline']): |
||||
cmdline = None if not len(p.info['cmdline']) else p.info['cmdline'][0] |
||||
if cmdline in WATCHED_PROCS: |
||||
cur[cmdline] = p |
||||
|
||||
if len(procs): |
||||
for p in WATCHED_PROCS: |
||||
if cur[p] != procs[p]: |
||||
cloudlog.event("android service pid changed", proc=p, cur=cur[p], prev=procs[p], error=True) |
||||
procs.update(cur) |
||||
|
||||
# log caught NetworkPolicy exceptions |
||||
msgs = messaging.drain_sock(androidLog) |
||||
for m in msgs: |
||||
try: |
||||
if m.androidLog.tag == "NetworkPolicy" and m.androidLog.message.startswith("problem with advise persist threshold"): |
||||
cloudlog.event("network policy exception caught", androidLog=m.androidLog, error=True) |
||||
except UnicodeDecodeError: |
||||
pass |
||||
|
||||
if os.path.exists(MODEM_PATH): |
||||
# check modem state |
||||
state = get_modem_state() |
||||
if state != modem_state and not modem_killed: |
||||
cloudlog.event("modem state changed", state=state) |
||||
modem_state = state |
||||
|
||||
# check modem crashes |
||||
cnt = get_modem_crash_count() |
||||
if cnt is not None: |
||||
if cnt > crash_count: |
||||
cloudlog.event("modem crash", count=cnt) |
||||
crash_count = cnt |
||||
|
||||
# handle excessive modem crashes |
||||
if crash_count > MAX_MODEM_CRASHES and not modem_killed: |
||||
cloudlog.event("killing modem", error=True) |
||||
with open("/sys/kernel/debug/msm_subsys/modem", "w") as f: |
||||
f.write("put") |
||||
modem_killed = True |
||||
|
||||
time.sleep(1) |
||||
|
||||
if __name__ == "__main__": |
||||
main() |
@ -1,73 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <cstdlib> |
||||
#include <fstream> |
||||
|
||||
#include <gui/ISurfaceComposer.h> |
||||
#include <gui/SurfaceComposerClient.h> |
||||
#include <hardware/hwcomposer_defs.h> |
||||
|
||||
#include "selfdrive/common/util.h" |
||||
#include "selfdrive/hardware/base.h" |
||||
|
||||
class HardwareEon : public HardwareNone { |
||||
public: |
||||
static constexpr float MAX_VOLUME = 1.0; |
||||
static constexpr float MIN_VOLUME = 0.5; |
||||
|
||||
static bool EON() { return true; } |
||||
static std::string get_os_version() { |
||||
return "NEOS " + util::read_file("/VERSION"); |
||||
}; |
||||
|
||||
static void reboot() { std::system("reboot"); }; |
||||
static void poweroff() { std::system("LD_LIBRARY_PATH= svc power shutdown"); }; |
||||
static void set_brightness(int percent) { |
||||
std::ofstream brightness_control("/sys/class/leds/lcd-backlight/brightness"); |
||||
if (brightness_control.is_open()) { |
||||
brightness_control << (int)(percent * (255/100.)) << "\n"; |
||||
brightness_control.close(); |
||||
} |
||||
}; |
||||
static void set_display_power(bool on) { |
||||
auto dtoken = android::SurfaceComposerClient::getBuiltInDisplay(android::ISurfaceComposer::eDisplayIdMain); |
||||
android::SurfaceComposerClient::setDisplayPowerMode(dtoken, on ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF); |
||||
}; |
||||
|
||||
static bool get_ssh_enabled() { |
||||
return std::system("getprop persist.neos.ssh | grep -qF '1'") == 0; |
||||
}; |
||||
static void set_ssh_enabled(bool enabled) { |
||||
std::string cmd = util::string_format("setprop persist.neos.ssh %d", enabled ? 1 : 0); |
||||
std::system(cmd.c_str()); |
||||
}; |
||||
|
||||
// android only
|
||||
inline static bool launched_activity = false; |
||||
static void check_activity() { |
||||
int ret = std::system("dumpsys SurfaceFlinger --list | grep -Fq 'com.android.settings'"); |
||||
launched_activity = ret == 0; |
||||
} |
||||
|
||||
static void close_activities() { |
||||
if(launched_activity) { |
||||
std::system("pm disable com.android.settings && pm enable com.android.settings"); |
||||
} |
||||
} |
||||
|
||||
static void launch_activity(std::string activity, std::string opts = "") { |
||||
if (!launched_activity) { |
||||
std::string cmd = "am start -n " + activity + " " + opts + |
||||
" --ez extra_prefs_show_button_bar true \
|
||||
--es extra_prefs_set_next_text ''"; |
||||
std::system(cmd.c_str()); |
||||
} |
||||
launched_activity = true; |
||||
} |
||||
static void launch_wifi() { |
||||
launch_activity("com.android.settings/.wifi.WifiPickerActivity", "-a android.net.wifi.PICK_WIFI_NETWORK"); |
||||
} |
||||
static void launch_tethering() { |
||||
launch_activity("com.android.settings/.TetherSettings"); |
||||
} |
||||
}; |
@ -1,425 +0,0 @@ |
||||
import binascii |
||||
import itertools |
||||
import os |
||||
import re |
||||
import serial |
||||
import struct |
||||
import subprocess |
||||
from typing import List, Union |
||||
|
||||
from cereal import log |
||||
from selfdrive.hardware.base import HardwareBase, ThermalConfig |
||||
|
||||
try: |
||||
from common.params import Params |
||||
except Exception: |
||||
# openpilot is not built yet |
||||
Params = None |
||||
|
||||
NetworkType = log.DeviceState.NetworkType |
||||
NetworkStrength = log.DeviceState.NetworkStrength |
||||
|
||||
MODEM_PATH = "/dev/smd11" |
||||
|
||||
def service_call(call: List[str]) -> Union[bytes, None]: |
||||
try: |
||||
ret = subprocess.check_output(["service", "call", *call], encoding='utf8').strip() |
||||
if 'Parcel' not in ret: |
||||
return None |
||||
return parse_service_call_bytes(ret) |
||||
except subprocess.CalledProcessError: |
||||
return None |
||||
|
||||
|
||||
def parse_service_call_unpack(r, fmt) -> Union[bytes, None]: |
||||
try: |
||||
return struct.unpack(fmt, r)[0] |
||||
except Exception: |
||||
return None |
||||
|
||||
|
||||
def parse_service_call_string(r: bytes) -> Union[str, None]: |
||||
try: |
||||
r = r[8:] # Cut off length field |
||||
r_str = r.decode('utf_16_be') |
||||
|
||||
# All pairs of two characters seem to be swapped. Not sure why |
||||
result = "" |
||||
for a, b, in itertools.zip_longest(r_str[::2], r_str[1::2], fillvalue='\x00'): |
||||
result += b + a |
||||
|
||||
return result.replace('\x00', '') |
||||
except Exception: |
||||
return None |
||||
|
||||
|
||||
def parse_service_call_bytes(ret: str) -> Union[bytes, None]: |
||||
try: |
||||
r = b"" |
||||
for hex_part in re.findall(r'[ (]([0-9a-f]{8})', ret): |
||||
r += binascii.unhexlify(hex_part) |
||||
return r |
||||
except Exception: |
||||
return None |
||||
|
||||
|
||||
def getprop(key: str) -> Union[str, None]: |
||||
try: |
||||
return subprocess.check_output(["getprop", key], encoding='utf8').strip() |
||||
except subprocess.CalledProcessError: |
||||
return None |
||||
|
||||
|
||||
class Android(HardwareBase): |
||||
def get_os_version(self): |
||||
with open("/VERSION") as f: |
||||
return f.read().strip() |
||||
|
||||
def get_device_type(self): |
||||
try: |
||||
if int(Params().get("LastPeripheralPandaType")) == log.PandaState.PandaType.uno: |
||||
return "two" |
||||
except Exception: |
||||
pass |
||||
return "eon" |
||||
|
||||
def get_sound_card_online(self): |
||||
return (os.path.isfile('/proc/asound/card0/state') and |
||||
open('/proc/asound/card0/state').read().strip() == 'ONLINE') |
||||
|
||||
def get_imei(self, slot): |
||||
slot = str(slot) |
||||
if slot not in ("0", "1"): |
||||
raise ValueError("SIM slot must be 0 or 1") |
||||
|
||||
return parse_service_call_string(service_call(["iphonesubinfo", "3", "i32", str(slot)])) |
||||
|
||||
def get_serial(self): |
||||
ret = getprop("ro.serialno") |
||||
if len(ret) == 0: |
||||
ret = "cccccccc" |
||||
return ret |
||||
|
||||
def get_subscriber_info(self): |
||||
ret = parse_service_call_string(service_call(["iphonesubinfo", "7"])) |
||||
if ret is None or len(ret) < 8: |
||||
return "" |
||||
return ret |
||||
|
||||
def reboot(self, reason=None): |
||||
# e.g. reason="recovery" to go into recover mode |
||||
if reason is None: |
||||
reason_args = ["null"] |
||||
else: |
||||
reason_args = ["s16", reason] |
||||
|
||||
subprocess.check_output([ |
||||
"service", "call", "power", "16", # IPowerManager.reboot |
||||
"i32", "0", # no confirmation, |
||||
*reason_args, |
||||
"i32", "1" # wait |
||||
]) |
||||
|
||||
def uninstall(self): |
||||
with open('/cache/recovery/command', 'w') as f: |
||||
f.write('--wipe_data\n') |
||||
# IPowerManager.reboot(confirm=false, reason="recovery", wait=true) |
||||
self.reboot(reason="recovery") |
||||
|
||||
def get_sim_info(self): |
||||
# Used for athena |
||||
# TODO: build using methods from this class |
||||
sim_state = getprop("gsm.sim.state").split(",") |
||||
network_type = getprop("gsm.network.type").split(',') |
||||
mcc_mnc = getprop("gsm.sim.operator.numeric") or None |
||||
|
||||
sim_id = parse_service_call_string(service_call(['iphonesubinfo', '11'])) |
||||
cell_data_state = parse_service_call_unpack(service_call(['phone', '46']), ">q") |
||||
cell_data_connected = (cell_data_state == 2) |
||||
|
||||
return { |
||||
'sim_id': sim_id, |
||||
'mcc_mnc': mcc_mnc, |
||||
'network_type': network_type, |
||||
'sim_state': sim_state, |
||||
'data_connected': cell_data_connected |
||||
} |
||||
|
||||
def get_network_info(self): |
||||
msg = log.DeviceState.NetworkInfo.new_message() |
||||
msg.state = getprop("gsm.sim.state") or "" |
||||
msg.technology = getprop("gsm.network.type") or "" |
||||
msg.operator = getprop("gsm.sim.operator.numeric") or "" |
||||
|
||||
try: |
||||
modem = serial.Serial(MODEM_PATH, 115200, timeout=0.1) |
||||
modem.write(b"AT$QCRSRP?\r") |
||||
msg.extra = modem.read_until(b"OK\r\n").decode('utf-8') |
||||
|
||||
rsrp = msg.extra.split("$QCRSRP: ")[1].split("\r")[0].split(",") |
||||
msg.channel = int(rsrp[1]) |
||||
except Exception: |
||||
pass |
||||
|
||||
return msg |
||||
|
||||
def get_network_type(self): |
||||
wifi_check = parse_service_call_string(service_call(["connectivity", "2"])) |
||||
if wifi_check is None: |
||||
return NetworkType.none |
||||
elif 'WIFI' in wifi_check: |
||||
return NetworkType.wifi |
||||
else: |
||||
cell_check = parse_service_call_unpack(service_call(['phone', '59']), ">q") |
||||
# from TelephonyManager.java |
||||
cell_networks = { |
||||
0: NetworkType.none, |
||||
1: NetworkType.cell2G, |
||||
2: NetworkType.cell2G, |
||||
3: NetworkType.cell3G, |
||||
4: NetworkType.cell2G, |
||||
5: NetworkType.cell3G, |
||||
6: NetworkType.cell3G, |
||||
7: NetworkType.cell3G, |
||||
8: NetworkType.cell3G, |
||||
9: NetworkType.cell3G, |
||||
10: NetworkType.cell3G, |
||||
11: NetworkType.cell2G, |
||||
12: NetworkType.cell3G, |
||||
13: NetworkType.cell4G, |
||||
14: NetworkType.cell4G, |
||||
15: NetworkType.cell3G, |
||||
16: NetworkType.cell2G, |
||||
17: NetworkType.cell3G, |
||||
18: NetworkType.cell4G, |
||||
19: NetworkType.cell4G |
||||
} |
||||
return cell_networks.get(cell_check, NetworkType.none) |
||||
|
||||
def get_network_strength(self, network_type): |
||||
network_strength = NetworkStrength.unknown |
||||
|
||||
# from SignalStrength.java |
||||
def get_lte_level(rsrp, rssnr): |
||||
INT_MAX = 2147483647 |
||||
if rsrp == INT_MAX: |
||||
lvl_rsrp = NetworkStrength.unknown |
||||
elif rsrp >= -95: |
||||
lvl_rsrp = NetworkStrength.great |
||||
elif rsrp >= -105: |
||||
lvl_rsrp = NetworkStrength.good |
||||
elif rsrp >= -115: |
||||
lvl_rsrp = NetworkStrength.moderate |
||||
else: |
||||
lvl_rsrp = NetworkStrength.poor |
||||
if rssnr == INT_MAX: |
||||
lvl_rssnr = NetworkStrength.unknown |
||||
elif rssnr >= 45: |
||||
lvl_rssnr = NetworkStrength.great |
||||
elif rssnr >= 10: |
||||
lvl_rssnr = NetworkStrength.good |
||||
elif rssnr >= -30: |
||||
lvl_rssnr = NetworkStrength.moderate |
||||
else: |
||||
lvl_rssnr = NetworkStrength.poor |
||||
return max(lvl_rsrp, lvl_rssnr) |
||||
|
||||
def get_tdscdma_level(tdscmadbm): |
||||
lvl = NetworkStrength.unknown |
||||
if tdscmadbm > -25: |
||||
lvl = NetworkStrength.unknown |
||||
elif tdscmadbm >= -49: |
||||
lvl = NetworkStrength.great |
||||
elif tdscmadbm >= -73: |
||||
lvl = NetworkStrength.good |
||||
elif tdscmadbm >= -97: |
||||
lvl = NetworkStrength.moderate |
||||
elif tdscmadbm >= -110: |
||||
lvl = NetworkStrength.poor |
||||
return lvl |
||||
|
||||
def get_gsm_level(asu): |
||||
if asu <= 2 or asu == 99: |
||||
lvl = NetworkStrength.unknown |
||||
elif asu >= 12: |
||||
lvl = NetworkStrength.great |
||||
elif asu >= 8: |
||||
lvl = NetworkStrength.good |
||||
elif asu >= 5: |
||||
lvl = NetworkStrength.moderate |
||||
else: |
||||
lvl = NetworkStrength.poor |
||||
return lvl |
||||
|
||||
def get_evdo_level(evdodbm, evdosnr): |
||||
lvl_evdodbm = NetworkStrength.unknown |
||||
lvl_evdosnr = NetworkStrength.unknown |
||||
if evdodbm >= -65: |
||||
lvl_evdodbm = NetworkStrength.great |
||||
elif evdodbm >= -75: |
||||
lvl_evdodbm = NetworkStrength.good |
||||
elif evdodbm >= -90: |
||||
lvl_evdodbm = NetworkStrength.moderate |
||||
elif evdodbm >= -105: |
||||
lvl_evdodbm = NetworkStrength.poor |
||||
if evdosnr >= 7: |
||||
lvl_evdosnr = NetworkStrength.great |
||||
elif evdosnr >= 5: |
||||
lvl_evdosnr = NetworkStrength.good |
||||
elif evdosnr >= 3: |
||||
lvl_evdosnr = NetworkStrength.moderate |
||||
elif evdosnr >= 1: |
||||
lvl_evdosnr = NetworkStrength.poor |
||||
return max(lvl_evdodbm, lvl_evdosnr) |
||||
|
||||
def get_cdma_level(cdmadbm, cdmaecio): |
||||
lvl_cdmadbm = NetworkStrength.unknown |
||||
lvl_cdmaecio = NetworkStrength.unknown |
||||
if cdmadbm >= -75: |
||||
lvl_cdmadbm = NetworkStrength.great |
||||
elif cdmadbm >= -85: |
||||
lvl_cdmadbm = NetworkStrength.good |
||||
elif cdmadbm >= -95: |
||||
lvl_cdmadbm = NetworkStrength.moderate |
||||
elif cdmadbm >= -100: |
||||
lvl_cdmadbm = NetworkStrength.poor |
||||
if cdmaecio >= -90: |
||||
lvl_cdmaecio = NetworkStrength.great |
||||
elif cdmaecio >= -110: |
||||
lvl_cdmaecio = NetworkStrength.good |
||||
elif cdmaecio >= -130: |
||||
lvl_cdmaecio = NetworkStrength.moderate |
||||
elif cdmaecio >= -150: |
||||
lvl_cdmaecio = NetworkStrength.poor |
||||
return max(lvl_cdmadbm, lvl_cdmaecio) |
||||
|
||||
if network_type == NetworkType.none: |
||||
return network_strength |
||||
if network_type == NetworkType.wifi: |
||||
out = subprocess.check_output('dumpsys connectivity', shell=True).decode('utf-8') |
||||
network_strength = NetworkStrength.unknown |
||||
for line in out.split('\n'): |
||||
signal_str = "SignalStrength: " |
||||
if signal_str in line: |
||||
lvl_idx_start = line.find(signal_str) + len(signal_str) |
||||
lvl_idx_end = line.find(']', lvl_idx_start) |
||||
lvl = int(line[lvl_idx_start : lvl_idx_end]) |
||||
if lvl >= -50: |
||||
network_strength = NetworkStrength.great |
||||
elif lvl >= -60: |
||||
network_strength = NetworkStrength.good |
||||
elif lvl >= -70: |
||||
network_strength = NetworkStrength.moderate |
||||
else: |
||||
network_strength = NetworkStrength.poor |
||||
return network_strength |
||||
else: |
||||
# check cell strength |
||||
out = subprocess.check_output('dumpsys telephony.registry', shell=True).decode('utf-8') |
||||
for line in out.split('\n'): |
||||
if "mSignalStrength" in line: |
||||
arr = line.split(' ') |
||||
ns = 0 |
||||
if ("gsm" in arr[14]): |
||||
rsrp = int(arr[9]) |
||||
rssnr = int(arr[11]) |
||||
ns = get_lte_level(rsrp, rssnr) |
||||
if ns == NetworkStrength.unknown: |
||||
tdscmadbm = int(arr[13]) |
||||
ns = get_tdscdma_level(tdscmadbm) |
||||
if ns == NetworkStrength.unknown: |
||||
asu = int(arr[1]) |
||||
ns = get_gsm_level(asu) |
||||
else: |
||||
cdmadbm = int(arr[3]) |
||||
cdmaecio = int(arr[4]) |
||||
evdodbm = int(arr[5]) |
||||
evdosnr = int(arr[7]) |
||||
lvl_cdma = get_cdma_level(cdmadbm, cdmaecio) |
||||
lvl_edmo = get_evdo_level(evdodbm, evdosnr) |
||||
if lvl_edmo == NetworkStrength.unknown: |
||||
ns = lvl_cdma |
||||
elif lvl_cdma == NetworkStrength.unknown: |
||||
ns = lvl_edmo |
||||
else: |
||||
ns = min(lvl_cdma, lvl_edmo) |
||||
network_strength = max(network_strength, ns) |
||||
|
||||
return network_strength |
||||
|
||||
def get_battery_capacity(self): |
||||
return self.read_param_file("/sys/class/power_supply/battery/capacity", int, 100) |
||||
|
||||
def get_battery_status(self): |
||||
# This does not correspond with actual charging or not. |
||||
# If a USB cable is plugged in, it responds with 'Charging', even when charging is disabled |
||||
return self.read_param_file("/sys/class/power_supply/battery/status", lambda x: x.strip(), '') |
||||
|
||||
def get_battery_current(self): |
||||
return self.read_param_file("/sys/class/power_supply/battery/current_now", int) |
||||
|
||||
def get_battery_voltage(self): |
||||
return self.read_param_file("/sys/class/power_supply/battery/voltage_now", int) |
||||
|
||||
def get_battery_charging(self): |
||||
# This does correspond with actually charging |
||||
return self.read_param_file("/sys/class/power_supply/battery/charge_type", lambda x: x.strip() != "N/A", True) |
||||
|
||||
def set_battery_charging(self, on): |
||||
with open('/sys/class/power_supply/battery/charging_enabled', 'w') as f: |
||||
f.write(f"{1 if on else 0}\n") |
||||
|
||||
def get_usb_present(self): |
||||
return self.read_param_file("/sys/class/power_supply/usb/present", lambda x: bool(int(x)), False) |
||||
|
||||
def get_current_power_draw(self): |
||||
if self.get_battery_status() == 'Discharging': |
||||
# If the battery is discharging, we can use this measurement |
||||
# On C2: this is low by about 10-15%, probably mostly due to UNO draw not being factored in |
||||
return ((self.get_battery_voltage() / 1000000) * (self.get_battery_current() / 1000000)) |
||||
else: |
||||
# We don't have a good direct way to measure this if it's not "discharging" |
||||
return None |
||||
|
||||
def shutdown(self): |
||||
os.system('LD_LIBRARY_PATH="" svc power shutdown') |
||||
|
||||
def get_thermal_config(self): |
||||
# the thermal sensors on the 820 don't have meaningful names |
||||
return ThermalConfig(cpu=((5, 7, 10, 12), 10), gpu=((16,), 10), mem=(2, 10), |
||||
bat=("battery", 1000), ambient=("pa_therm0", 1), pmic=(("pm8994_tz",), 1000)) |
||||
|
||||
def set_screen_brightness(self, percentage): |
||||
with open("/sys/class/leds/lcd-backlight/brightness", "w") as f: |
||||
f.write(str(int(percentage * 2.55))) |
||||
|
||||
def get_screen_brightness(self): |
||||
try: |
||||
with open("/sys/class/leds/lcd-backlight/brightness") as f: |
||||
return int(float(f.read()) / 2.55) |
||||
except Exception: |
||||
return 0 |
||||
|
||||
def set_power_save(self, powersave_enabled): |
||||
pass |
||||
|
||||
def get_gpu_usage_percent(self): |
||||
try: |
||||
used, total = open('/sys/devices/soc/b00000.qcom,kgsl-3d0/kgsl/kgsl-3d0/gpubusy').read().strip().split() |
||||
perc = 100.0 * int(used) / int(total) |
||||
return min(max(perc, 0), 100) |
||||
except Exception: |
||||
return 0 |
||||
|
||||
def get_modem_temperatures(self): |
||||
# Not sure if we can get this on the LeEco |
||||
return [] |
||||
|
||||
def get_nvme_temperatures(self): |
||||
return [] |
||||
|
||||
def initialize_hardware(self): |
||||
pass |
||||
|
||||
def get_networks(self): |
||||
return None |
@ -1,7 +0,0 @@ |
||||
{ |
||||
"ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-50da8800caa5cbc224acbaa21f3a83d21802a31d89cccfc62a898903a8eb19e7.zip", |
||||
"ota_hash": "50da8800caa5cbc224acbaa21f3a83d21802a31d89cccfc62a898903a8eb19e7", |
||||
"recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-fe76739438d28ea6111853a737b616afdf340ba75c01c0ee99e6a28c19ecc29f.img", |
||||
"recovery_len": 15222060, |
||||
"recovery_hash": "fe76739438d28ea6111853a737b616afdf340ba75c01c0ee99e6a28c19ecc29f" |
||||
} |
@ -1,130 +0,0 @@ |
||||
#!/usr/bin/env python3 |
||||
import argparse |
||||
import hashlib |
||||
import json |
||||
import logging |
||||
import os |
||||
import requests |
||||
|
||||
NEOSUPDATE_DIR = "/data/neoupdate" |
||||
|
||||
RECOVERY_DEV = "/dev/block/bootdevice/by-name/recovery" |
||||
RECOVERY_COMMAND = "/cache/recovery/command" |
||||
|
||||
|
||||
def get_fn(url: str): |
||||
return os.path.join(NEOSUPDATE_DIR, os.path.basename(url)) |
||||
|
||||
|
||||
def download_file(url: str, fn: str, sha256: str, display_name: str, cloudlog=logging) -> None: |
||||
# check if already downloaded |
||||
if check_hash(fn, sha256): |
||||
cloudlog.info(f"{display_name} already cached") |
||||
return |
||||
|
||||
try: |
||||
with open(fn, "ab+") as f: |
||||
headers = {"Range": f"bytes={f.tell()}-"} |
||||
r = requests.get(url, stream=True, allow_redirects=True, headers=headers) |
||||
r.raise_for_status() |
||||
|
||||
total = int(r.headers['Content-Length']) |
||||
if 'Content-Range' in r.headers: |
||||
total = int(r.headers['Content-Range'].split('/')[-1]) |
||||
|
||||
for chunk in r.iter_content(chunk_size=1024 * 1024): |
||||
f.write(chunk) |
||||
print(f"Downloading {display_name}: {f.tell() / total * 100}", flush=True) |
||||
except Exception: |
||||
cloudlog.error("download error") |
||||
if os.path.isfile(fn): |
||||
os.unlink(fn) |
||||
raise |
||||
|
||||
if not check_hash(fn, sha256): |
||||
if os.path.isfile(fn): |
||||
os.unlink(fn) |
||||
raise Exception("downloaded update failed hash check") |
||||
|
||||
|
||||
def check_hash(fn: str, sha256: str, length: int = -1) -> bool: |
||||
if not os.path.exists(fn): |
||||
return False |
||||
|
||||
h = hashlib.sha256() |
||||
with open(fn, "rb") as f: |
||||
while f.tell() != length: |
||||
r = min(max(0, length - f.tell()), 1024 * 1024) if length > 0 else 1024 * 1024 |
||||
dat = f.read(r) |
||||
if not dat: |
||||
break |
||||
h.update(dat) |
||||
return h.hexdigest().lower() == sha256.lower() |
||||
|
||||
|
||||
def flash_update(update_fn: str, out_path: str) -> None: |
||||
with open(update_fn, "rb") as update, open(out_path, "w+b") as out: |
||||
while True: |
||||
dat = update.read(8192) |
||||
if len(dat) == 0: |
||||
break |
||||
out.write(dat) |
||||
|
||||
|
||||
def download_neos_update(manifest_path: str, cloudlog=logging) -> None: |
||||
with open(manifest_path) as f: |
||||
m = json.load(f) |
||||
|
||||
os.makedirs(NEOSUPDATE_DIR, exist_ok=True) |
||||
|
||||
# handle recovery updates |
||||
if not check_hash(RECOVERY_DEV, m['recovery_hash'], m['recovery_len']): |
||||
cloudlog.info("recovery needs update") |
||||
recovery_fn = os.path.join(NEOSUPDATE_DIR, os.path.basename(m['recovery_url'])) |
||||
download_file(m['recovery_url'], recovery_fn, m['recovery_hash'], "recovery", cloudlog) |
||||
|
||||
flash_update(recovery_fn, RECOVERY_DEV) |
||||
assert check_hash(RECOVERY_DEV, m['recovery_hash'], m['recovery_len']), "recovery flash corrupted" |
||||
cloudlog.info("recovery successfully flashed") |
||||
|
||||
# download OTA update |
||||
download_file(m['ota_url'], get_fn(m['ota_url']), m['ota_hash'], "system", cloudlog) |
||||
|
||||
|
||||
def verify_update_ready(manifest_path: str) -> bool: |
||||
with open(manifest_path) as f: |
||||
m = json.load(f) |
||||
|
||||
ota_downloaded = check_hash(get_fn(m['ota_url']), m['ota_hash']) |
||||
recovery_flashed = check_hash(RECOVERY_DEV, m['recovery_hash'], m['recovery_len']) |
||||
return ota_downloaded and recovery_flashed |
||||
|
||||
|
||||
def perform_ota_update(manifest_path: str) -> None: |
||||
with open(manifest_path) as f: |
||||
m = json.load(f) |
||||
|
||||
# reboot into recovery |
||||
ota_fn = get_fn(m['ota_url']) |
||||
with open(RECOVERY_COMMAND, "w") as rf: |
||||
rf.write(f"--update_package={ota_fn}\n") |
||||
os.system("service call power 16 i32 0 s16 recovery i32 1") |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
parser = argparse.ArgumentParser(description="NEOS update utility", |
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter) |
||||
parser.add_argument("--swap", action="store_true", help="Peform update after downloading") |
||||
parser.add_argument("--swap-if-ready", action="store_true", help="Perform update if already downloaded") |
||||
parser.add_argument("manifest", help="Manifest json") |
||||
args = parser.parse_args() |
||||
|
||||
logging.basicConfig(level=logging.INFO) |
||||
|
||||
if args.swap_if_ready: |
||||
if verify_update_ready(args.manifest): |
||||
perform_ota_update(args.manifest) |
||||
else: |
||||
download_neos_update(args.manifest, logging) |
||||
if args.swap: |
||||
perform_ota_update(args.manifest) |
@ -1,34 +0,0 @@ |
||||
#!/usr/bin/env python3 |
||||
import os |
||||
import time |
||||
import datetime |
||||
|
||||
from common.params import Params |
||||
from selfdrive.hardware.eon.hardware import getprop |
||||
from selfdrive.swaglog import cloudlog |
||||
|
||||
def main(): |
||||
prev = b"" |
||||
params = Params() |
||||
while True: |
||||
with open("/dev/__properties__", 'rb') as f: |
||||
cur = f.read() |
||||
|
||||
if cur != prev: |
||||
prev = cur |
||||
|
||||
# 0 for shutdown, 1 for reboot |
||||
prop = getprop("sys.shutdown.requested") |
||||
if prop is not None and len(prop) > 0: |
||||
os.system("pkill -9 loggerd") |
||||
params.put("LastSystemShutdown", f"'{prop}' {datetime.datetime.now()}") |
||||
os.sync() |
||||
|
||||
time.sleep(120) |
||||
cloudlog.error('shutdown false positive') |
||||
break |
||||
|
||||
time.sleep(0.1) |
||||
|
||||
if __name__ == "__main__": |
||||
main() |
@ -1,145 +0,0 @@ |
||||
#!/usr/bin/env python3 |
||||
import hashlib |
||||
import http.server |
||||
import json |
||||
import os |
||||
import unittest |
||||
import random |
||||
import requests |
||||
import shutil |
||||
import socketserver |
||||
import tempfile |
||||
import multiprocessing |
||||
from pathlib import Path |
||||
|
||||
from selfdrive.hardware.eon.neos import RECOVERY_DEV, NEOSUPDATE_DIR, get_fn, download_file, \ |
||||
verify_update_ready, download_neos_update |
||||
|
||||
EON_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__))) |
||||
MANIFEST = os.path.join(EON_DIR, "neos.json") |
||||
|
||||
PORT = 8000 |
||||
|
||||
def server_thread(port): |
||||
socketserver.TCPServer.allow_reuse_address = True |
||||
httpd = socketserver.TCPServer(("", port), http.server.SimpleHTTPRequestHandler) |
||||
httpd.serve_forever() |
||||
|
||||
|
||||
class TestNeosUpdater(unittest.TestCase): |
||||
|
||||
@classmethod |
||||
def setUpClass(cls): |
||||
# generate a fake manifest |
||||
cls.manifest = {} |
||||
for i in ('ota', 'recovery'): |
||||
with tempfile.NamedTemporaryFile(delete=False, dir=os.getcwd()) as f: |
||||
dat = os.urandom(random.randint(1000, 100000)) |
||||
f.write(dat) |
||||
cls.manifest[f"{i}_url"] = f"http://localhost:{PORT}/" + os.path.relpath(f.name) |
||||
cls.manifest[F"{i}_hash"] = hashlib.sha256(dat).hexdigest() |
||||
if i == "recovery": |
||||
cls.manifest["recovery_len"] = len(dat) |
||||
|
||||
with tempfile.NamedTemporaryFile(delete=False, mode='w') as f: |
||||
f.write(json.dumps(cls.manifest)) |
||||
cls.fake_manifest = f.name |
||||
|
||||
@classmethod |
||||
def tearDownClass(cls): |
||||
os.unlink(cls.fake_manifest) |
||||
os.unlink(os.path.basename(cls.manifest['ota_url'])) |
||||
os.unlink(os.path.basename(cls.manifest['recovery_url'])) |
||||
|
||||
def setUp(self): |
||||
# server for update files |
||||
self.server = multiprocessing.Process(target=server_thread, args=(PORT, )) |
||||
self.server.start() |
||||
|
||||
# clean up |
||||
if os.path.exists(NEOSUPDATE_DIR): |
||||
shutil.rmtree(NEOSUPDATE_DIR) |
||||
|
||||
def tearDown(self): |
||||
self.server.kill() |
||||
self.server.join(1) |
||||
|
||||
def _corrupt_recovery(self): |
||||
with open(RECOVERY_DEV, "wb") as f: |
||||
f.write(b'\x00'*100) |
||||
|
||||
def test_manifest(self): |
||||
with open(MANIFEST) as f: |
||||
m = json.load(f) |
||||
|
||||
assert m['ota_hash'] in m['ota_url'] |
||||
assert m['recovery_hash'] in m['recovery_url'] |
||||
assert m['recovery_len'] > 0 |
||||
|
||||
for url in (m['ota_url'], m['recovery_url']): |
||||
r = requests.head(m['recovery_url']) |
||||
r.raise_for_status() |
||||
self.assertEqual(r.headers['Content-Type'], "application/octet-stream") |
||||
if url == m['recovery_url']: |
||||
self.assertEqual(int(r.headers['Content-Length']), m['recovery_len']) |
||||
|
||||
def test_download_hash_check(self): |
||||
os.makedirs(NEOSUPDATE_DIR, exist_ok=True) |
||||
Path(get_fn(self.manifest['ota_url'])).touch() |
||||
with self.assertRaisesRegex(Exception, "failed hash check"): |
||||
download_file(self.manifest['ota_url'], get_fn(self.manifest['ota_url']), |
||||
self.manifest['ota_hash']+'a', "system") |
||||
|
||||
# should've unlinked after the failed hash check, should succeed now |
||||
download_file(self.manifest['ota_url'], get_fn(self.manifest['ota_url']), |
||||
self.manifest['ota_hash'], "system") |
||||
|
||||
# TODO: needs an http server that supports Content-Range |
||||
#def test_download_resume(self): |
||||
# os.makedirs(NEOSUPDATE_DIR, exist_ok=True) |
||||
# with open(os.path.basename(self.manifest['ota_url']), "rb") as src, \ |
||||
# open(get_fn(self.manifest['ota_url']), "wb") as dest: |
||||
# l = dest.write(src.read(8192)) |
||||
# assert l == 8192 |
||||
# download_file(self.manifest['ota_url'], get_fn(self.manifest['ota_url']), |
||||
# self.manifest['ota_hash'], "system") |
||||
|
||||
def test_download_no_internet(self): |
||||
self.server.kill() |
||||
os.makedirs(NEOSUPDATE_DIR, exist_ok=True) |
||||
# fail, no internet |
||||
with self.assertRaises(requests.exceptions.ConnectionError): |
||||
download_file(self.manifest['ota_url'], get_fn(self.manifest['ota_url']), |
||||
self.manifest['ota_hash'], "system") |
||||
|
||||
# already cached, ensure we don't hit the server |
||||
shutil.copyfile(os.path.basename(self.manifest['ota_url']), get_fn(self.manifest['ota_url'])) |
||||
download_file(self.manifest['ota_url'], get_fn(self.manifest['ota_url']), |
||||
self.manifest['ota_hash'], "system") |
||||
|
||||
|
||||
def test_download_update(self): |
||||
download_neos_update(self.fake_manifest) |
||||
self.assertTrue(verify_update_ready(self.fake_manifest)) |
||||
|
||||
def test_verify_update(self): |
||||
# good state |
||||
download_neos_update(self.fake_manifest) |
||||
self.assertTrue(verify_update_ready(self.fake_manifest)) |
||||
|
||||
# corrupt recovery |
||||
self._corrupt_recovery() |
||||
self.assertFalse(verify_update_ready(self.fake_manifest)) |
||||
|
||||
# back to good state |
||||
download_neos_update(self.fake_manifest) |
||||
self.assertTrue(verify_update_ready(self.fake_manifest)) |
||||
|
||||
# corrupt ota |
||||
self._corrupt_recovery() |
||||
with open(os.path.join(NEOSUPDATE_DIR, os.path.basename(self.manifest['ota_url'])), "ab") as f: |
||||
f.write(b'\x00') |
||||
self.assertFalse(verify_update_ready(self.fake_manifest)) |
||||
|
||||
if __name__ == "__main__": |
||||
unittest.main() |
@ -1,4 +0,0 @@ |
||||
#!/usr/bin/bash |
||||
|
||||
ROOT=$PWD/../../.. |
||||
$ROOT/installer/updater/updater "file://$ROOT/installer/updater/update.json" |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:93fa3a75fe891d75c3adc515c65dcd899ace6063e16eaf417d202b6befaba3d1 |
||||
size 3193008 |
@ -1,6 +1,3 @@ |
||||
Import('env', 'cereal', 'messaging', 'common', 'arch') |
||||
Import('env', 'cereal', 'messaging', 'common') |
||||
|
||||
if arch == "aarch64": |
||||
env.Program('logcatd', 'logcatd_android.cc', LIBS=[cereal, messaging, common, 'cutils', 'zmq', 'capnp', 'kj']) |
||||
else: |
||||
env.Program('logcatd', 'logcatd_systemd.cc', LIBS=[cereal, messaging, common, 'zmq', 'capnp', 'kj', 'systemd', 'json11']) |
||||
env.Program('logcatd', 'logcatd_systemd.cc', LIBS=[cereal, messaging, common, 'zmq', 'capnp', 'kj', 'systemd', 'json11']) |
||||
|
@ -1,51 +0,0 @@ |
||||
#include <android/log.h> |
||||
#include <log/logger.h> |
||||
#include <log/logprint.h> |
||||
#include <sys/resource.h> |
||||
|
||||
#include <csignal> |
||||
|
||||
#include "cereal/messaging/messaging.h" |
||||
|
||||
#undef LOG_ID_KERNEL |
||||
#define LOG_ID_KERNEL 5 |
||||
|
||||
int main() { |
||||
std::signal(SIGINT, exit); |
||||
std::signal(SIGTERM, exit); |
||||
setpriority(PRIO_PROCESS, 0, -15); |
||||
|
||||
// setup android logging
|
||||
logger_list *logger_list = android_logger_list_alloc(ANDROID_LOG_RDONLY, 0, 0); |
||||
assert(logger_list); |
||||
for (auto log_id : {LOG_ID_MAIN, LOG_ID_RADIO, LOG_ID_SYSTEM, LOG_ID_CRASH, (log_id_t)LOG_ID_KERNEL}) { |
||||
logger *logger = android_logger_open(logger_list, log_id); |
||||
assert(logger); |
||||
} |
||||
|
||||
PubMaster pm({"androidLog"}); |
||||
|
||||
while (true) { |
||||
log_msg log_msg; |
||||
int err = android_logger_list_read(logger_list, &log_msg); |
||||
if (err <= 0) break; |
||||
|
||||
AndroidLogEntry entry; |
||||
err = android_log_processLogBuffer(&log_msg.entry_v1, &entry); |
||||
if (err < 0) continue; |
||||
|
||||
MessageBuilder msg; |
||||
auto androidEntry = msg.initEvent().initAndroidLog(); |
||||
androidEntry.setId(log_msg.id()); |
||||
androidEntry.setTs(entry.tv_sec * NS_PER_SEC + entry.tv_nsec); |
||||
androidEntry.setPriority(entry.priority); |
||||
androidEntry.setPid(entry.pid); |
||||
androidEntry.setTid(entry.tid); |
||||
androidEntry.setTag(entry.tag); |
||||
androidEntry.setMessage(entry.message); |
||||
pm.send("androidLog", msg); |
||||
} |
||||
|
||||
android_logger_list_free(logger_list); |
||||
return 0; |
||||
} |
@ -1,45 +0,0 @@ |
||||
#!/usr/bin/env python3 |
||||
import os |
||||
import random |
||||
import string |
||||
import time |
||||
import unittest |
||||
import uuid |
||||
|
||||
import cereal.messaging as messaging |
||||
from selfdrive.test.helpers import with_processes |
||||
|
||||
class TestLogcatdAndroid(unittest.TestCase): |
||||
|
||||
@with_processes(['logcatd']) |
||||
def test_log(self): |
||||
sock = messaging.sub_sock("androidLog", conflate=False) |
||||
|
||||
# make sure sockets are ready |
||||
time.sleep(1) |
||||
messaging.drain_sock(sock) |
||||
|
||||
sent_msgs = {} |
||||
for _ in range(random.randint(2, 10)): |
||||
# write some log messages |
||||
for __ in range(random.randint(5, 50)): |
||||
tag = uuid.uuid4().hex |
||||
msg = ''.join(random.choice(string.ascii_letters) for _ in range(random.randrange(2, 50))) |
||||
sent_msgs[tag] = {'recv_cnt': 0, 'msg': msg} |
||||
os.system(f"log -t '{tag}' '{msg}'") |
||||
|
||||
time.sleep(1) |
||||
msgs = messaging.drain_sock(sock) |
||||
for m in msgs: |
||||
self.assertTrue(m.valid) |
||||
self.assertLess(time.monotonic() - (m.logMonoTime / 1e9), 30) |
||||
tag = m.androidLog.tag |
||||
if tag in sent_msgs: |
||||
sent_msgs[tag]['recv_cnt'] += 1 |
||||
self.assertEqual(m.androidLog.message.strip(), sent_msgs[tag]['msg']) |
||||
|
||||
for v in sent_msgs.values(): |
||||
self.assertEqual(v['recv_cnt'], 1) |
||||
|
||||
if __name__ == "__main__": |
||||
unittest.main() |
@ -1,22 +1,19 @@ |
||||
Import('env', 'arch', 'common', 'cereal', 'messaging') |
||||
|
||||
if arch == "aarch64": |
||||
env.Program('_sensord', 'sensors_qcom.cc', LIBS=['hardware', common, cereal, messaging, 'capnp', 'zmq', 'kj']) |
||||
else: |
||||
sensors = [ |
||||
'sensors/file_sensor.cc', |
||||
'sensors/i2c_sensor.cc', |
||||
'sensors/light_sensor.cc', |
||||
'sensors/bmx055_accel.cc', |
||||
'sensors/bmx055_gyro.cc', |
||||
'sensors/bmx055_magn.cc', |
||||
'sensors/bmx055_temp.cc', |
||||
'sensors/lsm6ds3_accel.cc', |
||||
'sensors/lsm6ds3_gyro.cc', |
||||
'sensors/lsm6ds3_temp.cc', |
||||
'sensors/mmc5603nj_magn.cc', |
||||
] |
||||
libs = [common, cereal, messaging, 'capnp', 'zmq', 'kj'] |
||||
if arch == "larch64": |
||||
libs.append('i2c') |
||||
env.Program('_sensord', ['sensors_qcom2.cc'] + sensors, LIBS=libs) |
||||
sensors = [ |
||||
'sensors/file_sensor.cc', |
||||
'sensors/i2c_sensor.cc', |
||||
'sensors/light_sensor.cc', |
||||
'sensors/bmx055_accel.cc', |
||||
'sensors/bmx055_gyro.cc', |
||||
'sensors/bmx055_magn.cc', |
||||
'sensors/bmx055_temp.cc', |
||||
'sensors/lsm6ds3_accel.cc', |
||||
'sensors/lsm6ds3_gyro.cc', |
||||
'sensors/lsm6ds3_temp.cc', |
||||
'sensors/mmc5603nj_magn.cc', |
||||
] |
||||
libs = [common, cereal, messaging, 'capnp', 'zmq', 'kj'] |
||||
if arch == "larch64": |
||||
libs.append('i2c') |
||||
env.Program('_sensord', ['sensors_qcom2.cc'] + sensors, LIBS=libs) |
||||
|
@ -1,228 +0,0 @@ |
||||
#include <cutils/log.h> |
||||
#include <hardware/sensors.h> |
||||
#include <sys/cdefs.h> |
||||
#include <sys/resource.h> |
||||
#include <sys/time.h> |
||||
#include <sys/types.h> |
||||
#include <unistd.h> |
||||
#include <utils/Timers.h> |
||||
|
||||
#include <cassert> |
||||
#include <cstdint> |
||||
#include <cstdio> |
||||
#include <cstdlib> |
||||
#include <cstring> |
||||
#include <map> |
||||
#include <set> |
||||
|
||||
#include "cereal/messaging/messaging.h" |
||||
#include "selfdrive/common/swaglog.h" |
||||
#include "selfdrive/common/timing.h" |
||||
#include "selfdrive/common/util.h" |
||||
|
||||
// ACCELEROMETER_UNCALIBRATED is only in Android O
|
||||
// https://developer.android.com/reference/android/hardware/Sensor.html#STRING_TYPE_ACCELEROMETER_UNCALIBRATED
|
||||
|
||||
#define SENSOR_ACCELEROMETER 1 |
||||
#define SENSOR_MAGNETOMETER 2 |
||||
#define SENSOR_GYRO 4 |
||||
#define SENSOR_MAGNETOMETER_UNCALIBRATED 3 |
||||
#define SENSOR_GYRO_UNCALIBRATED 5 |
||||
#define SENSOR_PROXIMITY 6 |
||||
#define SENSOR_LIGHT 7 |
||||
|
||||
ExitHandler do_exit; |
||||
volatile sig_atomic_t re_init_sensors = 0; |
||||
|
||||
namespace { |
||||
|
||||
void sigpipe_handler(int sig) { |
||||
LOGE("SIGPIPE received"); |
||||
re_init_sensors = true; |
||||
} |
||||
|
||||
void sensor_loop() { |
||||
LOG("*** sensor loop"); |
||||
|
||||
uint64_t frame = 0; |
||||
bool low_power_mode = false; |
||||
|
||||
while (!do_exit) { |
||||
SubMaster sm({"deviceState"}); |
||||
PubMaster pm({"sensorEvents"}); |
||||
|
||||
struct sensors_poll_device_t* device; |
||||
struct sensors_module_t* module; |
||||
|
||||
hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); |
||||
sensors_open(&module->common, &device); |
||||
|
||||
// required
|
||||
struct sensor_t const* list; |
||||
int count = module->get_sensors_list(module, &list); |
||||
LOG("%d sensors found", count); |
||||
|
||||
if (getenv("SENSOR_TEST")) { |
||||
exit(count); |
||||
} |
||||
|
||||
for (int i = 0; i < count; i++) { |
||||
LOGD("sensor %4d: %4d %60s %d-%ld us", i, list[i].handle, list[i].name, list[i].minDelay, list[i].maxDelay); |
||||
} |
||||
|
||||
std::set<int> sensor_types = { |
||||
SENSOR_TYPE_ACCELEROMETER, |
||||
SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED, |
||||
SENSOR_TYPE_MAGNETIC_FIELD, |
||||
SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, |
||||
SENSOR_TYPE_GYROSCOPE, |
||||
SENSOR_TYPE_PROXIMITY, |
||||
SENSOR_TYPE_LIGHT, |
||||
}; |
||||
|
||||
std::map<int, int64_t> sensors = { |
||||
{SENSOR_GYRO_UNCALIBRATED, ms2ns(10)}, |
||||
{SENSOR_MAGNETOMETER_UNCALIBRATED, ms2ns(100)}, |
||||
{SENSOR_ACCELEROMETER, ms2ns(10)}, |
||||
{SENSOR_GYRO, ms2ns(10)}, |
||||
{SENSOR_MAGNETOMETER, ms2ns(100)}, |
||||
{SENSOR_PROXIMITY, ms2ns(100)}, |
||||
{SENSOR_LIGHT, ms2ns(100)} |
||||
}; |
||||
|
||||
// sensors needed while offroad
|
||||
std::set<int> offroad_sensors = { |
||||
SENSOR_LIGHT, |
||||
SENSOR_ACCELEROMETER, |
||||
SENSOR_GYRO_UNCALIBRATED, |
||||
}; |
||||
|
||||
// init all the sensors
|
||||
for (auto &s : sensors) { |
||||
device->activate(device, s.first, 0); |
||||
device->activate(device, s.first, 1); |
||||
device->setDelay(device, s.first, s.second); |
||||
} |
||||
|
||||
// TODO: why is this 16?
|
||||
static const size_t numEvents = 16; |
||||
sensors_event_t buffer[numEvents]; |
||||
|
||||
while (!do_exit) { |
||||
int n = device->poll(device, buffer, numEvents); |
||||
if (n == 0) continue; |
||||
if (n < 0) { |
||||
LOG("sensor_loop poll failed: %d", n); |
||||
continue; |
||||
} |
||||
|
||||
int log_events = 0; |
||||
for (int i=0; i < n; i++) { |
||||
if (sensor_types.find(buffer[i].type) != sensor_types.end()) { |
||||
log_events++; |
||||
} |
||||
} |
||||
|
||||
MessageBuilder msg; |
||||
auto sensor_events = msg.initEvent().initSensorEvents(log_events); |
||||
|
||||
int log_i = 0; |
||||
for (int i = 0; i < n; i++) { |
||||
|
||||
const sensors_event_t& data = buffer[i]; |
||||
|
||||
if (sensor_types.find(data.type) == sensor_types.end()) { |
||||
continue; |
||||
} |
||||
|
||||
auto log_event = sensor_events[log_i]; |
||||
log_event.setSource(cereal::SensorEventData::SensorSource::ANDROID); |
||||
log_event.setVersion(data.version); |
||||
log_event.setSensor(data.sensor); |
||||
log_event.setType(data.type); |
||||
log_event.setTimestamp(data.timestamp); |
||||
|
||||
switch (data.type) { |
||||
case SENSOR_TYPE_ACCELEROMETER: { |
||||
auto svec = log_event.initAcceleration(); |
||||
svec.setV(data.acceleration.v); |
||||
svec.setStatus(data.acceleration.status); |
||||
break; |
||||
} |
||||
case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED: { |
||||
auto svec = log_event.initMagneticUncalibrated(); |
||||
// assuming the uncalib and bias floats are contiguous in memory
|
||||
kj::ArrayPtr<const float> vs(&data.uncalibrated_magnetic.uncalib[0], 6); |
||||
svec.setV(vs); |
||||
break; |
||||
} |
||||
case SENSOR_TYPE_MAGNETIC_FIELD: { |
||||
auto svec = log_event.initMagnetic(); |
||||
svec.setV(data.magnetic.v); |
||||
svec.setStatus(data.magnetic.status); |
||||
break; |
||||
} |
||||
case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: { |
||||
auto svec = log_event.initGyroUncalibrated(); |
||||
// assuming the uncalib and bias floats are contiguous in memory
|
||||
kj::ArrayPtr<const float> vs(&data.uncalibrated_gyro.uncalib[0], 6); |
||||
svec.setV(vs); |
||||
break; |
||||
} |
||||
case SENSOR_TYPE_GYROSCOPE: { |
||||
auto svec = log_event.initGyro(); |
||||
svec.setV(data.gyro.v); |
||||
svec.setStatus(data.gyro.status); |
||||
break; |
||||
} |
||||
case SENSOR_TYPE_PROXIMITY: { |
||||
log_event.setProximity(data.distance); |
||||
break; |
||||
} |
||||
case SENSOR_TYPE_LIGHT: |
||||
log_event.setLight(data.light); |
||||
break; |
||||
} |
||||
|
||||
log_i++; |
||||
} |
||||
|
||||
pm.send("sensorEvents", msg); |
||||
|
||||
if (re_init_sensors) { |
||||
LOGE("Resetting sensors"); |
||||
re_init_sensors = false; |
||||
break; |
||||
} |
||||
|
||||
// Check whether to go into low power mode at 5Hz
|
||||
if (frame % 20 == 0) { |
||||
sm.update(0); |
||||
bool offroad = !sm["deviceState"].getDeviceState().getStarted(); |
||||
if (low_power_mode != offroad) { |
||||
for (auto &s : sensors) { |
||||
device->activate(device, s.first, 0); |
||||
if (!offroad || offroad_sensors.find(s.first) != offroad_sensors.end()) { |
||||
device->activate(device, s.first, 1); |
||||
} |
||||
} |
||||
low_power_mode = offroad; |
||||
} |
||||
} |
||||
|
||||
frame++; |
||||
} |
||||
sensors_close(device); |
||||
} |
||||
} |
||||
|
||||
}// Namespace end
|
||||
|
||||
int main(int argc, char *argv[]) { |
||||
setpriority(PRIO_PROCESS, 0, -18); |
||||
signal(SIGPIPE, (sighandler_t)sigpipe_handler); |
||||
|
||||
sensor_loop(); |
||||
|
||||
return 0; |
||||
} |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:56a3413e09c42849a190031665a2bdabf628a495fd3c8e181c8e863c22a7cd64 |
||||
size 3166352 |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:8c33f9f4090720b23f3c70cf1fe5b3bda23f31fe17a20f769279bf14dbb1178e |
||||
size 3214400 |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:fa02515dd1229ea78c0354189112f1d5ca777f581803d4344f744e80e3b2aa91 |
||||
size 576129 |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:ed4929ed8af91c883a28d53e491eca6e970cebc09669a3499db4cd380c937a9a |
||||
size 1200745 |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:d6873d1bf018369aaf13cabe5d870d3154656668b31647df0a1a648b3bb383dc |
||||
size 1324409 |
@ -1 +0,0 @@ |
||||
libqpOASES_e.so.3.1 |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:17841debecba17ce4bb1150820c61f9d965c3cb045f46afc8b20ee286dd42350 |
||||
size 218545 |
@ -1,3 +0,0 @@ |
||||
version https://git-lfs.github.com/spec/v1 |
||||
oid sha256:c3f13c06f967ae8c785c73e716c9e0ce9f4688b55fde0d798d4fa077a1edb0ad |
||||
size 4498992 |
@ -1,3 +0,0 @@ |
||||
git clone https://github.com/CyanogenMod/android_frameworks_native.git && cd android_frameworks_native |
||||
git reset --hard b22bca465e55618a949d9cbdea665a1a3a831241 |
||||
cp -r include ~/one/third_party/android_frameworks_native/ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue