作者归档:softsim

Linux下给ccid驱动添加新的读卡器支持

很多PC/SC读卡器都是标准读卡器,但是 作者并没有测试过 https://ccid.apdu.fr/
需要自己手动添加支持。
以Debian系统为例
修改 /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
添加 ifdVendorID ifdProductID 和 ifdFriendlyName等三项
具体信息,可以用 lsusb命令查看

058c:9590 In Focus Systems EMV Smartcard Reader

这个读卡器在 马大师 的平台上卖20元左右

SPRD有关vsim的at命令更详细的介绍

AT+VIRUALSIMINIT=0
表示使用物理卡
AT+VIRUALSIMINIT=1
表示使用虚拟卡

0:实体卡
1:云卡
2:软卡


AT+VIRTUALSIMINIT=0,0
物理卡, 不写入NV
AT+VIRTUALSIMINIT=0,1
物理卡, 写入nv


AT+VIRTUALSIMINIT?
查询是否开启VSIM


VSIM_CREATE:AT+RSIMRSP=”VSIM”,1
VSIM_INIT:AT+RSIMRSP=”VSIM”,1
开启VSIM功能

前缀不重要, rild会对 这个命令进行处理, 只发送AT+RSIMRSP=”VSIM”,1给基带


AT+RSIMRSP=
发送rAPDU给modem


VSIM_EXIT:AT+RSIMRSP=”VSIM”,0
关闭vsim功能
实际也只是发送 AT+RSIMRSP=”VSIM”,0 给基带


AT+SPVSIMAUTHSET=
设置鉴权数据通过哪个 卡槽的实体卡 发送给卡池


AT+SPVSIMAUTHSET?
查询鉴权通道 通过哪个卡槽的实体卡,发送给云端

RILC_ATCI

socket_local_client “atci_socket0”

“vsim_socket_0”

@vsim_socket_1 (Rild 用 libsprd-ril.so 创建 vism 服务socket)

从 socket里 读取AT命令, 解析成APDU


Android 4.4 采用的socket,而不是8.0之后的 hwbinder

netstat -xunlp
...
unix  2      [ ACC ]     STREAM     LISTENING       5189 595/sprdrild        @atci_socket1
unix  2      [ ACC ]     STREAM     LISTENING       4600 596/sprdrild        @atci_socket2
...
unix  2      [ ACC ]     STREAM     LISTENING       7262 596/sprdrild        @vsim_socket_1

USB主机与集成电路卡接口设备间的通道

1.控制通道(Control pipe)

控制通道消息(包括标准请求,比如GET_DESCRIPTOR和SET_CONFIGURATION)

2. 中断通道(Interrupt pipe)

异步事件(ICC卡存在,ICC卡移除,硬件错误)

3. Bulk-in, Bulk-out pipes


Android API的使用

1. 通过 usbManager.getDeviceList() 来获取设备
android.hardware.usb.UsbManager

2. UsbDevice (表示连接的 USB 设备,并包含用于访问其标识信息、接口和端点的方法。)
getDeviceClass()
getDeviceId()
getDeviceName()
getDeviceProtocol()
getDeviceSubclass()
getManufacturerName()
getProductId()
getSerialNumber()
getVendorId()
得到设备的信息
最重要是可以 通过 getInterface(int index)得到接口

3. UsbInterface 定义设备的一组功能。 设备可以具有一个或多个用于通信的接口。

4. UsbEndpoint 接口端点,是此接口的通信通道。一个接口可以具有一个或多个端点,并且通常具有用于与设备进行双向通信的输入和输出端点。

openDevice(UsbDevice device)

Nubia Watch解锁bootloader安装app

第1代是 Nubia Alpha 型号 SW1002, 高通W2100(MSM8909W),1+8存储组合,重量:很重,电池500mAh,有扬声器,有摄像头,没NFC。
第2代是 Nubia Watch 型号 SW1003, 高通W2100(MSM8909W),1+8存储组合,重98g,电池425mAh,没有扬声器,没有摄像头,没NFC。
Wear 2100是高通2016年发布的U,28nm工艺。 华米Amazfit智能手表2, 华为Watch 2 Pro/2019, Ticwatch Pro 4G 都是用的这款芯片。
———————————
Nubia Watch 基于Android 7.1.1, 默认开启adb, 不过依然可以调用 *#7678# 来打开设置

