IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android Tv遥控器加密协议和具体添加方式 -> 正文阅读

[移动开发]Android Tv遥控器加密协议和具体添加方式

dongle加密协议规范与演示

一、通信端点:03

二、PID/VID

PID:0xB006

VID:0x1006

三、加密协议

1、 主机检测到 Dongle 插入,一秒钟后每隔 5 秒钟发送查询命令(只发送 5 次):

0x0D+0x43+0x57+0x52+0x55+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+crc8(Byte1-Byte18)
Dongle 答复:
0x0D+0x44+0x44+0x49+0x4e+0x47+0x4B+0x45+0x20+0x52+0x45+0x4d+0x4F+0x54+0x45+0x00+0x00+0x00+0x00+crc8(Byte1-Byte18)

2、 加密过程

主机收到 Dongle 答复后,生成两组 6 个随机数用作校验比如
unsigned char ramdom_tbl1[6] = {0x33, 0x44, 0x55, 0x31, 0x4e, 0xb9};
unsigned char ramdom_tbl2[6] = {0x88, 0x25, 0x4e, 0x99, 0xa7, 0xc7};
然后把第一组随机数组异或一组固定的数据
byte xor_table1[6] = {0xA8, 0x25, 0x3f, 0x97, 0x4e, 0xb9};
for(int i = 0; i < 6; i++)
 {
 Data[i] = ramdom_tbl1 [i]^xor_table1[i];
}
主机把 Data 数组组合成加密数据包发送给 Dongle,格式如下:
0x0D+0x53+data[0]+data[1]+data[2]+data[3]+data[4]+data[5]+ ramdom_tbl2 [0]+ramdom_tbl2 [1]+ ramdom_tbl2 [2]+ ramdom_tbl2 [3]+ ramdom_tbl2 [4]+ramdom_tbl2 [5]+0x00+0x00+0x00+0x00+0x00+ crc8(Byte1-Byte18)
Dongle 收到加密验证代码后,会把收到第一组数据异或 xor_table1 恢复原值,然后把 ramdom 的数据跟 Dongle 的 Mac 地址进行相加,只保留低 8 位(溢出丢弃),得到的数据再跟一组固定数据进行异或计算得到 encrypt_tbl [6];
 byte Xor_table2[6] = {0x1c, 0xab, 0x17, 0x95, 0x3e, 0x9f};
Mac 地址的数据同样会进行异或 xor_table2 的计算得到 mac[6];Dongle 的回包格式即为
0x0D+0x54+encrypt[0]+ encrypt[1]+ encrypt[2]+ encrypt[3]+ encrypt[4]+encrypt[5]+mac[0]+mac[1]+mac[2]+mac[3]+mac[4]+mac[5]+0x00+0x00+0x00+0x00+0x00+crc8(Byte1-Byte18)
主机收到 Dongle 的回包后,把加密数据以及 Dongle 的 Mac 地址异或 xor_table2恢复回来,然后判断 encrypt 数据是否跟 ramdom_tbl1 跟 mac 数组各元素的和相等,如果都符合,则验证通过,不符合则验证失败。

四、示例

1、 原始数据

byte ramdom_tbl1[6] = {0x33, 0x44, 0x55, 0x31, 0x4e, 0xb9};
byte ramdom_tbl2[6] = {0x88, 0x25, 0x4e, 0x99, 0xa7, 0xc7};
byte xor_tbl1[6] = {0xA8, 0x25, 0x3f, 0x97, 0x4e, 0xb9};
byte xor_tbl2[6] = {0x1c, 0xab, 0x17, 0x95, 0x3e, 0x9f};
byte mac[6] = {0x13, 0x32, 0xbc, 0x55, 0x33, 0x55};

2、 交互过程

Master 发送:

0x0D+0x43+0x57+0x52+0x55+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x5d

Dongle 答复:

0x0D+0x44+0x44+0x49+0x4e+0x47+0x4B+0x45+0x20+0x52+0x45+0x4d+0x4F+0x54+0x45+0x00+0x00+0x00+0x00+0x9b

