102 lines
3.3 KiB
Python
Executable file
102 lines
3.3 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# 2020 - Marco Trevisan
|
|
#
|
|
# Initializer for ThinkPad's validity sensors 138a:0090 and 138a:0097 and 06cb:009a
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import argparse
|
|
import hashlib
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import urllib.request
|
|
|
|
from usb import core as usb_core
|
|
|
|
from validitysensor.init_data_dir import PYTHON_VALIDITY_DATA_DIR
|
|
from validitysensor.firmware_tables import FIRMWARE_NAMES, FIRMWARE_URIS
|
|
from validitysensor.usb import SupportedDevices
|
|
|
|
|
|
|
|
def download_and_extract_fw(dev_type, fwdir, fwuri=None):
|
|
fwuri = fwuri if fwuri else FIRMWARE_URIS[dev_type]['driver']
|
|
expected_hash = FIRMWARE_URIS[dev_type]['sha512']
|
|
fwarchive = os.path.join(fwdir, 'fwinstaller.exe')
|
|
fwname = FIRMWARE_NAMES[dev_type]
|
|
|
|
print('Downloading {} to extract {}'.format(fwuri, fwname))
|
|
|
|
req = urllib.request.Request(fwuri)
|
|
req.add_header('Referer', FIRMWARE_URIS[dev_type].get('referral', ''))
|
|
req.add_header('User-Agent', 'Mozilla/5.0 (X11; U; Linux)')
|
|
|
|
hash = hashlib.sha512()
|
|
with urllib.request.urlopen(req) as response:
|
|
with open(fwarchive, 'wb') as out_file:
|
|
data = response.read()
|
|
hash.update(data)
|
|
out_file.write(data)
|
|
|
|
actual_hash = hash.hexdigest()
|
|
if actual_hash != expected_hash:
|
|
raise Exception('Hash mismatch for driver download! Expected {}, got {}'.format(
|
|
expected_hash, actual_hash))
|
|
|
|
subprocess.check_call([
|
|
'innoextract', '--output-dir', fwdir, '--include', fwname, '--collisions', 'overwrite',
|
|
fwarchive
|
|
])
|
|
|
|
fwpath = subprocess.check_output(['find', fwdir, '-name', fwname]).decode('utf-8').strip()
|
|
print('Found firmware at {}'.format(fwpath))
|
|
|
|
if not fwpath:
|
|
raise Exception('No {} found in the archive'.format(fwname))
|
|
|
|
return fwpath
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--driver-uri')
|
|
|
|
args = parser.parse_args()
|
|
|
|
if os.geteuid() != 0:
|
|
raise Exception('This script needs to be executed as root')
|
|
|
|
dev_type = None
|
|
for d in SupportedDevices:
|
|
dev = usb_core.find(idVendor=d.value[0], idProduct=d.value[1])
|
|
if dev:
|
|
dev_type = d
|
|
|
|
if not dev_type:
|
|
raise Exception('No supported validity device found')
|
|
|
|
try:
|
|
subprocess.check_call(['innoextract', '--version'], stdout=subprocess.DEVNULL)
|
|
except Exception as e:
|
|
print('Impossible to run innoextract: {}'.format(e))
|
|
sys.exit(1)
|
|
|
|
with tempfile.TemporaryDirectory() as fwdir:
|
|
fwpath = download_and_extract_fw(dev_type, fwdir, fwuri=args.driver_uri)
|
|
shutil.copy(fwpath, PYTHON_VALIDITY_DATA_DIR)
|