解锁

adb reboot bootloader
fastboot oem nubia_unlock NUBIA_SW1003
fastboot boot sw1003.img
如果是Nubia Alpha
fast boot oem nubia_unlock NUBIA_SW1002
fast boot recovery-nubia.img

安装Magisk.apk

adb install -r -n nubia  magisk.apk

需要传递一个 -n nubia选项

用recovery来修补boot分区

adb push  magisk.zip /sdcard
adb reboot bootloader
fastboot boot rec.img

其中magisk.zip是由magisk.apk改名而来
启动到recovery后,安装zip文件,会自动对 boot分区patch

华为手表从出厂刷机包和OTA包中生成最终的boot.img

以华为Watch 2 2018为例,
出厂的刷机包 “HUAWEI WATCH 2 Modem_中国版升级_NWD1.170711.022_release.exe”, 这是一个fastboot刷机包

0. 编译 ApplyPatch

apt install libbz2-dev
git clone https://github.com/erfanoabdi/imgpatchtools
cd imgpatchtools
make

1. 从OTA升级包update.zip 获取相关文件和信息

META-INF/com/google/android/updater-script
...
ui_print("Source: huawei/sawshark_sw/sawshark:7.1.1/NWD1.170711.002/4172583:user/release-keys");
ui_print("Target: huawei/sawshark_sw/sawshark:7.1.1/N7I56C/4304100:user/release-keys");
...
apply_patch("EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8062181:ac228af93437500c11504bdaa7f0dcae261f8b90:8064229:3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96",
            "-", 3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96, 8064229,
            ac228af93437500c11504bdaa7f0dcae261f8b90,
            package_extract_file("patch/boot.img.p")) ||
    abort("E3008: Failed to apply patch to EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8062181:ac228af93437500c11504bdaa7f0dcae261f8b90:8064229:3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96");

可以看出原始的 boot.img的sha1为 ac228af93437500c11504bdaa7f0dcae261f8b90, 打好补丁后为 3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96

./ApplyPatch  boot.img  new.img  3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96  8064229  ac228af93437500c11504bdaa7f0dcae261f8b90 patch/boot.img.p

命令行选项

	file = source file from rom zip
	target = target file (use "-" to patch source file)
	tgt_sha1 = target SHA1 Sum after patching
	size = file size
	init_sha1 = file SHA1 sum
	patch = patch file (.p) from OTA zip

验证
sha1sum -b boot.img
ac228af93437500c11504bdaa7f0dcae261f8b90 *boot.img

sha1sum -b new.img
3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96 *new.img

以后的各版本

ui_print("Source: huawei/sawshark_sw/sawshark:7.1.1/N7I56C/4304100:user/release-keys");
ui_print("Target: huawei/sawshark_sw/sawshark:7.1.1/N7I92E/4403039:user/release-keys");
...
apply_patch("EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8064229:3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96:8064229:91a8457809ca7534d87b46ec44bf7991d3b53179",
            "-", 91a8457809ca7534d87b46ec44bf7991d3b53179, 8064229,
            3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96,
            package_extract_file("patch/boot.img.p")) ||
    abort("E3008: Failed to apply patch to EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8064229:3f29ba5b40328b1e3dc16515ff4a4e3bbe2ddb96:8064229:91a8457809ca7534d87b46ec44bf7991d3b53179");
-----
ui_print("Source: huawei/sawshark_sw/sawshark:7.1.1/N7I92E/4403039:user/release-keys");
ui_print("Target: huawei/sawshark_sw/sawshark:7.1.1/NWD1.171123.001/4467331:user/release-keys");
...
apply_patch("EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8064229:91a8457809ca7534d87b46ec44bf7991d3b53179:8064229:8d05322cc211052be5d0264f6e8671e0f5ea28e1",
            "-", 8d05322cc211052be5d0264f6e8671e0f5ea28e1, 8064229,
            91a8457809ca7534d87b46ec44bf7991d3b53179,
            package_extract_file("patch/boot.img.p")) ||
    abort("E3008: Failed to apply patch to EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8064229:91a8457809ca7534d87b46ec44bf7991d3b53179:8064229:8d05322cc211052be5d0264f6e8671e0f5ea28e1");