Master 发送:

0x0d+0x53+0x9b+0x61+0x6a+0xa6+0x00+0x00+0x88+0x25+0x4e+0x99+0xa7+0xc7+0x00+0x00+0x00+0x00+0x00+0xee

Dongle 答复:

0x0d+0x54+0x5a+0xdd+0x06+0x13+0xbf+0x91+0x0f+0x99+0xab+0xc0+0x0d+0xca+0x00+0x00+0x00+0x00+0x00+0xfb

五、CRC 校验算法

    public static byte getCrc(byte[] data, int offset, int length) {
        byte crc = 0;

        for (int i = offset; i < length; i++) {
            crc = (byte) (crc + data[i]);

            for (int j = 0; j < 8; j++) {
                if ((crc & 0x80) == 0) {
                    crc = (byte) (crc << 1);
                } else {
                    crc = (byte) ((crc << 1) ^ 0x31);
                }
            }
        }

        return crc;
    }

我是在androidFramework中去处理加密,目的是加密协议校验通过的遥控器可以操作电视。

下面就是具体的代码实现;通过插拔dongle开始进行处理;

可以在PhoneWindowManager中的interceptKeyBeforeDispatching方法调用isKeyEventAvailable方法做拦截处理

package com.android.internal.policy.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.InputDevice;
import android.view.KeyEvent;

public class UsbDeviceManager extends BroadcastReceiver {

    private static final String TAG = "UsbDeviceManager";

    public static final char[] HEX = "0123456789ABCDEF".toCharArray();

    public static final int VID = 4310;
    public static final int PID = 45062;

    private final Context mContext;

    private final Object mLock = new Object();

    private final SparseArray<Device> mDevices = new SparseArray<Device>();

    public UsbDeviceManager(Context context) {
        mContext = context;

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction("com.toptech.action.REQUEST_MAC_ADDRESS");

        mContext.registerReceiver(this, filter);
    }

    protected UsbManager getUsbManager() {
        return (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
    }

    protected void onBootCompleted() {
        Log.d(TAG, "UsbDeviceManager - onBootCompleted.");

        UsbManager usbManager = getUsbManager();
        if (usbManager == null) {
            return;
        }

        HashMap<String, UsbDevice> devices = usbManager.getDeviceList();
        if (devices == null || devices.isEmpty()) {
            return;
        }
        for (UsbDevice usbDevice : devices.values()) {
            onUsbDeviceAdded(usbDevice);
        }
    }

    protected void onUsbDeviceAdded(UsbDevice usbDevice) {
        if (usbDevice == null) {
            return;
        }

        Device device = new Device(usbDevice);

        Log.d(TAG, "UsbDeviceManager - onUsbDeviceAdded: " + usbDevice + " >>> name: " + device.name());

        checkDevice(device);

        synchronized (mLock) {
            mDevices.put(usbDevice.getDeviceId(), device);
        }
    }

    protected void onUsbDeviceRemoved(UsbDevice usbDevice) {
        if (usbDevice == null) {
            return;
        }
        Log.d(TAG, "UsbDeviceManager - onUsbDeviceRemoved: " + usbDevice);

        Device device = mDevices.get(usbDevice.getDeviceId());
        if (device == null) {
            return;
        }

        device.status.set(Device.STATUS_REMOVED);

        synchronized (mLock) {
            mDevices.remove(usbDevice.getDeviceId());
        }
    }

    protected boolean checkPermission(UsbDevice device) {
        UsbManager usbManager = getUsbManager();
        if (usbManager == null) {
            return false;
        }

        if (device == null) {
            return false;
        }

        return usbManager.hasPermission(device);
    }

    protected boolean grantPermission(UsbDevice device) {
        if (device == null) {
            return false;
        }

        if (checkPermission(device)) {
            return true;
        }

        IBinder binder = ServiceManager.getService(Context.USB_SERVICE);
        IUsbManager manager = IUsbManager.Stub.asInterface(binder);

        final int uid = Binder.getCallingUid();
        try {
            manager.grantDevicePermission(device, uid);

            manager.setDevicePackage(device, mContext.getPackageName(), UserHandle.getUserId(uid));
        } catch (Exception e) {
            return false;
        }

        return checkPermission(device);
    }

    protected void checkDevice(Device device) {
        UsbManager usbManager = getUsbManager();
        if (usbManager == null) {
            return;
        }

        if (device == null) {
            return;
        }

        UsbDevice usbDevice = device.device();
        if (usbDevice.getVendorId() == VID && usbDevice.getProductId() == PID) {
            UsbDeviceConnection usbConnection = usbManager.openDevice(usbDevice);
            if (usbConnection == null) {
                device.status.set(Device.STATUS_INVALID);
                return;
            }

            UsbInterface usbInterface = getUsbInterface(usbDevice);
            if (usbInterface == null) {
                device.status.set(Device.STATUS_INVALID);
                return;
            }

            if (!usbConnection.claimInterface(usbInterface, true)) {
                device.status.set(Device.STATUS_INVALID);
                return;
            }

            if (!checkPermission(usbDevice)) {
                if (!grantPermission(usbDevice)) {
                    Log.w(TAG, "Grant permission failed.");

                    device.status.set(Device.STATUS_INVALID);
                    return;
                }
            }

            new DeviceCheckThread(device, usbConnection, usbInterface).start();
        } else {
            device.status.set(Device.STATUS_CHECKED);
        }
    }

    protected Device getUsbDevice(String name) {
        if (TextUtils.isEmpty(name)) {
            return null;
        }
        synchronized (mLock) {
            for (int i = 0, j = mDevices.size(); i < j; i++) {
                Device device = mDevices.valueAt(i);
                if (name.equals(device.name())) {
                    return device;
                }
            }
        }
        return null;
    }

    protected String getMacAddress(int vendorId, int productId) {
        synchronized (mLock) {
            for (int i = 0, j = mDevices.size(); i < j; i++) {
                Device device = mDevices.valueAt(i);

                if (device.device().getVendorId() == vendorId && device.device().getProductId() == productId) {
                    if (TextUtils.isEmpty(device.mac())) {
                        continue;
                    }
                    return device.mac();
                }
            }
        }
        return null;
    }

    public boolean isKeyEventAvailable(KeyEvent event) {
        if (event == null) {
            return false;
        }

        InputDevice device = event.getDevice();

        if (device.getVendorId() == 0 && device.getProductId() == 0) {
            return true;
        }
        Device usbDevice = getUsbDevice(device.getName());

        if (usbDevice == null) {
            return true;
        }

        return usbDevice.status() == Device.STATUS_CHECKED;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();

        Log.d(TAG, "action: " + action);

        if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
            onBootCompleted();
            return;
        }
        if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
            onUsbDeviceAdded((UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
            return;
        }
        if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
            onUsbDeviceRemoved((UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE));
            return;
        }

        if ("com.toptech.action.REQUEST_MAC_ADDRESS".equals(action)) {
            Bundle extras = intent.getExtras();
            if (extras == null || extras.isEmpty()) {
                return;
            }
            int vendorId = extras.getInt("VendorId", 0);
            int productId = extras.getInt("ProductId", 0);
            if (vendorId == 0 && productId == 0) {
                return;
            }

            Log.d(TAG, "Request mac address -> vid: " + vendorId + ", pid: " + productId);

            String macAddress = getMacAddress(vendorId, productId);
            if (TextUtils.isEmpty(macAddress)) {
                return;
            }

            IBinder binder = extras.getBinder("Messenger");
            if (binder == null) {
                return;
            }

            Bundle result = new Bundle();
            result.putString("MacAddress", macAddress);

            Message message = Message.obtain();
            message.what = 0;
            message.obj = result;

            Messenger messenger = new Messenger(binder);
            try {
                messenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            return;
        }
    }

    private static UsbInterface getUsbInterface(UsbDevice device) {
        if (device == null) {
            return null;
        }

        for (int i = 0, j = device.getInterfaceCount(); i < j; i++) {
            UsbInterface usbInterface = device.getInterface(i);

            if (getInput(usbInterface) == null) {
                continue;
            }
            if (getOutput(usbInterface) == null) {
                continue;
            }

            return usbInterface;
        }

        return null;
    }

    private static UsbEndpoint getInput(UsbInterface usbInterface) {
        for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
            UsbEndpoint end = usbInterface.getEndpoint(i);
            if (end.getDirection() == UsbConstants.USB_DIR_IN) {
                return end;
            }
        }
        return null;
    }