---------------------------------
ui_print("Source: huawei/sawshark_sw/sawshark:7.1.1/NWD1.171123.001/4467331:user/release-keys");
ui_print("Target: huawei/sawshark_sw/sawshark:8.0.0/OWDE.180122.014/4586409:user/release-keys");
...
apply_patch("EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8064229:8d05322cc211052be5d0264f6e8671e0f5ea28e1:8594662:07c12ecbf36151a617ff05677f4896405e421ebc",
            "-", 07c12ecbf36151a617ff05677f4896405e421ebc, 8594662,
            8d05322cc211052be5d0264f6e8671e0f5ea28e1,
            package_extract_file("patch/boot.img.p")) ||
    abort("E3008: Failed to apply patch to EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8064229:8d05322cc211052be5d0264f6e8671e0f5ea28e1:8594662:07c12ecbf36151a617ff05677f4896405e421ebc");
-------------------

ui_print("Source: huawei/sawshark_sw/sawshark:8.0.0/OWDE.180122.014/4586409:user/release-keys");
ui_print("Target: huawei/sawshark_sw/sawshark:8.0.0/OWDE.180215.020/4633085:user/release-keys");

....

apply_patch("EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8594662:07c12ecbf36151a617ff05677f4896405e421ebc:8594662:17625d3b58ca903ec0ad8cdf3c8fe872ad8e11d3",
            "-", 17625d3b58ca903ec0ad8cdf3c8fe872ad8e11d3, 8594662,
            07c12ecbf36151a617ff05677f4896405e421ebc,
            package_extract_file("patch/boot.img.p")) ||
    abort("E3008: Failed to apply patch to EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8594662:07c12ecbf36151a617ff05677f4896405e421ebc:8594662:17625d3b58ca903ec0ad8cdf3c8fe872ad8e11d3");
-----------------------------------
ui_print("Source: huawei/sawshark_sw/sawshark:8.0.0/OWDE.180215.020/4633085:user/release-keys");
ui_print("Target: huawei/sawshark_sw/sawshark:8.0.0/OWDE.180707.001.E1/4958530:user/release-keys");
....
apply_patch("EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8594662:17625d3b58ca903ec0ad8cdf3c8fe872ad8e11d3:8604902:4946f61ba431ec844dae06afe2e572f491a99a5a",
            "-", 4946f61ba431ec844dae06afe2e572f491a99a5a, 8604902,
            17625d3b58ca903ec0ad8cdf3c8fe872ad8e11d3,
            package_extract_file("patch/boot.img.p")) ||
    abort("E3008: Failed to apply patch to EMMC:/dev/block/platform/soc/7824900.sdhci/by-name/boot:8594662:17625d3b58ca903ec0ad8cdf3c8fe872ad8e11d3:8604902:4946f61ba431ec844dae06afe2e572f491a99a5a");


腾讯车联卡通过ICCID查询流量

#!/usr/bin/python3

import time
import hashlib
import json
import base64
import hmac

import requests
import jwt



import sys
if len(sys.argv) != 2:
    print("i need one ICCID.")
    exit(-1)


iccid = sys.argv[1]




private_key = b"""-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtkpIspKwGBKe/
qSrx/JwOf/p/phAP132Tuy2XSSmas1hx49EMRZg6meEkPwz2utYQX2NKFi/CrYd3
fOrFa4HguokD9A5mdlX4TPxea91fOnFOOTdpS3iYYAYQpbR3lsE5Xau/jCcExaXz
MEgG5XVRxpmFcqwvC5LYvbt37XjxvlZE2VpY8sEItOl9ALyYT3Phxyt7bHz1Vhtk
/C5mtADf7OW9eUaORIVoKfFss4vsRf3MS7oi81II+izxde0StR+Psr6htlKerylh
4FffN6buyCooKk7Lj4Y2uvy7eMsWgjanYOZdZ17+2nojDq3ev5BuD/yGrzX1NYFO
m4JhZd2FAgMBAAECggEANpW7hnKa7qGUJ4AJ02P/p8ezfWU58+FuyoC4y7TkcpQo
IljkqxlP0E4IMZ/qccU8AJYe4XOsvWpZCcitBDzU8Vl4MVgVFz/rtVRwoTkGuyXj
8BeqR2DGohTAk4epA1rTlTjSBEENHEET+TCb1h9fD8KHESKI55qaKbMxO3vg5xTR
5cCb+Zp6vu/tZw/LeYY3aNocD9Jy7WHDLk7HgT9QQ58LI7zOAhfVj+eVnhR8m/me
3tz2LWCOxzKi5QpCP8dAUxED17C0sl+8uOup/pDvcz9s9FBmTNeljtSV6xlJ8Xhr
V9LvzRrPmERc4bVikmomeS7BAAkOcVeUUQixNB5SmQKBgQDY0CYPAGZA8ST7HVCb
5eMTpxozczQTOjK0z9PETgXsepLcIcmVtAQU7NM6rkigOp1ocHOP0JGyUWNuyWhc
zeKy/5mcWdxXPnJaiYoWY5p9WfYWALkgTe1FyFwsqMPS9m4BX4vxE6htvEZ315mE
uQMS35Fqv8UqhZdHelu14lwfqwKBgQDM8bNY7pc6V5KPaghJUpXmkCn9JoWKANZV
N41zUAS8V9iZgovrys0/988uHYNB8NRlDy7gfHrcm9KJfqnuDE/aA5+E/siQCzJp
CHn+FTPOVVATj6OHgppYy6bFizoPt1B9hN2utebUmn7g9JsKsXcepHbwyf51iFX9
G1w3KLeHjwKBgA5v7djZ4fU5GYlPLmrzJ+fLHMeISFNvcKjxndxYhbR1hQn7hfzd
+9eY3Yfuyw9AV/L4afmNneYN3V0nNDfZzdq1gnkS0sVMdzjoJ7XN9B+cufJFIg6w
obgf22Nt6XxGxJR61Eq9UF3eR6L7TFG2MCo1kO1Wz75BHw23bBv0csX5AoGAdFuy
QQbNk9FOo+BGriKWex5UyKcLYIwTJLTyuYqv9aNGlfm5qXkuSWhQF9WnxVOPs4UI
T2o9c22A/pGMt1wEJjqyYhcqFiZVS68FXE37aOWlHkYKSZDMQyf1GuluYKfqqik6
l8wtL348FUqrkEmr4Rjtcs6si1yJvbfABo02jl8CgYEApDr46GEcAV0dfr3AvhS7
t9DNYCdXiXa8RLcSKiNO6Iimwav7hn+IuN2WKJ/uPXqCSFAwVSYhRyiLqWQ6QSRy
vU4q1zVDn+SxxY79dWWsSrRlAuCmyVmD5mJdQlmY3FC8KXj14mEsG+eZtmHX7HTU
UaKPdheWKWAOQeqtRRNEZew=
-----END PRIVATE KEY-----
"""

publick_key = b"""-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArZKSLKSsBgSnv6kq8fyc
Dn/6f6YQD9d9k7stl0kpmrNYcePRDEWYOpnhJD8M9rrWEF9jShYvwq2Hd3zqxWuB
4LqJA/QOZnZV+Ez8XmvdXzpxTjk3aUt4mGAGEKW0d5bBOV2rv4wnBMWl8zBIBuV1
UcaZhXKsLwuS2L27d+148b5WRNlaWPLBCLTpfQC8mE9z4ccre2x89VYbZPwuZrQA
3+zlvXlGjkSFaCnxbLOL7EX9zEu6IvNSCPos8XXtErUfj7K+obZSnq8pYeBX3zem
7sgqKCpOy4+GNrr8u3jLFoI2p2DmXWde/tp6Iw6t3r+Qbg/8hq819TWBTpuCYWXd
hQIDAQAB
-----END PUBLIC KEY-----
"""


ts = int(time.time())


headers = {
    "typ": "JWT",
    "kid": "tsmkc-client",
    "alg": "RS256"
}