    private static UsbEndpoint getOutput(UsbInterface usbInterface) {
        for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
            UsbEndpoint end = usbInterface.getEndpoint(i);
            if (end.getDirection() == UsbConstants.USB_DIR_OUT) {
                return end;
            }
        }
        return null;
    }

    private static List<String> getUsbPaths() {
        File directory = new File("/sys/bus/usb/devices");

        File[] files = directory.listFiles();
        if (files == null || files.length == 0) {
            return Collections.emptyList();
        }

        List<String> paths = new ArrayList<String>();

        for (File file : files) {
            String name = file.getName();
            if (TextUtils.isEmpty(name)) {
                continue;
            }
            if (!name.matches("\\d+-\\d+")) {
                continue;
            }

            String realPath;
            try {
                realPath = file.getCanonicalPath();
            } catch (IOException e) {
                continue;
            }

            paths.add(realPath);
        }

        return paths;
    }

    private static String getUsbDevicePath(File event) {
        if (event == null || !event.exists()) {
            return null;
        }

        Scanner scanner;
        try {
            scanner = new Scanner(event);

            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                if (line.startsWith("DEVNAME=")) {
                    return line.replace("DEVNAME=", "/dev/");
                }
            }
        } catch (FileNotFoundException e) {
            return null;
        }

        return null;
    }

    private static Map<String, String> getUsbDevices() {
        Map<String, String> devices = new HashMap<String, String>();

        List<String> paths = getUsbPaths();
        for (String path : paths) {
            File file = new File(path);
            if (!file.exists()) {
                continue;
            }

            File event = new File(file, "uevent");
            String devicePath = getUsbDevicePath(event);
            if (TextUtils.isEmpty(devicePath)) {
                continue;
            }

            devices.put(path, devicePath);
        }

        return devices;
    }

    private static String getUsbDevicePath(UsbDevice device) {
        if (device == null) {
            return null;
        }

        final String name = device.getDeviceName();
        if (TextUtils.isEmpty(name)) {
            return null;
        }

        Map<String, String> devices = getUsbDevices();
        if (devices == null || devices.isEmpty()) {
            return null;
        }

        for (String path : devices.keySet()) {
            if (name.equals(devices.get(path))) {
                return path;
            }
        }

        return null;
    }

    private static void send(UsbDeviceConnection connection, UsbEndpoint out, byte[] data) {
        if (connection == null || out == null) {
            return;
        }
        if (data == null || data.length == 0) {
            return;
        }
        String hex = bytesToHex(data);
        Log.d(TAG, "request: " + hex);

        try {
            connection.bulkTransfer(out, data, data.length, 0);
        } catch (Exception e) {
            Log.e(TAG, "send error.", e);
        }
    }

    private static byte[] read(UsbDeviceConnection connection, UsbEndpoint in, int timeout, int retry) {
        if (connection == null || in == null) {
            return null;
        }

        byte[] data = new byte[in.getMaxPacketSize()];

        for (int i = retry; i > 0; i--) {
            int length;
            try {
                length = connection.bulkTransfer(in, data, data.length, timeout);
                if (length <= 0) {
                    continue;
                }
            } catch (Exception e) {
                continue;
            }

            String hex = bytesToHex(data, length);
            Log.d(TAG, "response: " + hex);

            return Arrays.copyOf(data, length);
        }

        return null;
    }

    public static String bytesToHex(byte[] bytes) {
        return bytesToHex(bytes, bytes.length);
    }

    public static String bytesToHex(byte[] bytes, int length) {
        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < Math.min(length, bytes.length); j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEX[v >>> 4];
            hexChars[j * 2 + 1] = HEX[v & 0x0F];
        }
        return new String(hexChars);
    }

    public static byte[] hex2Byte(String hex) {
        String[] parts = hex.split(" ");
        byte[] bytes = new byte[parts.length];
        for (int i = 0; i < parts.length; i++) {
            bytes[i] = (byte) Integer.parseInt(parts[i], 16);
        }
        return bytes;
    }

    public static boolean allEquals(byte[] bytes, byte value) {
        if (bytes == null || bytes.length == 0) {
            return false;
        }
        for (int i = 0; i < bytes.length; i++) {
            if (bytes[i] != value) {
                return false;
            }
        }
        return true;
    }

    public static String randomHexString(int length) {
        StringBuffer result = new StringBuffer();

        Random random = new Random();
        try {
            for (int i = 0; i < length; i++) {
                String hexString = Integer.toHexString(random.nextInt(255));
                if (hexString.length() == 1) {
                    result.append("0");
                }
                result.append(hexString).append(" ");
            }
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static byte getCrc(byte[] data, int offset, int length) {
        byte crc = 0;

        for (int i = offset; i < length; i++) {
            crc = (byte) (crc + data[i]);

            for (int j = 0; j < 8; j++) {
                if ((crc & 0x80) == 0) {
                    crc = (byte) (crc << 1);
                } else {
                    crc = (byte) ((crc << 1) ^ 0x31);
                }
            }
        }

        return crc;
    }

    private static String read(File file) {
        if (file == null || !file.exists()) {
            return null;
        }

        StringBuilder builder = new StringBuilder();

        Scanner scanner;
        try {
            scanner = new Scanner(file);

            while (scanner.hasNextLine()) {
                builder.append(scanner.nextLine()).append('\n');
            }
            builder.deleteCharAt(builder.length() - 1);
        } catch (FileNotFoundException e) {
            return null;
        }

        if (scanner != null) {
            scanner.close();
        }

        return builder.toString();
    }

    public static void write(File file, String content) {
        if (file == null) {
            return;
        }

        FileWriter writer;
        try {
            writer = new FileWriter(file);

            writer.write(content);
            writer.flush();
        } catch (IOException e) {
            return;
        }

        if (writer != null) {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    class DeviceCheckThread extends Thread {

        final Device device;

        final UsbDeviceConnection usbConnection;
        final UsbInterface usbInterface;

        final UsbEndpoint in;
        final UsbEndpoint out;

        public DeviceCheckThread(Device device, UsbDeviceConnection usbConnection, UsbInterface usbInterface) {
            this.device = device;

            this.usbConnection = usbConnection;
            this.usbInterface = usbInterface;

            this.in = getInput(usbInterface);
            this.out = getOutput(usbInterface);
        }

        public boolean checkDevice(UsbDeviceConnection usbConnection, UsbEndpoint in, UsbEndpoint out) {
            if (usbConnection == null || in == null || out == null) {
                return false;
            }

            final byte[] xor_table1 = { (byte) 0xA8, (byte) 0x25, (byte) 0x3f, (byte) 0x97, (byte) 0x4e, (byte) 0xb9 };
            final byte[] xor_table2 = { (byte) 0x1c, (byte) 0xab, (byte) 0x17, (byte) 0x95, (byte) 0x3e, (byte) 0x9f };

            final byte[] random_table1 = hex2Byte(randomHexString(6));
            final byte[] random_table2 = hex2Byte(randomHexString(6));

            // Step 1
            {
                byte[] request = new byte[20];
                Arrays.fill(request, (byte) 0x00);

                request[0] = (byte) 0x0D;
                request[1] = (byte) 0x43;
                request[2] = (byte) 0x57;
                request[3] = (byte) 0x52;
                request[4] = (byte) 0x55;

                send(usbConnection, out, request);
            }

            // Step 2
            {
                byte[] response = read(usbConnection, in, 500, 3);
                if (response == null || response.length == 0) {
                    Log.w(TAG, "Check device -> step 2: none response.");
                    return false;
                }

                if (response.length < 2 || response[0] != (byte) 0x0D || response[1] != (byte) 0x44) {
                    Log.w(TAG, "Check device -> step 2: invalid response.");
                    return false;
                }

                byte[] request = new byte[20];
                Arrays.fill(request, (byte) 0x00);

                request[0] = (byte) 0x0D;
                request[1] = (byte) 0x53;
                request[2] = (byte) (random_table1[0] ^ xor_table1[0]);
                request[3] = (byte) (random_table1[1] ^ xor_table1[1]);
                request[4] = (byte) (random_table1[2] ^ xor_table1[2]);
                request[5] = (byte) (random_table1[3] ^ xor_table1[3]);
                request[6] = (byte) (random_table1[4] ^ xor_table1[4]);
                request[7] = (byte) (random_table1[5] ^ xor_table1[5]);
                request[8] = random_table2[0];
                request[9] = random_table2[1];
                request[10] = random_table2[2];
                request[11] = random_table2[3];
                request[12] = random_table2[4];
                request[13] = random_table2[5];
                request[19] = getCrc(request, 1, request.length - 1);

                send(usbConnection, out, request);
            }

            // Step 3
            {
                byte[] response = read(usbConnection, in, 500, 3);
                if (response == null || response.length == 0) {
                    Log.w(TAG, "Check device -> step 3: none response.");
                    return false;
                }

                if (response.length < 14 || response[0] != (byte) 0x0D || response[1] != (byte) 0x54) {
                    Log.w(TAG, "Check device -> step 3: invalid response.");
                    return false;
                }

                byte[] data = Arrays.copyOfRange(response, 2, 2 + 6);
                byte[] mac = Arrays.copyOfRange(response, 8, 8 + 6);

                byte[] data_xor = new byte[data.length];
                for (int i = 0; i < data.length; i++) {
                    data_xor[i] = (byte) (data[i] ^ xor_table2[i]);
                }
                byte[] mac_xor = new byte[mac.length];
                for (int i = 0; i < mac.length; i++) {
                    mac_xor[i] = (byte) (mac[i] ^ xor_table2[i]);
                }

                byte[] encrypt_xor = new byte[6];
                for (int i = 0; i < encrypt_xor.length; i++) {
                    encrypt_xor[i] = (byte) (mac_xor[i] + random_table1[i]);
                }

                if (Arrays.equals(data_xor, encrypt_xor)) {
                    Log.i(TAG, "Check device succeed.");
                    return true;
                } else {
                    Log.w(TAG, "Check device failed.");
                    return false;
                }
            }
        }

        public String requestMacAddress(UsbDeviceConnection usbConnection, UsbEndpoint in, UsbEndpoint out) {
            if (usbConnection == null || in == null || out == null) {
                return null;
            }

            final byte[] mac = new byte[6];

            Arrays.fill(mac, (byte) 0x00);

            // Step 1
            {
                byte[] request = new byte[9];

                Arrays.fill(request, (byte) 0x00);

                request[0] = (byte) 0x0D;
                request[1] = (byte) 0xDB;
                request[2] = (byte) 0x61;
                request[3] = (byte) 0xBB;
                request[4] = (byte) 0x01;

                send(usbConnection, out, request);
            }

            // Step 2
            {
                byte[] response = read(usbConnection, in, 500, 3);
                if (response == null || response.length == 0) {
                    Log.w(TAG, "Request mac address -> step 2: none response.");
                    return null;
                }

                if (response.length < 3 || response[0] != (byte) 0x0D || response[1] != (byte) 0xDC || response[2] != (byte) 0x71) {
                    Log.w(TAG, "Request mac address -> step 2: invalid response.");
                    return null;
                }

                if (response.length < 9) {
                    Log.w(TAG, "Request mac address -> step 2: invalid length.");
                    return null;
                } else {
                    for (int i = 0; i < mac.length; i++) {
                        mac[i] = response[3 + i];
                    }

                    if (allEquals(mac, (byte) 0x00)) {
                        Log.w(TAG, "Request mac address -> step 2: invalid data.");
                        return null;
                    }
                    Log.d(TAG, "Check mac address: " + bytesToHex(mac));
                }

                byte[] request = new byte[9];

                Arrays.fill(request, (byte) 0x00);

                request[0] = (byte) 0x0D;
                request[1] = (byte) 0xDB;
                request[2] = (byte) 0x62;

                for (int i = 0; i < mac.length; i++) {
                    request[i + 3] = mac[i];
                }

                send(usbConnection, out, request);
            }

            // Step 3
            {
                byte[] response = read(usbConnection, in, 500, 3);
                if (response == null || response.length == 0) {
                    Log.w(TAG, "Request mac address -> step 3: none response.");
                    return null;
                }

                if (response.length < 3 || response[0] != (byte) 0x0D || response[1] != (byte) 0xDC || response[2] != (byte) 0x72) {
                    Log.w(TAG, "Request mac address -> step 3: invalid response.");
                    return null;
                }

                if (response.length < 5 || response[3] != (byte) 0x06 || response[4] != (byte) 0x06) {
                    Log.w(TAG, "Request mac address -> step 3: check failed.");
                    return null;
                }
            }

            return bytesToHex(mac);
        }

        @Override
        public void run() {
            try {
                device.status.set(Device.STATUS_CHECKING);

                if (checkDevice(usbConnection, in, out)) {
                    if (device.status() != Device.STATUS_REMOVED) {
                        device.status.set(Device.STATUS_CHECKED);
                    }

                    while (device.status() != Device.STATUS_REMOVED) {
                        String mac = requestMacAddress(usbConnection, in, out);
                        if (TextUtils.isEmpty(mac)) {
                            try {
                                Thread.sleep(1500);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            continue;
                        }

                        device.mac.set(mac);

                        if (!TextUtils.isEmpty(device.path())) {
                            File file = new File(device.path(), "mac");

                            write(file, mac);
                        }
                        break;
                    }
                } else {
                    if (device.status() != Device.STATUS_REMOVED) {
                        device.status.set(Device.STATUS_INVALID);
                    }
                }
            } finally {
                try {
                    usbConnection.releaseInterface(usbInterface);

                    usbConnection.close();
                } catch (Exception e) {
                }
            }
        }

    }

    static class Device {

        public static final int STATUS_IDLE     = 0;
        public static final int STATUS_CHECKING = 1;
        public static final int STATUS_CHECKED  = 2;
        public static final int STATUS_INVALID  = 3;
        public static final int STATUS_REMOVED  = 4;

        final AtomicInteger status = new AtomicInteger(STATUS_IDLE);

        final AtomicReference<String> mac = new AtomicReference<String>();

        final UsbDevice device;

        final String path;

        final String manufacturer;
        final String product;

        public Device(UsbDevice device) {
            this.device = device;

            path = getUsbDevicePath(device);
            if (TextUtils.isEmpty(path)) {
                manufacturer = null;
                product = null;
            } else {
                manufacturer = read(new File(path, "manufacturer"));
                product = read(new File(path, "product"));
            }
        }

        public String path() {
            return path;
        }

        public String manufacturer() {
            return manufacturer;
        }

        public String product() {
            return product;
        }

        public String name() {
            if (TextUtils.isEmpty(manufacturer) || TextUtils.isEmpty(product)) {
                return null;
            }
            return manufacturer + " " + product;
        }

        public int status() {
            return status.get();
        }

        public String mac() {
            return mac.get();
        }

        public UsbDevice device() {
            return device;
        }

    }

}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-21 21:40:09  更:2022-07-21 21:41:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:57:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码