claims = {
	"sub":    "kingcard",
	"iss":    "tsmkc.qq.com",
	"exp":    ts + 300,
	"iat":    ts - 10,
	"iccid":  iccid,
	"userid":  "",
	"usersig": ""
}

encoded_token = jwt.encode(claims,  private_key,   algorithm="RS256",   headers=headers)

get_headers = {
	'Content-Type': 'application/json',
	'user-agent': 'okhttp/3.5.0',
	'Authorization': 'Bearer ' + encoded_token.decode("ascii")
}

r = requests.get('https://api.tsmkc.qq.com/prd/v1/package/packageinfo', headers=get_headers)
print(r.text)

用的jwt做的认证

用usim卡接入ims

USIM可接入2G/3G/4G/5G网络,但不存储IMS网络相关的用户信息.接入VoLTE网络时, 需要终端 通过某种规则,生成ims系统的用户码号和归属地等信息。 或者直接从ISIM读取相关信息:
1. 私有标识(IMPI)
归属网络提供的用户全球唯一标识,用于IMS网络对IMS用户进行鉴权认证
EF_IMPI (IMS private user identity)
文件标识符:6F02
SFI: 02
内容格式为 NAI TLV, tag(type) 值为 0x80

建议的生成规则(以中国移动为例子):
IMSI@ims.mnc00.mcc46.3gppnetwork.org

2. EF_DOMAIN (Home Network Domain Name)
6F03
SFI: 05
归属地运营商的网络域名
tag也为80

3. EF_IMPU (IMS public user identity)
6F04
SFI: 04
本文件可以含有一个或者多个记录。每个记录是一个公开的 SIP Identity (SIP URI)

用于用户之间进行通信的标识,对用户可见。IMPU采用SIP URI 和 TEL URI 格式。
SIP URI的例子: sip:user@chinamobile.com:port
sip:10086@bj.imsi.mnc00.mcc460.3gppnetwork.org
TEL URI的例子: tel:+8610086

———————————
对于没有ISIM aid的USIM卡,可以通过IMSI来生成自己的IMPI和IMPU:
IMPI: imsi@ims.mnc00.mcc460.3gppnetwork.org
IMPU: sip:imsi@ims.mnc00.mcc460.3gppnetwork.org

临时IMPU仅仅用于注册请求。如果成功注册后,UE 将获得相应的公有用户标识,UE 将在后续非注册请求中用任意一个公有用户标识。
在注册时,携带导出的IMPI和IMPU,注册成功后,网络根据用户签约返回两个IMPU值,分别为Tel URI 和 SIP URI形式。
Tel URI用于语音呼叫,SIP URI用于IMS网络路由。

ISO 14443 非接触式IC卡

PICC : Proximity Integrated Circuit Card 卡
PCD: Proximity Coupling Device 接近式耦合设备,通常指读卡器

ReqA: Request command, Type A
ReqB: Request command, Type A, 在 NFC中,叫 SENSB_REQ
ATQA: Answer To Request, Type A, 在NFC标准中,叫 SENS_RES
ATQB: Answer To Request, Type B, 在NFC标准,这个叫 SENSB_RES
ATTRIB: PICC 选择命令,TypeB
WUPA: Wake-Up Command, Type A
WUPB: Wake-Up Command, Type B, 在NFC中,叫 ALLB_REQ, 轮询命令
ATS: Answer to Select
ATR: Answer to Reset
PTS: Protocol Type Selection
PPS: Protocol and Parameter Selectrion
RATS: Request for Answer to Select

——————————————————
当 PICC 暴露于未调制的工作场内,它能在5ms 内接受一个请求。
例如:
当类型A PICC 接收到任何类型B 命令时,它能在5ms 内接受一个REQA。
当类型B PICC 接收到任何类型A 命令时,它能在5ms 内接受一个REQB。

为了检测到是否有PICCs进入到PCD的有效作用区域,PCD重复的发出请求信号REQ,并判断是否有响应ATQ。请求信号必须是REQA和REQB,附加ISO/IEC14443其它部分的描述的代码。A型卡和B型卡的命令和响应不能够相互干扰。
———————————————-
当一个B型卡被置入阅读器的作用范围内,IC卡执行一些预置程序后进入”闲置状态”,等待接收有效的REQB命令。对于B型卡,通过发送REQB命令,可以直接启动SlottedALOHA防碰撞算法,选出一张卡,对其进行操作。

当接收到有效的REQB帧的命令,PICC定义了单一的时间槽用来发送ATQB。
如果是PICC定义的第一个时间槽,PICC必须发送ATQB的响应信号,然后进入准备—已声明子状态。
如果不是PICC定义的第一个时间槽,PICC进入准备—已请求子状态。
———————
在已声明子状态下,PICC已经上电,并且已经发送了对REQB的ATQB响应。
它监听REQB和ATTRIB的数据帧。
————
激活状态
PICC已经上电,并且通过ATTRIB命令的前缀分配到了通道号,进入到应用模式。
————————-
frameworks / base / core / java / android / nfc / tech / NfcB.java

public byte[] getApplicationData()
在Tag发现阶段,从 ATQB/SENSB_RES 中得到的应用数据

public byte[] getProtocolInfo()
在Tag发现阶段,从 ATQB/SENSB_RES 中得到的协议信息

public byte[] transceive(byte[] data)
发送原生的nfcb命令给tag, 并收到响应
1)应用 不必要添加 EoD (CRC) 到payload, 校验会被自动计算。
2)应用也不应该发送那些管理 轮询和初始化的命令 :SENSB_REQ, SLOT_MARKER 等
——————————-
frameworks/base/core/java/android/nfc/Tag.java
public byte[] getPollBytes() {
在轮询时间,Tag返回的底层字节
这些字节的意义,依赖于所采用的Tag技术
在ISO14443-3A , 叫做 ATQA/SENS_RES
在ISO14443-3B, 包含 来自于 ATQB/SENSB_RES 的 Application data (4 bytes) 和 Protocol Info (3 bytes)

public byte[] getActivationBytes() {
在激活阶段, Tag返回的底层字节
ISO14443-3B & ISO14443-4中,叫 ATTRIB response
ISO14443-3A & ISO14443-4 叫做 SAK/SEL_RES, historical bytes from ATS

Quectel RM500U-CN

移远通信RM500U-CN 是一款专为 IoT/eMBB 应用而设计的 5G Sub-6 GHz 模块。采用 3GPP Release 15 技术,同时支持 5G NSA 和 SA 模式。RM500U-CN 采用 M.2 封装,与移远通信RM500Q系列模块兼容。

RM500U-CN 支持国内四大运营商。

RM500U-CN为工规级模块,仅适用于工业级和商业级应用。

RM500U-CN 内置丰富的网络协议,集成多个工业标准接口,并支持多种驱动和软件功能(如 Windows、Linux、Android 等操作系统下的 USB/PCIe 驱动等)

支持频段: n1/n28(广电700M)/n41/n77/n78/n79

cat /sys/kernel/debug/usb/devices

T: Bus=02 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 3 Spd=5000 MxCh= 0
D: Ver= 3.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1
P: Vendor=2c7c ProdID=0900 Rev= 4.04
S: Manufacturer=Quectel
S: Product=RM500U-CN
S: SerialNumber=0123456789ABCDEF
C:* #Ifs= 7 Cfg#= 1 Atr=c0 MxPwr=504mA
A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=03
I:* If#= 0 Alt= 0 #EPs= 1 Cls=e0(wlcon) Sub=01 Prot=03 Driver=rndis_host
E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=85(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
E: Ad=87(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms


# modprobe  -v option
insmod /lib/modules/5.10.0-8-amd64/kernel/drivers/usb/serial/usbserial.ko
insmod /lib/modules/5.10.0-8-amd64/kernel/drivers/usb/serial/usb_wwan.ko
insmod /lib/modules/5.10.0-8-amd64/kernel/drivers/usb/serial/option.ko
# echo '2c7c 0900' > /sys/bus/usb-serial/drivers/option1/new_id

就会正确加载驱动了
T: Bus=02 Lev=01 Prnt=01 Port=04 Cnt=01 Dev#= 3 Spd=5000 MxCh= 0
D: Ver= 3.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1
P: Vendor=2c7c ProdID=0900 Rev= 4.04
S: Manufacturer=Quectel
S: Product=RM500U-CN
S: SerialNumber=0123456789ABCDEF
C:* #Ifs= 7 Cfg#= 1 Atr=c0 MxPwr=504mA
A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=03
I:* If#= 0 Alt= 0 #EPs= 1 Cls=e0(wlcon) Sub=01 Prot=03 Driver=rndis_host
E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host
E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=85(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
I:* If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
E: Ad=87(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
E: Ad=06(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
在 /dev/下会出现多个usb串口,第3个是AT命令端口

picocom -b 23400 -c /dev/ttyUSB2
at+cgmr
Platform Version: MOCORTM_20C_W21.17.3_P2_Debug
Project Version:   Orca_NR_modem
BASE  Version:    5G_MODEM_20C_W21.17.3_P2

用lsusb -t 以树形显示 挂载关系和速率

# lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/8p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Wireless, Driver=rndis_host, 5000M
    |__ Port 1: Dev 2, If 1, Class=CDC Data, Driver=rndis_host, 5000M
    |__ Port 1: Dev 2, If 2, Class=Vendor Specific Class, Driver=, 5000M
    |__ Port 1: Dev 2, If 3, Class=Vendor Specific Class, Driver=, 5000M
    |__ Port 1: Dev 2, If 4, Class=Vendor Specific Class, Driver=, 5000M
    |__ Port 1: Dev 2, If 5, Class=Vendor Specific Class, Driver=, 5000M
    |__ Port 1: Dev 2, If 6, Class=Vendor Specific Class, Driver=, 5000M

可以看到 2,3,4,5,6 功能没有加载正确的驱动

ls -la /sys/bus/usb/devices/
...
lrwxrwxrwx 1 root root 0  9月 22 00:42 2-1:1.2 -> ../../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.2
lrwxrwxrwx 1 root root 0  9月 22 00:42 2-1:1.3 -> ../../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.3
lrwxrwxrwx 1 root root 0  9月 22 00:42 2-1:1.4 -> ../../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.4
lrwxrwxrwx 1 root root 0  9月 22 00:42 2-1:1.5 -> ../../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.5
lrwxrwxrwx 1 root root 0  9月 22 00:42 2-1:1.6 -> ../../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.6
...

手动绑定

ls -la /sys/bus/usb/drivers/rndis_host/
echo '2-1:1.0'  >   /sys/bus/usb/drivers/rndis_host/bind
echo '2-1:1.1'  >   /sys/bus/usb/drivers/rndis_host/bind

查询/设置当前usb网卡驱动模型

AT+QCFG="usbnet"[,net]

1 表示 ECM
2 表示 MBIM
3 表示 RNDIS
5 表示 NCM
默认为 3, 因为rndis在Linux和Windows下都有驱动

配置网卡模式

AT+QCFG="nat"[,nat]
0=网卡模式
1=路由模式
2=网桥模式
默认为0,网卡模式。网卡模式下,分配给PC机的地址为公网地址(也就是核心网分配给基带的地址)。此时modem内部无法连接外网,因为它都没有IP了,IP给了PC机


网桥模式和路由模式为 内网地址

AT+QCFG=”ethernet” (通过 pcie外接了以太网网卡芯片,这个指令才有用)

配置USB

AT+QCFG="usbcfg"[, vid, pid, diag,log,at_port,modem,NMEA,ADB]
示例:
AT+QCFG="usbcfg",0x2c7c,0x0900,1,1,1,1,1,1
打开全部功能,包括adb
默认情况下,adb是关闭的
还可以用AT+QCFG="usbid"[,vid,pid] 来单独配置vid和pid

启用ims/volte

AT+QCFG="ims",1

配置网络搜索模式

AT+QNWPREFCFG="mode_pref"

配置通话语音

AT+QNWPREFCFG="voice_domain"

配置语音优先还是数据优先

AT+QNWPREFCFG="ue_usage_setting"

查询5G注册状态

AT+C5GREG

+C5GREG: 0,1

查询5G网络质量

AT+C5GQOS?
+C5GQOS: 1,0,0,0,0,0
+C5GQOS: 2,0,0,0,0,0
+C5GQOS: 11,0,0,0,0,0


AT+C5GQOSRDP=1