Send_44_info

package ccwp;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
//import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import ccwp.Ccw_push_record_temp_50;
public class Send_44_info {
private static String db_config="db_config.properties";
public static String DRIVERS=null;
public static String USER=null;
public static String URL=null;
public static String PASSWORD=null;
public static  long V_WAYBILLNO2;


static{
Properties props=new Properties();
InputStream inStr=null;
try{
inStr=ClassLoader.getSystemResourceAsStream(db_config);
props.load(inStr);
}catch (IOException e){
e.printStackTrace();
}
DRIVERS=props.getProperty("drivers");
URL=props.getProperty("url");
USER=props.getProperty("user");
PASSWORD=props.getProperty("pwd");

  
}

public static Connection getConnection(){
Connection con = null;
 try{   
   con =  DriverManager.getConnection(URL , USER , PASSWORD ) ;   
    }catch(SQLException se){   
   System.out.println("数据库连接失败!");   
   se.printStackTrace() ;   
    } 
 return con;}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Connection con = getConnection();
Statement statement = null;
String sql1=null;
String sql2=null;
String sql3="commit";
Ccw_push_record_temp_50 r=new Ccw_push_record_temp_50();
String V_WAYBILLNO=r.bno_from_recordtemp();
try {
statement=con.createStatement();
sql1="insert into tt_bar_record" +
"(" +
"BAR_RECORD_ID," +
"WAYBILL_NO," +
"ZONE_CODE," +
"OP_CODE," +
"OP_ATTACH_INFO," +
"COURIER_CODE," +
"BAR_OPR_CODE," +
"BAR_UPLOAD_TM," +
"OBJ_TYPE_CODE," +
"CONTNR_CODE," +
"PAY_FLG," +
"STAY_WHY_CODE," +
"SUBBILL_PIECE_QTY," +
"BAR_UPLOAD_TYPE_CODE," +
"WEIGHT_QTY," +
"FEE_AMT," +
"ACCOUNTANT_CODE," +
"OTHER_INFO," +
"OP_NAME," +
"ZONE_TYPE_CODE," +
"ENCRYPT_STRING," +
"BAR_SN," +
"SCHEDULE_CODE," +
"SIGN_TYPE_CODE," +
"SRC_CONTNR_CODE," +
"PHONE_ZONE," +
"PHONE," +
"STOP_OVER_FLG," +
"BATCH_CODE," +
"DEST_ZONE_CODE," +
"AUTOLOADING," +
"BAR_SCAN_TM," +
"BAR_SCAN_DT," +
"EXTEND_ATTACH_1," +
"EXTEND_ATTACH_2," +
"BAR_UPLOAD_OPR_CODE," +
"EXTEND_ATTACH_3," +
"EXTEND_ATTACH_4," +
"EXTEND_ATTACH_5," +
"EXTEND_ATTACH_6," +
"EXTEND_ATTACH_7," +
"BAR_UPLOAD_TM_STD," +
"BAR_SCAN_TM_STD" +
")" +
"values" +
"(" +
V_WAYBILLNO +
","+
V_WAYBILLNO +
","+
"'755A'," +
"'44'," +
"''," +
"'046154'," +
"'1000005565'," +
"sysdate," +
"20," +
"''," +
"0," +
"''," +
"0," +
"0," +
"'1.000'," +
"0.0000," +
"''," +
"'T4'," +
"'派件中'," +
"0," +
"'424'," +
"'V6.6.2'," +
"''," +
"0," +
"''," +
"'755'," +
"''," +
"0," +
"''," +
"''," +
"'1'," +
"sysdate," +
"sysdate," +
"''," +
"''," +
"'171403'," +
"''," +
"''," +
"''," +
"''," +
"sysdate," +
"sysdate," +
"sysdate" +
")";
V_WAYBILLNO2 = Long.parseLong(V_WAYBILLNO);
sql2="INSERT INTO tt_bar_record_log (record_id) SELECT bar_record_id FROM tt_bar_record WHERE waybill_no ='"+V_WAYBILLNO2+"'";
System.out.println(sql2);
statement.executeQuery(sql1);
statement.executeQuery(sql3);
statement.executeQuery(sql2);
statement.executeQuery(sql3);
}
catch (SQLException e) {
e.printStackTrace();
}
}
public long getBno(){
// TODO Auto-generated method stub
Connection con = getConnection();
Statement statement = null;
String sql1=null;
String sql2=null;
String sql3="commit";
Ccw_push_record_temp_50 r=new Ccw_push_record_temp_50();
String V_WAYBILLNO=r.bno_from_recordtemp();
try {
statement=con.createStatement();
sql1="insert into tt_bar_record" +
"(" +
"BAR_RECORD_ID," +
"WAYBILL_NO," +
"ZONE_CODE," +
"OP_CODE," +
"OP_ATTACH_INFO," +
"COURIER_CODE," +
"BAR_OPR_CODE," +
"BAR_UPLOAD_TM," +
"OBJ_TYPE_CODE," +
"CONTNR_CODE," +
"PAY_FLG," +
"STAY_WHY_CODE," +
"SUBBILL_PIECE_QTY," +
"BAR_UPLOAD_TYPE_CODE," +
"WEIGHT_QTY," +
"FEE_AMT," +
"ACCOUNTANT_CODE," +
"OTHER_INFO," +
"OP_NAME," +
"ZONE_TYPE_CODE," +
"ENCRYPT_STRING," +
"BAR_SN," +
"SCHEDULE_CODE," +
"SIGN_TYPE_CODE," +
"SRC_CONTNR_CODE," +
"PHONE_ZONE," +
"PHONE," +
"STOP_OVER_FLG," +
"BATCH_CODE," +
"DEST_ZONE_CODE," +
"AUTOLOADING," +
"BAR_SCAN_TM," +
"BAR_SCAN_DT," +
"EXTEND_ATTACH_1," +
"EXTEND_ATTACH_2," +
"BAR_UPLOAD_OPR_CODE," +
"EXTEND_ATTACH_3," +
"EXTEND_ATTACH_4," +
"EXTEND_ATTACH_5," +
"EXTEND_ATTACH_6," +
"EXTEND_ATTACH_7," +
"BAR_UPLOAD_TM_STD," +
"BAR_SCAN_TM_STD" +
")" +
"values" +
"(" +
V_WAYBILLNO +
","+
V_WAYBILLNO +
","+
"'755A'," +
"'44'," +
"''," +
"'046154'," +
"'1000005565'," +
"sysdate," +
"20," +
"''," +
"0," +
"''," +
"0," +
"0," +
"'1.000'," +
"0.0000," +
"''," +
"'T4'," +
"'派件中'," +
"0," +
"'424'," +
"'V6.6.2'," +
"''," +
"0," +
"''," +
"'755'," +
"''," +
"0," +
"''," +
"''," +
"'1'," +
"sysdate," +
"sysdate," +
"''," +
"''," +
"'171403'," +
"''," +
"''," +
"''," +
"''," +
"sysdate," +
"sysdate," +
"sysdate" +
")";
V_WAYBILLNO2 = Long.parseLong(V_WAYBILLNO);
sql2="INSERT INTO tt_bar_record_log (record_id) SELECT bar_record_id FROM tt_bar_record WHERE waybill_no ='"+V_WAYBILLNO2+"'";
System.out.println(sql2);
statement.executeQuery(sql1);
statement.executeQuery(sql3);
statement.executeQuery(sql2);
statement.executeQuery(sql3);
}
catch (SQLException e) {
e.printStackTrace();
}
return V_WAYBILLNO2;
}
}



帮我用qtc++做一个跟这个效果差不多的import sys import serial import serial.tools.list_ports from PyQt5.QtWidgets import ( QApplication, QWidget, QLabel, QLineEdit, QPushButton, QTextEdit, QVBoxLayout, QHBoxLayout, QComboBox, QCheckBox, QGroupBox, QFormLayout, QGridLayout, QSpacerItem, QSizePolicy ) from PyQt5.QtCore import QTimer, QThread, pyqtSignal, Qt from PyQt5.QtGui import QFont def crc16_modbus(data: bytes) -> int: crc = 0xFFFF for byte in data: crc ^= byte for _ in range(8): if crc & 0x0001: crc >>= 1 crc ^= 0xA001 # 异或反向多项式 else: crc >>= 1 return crc class SerialReader(QThread): data_received = pyqtSignal(bytes) def __init__(self, port, baudrate): super().__init__() self.port = port self.baudrate = baudrate self.serial_port = None self.running = True def run(self): try: self.serial_port = serial.Serial(self.port, self.baudrate, timeout=1) while self.running: data = self.serial_port.read(256) if data: self.data_received.emit(data) except Exception as e: print("串口读取错误:", e) def stop(self): self.running = False if self.serial_port and self.serial_port.is_open: self.serial_port.close() self.wait() class SerialDataDisplay(QWidget): def __init__(self): super().__init__() self.setWindowTitle("串口数据显示界面") self.resize(1500, 1000) self.serial_reader = None self.buffer = bytearray() self.max_lines = 100 self.band_data_cache = { "band1": {}, "band2": {}, "band3": {}, "band4": {} } self.loop_timer = QTimer() self.loop_timer.timeout.connect(self.do_send_data) # 新增:保存上一次发送的预设帧 self.last_preset_data = None self.last_combined_frame = None # 保存最后一次发送的组合帧 # 新增:缓存原始数据用于显示 self.raw_data_lines = [] self.init_ui() self.refresh_ports() # 设置定时器刷新界面 self.update_timer = QTimer() self.update_timer.timeout.connect(self.flush_display) self.update_timer.start(100) def init_ui(self): main_layout = QVBoxLayout() # 版本查询按钮组 version_group = QGroupBox("版本查询") version_group.setFont(QFont("Arial", 12)) version_layout = QHBoxLayout() self.version_button = QPushButton("查询版本") self.version_button.setFont(QFont("Arial", 12)) self.version_button.clicked.connect(self.send_version_query) version_layout.addWidget(self.version_button) version_group.setLayout(version_layout) main_layout.addWidget(version_group) # 串口设置区域 port_config_layout = QHBoxLayout() self.port_combo = QComboBox() self.port_combo.setEditable(True) self.port_combo.setFont(QFont("Arial", 12)) self.port_combo.setFixedWidth(200) self.baud_combo = QComboBox() self.baud_combo.addItems(["9600", "19200", "38400", "57600", "115200"]) self.baud_combo.setCurrentText("115200") self.baud_combo.setFont(QFont("Arial", 12)) self.baud_combo.setFixedWidth(100) self.refresh_button = QPushButton("刷新串口") self.refresh_button.setFont(QFont("Arial", 12)) self.connect_button = QPushButton("连接串口") self.connect_button.setFont(QFont("Arial", 12)) self.status_label = QLabel("未连接") self.status_label.setFont(QFont("Arial", 12)) self.status_label.setStyleSheet("color: red;") port_config_layout.addWidget(QLabel("串口号:")) port_config_layout.addWidget(self.port_combo) port_config_layout.addWidget(QLabel("波特率:")) port_config_layout.addWidget(self.baud_combo) port_config_layout.addWidget(self.refresh_button) port_config_layout.addWidget(self.connect_button) port_config_layout.addWidget(self.status_label) port_config_layout.addSpacerItem(QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) main_layout.addLayout(port_config_layout) # 频段信息显示区域 band_layout = QGridLayout() self.band_widgets = {} for i in range(4): group = QGroupBox(f"频段 {i + 1}") group.setFont(QFont("Arial", 12)) form = QFormLayout() form.setLabelAlignment(Qt.AlignLeft) enabled = QCheckBox() enabled.setEnabled(False) temp = QLineEdit(" ") temp.setReadOnly(True) temp.setFont(QFont("Arial", 11)) current = QLineEdit(" ") current.setReadOnly(True) current.setFont(QFont("Arial", 11)) voltage = QLineEdit(" ") voltage.setReadOnly(True) voltage.setFont(QFont("Arial", 11)) form.addRow("开启状态:", enabled) form.addRow("温度:", temp) form.addRow("电流:", current) form.addRow("电压:", voltage) self.band_widgets[f"band{i + 1}"] = { "enabled": enabled, "temp": temp, "current": current, "voltage": voltage } group.setLayout(form) band_layout.addWidget(group, i // 2, i % 2) main_layout.addLayout(band_layout) # 发送数据帧输入框 send_layout = QHBoxLayout() self.send_input = QLineEdit() self.send_input.setFont(QFont("Arial", 12)) self.send_input.setPlaceholderText("请输入Hex数据,如:5A 5A 5A 5A 01 02 03") self.send_button = QPushButton("发送") self.send_button.setFont(QFont("Arial", 12)) self.send_status = QLabel("") self.send_status.setFont(QFont("Arial", 11)) self.send_status.setStyleSheet("color: blue;") self.loop_checkbox = QCheckBox("循环发送") self.loop_checkbox.setFont(QFont("Arial", 12)) self.interval_input = QLineEdit("1000") # 默认间隔1000ms self.interval_input.setFixedWidth(80) self.interval_input.setFont(QFont("Arial", 12)) self.interval_input.setToolTip("发送间隔(毫秒)") send_layout.addWidget(QLabel("发送数据帧 (Hex):")) send_layout.addWidget(self.send_input) send_layout.addWidget(self.send_button) send_layout.addWidget(self.send_status) send_layout.addWidget(self.loop_checkbox) send_layout.addWidget(QLabel("间隔(ms):")) send_layout.addWidget(self.interval_input) main_layout.addLayout(send_layout) # 频段组合发送组 preset_group = QGroupBox("频段组合发送") preset_group.setFont(QFont("Arial", 12)) preset_layout = QGridLayout() self.band_checkboxes = [] # 每个频段的位掩码 self.band_masks = { "频段1": 0x01, "频段2": 0x02, "频段3": 0x04, "频段4": 0x08, } # 原始帧模板(去掉CRC部分) self.preset_frame_template = bytes.fromhex( "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", ) row = 0 for i, (name, mask) in enumerate(self.band_masks.items()): checkbox = QCheckBox(name) checkbox.setFont(QFont("Arial", 11)) checkbox.stateChanged.connect(self.update_combined_frame) self.band_checkboxes.append(checkbox) preset_layout.addWidget(checkbox, row // 2, row % 2) row += 1 self.send_combined_button = QPushButton("发送组合帧") self.send_combined_button.setFont(QFont("Arial", 12)) self.send_combined_button.clicked.connect(self.send_combined_frame) preset_layout.addWidget(self.send_combined_button, row // 2 + 1, 0, 1, 2) preset_group.setLayout(preset_layout) main_layout.addWidget(preset_group) # 自定义帧按钮组 custom_frame_group = QGroupBox("自定义帧") custom_frame_group.setFont(QFont("Arial", 12)) custom_frame_layout = QHBoxLayout() self.custom_frame_button = QPushButton("持续时间") self.custom_frame_button.setFont(QFont("Arial", 12)) self.custom_frame_button.clicked.connect(self.send_custom_frame) self.duration_input = QLineEdit("0") self.duration_input.setFixedWidth(80) self.duration_input.setToolTip("输入0~65535的持续时间") custom_frame_layout.addWidget(self.custom_frame_button) custom_frame_layout.addWidget(QLabel("持续时间 (0~65535):")) custom_frame_layout.addWidget(self.duration_input) custom_frame_layout.addSpacerItem(QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) custom_frame_group.setLayout(custom_frame_layout) main_layout.addWidget(custom_frame_group) # 干扰码切换模块 jammer_group = QGroupBox("干扰码切换") jammer_group.setFont(QFont("Arial", 12)) jammer_layout = QGridLayout() # 按钮列表 self.jammer_buttons = { "900M-1": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "900M-2": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "1600M-1": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 0B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "1600M-2": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 0C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "2400M-1": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "2400M-2": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "5800M-1": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "5800M-2": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", } row = 0 col = 0 for name, hex_data in self.jammer_buttons.items(): btn = QPushButton(name) btn.setFont(QFont("Arial", 11)) btn.clicked.connect(lambda checked, data=hex_data: self.send_jammer_frame(data)) jammer_layout.addWidget(btn, row, col) col += 1 if col > 2: col = 0 row += 1 jammer_group.setLayout(jammer_layout) main_layout.addWidget(jammer_group) # 新增:功率控制模块 power_group = QGroupBox("功率控制") power_group.setFont(QFont("Arial", 12)) power_layout = QHBoxLayout() # 功率帧模板(A1 12 / A1 13 / A1 15) self.power_frames = { "低功率": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "中功率": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", "高功率": "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" } for name, frame_hex in self.power_frames.items(): btn = QPushButton(name) btn.setFont(QFont("Arial", 11)) btn.clicked.connect(lambda checked, data=frame_hex: self.send_power_frame(data)) power_layout.addWidget(btn) power_group.setLayout(power_layout) main_layout.addWidget(power_group) # 原始数据帧显示框 raw_data_group = QGroupBox("原始数据帧显示") raw_data_group.setFont(QFont("Arial", 12)) self.raw_data_display = QTextEdit() self.raw_data_display.setReadOnly(True) self.raw_data_display.setFont(QFont("Courier", 10)) layout = QVBoxLayout() layout.addWidget(self.raw_data_display) raw_data_group.setLayout(layout) main_layout.addWidget(raw_data_group) # 信号连接 self.refresh_button.clicked.connect(self.refresh_ports) self.connect_button.clicked.connect(self.toggle_serial_connection) self.send_button.clicked.connect(self.handle_send_button_click) self.send_input.returnPressed.connect(self.handle_send_button_click) self.setLayout(main_layout) self.update_timer = QTimer() self.update_timer.timeout.connect(self.flush_display) self.update_timer.start(100) #新增方法:发送功率帧 def send_power_frame(self, hex_data): try: data_bytes = bytes.fromhex(hex_data.replace(' ', '')) except ValueError: self.send_status.setText("功率帧数据格式错误") self.send_status.setStyleSheet("color: red;") return try: # 取第12字节之后的数据计算 CRC crc_data = data_bytes[12:] crc_value = crc16_modbus(crc_data) # 转为可变列表插入 CRC data_list = list(data_bytes) data_list[8] = (crc_value >> 8) & 0xFF # CRC 高位 → 第8字节 data_list[9] = crc_value & 0xFF # CRC 低位 → 第9字节 final_bytes = bytes(data_list) # 格式化为带空格的 Hex 字符串 hex_with_crc = ''.join(f"{b:02X}" for b in final_bytes) formatted_hex = ' '.join(hex_with_crc[i:i+2] for i in range(0, len(hex_with_crc), 2)) self.send_input.setText(formatted_hex) # 发送 if self.serial_reader and self.serial_reader.serial_port and self.serial_reader.serial_port.is_open: self.serial_reader.serial_port.write(final_bytes) cmd_code = hex_data.split()[13] self.send_status.setText(f"功率设置({cmd_code})发送成功") self.send_status.setStyleSheet("color: green;") else: self.send_status.setText("串口未连接") self.send_status.setStyleSheet("color: red;") except Exception as e: self.send_status.setText(f"功率帧发送失败: {str(e)}") self.send_status.setStyleSheet("color: red;") def send_jammer_frame(self, hex_data): try: data_bytes = bytes.fromhex(hex_data.replace(' ', '')) except ValueError: self.send_status.setText("干扰码数据格式错误") self.send_status.setStyleSheet("color: red;") return try: crc_data = data_bytes[12:] crc_value = crc16_modbus(crc_data) data_list = list(data_bytes) data_list[8] = (crc_value >> 8) & 0xFF # 高位 data_list[9] = crc_value & 0xFF # 低位 hex_with_crc = ''.join(f"{b:02X}" for b in data_list) formatted_hex = ' '.join(hex_with_crc[i:i+2] for i in range(0, len(hex_with_crc), 2)) self.send_input.setText(formatted_hex) except Exception as e: self.send_status.setText("CRC计算失败:" + str(e)) self.send_status.setStyleSheet("color: red;") return if self.serial_reader and self.serial_reader.serial_port and self.serial_reader.serial_port.is_open: try: self.serial_reader.serial_port.write(data_bytes) #self.send_status.setText(f"干扰码 {hex_data} 发送成功") self.send_status.setStyleSheet("color: green;") except Exception as e: self.send_status.setText("发送失败:" + str(e)) self.send_status.setStyleSheet("color: red;") else: self.send_status.setText("串口未连接") self.send_status.setStyleSheet("color: red;") def handle_send_button_click(self): if self.loop_checkbox.isChecked(): try: interval = int(self.interval_input.text()) if interval < 100: self.send_status.setText("间隔太小(至少100ms)") self.send_status.setStyleSheet("color: red;") return self.loop_timer.start(interval) self.send_status.setText("循环发送中...") self.send_status.setStyleSheet("color: green;") except ValueError: self.send_status.setText("请输入有效的数字作为间隔") self.send_status.setStyleSheet("color: red;") else: self.loop_timer.stop() self.send_hex_data() def send_custom_frame(self): if not hasattr(self, 'last_combined_frame') or self.last_combined_frame is None: self.send_status.setText("请先发送一次组合帧") self.send_status.setStyleSheet("color: red;") return # 获取用户输入的持续时间 duration_str = self.duration_input.text().strip() try: duration = int(duration_str) if not (0 <= duration <= 65535): raise ValueError("范围必须在 0 ~ 65535 之间") except ValueError as e: self.send_status.setText(f"输入错误:{e}") self.send_status.setStyleSheet("color: red;") return # 将整数转换为两个字节(高位在前) byte16 = (duration >> 8) & 0xFF # 高位字节 byte17 = duration & 0xFF # 低位字节 # 拷贝上一次的组合帧 data_bytes = bytearray(self.last_combined_frame) # 插入到帧的第16和17个字节位置(索引16、17) data_bytes[16] = byte16 data_bytes[17] = byte17 try: # 计算 CRC(从第12字节开始) crc_data = bytes(data_bytes[12:]) crc_value = crc16_modbus(crc_data) # 插入 CRC 到第8、9字节 data_bytes[8] = (crc_value >> 8) & 0xFF data_bytes[9] = crc_value & 0xFF hex_with_crc = ''.join(f"{b:02X}" for b in data_bytes) self.send_input.setText(' '.join(hex_with_crc[i:i+2] for i in range(0, len(hex_with_crc), 2))) except Exception as e: self.send_status.setText("CRC计算失败:" + str(e)) self.send_status.setStyleSheet("color: red;") return if self.serial_reader and self.serial_reader.serial_port and self.serial_reader.serial_port.is_open: self.send_hex_data() else: self.send_status.setText("请先连接串口") self.send_status.setStyleSheet("color: red;") def send_version_query(self): hex_data = "5A 5A 5A 5A 43 00 42 4E 7A 0E 4C 47 A1 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" try: data_bytes = bytes.fromhex(hex_data.replace(' ', '')) except ValueError: self.send_status.setText("版本查询数据格式错误") self.send_status.setStyleSheet("color: red;") return try: crc_data = data_bytes[12:] crc_value = crc16_modbus(crc_data) data_list = list(data_bytes) data_list[8] = (crc_value >> 8) & 0xFF # 高位 data_list[9] = crc_value & 0xFF # 低位 hex_with_crc = ''.join(f"{b:02X}" for b in data_list) self.send_input.setText(' '.join(hex_with_crc[i:i+2] for i in range(0, len(hex_with_crc), 2))) except Exception as e: self.send_status.setText("CRC计算失败:" + str(e)) self.send_status.setStyleSheet("color: red;") return if self.serial_reader and self.serial_reader.serial_port and self.serial_reader.serial_port.is_open: self.send_hex_data() else: self.send_status.setText("请先连接串口") self.send_status.setStyleSheet("color: red;") def do_send_data(self): hex_str = self.send_input.text().strip() if not hex_str: return try: hex_bytes = bytes.fromhex(hex_str.replace(' ', '')) if self.serial_reader and self.serial_reader.serial_port and self.serial_reader.serial_port.is_open: self.serial_reader.serial_port.write(hex_bytes) else: self.loop_timer.stop() self.send_status.setText("串口已断开,停止循环发送") self.send_status.setStyleSheet("color: red;") except Exception as e: self.loop_timer.stop() self.send_status.setText("发送失败:" + str(e)) self.send_status.setStyleSheet("color: red;") def send_hex_data(self): hex_str = self.send_input.text().strip() if not hex_str: self.send_status.setText("请输入有效的Hex数据") self.send_status.setStyleSheet("color: red;") return try: hex_bytes = bytes.fromhex(hex_str.replace(' ', '')) if self.serial_reader and self.serial_reader.serial_port and self.serial_reader.serial_port.is_open: self.serial_reader.serial_port.write(hex_bytes) self.send_status.setText("发送成功") self.send_status.setStyleSheet("color: green;") else: self.send_status.setText("串口未连接") self.send_status.setStyleSheet("color: red;") except Exception as e: self.send_status.setText("发送失败:" + str(e)) self.send_status.setStyleSheet("color: red;") def refresh_ports(self): current_text = self.port_combo.currentText() self.port_combo.clear() ports = serial.tools.list_ports.comports() for port in ports: self.port_combo.addItem(port.device) if current_text and current_text not in [self.port_combo.itemText(i) for i in range(self.port_combo.count())]: self.port_combo.addItem(current_text) self.port_combo.setCurrentText(current_text) else: self.port_combo.setCurrentText(current_text if current_text else "") def toggle_serial_connection(self): if self.serial_reader and self.serial_reader.isRunning(): self.serial_reader.stop() self.status_label.setText("已断开") self.status_label.setStyleSheet("color: red;") self.connect_button.setText("连接串口") self.loop_timer.stop() else: port = self.port_combo.currentText() baud = int(self.baud_combo.currentText()) self.serial_reader = SerialReader(port, baud) self.serial_reader.data_received.connect(self.handle_serial_data) self.serial_reader.start() self.status_label.setText("已连接") self.status_label.setStyleSheet("color: green;") self.connect_button.setText("断开串口") def handle_serial_data(self, data): self.buffer.extend(data) self.raw_data_lines.append("Received (Hex): " + ' '.join(f"{b:02X}" for b in data)) # 将原始数据转换为Hex格式并添加到缓冲区 self.process_buffer() def process_buffer(self): while len(self.buffer) >= 78: found = False for i in range(len(self.buffer) - 77): if self.buffer[i + 12] == 0xA2 and self.buffer[i + 13] == 0x02: frame = self.buffer[i:i+78] self.buffer = self.buffer[i+78:] self.raw_data_lines.append("Received Frame (Hex): " + ' '.join(f"{b:02X}" for b in frame)) self.parse_hex_data(frame) found = True break if not found: break def flush_display(self): if self.raw_data_lines: lines = self.raw_data_lines self.raw_data_lines = [] for line in lines: cursor = self.raw_data_display.textCursor() cursor.movePosition(cursor.End) cursor.select(cursor.LineUnderCursor) line_count = self.raw_data_display.document().lineCount() if line_count >= self.max_lines: cursor.movePosition(cursor.Start) cursor.select(cursor.LineUnderCursor) cursor.removeSelectedText() cursor.deleteChar() cursor.movePosition(cursor.End) cursor.insertText(line + '\n') self.raw_data_display.setTextCursor(cursor) self.raw_data_display.ensureCursorVisible() for i in range(4): band_name = f"band{i + 1}" self.update_band_display(band_name, self.band_data_cache[band_name]) def parse_hex_data(self, data): try: hex_data = list(data) # 检查长度是否足够 if len(hex_data) < 78: return switch_byte = hex_data[15] switches = [(switch_byte >> i) & 1 for i in range(4)] if len(hex_data) > 29: temp = hex_data[25] volt = (hex_data[26] << 8) | hex_data[27] curr = (hex_data[28] << 8) | hex_data[29] self.band_data_cache["band1"]["temp"] = f"{temp}°C" self.band_data_cache["band1"]["voltage"] = f"{volt / 1000:.3f}V" self.band_data_cache["band1"]["current"] = f"{curr / 1000:.3f}A" self.band_data_cache["band1"]["enabled"] = "on" if switches[0] else "off" if len(hex_data) > 38: temp = hex_data[33] volt = (hex_data[34] << 8) | hex_data[35] curr = (hex_data[36] << 8) | hex_data[37] self.band_data_cache["band2"]["temp"] = f"{temp}°C" self.band_data_cache["band2"]["voltage"] = f"{volt / 1000:.3f}V" self.band_data_cache["band2"]["current"] = f"{curr / 1000:.3f}A" self.band_data_cache["band2"]["enabled"] = "on" if switches[1] else "off" if len(hex_data) > 46: temp = hex_data[41] volt = (hex_data[42] << 8) | hex_data[43] curr = (hex_data[44] << 8) | hex_data[45] self.band_data_cache["band3"]["temp"] = f"{temp}°C" self.band_data_cache["band3"]["voltage"] = f"{volt / 1000:.3f}V" self.band_data_cache["band3"]["current"] = f"{curr / 1000:.3f}A" self.band_data_cache["band3"]["enabled"] = "on" if switches[2] else "off" if len(hex_data) > 54: temp = hex_data[49] volt = (hex_data[50] << 8) | hex_data[51] curr = (hex_data[52] << 8) | hex_data[53] self.band_data_cache["band4"]["temp"] = f"{temp}°C" self.band_data_cache["band4"]["voltage"] = f"{volt / 1000:.3f}V" self.band_data_cache["band4"]["current"] = f"{curr / 1000:.3f}A" self.band_data_cache["band4"]["enabled"] = "on" if switches[3] else "off" except Exception as e: print("解析Hex数据失败:", e) def update_band_display(self, band_name, data): widgets = self.band_widgets.get(band_name) if not widgets: return if "enabled" in data: widgets["enabled"].setChecked(data["enabled"] == "on") if "temp" in data: widgets["temp"].setText(data["temp"]) if "current" in data: widgets["current"].setText(data["current"]) if "voltage" in data: widgets["voltage"].setText(data["voltage"]) def update_combined_frame(self): # 构造帧副本 frame = bytearray(self.preset_frame_template) # 计算启用的频段掩码 combined_mask = 0x00 for checkbox in self.band_checkboxes: if checkbox.isChecked(): band_name = checkbox.text() combined_mask |= self.band_masks[band_name] # 设置第16个字节 frame[15] = combined_mask # 计算 CRC(从第12字节开始) crc_data = bytes(frame[12:]) crc_value = crc16_modbus(crc_data) # 插入 CRC frame[8] = (crc_value >> 8) & 0xFF # 高位 frame[9] = crc_value & 0xFF # 低位 # 保存组合帧用于后续自定义帧使用 self.last_combined_frame = frame # 显示在发送框中 hex_with_crc = ''.join(f"{b:02X}" for b in frame) formatted_hex = ' '.join(hex_with_crc[i:i+2] for i in range(0, len(hex_with_crc), 2)) self.send_input.setText(formatted_hex) def send_combined_frame(self): hex_str = self.send_input.text().strip() if not hex_str: self.send_status.setText("请输入有效的Hex数据") self.send_status.setStyleSheet("color: red;") return try: hex_bytes = bytes.fromhex(hex_str.replace(' ', '')) if self.serial_reader and self.serial_reader.serial_port and self.serial_reader.serial_port.is_open: self.serial_reader.serial_port.write(hex_bytes) self.send_status.setText("组合帧发送成功") self.send_status.setStyleSheet("color: green;") else: self.send_status.setText("串口未连接") self.send_status.setStyleSheet("color: red;") except Exception as e: self.send_status.setText("发送失败:" + str(e)) self.send_status.setStyleSheet("color: red;") if __name__ == "__main__": app = QApplication(sys.argv) window = SerialDataDisplay() window.show() sys.exit(app.exec_())
11-18
/* * Vhost-user RDMA device : Handling rdma complete queue * * Copyright (C) 2025 KylinSoft Inc. and/or its affiliates. All rights reserved. * * Author: Xiong Weimin <xiongweimin@kylinos.cn> * * 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 2 of the License, or * (at your option) any later version. */ #include <rte_mbuf.h> #include "vhost_rdma_opcode.h" #include "vhost_rdma_ib.h" #include "vhost_rdma_queue.h" #include "vhost_rdma.h" #include "vhost_rdma_pkt.h" enum comp_state { VHOST_RDMA_COMPST_GET_ACK, VHOST_RDMA_COMPST_GET_WQE, VHOST_RDMA_COMPST_COMP_WQE, VHOST_RDMA_COMPST_COMP_ACK, VHOST_RDMA_COMPST_CHECK_PSN, VHOST_RDMA_COMPST_CHECK_ACK, VHOST_RDMA_COMPST_READ, VHOST_RDMA_COMPST_ATOMIC, VHOST_RDMA_COMPST_WRITE_SEND, VHOST_RDMA_COMPST_UPDATE_COMP, VHOST_RDMA_COMPST_ERROR_RETRY, VHOST_RDMA_COMPST_RNR_RETRY, VHOST_RDMA_COMPST_ERROR, VHOST_RDMA_COMPST_EXIT, /* We have an issue, and we want to rerun the completer */ VHOST_RDMA_COMPST_DONE, /* The completer finished successflly */ }; static const char *comp_state_name[] = { [VHOST_RDMA_COMPST_GET_ACK] = "GET ACK", [VHOST_RDMA_COMPST_GET_WQE] = "GET WQE", [VHOST_RDMA_COMPST_COMP_WQE] = "COMP WQE", [VHOST_RDMA_COMPST_COMP_ACK] = "COMP ACK", [VHOST_RDMA_COMPST_CHECK_PSN] = "CHECK PSN", [VHOST_RDMA_COMPST_CHECK_ACK] = "CHECK ACK", [VHOST_RDMA_COMPST_READ] = "READ", [VHOST_RDMA_COMPST_ATOMIC] = "ATOMIC", [VHOST_RDMA_COMPST_WRITE_SEND] = "WRITE/SEND", [VHOST_RDMA_COMPST_UPDATE_COMP] = "UPDATE COMP", [VHOST_RDMA_COMPST_ERROR_RETRY] = "ERROR RETRY", [VHOST_RDMA_COMPST_RNR_RETRY] = "RNR RETRY", [VHOST_RDMA_COMPST_ERROR] = "ERROR", [VHOST_RDMA_COMPST_EXIT] = "EXIT", [VHOST_RDMA_COMPST_DONE] = "DONE", }; enum ib_rnr_timeout { IB_RNR_TIMER_655_36 = 0, IB_RNR_TIMER_000_01 = 1, IB_RNR_TIMER_000_02 = 2, IB_RNR_TIMER_000_03 = 3, IB_RNR_TIMER_000_04 = 4, IB_RNR_TIMER_000_06 = 5, IB_RNR_TIMER_000_08 = 6, IB_RNR_TIMER_000_12 = 7, IB_RNR_TIMER_000_16 = 8, IB_RNR_TIMER_000_24 = 9, IB_RNR_TIMER_000_32 = 10, IB_RNR_TIMER_000_48 = 11, IB_RNR_TIMER_000_64 = 12, IB_RNR_TIMER_000_96 = 13, IB_RNR_TIMER_001_28 = 14, IB_RNR_TIMER_001_92 = 15, IB_RNR_TIMER_002_56 = 16, IB_RNR_TIMER_003_84 = 17, IB_RNR_TIMER_005_12 = 18, IB_RNR_TIMER_007_68 = 19, IB_RNR_TIMER_010_24 = 20, IB_RNR_TIMER_015_36 = 21, IB_RNR_TIMER_020_48 = 22, IB_RNR_TIMER_030_72 = 23, IB_RNR_TIMER_040_96 = 24, IB_RNR_TIMER_061_44 = 25, IB_RNR_TIMER_081_92 = 26, IB_RNR_TIMER_122_88 = 27, IB_RNR_TIMER_163_84 = 28, IB_RNR_TIMER_245_76 = 29, IB_RNR_TIMER_327_68 = 30, IB_RNR_TIMER_491_52 = 31 }; static unsigned long rnrnak_usec[32] = { [IB_RNR_TIMER_655_36] = 655360, [IB_RNR_TIMER_000_01] = 10, [IB_RNR_TIMER_000_02] = 20, [IB_RNR_TIMER_000_03] = 30, [IB_RNR_TIMER_000_04] = 40, [IB_RNR_TIMER_000_06] = 60, [IB_RNR_TIMER_000_08] = 80, [IB_RNR_TIMER_000_12] = 120, [IB_RNR_TIMER_000_16] = 160, [IB_RNR_TIMER_000_24] = 240, [IB_RNR_TIMER_000_32] = 320, [IB_RNR_TIMER_000_48] = 480, [IB_RNR_TIMER_000_64] = 640, [IB_RNR_TIMER_000_96] = 960, [IB_RNR_TIMER_001_28] = 1280, [IB_RNR_TIMER_001_92] = 1920, [IB_RNR_TIMER_002_56] = 2560, [IB_RNR_TIMER_003_84] = 3840, [IB_RNR_TIMER_005_12] = 5120, [IB_RNR_TIMER_007_68] = 7680, [IB_RNR_TIMER_010_24] = 10240, [IB_RNR_TIMER_015_36] = 15360, [IB_RNR_TIMER_020_48] = 20480, [IB_RNR_TIMER_030_72] = 30720, [IB_RNR_TIMER_040_96] = 40960, [IB_RNR_TIMER_061_44] = 61410, [IB_RNR_TIMER_081_92] = 81920, [IB_RNR_TIMER_122_88] = 122880, [IB_RNR_TIMER_163_84] = 163840, [IB_RNR_TIMER_245_76] = 245760, [IB_RNR_TIMER_327_68] = 327680, [IB_RNR_TIMER_491_52] = 491520, }; static __rte_always_inline enum comp_state vhost_rdma_get_wqe(struct vhost_rdma_qp *qp, struct vhost_rdma_pkt_info *pkt, struct vhost_rdma_send_wqe **wqe_p) { struct vhost_rdma_send_wqe *wqe; /* we come here whether or not we found a response packet to see if * there are any posted WQEs */ wqe = queue_head(&qp->sq.queue); *wqe_p = wqe; /* no WQE or requester has not started it yet */ if (!wqe || wqe->state == WQE_STATE_POSTED) return pkt ? VHOST_RDMA_COMPST_DONE : VHOST_RDMA_COMPST_EXIT; /* WQE does not require an ack */ if (wqe->state == WQE_STATE_DONE) return VHOST_RDMA_COMPST_COMP_WQE; /* WQE caused an error */ if (wqe->state == WQE_STATE_ERROR) return VHOST_RDMA_COMPST_ERROR; /* we have a WQE, if we also have an ack check its PSN */ return pkt ? VHOST_RDMA_COMPST_CHECK_PSN : VHOST_RDMA_COMPST_EXIT; } static __rte_always_inline void reset_retry_counters(struct vhost_rdma_qp *qp) { qp->comp.retry_cnt = qp->attr.retry_cnt; qp->comp.rnr_retry = qp->attr.rnr_retry; qp->comp.started_retry = 0; } static __rte_always_inline enum comp_state vhost_rdma_check_psn(struct vhost_rdma_qp *qp, struct vhost_rdma_pkt_info *pkt, struct vhost_rdma_send_wqe *wqe) { int32_t diff; diff = psn_compare(pkt->psn, wqe->last_psn); if (diff > 0) { if (wqe->state == WQE_STATE_PENDING) { if (wqe->mask & WR_ATOMIC_OR_READ_MASK) return VHOST_RDMA_COMPST_ERROR_RETRY; reset_retry_counters(qp); return VHOST_RDMA_COMPST_COMP_WQE; } else { return VHOST_RDMA_COMPST_DONE; } } /* compare response packet to expected response */ diff = psn_compare(pkt->psn, qp->comp.psn); if (diff < 0) { /* response is most likely a retried packet if it matches an * uncompleted WQE go complete it else ignore it */ if (pkt->psn == wqe->last_psn) return VHOST_RDMA_COMPST_COMP_ACK; else return VHOST_RDMA_COMPST_DONE; } else if ((diff > 0) && (wqe->mask & WR_ATOMIC_OR_READ_MASK)) { return VHOST_RDMA_COMPST_DONE; } else { return VHOST_RDMA_COMPST_CHECK_ACK; } } static __rte_always_inline enum comp_state vhost_rdma_check_ack(struct vhost_rdma_qp *qp, struct vhost_rdma_pkt_info *pkt, struct vhost_rdma_send_wqe *wqe) { struct vhost_rdma_device *dev = qp->dev; unsigned int mask = pkt->mask; uint8_t syn; switch (qp->comp.opcode) { case -1: /* Will catch all *_ONLY cases. */ if (!(mask & VHOST_START_MASK)) return VHOST_RDMA_COMPST_ERROR; break; case IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST: case IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE: if (pkt->opcode != IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE && pkt->opcode != IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST) { /* read retries of partial data may restart from * read response first or response only. */ if ((pkt->psn == wqe->first_psn && pkt->opcode == IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) || (wqe->first_psn == wqe->last_psn && pkt->opcode == IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY)) break; return VHOST_RDMA_COMPST_ERROR; } break; default: RDMA_LOG_ERR("should not reach here"); } /* Check operation validity. */ switch (pkt->opcode) { case IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST: case IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST: case IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY: syn = aeth_syn(pkt); if ((syn & AETH_TYPE_MASK) != AETH_ACK) return VHOST_RDMA_COMPST_ERROR; case IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE: if (wqe->wr->opcode != VHOST_RDMA_IB_WR_RDMA_READ) { wqe->status = VHOST_RDMA_IB_WC_FATAL_ERR; return VHOST_RDMA_COMPST_ERROR; } reset_retry_counters(qp); return VHOST_RDMA_COMPST_READ; case IB_OPCODE_RC_ACKNOWLEDGE: syn = aeth_syn(pkt); switch (syn & AETH_TYPE_MASK) { case AETH_ACK: reset_retry_counters(qp); return VHOST_RDMA_COMPST_WRITE_SEND; case AETH_RNR_NAK: vhost_rdma_counter_inc(dev, VHOST_RDMA_CNT_RCV_RNR); return VHOST_RDMA_COMPST_RNR_RETRY; case AETH_NAK: switch (syn) { case AETH_NAK_PSN_SEQ_ERROR: if (psn_compare(pkt->psn, qp->comp.psn) > 0) { vhost_rdma_counter_inc(dev, VHOST_RDMA_CNT_RCV_SEQ_ERR); qp->comp.psn = pkt->psn; if (qp->req.wait_psn) { qp->req.wait_psn = 0; vhost_rdma_run_task(&qp->req.task, 0); } } return VHOST_RDMA_COMPST_ERROR_RETRY; case AETH_NAK_INVALID_REQ: wqe->status = VHOST_RDMA_IB_WC_REM_INV_REQ_ERR; return VHOST_RDMA_COMPST_ERROR; case AETH_NAK_REM_ACC_ERR: wqe->status = VHOST_RDMA_IB_WC_REM_ACCESS_ERR; return VHOST_RDMA_COMPST_ERROR; case AETH_NAK_REM_OP_ERR: wqe->status = VHOST_RDMA_IB_WC_REM_OP_ERR; return VHOST_RDMA_COMPST_ERROR; default: RDMA_LOG_ERR("unexpected nak %x", syn); wqe->status = VHOST_RDMA_IB_WC_REM_OP_ERR; return VHOST_RDMA_COMPST_ERROR; } default: return VHOST_RDMA_COMPST_ERROR; } break; default: RDMA_LOG_ERR("unexpected opcode: %u\n", pkt->opcode); } return VHOST_RDMA_COMPST_ERROR; } static __rte_always_inline enum comp_state vhost_rdma_do_read(struct vhost_rdma_qp *qp, struct vhost_rdma_pkt_info *pkt, struct vhost_rdma_send_wqe *wqe) { int ret; ret = copy_data(qp->pd, VHOST_RDMA_IB_ACCESS_LOCAL_WRITE, &wqe->dma, payload_addr(pkt), payload_size(pkt), VHOST_RDMA_TO_MR_OBJ, NULL); if (ret) { wqe->status = VHOST_RDMA_IB_WC_LOC_PROT_ERR; return VHOST_RDMA_COMPST_ERROR; } if (wqe->dma.resid == 0 && (pkt->mask & VHOST_END_MASK)) return VHOST_RDMA_COMPST_COMP_ACK; return VHOST_RDMA_COMPST_UPDATE_COMP; } static __rte_always_inline enum comp_state vhost_rdma_do_atomic(struct vhost_rdma_qp *qp, struct vhost_rdma_pkt_info *pkt, struct vhost_rdma_send_wqe *wqe) { int ret; uint64_t atomic_orig = atmack_orig(pkt); ret = copy_data(qp->pd, VHOST_RDMA_IB_ACCESS_LOCAL_WRITE, &wqe->dma, &atomic_orig, sizeof(uint64_t), VHOST_RDMA_TO_MR_OBJ, NULL); if (ret) { wqe->status = VHOST_RDMA_IB_WC_LOC_PROT_ERR; return VHOST_RDMA_COMPST_ERROR; } return VHOST_RDMA_COMPST_COMP_ACK; } static enum vhost_rdma_ib_wc_opcode wr_to_wc_opcode(enum vhost_rdma_ib_wr_opcode opcode) { switch (opcode) { case VHOST_RDMA_IB_WR_RDMA_WRITE: return VHOST_RDMA_IB_WC_RDMA_WRITE; case VHOST_RDMA_IB_WR_RDMA_WRITE_WITH_IMM: return VHOST_RDMA_IB_WC_RDMA_WRITE; case VHOST_RDMA_IB_WR_SEND: return VHOST_RDMA_IB_WC_SEND; case VHOST_RDMA_IB_WR_SEND_WITH_IMM: return VHOST_RDMA_IB_WC_SEND; case VHOST_RDMA_IB_WR_RDMA_READ: return VHOST_RDMA_IB_WC_RDMA_READ; default: return 0xff; } } static void make_send_cqe(struct vhost_rdma_qp *qp, struct vhost_rdma_send_wqe *wqe, struct vhost_rdma_cq_req *cqe) { memset(cqe, 0, sizeof(*cqe)); cqe->wr_id = wqe->wr->wr_id; cqe->status = wqe->status; cqe->opcode = wr_to_wc_opcode(wqe->wr->opcode); if (wqe->wr->opcode == VHOST_RDMA_IB_WR_RDMA_WRITE_WITH_IMM || wqe->wr->opcode == VHOST_RDMA_IB_WR_SEND_WITH_IMM) cqe->wc_flags = VHOST_RDMA_WC_WITH_IMM; cqe->byte_len = wqe->dma.length; cqe->qp_num = qp->qpn; } static __rte_always_inline void advance_consumer(struct vhost_rdma_queue *q) { uint16_t cons; uint16_t desc; assert(q->consumer_index == q->vq->last_avail_idx); cons = q->consumer_index & (q->num_elems - 1); desc = q->vq->vring.avail->ring[cons]; vhost_rdma_queue_push(q->vq, desc, 0); q->consumer_index++; q->vq->last_avail_idx++; } /* * IBA Spec. Section 10.7.3.1 SIGNALED COMPLETIONS * ---------8<---------8<------------- * ...Note that if a completion error occurs, a Work Completion * will always be generated, even if the signaling * indicator requests an Unsignaled Completion. * ---------8<---------8<------------- */ static void vhost_rdma_do_complete(struct vhost_rdma_qp *qp, struct vhost_rdma_send_wqe *wqe) { struct vhost_rdma_device *dev = qp->dev; struct vhost_rdma_cq_req cqe; bool post; /* do we need to post a completion */ post = (qp->sq_sig_all || (wqe->wr->send_flags & VHOST_RDMA_IB_SEND_SIGNALED) || wqe->status != VHOST_RDMA_IB_WC_SUCCESS); if (post) make_send_cqe(qp, wqe, &cqe); advance_consumer(&qp->sq.queue); if (post) vhost_rdma_cq_post(dev, qp->scq, &cqe, 0); if (wqe->wr->opcode == VHOST_RDMA_IB_WR_SEND || wqe->wr->opcode == VHOST_RDMA_IB_WR_SEND_WITH_IMM) vhost_rdma_counter_inc(dev, VHOST_RDMA_CNT_RDMA_SEND); /* * we completed something so let req run again * if it is trying to fence */ if (qp->req.wait_fence) { qp->req.wait_fence = 0; vhost_rdma_run_task(&qp->req.task, 0); } } static __rte_always_inline enum comp_state vhost_rdma_complete_wqe(struct vhost_rdma_qp *qp, struct vhost_rdma_pkt_info *pkt, struct vhost_rdma_send_wqe *wqe) { if (pkt && wqe->state == WQE_STATE_PENDING) { if (psn_compare(wqe->last_psn, qp->comp.psn) >= 0) { qp->comp.psn = (wqe->last_psn + 1) & VHOST_RDMA_PSN_MASK; qp->comp.opcode = -1; } if (qp->req.wait_psn) { qp->req.wait_psn = 0; vhost_rdma_run_task(&qp->req.task, 1); } } vhost_rdma_do_complete(qp, wqe); return VHOST_RDMA_COMPST_GET_WQE; } static void vhost_rdma_rnr_nak_timer(__rte_unused struct rte_timer *timer, void* arg) { struct vhost_rdma_qp *qp = arg; RDMA_LOG_DEBUG_DP("qp#%d rnr nak timer fired", qp->qpn); vhost_rdma_run_task(&qp->req.task, 1); } static __rte_always_inline enum comp_state vhost_rdma_complete_ack(struct vhost_rdma_qp *qp, struct vhost_rdma_pkt_info *pkt, struct vhost_rdma_send_wqe *wqe) { if (wqe->has_rd_atomic) { wqe->has_rd_atomic = 0; rte_atomic32_inc(&qp->req.rd_atomic); if (qp->req.need_rd_atomic) { qp->comp.timeout_retry = 0; qp->req.need_rd_atomic = 0; vhost_rdma_run_task(&qp->req.task, 0); } } if (unlikely(qp->req.state == QP_STATE_DRAIN)) { /* state_lock used by requester & completer */ rte_spinlock_lock(&qp->state_lock); if ((qp->req.state == QP_STATE_DRAIN) && (qp->comp.psn == qp->req.psn)) { qp->req.state = QP_STATE_DRAINED; rte_spinlock_unlock(&qp->state_lock); // TODO: event // if (qp->ibqp.event_handler) { // struct ib_event ev; // ev.device = qp->ibqp.device; // ev.element.qp = &qp->ibqp; // ev.event = IB_EVENT_SQ_DRAINED; // qp->ibqp.event_handler(&ev, // qp->ibqp.qp_context); // } } else { rte_spinlock_unlock(&qp->state_lock); } } vhost_rdma_do_complete(qp, wqe); if (psn_compare(pkt->psn, qp->comp.psn) >= 0) return VHOST_RDMA_COMPST_UPDATE_COMP; else return VHOST_RDMA_COMPST_DONE; } static __rte_always_inline void free_pkt(struct vhost_rdma_pkt_info *pkt) { struct rte_mbuf *mbuf = PKT_TO_MBUF(pkt); vhost_rdma_drop_ref(pkt->qp, pkt->qp->dev, qp); rte_pktmbuf_free(mbuf); } static __rte_always_inline unsigned long rnrnak_ticks(uint8_t timeout) { uint64_t ticks_per_us = rte_get_timer_hz() / 1000000; return RTE_MAX(rnrnak_usec[timeout] * ticks_per_us, 1); } static void vhost_rdma_drain_resp_pkts(struct vhost_rdma_qp *qp, bool notify) { struct rte_mbuf *mbuf; struct vhost_rdma_send_wqe *wqe; struct vhost_rdma_queue *q = &qp->sq.queue; while (rte_ring_dequeue(qp->resp_pkts, (void**)&mbuf) == 0) { vhost_rdma_drop_ref(qp, qp->dev, qp); rte_pktmbuf_free(mbuf); } while ((wqe = queue_head(q))) { if (notify) { wqe->status = VHOST_RDMA_IB_WC_WR_FLUSH_ERR; vhost_rdma_do_complete(qp, wqe); } else { advance_consumer(q); } } } int vhost_rdma_completer(void* arg) { struct vhost_rdma_qp *qp = arg; struct vhost_rdma_device *dev = qp->dev; struct vhost_rdma_send_wqe *wqe = NULL; struct rte_mbuf *mbuf = NULL; struct vhost_rdma_pkt_info *pkt = NULL; enum comp_state state; int ret = 0; vhost_rdma_add_ref(qp); if (!qp->valid || qp->req.state == QP_STATE_ERROR || qp->req.state == QP_STATE_RESET) { vhost_rdma_drain_resp_pkts(qp, qp->valid && qp->req.state == QP_STATE_ERROR); ret = -EAGAIN; goto done; } if (qp->comp.timeout) { qp->comp.timeout_retry = 1; qp->comp.timeout = 0; } else { qp->comp.timeout_retry = 0; } if (qp->req.need_retry) { ret = -EAGAIN; goto done; } state = VHOST_RDMA_COMPST_GET_ACK; while (1) { RDMA_LOG_DEBUG_DP("qp#%d state = %s\n", qp->qpn, comp_state_name[state]); switch (state) { case VHOST_RDMA_COMPST_GET_ACK: if (rte_ring_dequeue(qp->resp_pkts, (void**)&mbuf) == 0) { pkt = MBUF_TO_PKT(mbuf); qp->comp.timeout_retry = 0; } else { mbuf = NULL; } state = VHOST_RDMA_COMPST_GET_WQE; break; case VHOST_RDMA_COMPST_GET_WQE: state = vhost_rdma_get_wqe(qp, pkt, &wqe); break; case VHOST_RDMA_COMPST_CHECK_PSN: state = vhost_rdma_check_psn(qp, pkt, wqe); break; case VHOST_RDMA_COMPST_CHECK_ACK: state = vhost_rdma_check_ack(qp, pkt, wqe); break; case VHOST_RDMA_COMPST_READ: state = vhost_rdma_do_read(qp, pkt, wqe); break; case VHOST_RDMA_COMPST_ATOMIC: state = vhost_rdma_do_atomic(qp, pkt, wqe); break; case VHOST_RDMA_COMPST_WRITE_SEND: if (wqe->state == WQE_STATE_PENDING && wqe->last_psn == pkt->psn) state = VHOST_RDMA_COMPST_COMP_ACK; else state = VHOST_RDMA_COMPST_UPDATE_COMP; break; case VHOST_RDMA_COMPST_COMP_ACK: state = vhost_rdma_complete_ack(qp, pkt, wqe); break; case VHOST_RDMA_COMPST_COMP_WQE: state = vhost_rdma_complete_wqe(qp, pkt, wqe); break; case VHOST_RDMA_COMPST_UPDATE_COMP: if (pkt->mask & VHOST_END_MASK) qp->comp.opcode = -1; else qp->comp.opcode = pkt->opcode; if (psn_compare(pkt->psn, qp->comp.psn) >= 0) qp->comp.psn = (pkt->psn + 1) & VHOST_RDMA_PSN_MASK; if (qp->req.wait_psn) { qp->req.wait_psn = 0; vhost_rdma_run_task(&qp->req.task, 1); } state = VHOST_RDMA_COMPST_DONE; break; case VHOST_RDMA_COMPST_DONE: goto done; case VHOST_RDMA_COMPST_EXIT: if (qp->comp.timeout_retry && wqe) { state = VHOST_RDMA_COMPST_ERROR_RETRY; break; } /* re reset the timeout counter if * (1) QP is type RC * (2) the QP is alive * (3) there is a packet sent by the requester that * might be acked (we still might get spurious * timeouts but try to keep them as few as possible) * (4) the timeout parameter is set */ if ((qp->type == VHOST_RDMA_IB_QPT_RC) && (qp->req.state == QP_STATE_READY) && (psn_compare(qp->req.psn, qp->comp.psn) > 0) && qp->qp_timeout_ticks) rte_timer_reset(&qp->retrans_timer, qp->qp_timeout_ticks, SINGLE, rte_lcore_id(), retransmit_timer, qp); ret = -EAGAIN; goto done; case VHOST_RDMA_COMPST_ERROR_RETRY: /* we come here if the retry timer fired and we did * not receive a response packet. try to retry the send * queue if that makes sense and the limits have not * been exceeded. remember that some timeouts are * spurious since we do not reset the timer but kick * it down the road or let it expire */ /* there is nothing to retry in this case */ if (!wqe || (wqe->state == WQE_STATE_POSTED)) { ret = -EAGAIN; goto done; } /* if we've started a retry, don't start another * retry sequence, unless this is a timeout. */ if (qp->comp.started_retry && !qp->comp.timeout_retry) goto done; if (qp->comp.retry_cnt > 0) { if (qp->comp.retry_cnt != 7) qp->comp.retry_cnt--; /* no point in retrying if we have already * seen the last ack that the requester could * have caused */ if (psn_compare(qp->req.psn, qp->comp.psn) > 0) { /* tell the requester to retry the * send queue next time around */ vhost_rdma_counter_inc(dev, VHOST_RDMA_CNT_COMP_RETRY); qp->req.need_retry = 1; qp->comp.started_retry = 1; vhost_rdma_run_task(&qp->req.task, 0); } goto done; } else { vhost_rdma_counter_inc(dev, VHOST_RDMA_CNT_RETRY_EXCEEDED); wqe->status = VHOST_RDMA_IB_WC_RETRY_EXC_ERR; state = VHOST_RDMA_COMPST_ERROR; } break; case VHOST_RDMA_COMPST_RNR_RETRY: if (qp->comp.rnr_retry > 0) { if (qp->comp.rnr_retry != 7) qp->comp.rnr_retry--; qp->req.need_retry = 1; RDMA_LOG_DEBUG_DP("qp#%d set rnr nak timer", qp->qpn); rte_timer_reset(&qp->rnr_nak_timer, rnrnak_ticks(aeth_syn(pkt) & ~AETH_TYPE_MASK), SINGLE, rte_lcore_id(), vhost_rdma_rnr_nak_timer, qp); ret = -EAGAIN; goto done; } else { vhost_rdma_counter_inc(dev, VHOST_RDMA_CNT_RNR_RETRY_EXCEEDED); wqe->status = VHOST_RDMA_IB_WC_RNR_RETRY_EXC_ERR; state = VHOST_RDMA_COMPST_ERROR; } break; case VHOST_RDMA_COMPST_ERROR: RDMA_LOG_ERR_DP("WQE Error: %u", wqe->status); vhost_rdma_do_complete(qp, wqe); vhost_rdma_qp_error(qp); ret = -EAGAIN; goto done; } } done: if (pkt) free_pkt(pkt); vhost_rdma_drop_ref(qp, qp->dev, qp); return ret; } 按照linux代码标准格式 优化一下 并加入英文注释
11-13
给我每行的注释#include <netinet/if_ether.h> #include <linux/filter.h> #include <linux/if_packet.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <net/if.h> #include "options.h" #include "packet.h" #include "dhcp.h" #include "dhcpc.h" #include "nsd_common.h" #include "libdms.h" #include "libds.h" #define DHCPC_SOCKET_RECV_BUF_SIZE (32 * 1024) #define DHCPC_SOCKET_SEND_BUF_SIZE (32 * 1024) #define DHCPC_SERVER_DETECT_TIMEOUT 60000000 //us(1 min) #define DHCPC_SERVER_DETECT_FAILED_MAX_TIME 5 LOCAL S32 discovery_timeout[DISCOVERY_RETRY_TIMES] = {2, 2, 4, 2, 12, 2, 2, 4, 2, 20, 2, 2, 4, 2, 20, 2, 2, 4, 2, 2}; /* DISCOVERY超时时间。 */ LOCAL DHCPC_PARAMS dhcpc_params = {0}; LOCAL struct dhcp_packet packet = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT #define DHCP_4G_ROUTER_STR "4g router" #define DHCPC_4G_IPC_DEV_NAME "usb0" #define DHCPC_WIRED_INTERNET_MODE 0 #define DHCPC_4G_INTERNET_MODE 1 LTE_CONFIG_INFO_DATA g_lte_config_data = {0}; S32 g_sock_idx = -1; S32 get_lte_config_data_flag = 0; /* 是否已经读取了lte_config_info_data的配置,0:未读取 ,1:已读取 */ #endif LOCAL S32 dhcpc_ip_reset() { DHCPC_MSG msg; memset(&msg, 0, sizeof(DHCPC_MSG)); msg.status = LINK_IP_RESET; msg.code = LINK_CODE_NORMAL; NSD_SEND(NSD_DHCPC_STATUS, (U8*)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL S32 dhcpc_flush_net(U32 status, U32 code) { DHCPC_MSG msg; PHY_STATUS phy_status = {0}; memset(&msg, 0, sizeof(DHCPC_MSG)); /* Stopped by caller, no need to send message. */ if (-1 == dhcpc_params.call_bk_id) { return OK; } msg.call_bk_id = dhcpc_params.call_bk_id; msg.ctrl = 0; //memcpy(msg.dev_name, dhcpc_params[iface].dev_name, DEV_NAME_LEN); msg.status = status; msg.code = code; msg.ip = dhcpc_params.yiaddr; msg.mask = dhcpc_params.mask; msg.gateway = dhcpc_params.gateway; msg.mtu = dhcpc_params.mtu; /*msg.proto = PROTO_DHCP;*/ if (FALSE == dhcpc_params.manual_dns) { msg.dns[0] = dhcpc_params.dns[0]; msg.dns[1] = dhcpc_params.dns[1]; } memcpy(msg.mac, dhcpc_params.server_mac, MAC_ADDR_SIZE); ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG("DHCP success,clean tag"); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 *)&phy_status, sizeof(PHY_STATUS)); } NSD_SEND(NSD_DHCPC_STATUS, (U8*)&msg, sizeof(DHCPC_MSG)); return OK; } LOCAL void dhcpc_timeout_flush_net() { PHY_STATUS phy_status = {0}; EXCEPTION_STATUS_MSG msg = {0}; ds_read(PHY_STATUS_PATH, &phy_status, sizeof(PHY_STATUS)); if (phy_status.diag_wlan == 1) { DHCPC_DEBUG("record wrong code"); msg.type = WLAN_GATEWAY_UNREACHABLE; msg.status = 1; msg_send(EXCEPTION_STATUS_MID, (U8 *)&msg, sizeof(msg)); phy_status.diag_wlan = 0; ds_write(PHY_STATUS_PATH, (U8 *)&phy_status, sizeof(PHY_STATUS)); } if (dhcpc_params.dhcp_timeout == 1) { dhcpc_flush_net(LINK_UP, LINK_CODE_DHCP_TIMEOUT); dhcpc_params.dhcp_timeout = 0; } return; } /* Multi-wans support: add parameter S32 i for all function. By xcl, 2011-05-04.*/ /* initialize a packet with the proper defaults */ LOCAL void init_packet(char type) { struct vendor { char vendor, length; char str[sizeof("MSFT 5.0")]; } vendor_id = { DHCP_VENDOR, sizeof("MSFT 5.0") - 1, "MSFT 5.0"}; /* Changed by lsz 080424, cheat server:"I am Windows XP" */ /* vendor_id = { DHCP_VENDOR, sizeof("udhcp "VERSION) - 1, "udhcp "VERSION};*/ init_header(&packet, type); /* message type */ memcpy(packet.chaddr, dhcpc_params.mac, 6); /* moved by tiger 20090304, from send_discover, flags should be setting for all packet in that mode */ /* Modified by Li Shaozhang, 070707 */ /* Multi-wans support.*/ if (dhcpc_params.flags/*get_runtime_dhcp_flags()*/) /* server reply mode choose */ packet.flags &= htons(0x7FFF); /* set first bit to 0, just AND 0111 1111 1111 1111 */ else /* server reply in broadcast mode */ packet.flags |= htons(0x8000); /* set first bit to 1, just OR 1000 0000 0000 0000 */ /* Edited by xcl, 13Feb12. * According to rfc2131, release packet must include options 53、54 and may 61, must not others. * decline packet is most the same but must include options 50. */ if (DHCPRELEASE != type && DHCPDECLINE != type) { /* 080501, add maximum size option --- lsz */ /* Explicitly saying that we want RFC-compliant packets helps * some buggy DHCP servers to NOT send bigger packets */ add_simple_option(packet.options, DHCP_MAX_SIZE, htons(DHCP_MAX_MSG_SIZE)); } if (dhcpc_params.client[OPT_DATA]) add_option_string(packet.options, (uint8_t *)dhcpc_params.client);/* client id */ /* Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 12. */ if (DHCPRELEASE != type && DHCPDECLINE != type && dhcpc_params.name[OPT_DATA]) add_option_string(packet.options, (uint8_t *)dhcpc_params.name);/* hostname */ /* Edited by xcl, 13Feb12. * According to rfc2131, release and decline packet must not include option 60. */ if (DHCPRELEASE != type && DHCPDECLINE != type) add_option_string(packet.options, (uint8_t *) &vendor_id); /* vendor id */ } /* Add a parameter request list for stubborn DHCP servers. Pull the data * from the struct in options.c. Don't do bounds checking here because it * goes towards the head of the packet. */ LOCAL void add_requests() { S32 end = end_option(packet.options); S32 i, len = 0; packet.options[end + OPT_CODE] = DHCP_PARAM_REQ; for (i = 0; dhcp_options[i].code; i++) if (dhcp_options[i].flags & OPTION_REQ) packet.options[end + OPT_DATA + len++] = dhcp_options[i].code; packet.options[end + OPT_LEN] = len; packet.options[end + OPT_DATA + len] = DHCP_END; } /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ LOCAL S32 send_discover() { init_packet(DHCPDISCOVER); packet.xid = dhcpc_params.xid; /* 080424, del by lsz, cauz some server may ignore our request with an requested ip */ #if 0 if (requested) add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); #endif add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Broadcasts a DHCP request message */ LOCAL S32 send_selecting(U32 server, U32 requested) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); add_requests(&packet); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } /* Unicasts or broadcasts a DHCP renew message */ LOCAL S32 send_renew(U32 server, U32 ciaddr) { init_packet(DHCPREQUEST); packet.xid = dhcpc_params.xid; packet.ciaddr = ciaddr; add_requests(&packet); /* 指定了server的,就单播发送 */ if (server) { return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } #if 0 /* Unicasts a DHCP release message */ LOCAL S32 send_release(U32 server, U32 ciaddr) { init_packet(DHCPRELEASE); packet.xid = random(); /* 使用新ID */ packet.ciaddr = ciaddr; /* Del by xcl, 13Feb12. According to rfc2131, release packet must not include option 50 */ /*add_simple_option(packet.options, DHCP_REQUESTED_IP, ciaddr);*/ add_simple_option(packet.options, DHCP_SERVER_ID, server); return send_dhcp_packet(&packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); } #endif /* send broadcast when GARP checking failed added by tiger 20090825 */ LOCAL S32 send_decline(U32 server, U32 requested) { init_packet(DHCPDECLINE); packet.xid = dhcpc_params.xid; add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); add_simple_option(packet.options, DHCP_SERVER_ID, server); return make_and_send_dhcp_frame(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, dhcpc_params.dev); } LOCAL void dhcpc_params_update() { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read dev_name:%s failed", dhcpc_params.dev_name); return; } dhcpc_params.code = LINK_CODE_NORMAL; if (NULL != dhcpc_params.path) { ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; } /* start dial */ LOCAL S32 link_up_inner() { U64 cur_time = NSD_TIMESTAMP(); LINK_STATUS link_status = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data failed"); return ERROR; } if(lte_config.internet_wired_enable == 0) { LTE_DHCP_IP dhcp_ip = {0}; if (0 == ds_read(LTE_DHCP_IP_PATH, &dhcp_ip, sizeof(LTE_DHCP_IP))) { DHCPC_ERROR("Read lte dhcp ip failed"); return ERROR; } /* 4G_IPC: 用当前生效的ip去尝试续约 */ if (dhcp_ip.ipaddr != 0) { dhcpc_params.yiaddr = dhcp_ip.ipaddr; if(dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } }else { if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } /* 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } } #else if (0 == ds_read(LINK_STATUS_PATH, &link_status, sizeof(LINK_STATUS))) { return ERROR; } /* 用当前生效的ip去尝试续约 */ if (link_status.ipaddr != 0) { dhcpc_params.yiaddr = link_status.ipaddr; if (dhcpc_params.server != 0) { dhcpc_params.state = RECONNECT_RENEWING; DHCPC_DEBUG("Use ip %x server %x to renewing.", dhcpc_params.yiaddr, dhcpc_params.server); } else { dhcpc_params.state = RECONNECT_REBINDING; DHCPC_DEBUG("Use ip %x to rebinding.", dhcpc_params.yiaddr); } } else { DHCPC_DEBUG("No old ip, try discovery."); dhcpc_params.state = DISCOVERY; } #endif if (DISCOVERY == dhcpc_params.state || RECONNECT_RENEWING == dhcpc_params.state) { DHCPC_DEBUG("dhcpc_ip_reset"); dhcpc_ip_reset(); } switch (dhcpc_params.state) { case DISCOVERY: dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; /* 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 */ break; case RECONNECT_REBINDING: dhcpc_params.timeout = 0; dhcpc_params.t2 = 60; dhcpc_params.start = cur_time - dhcpc_params.t2; dhcpc_params.lease = 120; break; case RECONNECT_RENEWING: dhcpc_params.timeout = 0; dhcpc_params.start = cur_time; dhcpc_params.lease = 120; dhcpc_params.t2 = 60; dhcpc_params.t1 = 0; break; } dhcpc_params.dhcp_timeout = 1; /* 重连才触发dhcp timeout*/ #if 0 /* 如果当前正处在释放IP状态。 */ if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { dhcpc_params.re_dial = TRUE; /* IP地址释放完毕之后会自动重拨。 */ return 0; } /* 如果已经拨上号了,断线重连。 */ if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { /* 断开DHCPC-LAN的连接时,不要释放租约,对外表现与SLP平台保持一致,详解见linkDownInner。 */ if (dhcpc_params.send_release) { DHCPC_DEBUG("Send RELEASE to server %.8x", ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ } dhcpc_params.timeout = 0; /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; dhcpc_params.re_dial = TRUE; /* IP地址释放完毕之后会自动重拨。 */ #endif return OK; } /* stop dial */ LOCAL S32 link_down_inner(U32 code) { /* 智能ip策略,不需要发送release包,直接停止状态机即可 */ if (INIT != dhcpc_params.state) { /* 保留已经获取的ip */ /*dhcpc_params.yiaddr = 0;*/ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); } dhcpc_flush_net(LINK_DOWN, code); #if 0 /* 如果已经拨上号了,需要发送release包。 */ if ((BOUND == dhcpc_params.state) || (RENEWING == dhcpc_params.state) || (REBINDING == dhcpc_params.state)) { /* 修复Bug 185658 & 185215,由于桥接到rootAP使用的MAC与DHCPC-LAN使用的LAN MAC不同,因此重桥会出 * 现以下问题: * 如果发送DHCP RELEASE释放了原来的租约,那么重桥重新获取IP时,rootAP的DHCPS可能会发ARP Request * 来探测原来分配的IP是否被使用,因为此时LAN口已配置了该IP,因此会给rootAP ARP Reply,告知该IP对 * 应的是LAN MAC。 * 但在rootAP端来看,ARP reply的MAC与DHCPC DISCOVER里携带MAC不同,因此DHCPS会误判成IP已被另一个设 * 备使用,从而又分配了另一个可用的IP,导致重桥后的LAN IP改变。 * SLP平台机型在重桥时因为没有发DHCP RELEASE释放租约,因此在租约有效期间重桥能够保持LAN IP不变。 * 当租约被老化清理掉,重桥同样会导致LAN IP改变。 * 要完全修复此bug需要无线驱动与DHCPC-LAN互相配合着修改,现在先部分修复,断开DHCPC-LAN的连接时, * 不要发DHCP RELEASE释放租约,令SDMP平台的对外表现与SLP平台一致。 */ if (dhcpc_params.send_release) { /* 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP * 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 */ DHCPC_DEBUG("Send RELEASE to server %.8x", ntohl(dhcpc_params.server)); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ } dhcpc_params.timeout = 0; /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; return 0; } /* 如果正在断开,保持当前的状态机即可。 */ if ((RELEASED == dhcpc_params.state) || (IFDOWN == dhcpc_params.state)) { return 0; } /* 如果正在拨号,停止状态机即可。 */ if (INIT != dhcpc_params.state) { dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); } #endif return 0; } LOCAL void dhcpc_check_timer() { U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}; #if 0 NVR_STREAM_NUM stream_num = {0}; if(BOUND == dhcpc_params.state) { if(dhcpc_params.arp_failed_times > DHCPC_SERVER_DETECT_FAILED_MAX_TIME) { DHCPC_ERROR("detect server exceed maximum, failed times:%d", dhcpc_params.arp_failed_times); dhcpc_params.timeout = cur_time; dhcpc_params.state = RENEWING; dhcpc_params.t1 = dhcpc_params.t2; } else { if(0 == dhcpc_params.last_arp_timestamp || (dhcpc_params.last_arp_timestamp + DHCPC_SERVER_DETECT_TIMEOUT)< cur_time) { /* 对于VIGI NVR拉流中,则不进行DHCP的ARP探测 */ ds_read(TP_NVR_STREAM_NUM_PATH, &stream_num, sizeof(NVR_STREAM_NUM)); if(0 == stream_num.num) { if(arpping(dhcpc_params.server, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300)) { DHCPC_ERROR("can't find dhcp server %x",dhcpc_params.server); dhcpc_params.arp_failed_times++; } else { dhcpc_params.arp_failed_times = 0; } } else { dhcpc_params.arp_failed_times = 0; } dhcpc_params.last_arp_timestamp = cur_time; } } } #endif /* DHCPC_DEBUG("DHCP state is %d", dhcpc_params.state); */ if (cur_time < dhcpc_params.timeout) /* 暂不考虑溢出问题。 */ { return; } switch (dhcpc_params.state) { case INIT: /* just do nothing */ break; /* 和发REQUEST包行为统一,第一个包要在收包前一个状态发,避免还未发DISCOVER包,就开始收包。 */ case DISCOVERY: DHCPC_DEBUG("Send DISCOVER with unicast flag %d", dhcpc_params.flags); dhcpc_params.xid = random(); /* 每次重新拨号,每次续约时才更换xid,若没有得到响应,可以不更换xid。 */ send_discover(); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[0]); dhcpc_params.packet++; dhcpc_params.state = SELECTING; break; case SELECTING: if (dhcpc_params.packet >= DISCOVERY_RETRY_TIMES) { /* DHCPC fail, start in 2s again. */ DHCPC_DEBUG("Dhcpc failed, retry count = %d", dhcpc_params.packet); dhcpc_params.timeout = cur_time + 2; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } /* change runtime dhcp flags when exceed DISCOVER_INVERT_TIMES added by tiger 20090819 apply 11G and XP's option */ /* 修复Bug 40838:切换单/广播时需同步加/卸载filter(20130924) */ /* 在PNE2.2平台里,每5个包为一组,每组里第三个包开始切换 */ if ((dhcpc_params.support_un_cast) && (DISCOVERY_INVERT_TIMES == (dhcpc_params.packet % DISCOVERY_GROUP_TIMES))) { dhcpc_params.flags = !dhcpc_params.flags; } DHCPC_DEBUG("Send DISCOVER with unicast flag %d", dhcpc_params.flags); dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(discovery_timeout[dhcpc_params.packet]); send_discover(); dhcpc_params.packet++; if (DISCOVERY_RETRY_TIMEOUT == dhcpc_params.packet) { dhcpc_timeout_flush_net(); } break; case REQUESTING: if (dhcpc_params.packet > REQUESTING_RETRY_TIMES) /* 当尝试超过一定次数,重新发DISCOVERY。*/ { DHCPC_DEBUG("Recv no ACK, restart"); dhcpc_params.timeout = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; break; } ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send REQUEST to server %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = /*time(0) + ((cur_client->packet_num == 2) ? 10 : 2)*/cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.packet++; break; case BOUND: case RENEWING: /* Either set a new T1, or enter REBINDING state */ if ((dhcpc_params.t2 - dhcpc_params.t1) <= (dhcpc_params.lease / 14400 + 1)) { /* timed out, enter rebinding state */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(dhcpc_params.t2 - dhcpc_params.t1); dhcpc_params.state = REBINDING; /* 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server */ dhcpc_params.server = 0; dhcpc_params.arp_failed_times = 0; DHCPC_DEBUG("Entering rebinding state"); break; } /* send a request packet */ DHCPC_DEBUG("Send REQUEST to server %.8x", dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.t1 = (dhcpc_params.t2 - dhcpc_params.t1) / 2 + dhcpc_params.t1; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + dhcpc_params.start; dhcpc_params.state = RENEWING; break; case REBINDING: /* Either set a new T2, or enter INIT state */ //DHCPC_ERROR("dhcpc_params.lease:%d, dhcpc_params.t2:%d, limit:%d", dhcpc_params.lease, dhcpc_params.t2, (dhcpc_params.lease / 14400 + 1)); if ((dhcpc_params.lease - dhcpc_params.t2) <= (dhcpc_params.lease / 14400 + 1)) { //dhcpc_flush_net(LINK_DOWN, LINK_CODE_NOECHO); DHCPC_DEBUG("Lease lost, entering DISCOVERY state"); /* timed out, enter init state */ dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); /* 智能ip:rebinding失败,视为之前的ip失效了 */ dhcpc_params.yiaddr = 0; break; } ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG("broadcast REQUEST with request ip %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.t2 = (dhcpc_params.lease - dhcpc_params.t2) / 2 + dhcpc_params.t2; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t2) + dhcpc_params.start; dhcpc_params.packet++; break; case RECONNECT_RENEWING: /* 每秒发一次包,等待 RECONNECT_RENEWING_TIMES 秒 */ if (dhcpc_params.packet > RECONNECT_RENEWING_TIMES) { /* timed out, enter rebinding state */ dhcpc_params.timeout = cur_time; dhcpc_params.state = RECONNECT_REBINDING; dhcpc_params.packet = 0; /* 智能ip:renewing失败,视为以前的server失效了,重新在REBINDING状态收到包时会更新server */ dhcpc_params.server = 0; DHCPC_DEBUG("[RECONNECT]Entering reconect_rebinding state"); break; } /* send a request packet */ DHCPC_DEBUG("[RECONNECT]Send REQUEST to server %.8x", dhcpc_params.server); send_renew(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.packet++; dhcpc_params.timeout = 0; break; case RECONNECT_REBINDING: /* 每秒发一次包,等待 RECONNECT_REBINDING_TIMES 秒 */ if (dhcpc_params.packet > RECONNECT_REBINDING_TIMES) { /* timed out, enter init state */ dhcpc_params.timeout = cur_time; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; /* 智能ip:rebinding失败,视为之前的ip失效了 */ dhcpc_params.yiaddr = 0; DHCPC_DEBUG("[RECONNECT]Reconnect fail, Entering discovery state"); break; } /* send a request packet */ ip_addr.ipAddr = dhcpc_params.yiaddr; DHCPC_DEBUG("broadcast REQUEST with request ip %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_renew(0, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = cur_time; dhcpc_params.packet++; break; #if 0 case RELEASED: /* 实际上release包不一定能马上发出了,因为有可能发DHCP release时,ARP * 已经老化,于是还要先等ARP查询结果,所以1s后再释放接口IP比较稳妥。 */ ip_addr.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send RELEASE to server %d.%d.%d.%d", ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_release(dhcpc_params.server, dhcpc_params.yiaddr); /* unicast */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(1); /* 确保release包发出之后再释放接口IP */ dhcpc_params.state = IFDOWN; break; case IFDOWN: dhcpc_flush_net(LINK_DOWN, LINK_CODE_MANUAL); /* 注释掉,保存上次获取的ip */ //dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0xFFFFFFFF; dhcpc_params.state = INIT; if (-1 != dhcpc_params.call_bk_id_new) { dhcpc_params.call_bk_id = dhcpc_params.call_bk_id_new; dhcpc_params.call_bk_id_new = -1; } memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); if (TRUE == dhcpc_params.re_dial) { dhcpc_params.re_dial = FALSE; dhcpc_params_update(); dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.timeout = 0; /* 最迟1s以后,DHCPC进程自动发送DISCOVERY包。 */ dhcpc_params.state = DISCOVERY; } break; #endif } } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL void write_mobile_access(U8 val) { DEVICE_BASIC_INFO info = {0}; if (0 == ds_read(DEVICE_BASIC_INFO_PATH, &info, sizeof(info))) { DHCPC_ERROR("ds read device basic_info failed"); return; } else { info.mobile_access = val; ds_write(DEVICE_BASIC_INFO_PATH, &info, sizeof(info)); } } #endif #if 0 LOCAL S32 dhcp_renew_handle(DS_HANDLE_CONTEXT *context, JSON_OBJPTR param) { /* 仅对处于BOUND状态的DHCP进行renew操作 */ DHCPC_ERROR("Recv DHCP Renew, state(%d)", dhcpc_params.state); if(BOUND == dhcpc_params.state) { dhcpc_params.arp_failed_times = (DHCPC_SERVER_DETECT_FAILED_MAX_TIME + 1); } return OK; } #endif LOCAL void dhcpc_handle(S32 sock) { S32 bytes = 0; U8 *message = NULL, *option = NULL; U64 cur_time = NSD_TIMESTAMP(); IP_ADDR ip_addr = {0}, mask = {0}, gateway = {0}, server = {0}; U32 dns[2] = {0}; #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LTE_CONFIG_INFO_DATA lte_config = {0}; if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config error"); return; } #endif /* 收到DHCP服务器的响应报文。 */ bytes = get_packet(&packet, sock); if (bytes < 0) { DHCPC_WARNING("Error on read, %m, reopening socket"); return; } /* Ignore packets that aren't for us */ if (memcmp(packet.chaddr, dhcpc_params.mac, sizeof(dhcpc_params.mac))) { DHCPC_DEBUG("Packet does not have our chaddr -- ignoring"); return; } if ((message = get_option(&packet, DHCP_MESSAGE_TYPE)) == NULL) { DHCPC_WARNING("Couldnt get option from packet -- ignoring"); return; } if (packet.xid != dhcpc_params.xid) { DHCPC_WARNING("ignoring XID %lx (our xid is %lx)", packet.xid, dhcpc_params.xid); return; } switch (dhcpc_params.state) { case INIT: case DISCOVERY: /* just drop all message. */ break; case SELECTING: if ((DHCPOFFER != *message) || /* 在此处只能接收OFFER包,其它包丢弃 */ (NULL == (option = get_option(&packet, DHCP_SERVER_ID)))) /* 必须带有SERVER_ID。 */ { break; } memcpy(&dhcpc_params.server, option, 4); dhcpc_params.mask = inet_addr("255.255.255.255"); switch (ip_network_id(packet.yiaddr)) { case 'A': dhcpc_params.mask = inet_addr("255.0.0.0"); break; case 'B': dhcpc_params.mask = inet_addr("255.255.0.0"); break; case 'C': dhcpc_params.mask = inet_addr("255.255.255.0"); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } /*dhcpc_params[iface].xid = packet.xid;*/ /* 忽略? */ dhcpc_params.yiaddr = packet.yiaddr; ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Recv OFFER from server %d.%d.%d.%d with ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); /* 在此处验证获得的IP的合法性。这里DHCP不回MTU */ if ((OK != check_valid_param(dhcpc_params.mtu, dhcpc_params.yiaddr, dhcpc_params.mask, 0))) { DHCPC_DEBUG("check_valid_param failed."); break; /* 继续等待其它的服务器响应 */ } /* 合法性验证通过后,发送Request报文,跳转到REQUESTING状态。 */ ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_DEBUG("Send REQUEST to server %d.%d.%d.%d with request ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); send_selecting(dhcpc_params.server, dhcpc_params.yiaddr); /* broadcast */ dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(REQUESTING_TIMEOUT); dhcpc_params.state = REQUESTING; dhcpc_params.packet = 0; dhcpc_params.retry = 0; break; case RENEWING: case REBINDING: case REQUESTING: case RECONNECT_RENEWING: case RECONNECT_REBINDING: /* 是否要验证server id?这里暂且验证下,个人认为这样安全。 */ if (NULL == (option = get_option(&packet, DHCP_SERVER_ID))) { break; /* unknown dhcp server? */ } /* REBINDING阶段更新server */ if (dhcpc_params.state == REBINDING || dhcpc_params.state == RECONNECT_REBINDING) { memcpy(&dhcpc_params.server, option, 4); } /* REBINDING阶段可能会切换server,此时不可检查 */ #if 0 if (dhcpc_params[iface].server != *(U32 *)option) { break; /* invalid dhcp server? */ } #endif if (DHCPACK == *message) { dhcpc_params.lease = 60*60; /* 默认1小时。 */ if (NULL != (option = get_option(&packet, DHCP_LEASE_TIME))) { memcpy(&dhcpc_params.lease, option, 4); dhcpc_params.lease = ntohl(dhcpc_params.lease); } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { IF_CONF if_conf = {0}; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return; } char dev_name[32] = {0}; U8 dev_mac[6] = {0}; snprintf(dev_name, sizeof(dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dev_name, NULL, dev_mac)) { DHCPC_ERROR("read usb0 device info error"); return; } /* 发送GARP验证IP是否被占用。 */ if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && ((0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300)) || (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dev_mac, dev_name, 300)))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in use, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } }else #endif { /* 发送GARP验证IP是否被占用。 */ if (((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && (0 == arpping(packet.yiaddr, NULL, (uint32_t)0, dhcpc_params.mac, dhcpc_params.dev_name, 300))) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in use, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT /* 在有线上网模式下,dhcp server分配的IP不能为4G网关192.168.43.1 */ if(((packet.yiaddr != dhcpc_params.yiaddr) || (REQUESTING == dhcpc_params.state)) && packet.yiaddr == 0x012ba8c0) { server.ipAddr = dhcpc_params.server; DHCPC_WARNING("Offered address is in Gateway for 4G, send DECLINE to server %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3]); send_decline(dhcpc_params.server, packet.yiaddr); dhcpc_params.yiaddr = 0; dhcpc_params.timeout = cur_time + NSD_SECTOUSEC(10); /* 推迟一段时间再重新申请。 */ dhcpc_params.packet = 0; dhcpc_params.retry = 0; dhcpc_params.state = DISCOVERY; dhcpc_timeout_flush_net(); memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } #endif } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if (NULL != (option = get_option(&packet, DHCP_4G_ROUTER))) { if(0 == memcmp(option, DHCP_4G_ROUTER_STR, strlen(DHCP_4G_ROUTER_STR))) { DHCPC_INFO("get option DHCP_4G_ROUTER"); write_mobile_access(1); } else { write_mobile_access(0); } } else { write_mobile_access(0); } #endif /* 分配的IP没有被占用,则使用该IP,并且进入bound状态。 */ dhcpc_params.t1 = dhcpc_params.lease/2; dhcpc_params.t2 = ((dhcpc_params.lease * 0x7) >> 3);/* little fixed point for n * .875 */ //DHCPC_ERROR("dhcpc_params.t1:%d, dhcpc_params.t2:%d", dhcpc_params.t1, dhcpc_params.t2); dhcpc_params.start = cur_time; dhcpc_params.timeout = NSD_SECTOUSEC(dhcpc_params.t1) + cur_time; ip_addr.ipAddr = dhcpc_params.yiaddr; /* 保留原IP的值 */ dhcpc_params.yiaddr = packet.yiaddr; /* 获取网关。 */ gateway.ipAddr = dhcpc_params.gateway; dhcpc_params.gateway = 0; if (NULL != (option = get_option(&packet, DHCP_ROUTER))) { if(0 != *option) { memcpy(&dhcpc_params.gateway, option, 4); } else if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR("Received ACK but gateway option is zero, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]", dhcpc_params.gateway, dhcpc_params.server); } else { #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(lte_config.internet_wired_enable == 0) { dhcpc_params.gateway = 0x012ba8c0; /* 4G上网模式下,无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.43.1 */ DHCPC_ERROR("Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.43.1", dhcpc_params.gateway); }else #endif { dhcpc_params.gateway = 0x0100a8c0; /* 无法从dhcp服务器获取网关信息的情况下将网关设置为192.168.0.1 */ DHCPC_ERROR("Received ACK but gateway and source IP are zero, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1", dhcpc_params.gateway); } } } else { if(0 != dhcpc_params.server) { dhcpc_params.gateway = dhcpc_params.server; DHCPC_ERROR("Received ACK but gateway option is empty, making the dhcpc_params.gateway [%.8x] equal to the dhcpc_params.server [%.8x]", dhcpc_params.gateway, dhcpc_params.server); } else { dhcpc_params.gateway = 0x0100a8c0; DHCPC_ERROR("Received ACK but the gateway and source IP are illegal, making the dhcpc_params.gateway [%.8x] equal to 192.168.0.1", dhcpc_params.gateway); } } /* 获取掩码。 */ mask.ipAddr = dhcpc_params.mask; dhcpc_params.mask = inet_addr("255.255.255.255"); switch (ip_network_id(packet.yiaddr)) { case 'A': dhcpc_params.mask = inet_addr("255.0.0.0"); break; case 'B': dhcpc_params.mask = inet_addr("255.255.0.0"); break; case 'C': dhcpc_params.mask = inet_addr("255.255.255.0"); break; } if (NULL != (option = get_option(&packet, DHCP_SUBNET))) { memcpy(&dhcpc_params.mask, option, 4); } /* 获取DNS. */ if (FALSE == dhcpc_params.manual_dns) { dns[0] = dhcpc_params.dns[0]; dns[1] = dhcpc_params.dns[1]; dhcpc_params.dns[0] = 0; dhcpc_params.dns[1] = 0; if (NULL != (option = get_option(&packet, DHCP_DNS_SERVER))) { S32 dnsNum = 0; S32 i = 0; dnsNum = (*(option - 1))/4; dnsNum = dnsNum > 2 ? 2 : dnsNum; for (i = 0; i < dnsNum; i++) { memcpy(dhcpc_params.dns + i, option + 4 * i, 4); } } } /* REQUESTING状态或者ip、gateway、mask有更新则刷新接口。 */ /* RECONNECT_RENEWING 和 RECONNECT_REBINDING状态可能是静态转为动态,因此也要进行设置 */ if ((REQUESTING == dhcpc_params.state) || dhcpc_params.state == RECONNECT_RENEWING || dhcpc_params.state == RECONNECT_REBINDING || (ip_addr.ipAddr != dhcpc_params.yiaddr) || (gateway.ipAddr != dhcpc_params.gateway) || (mask.ipAddr != dhcpc_params.mask)) { /* 根据获得的IP配置本地接口。 */ ip_addr.ipAddr = dhcpc_params.yiaddr; mask.ipAddr = dhcpc_params.mask; gateway.ipAddr = dhcpc_params.gateway; DHCPC_INFO("%s set ip %d.%d.%d.%d mask %d.%d.%d.%d gateway %d.%d.%d.%d lease time %ld", dhcpc_params.dev_name, ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3], mask.ipAddrByteFormat[0], mask.ipAddrByteFormat[1], mask.ipAddrByteFormat[2], mask.ipAddrByteFormat[3], gateway.ipAddrByteFormat[0], gateway.ipAddrByteFormat[1], gateway.ipAddrByteFormat[2], gateway.ipAddrByteFormat[3], dhcpc_params.lease); dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } else if ((TRUE != dhcpc_params.manual_dns) && ((dns[0] != dhcpc_params.dns[0]) || (dns[1] != dhcpc_params.dns[1]))) { dhcpc_flush_net(LINK_UP, LINK_CODE_NORMAL); } DHCPC_DEBUG("Recv ACK from server %.8x with ip %.8x lease time %ld", dhcpc_params.server, dhcpc_params.yiaddr, dhcpc_params.lease); dhcpc_params.retry = 0; /* clear the retry counter */ dhcpc_params.packet = 0; dhcpc_params.state = BOUND; break; } if (DHCPNAK != *message) { break; } /* 这里需要考虑两种情况: */ /* 在未配置本地IP的情况(即REQUESTING状态),只需更新状态到INIT_SELECTING状态即可。 */ /* 其它状态则需要释放已配置的IP。 */ if (REQUESTING != dhcpc_params.state) { DHCPC_DEBUG("state [%d] receive NACK", dhcpc_params.state); dhcpc_flush_net(LINK_DOWN, LINK_CODE_DENY); } ip_addr.ipAddr = dhcpc_params.yiaddr; server.ipAddr = dhcpc_params.server; DHCPC_INFO("Recv NAK from server %d.%d.%d.%d with ip %d.%d.%d.%d", server.ipAddrByteFormat[0], server.ipAddrByteFormat[1], server.ipAddrByteFormat[2], server.ipAddrByteFormat[3], ip_addr.ipAddrByteFormat[0], ip_addr.ipAddrByteFormat[1], ip_addr.ipAddrByteFormat[2], ip_addr.ipAddrByteFormat[3]); if (dhcpc_params.state != RECONNECT_RENEWING && dhcpc_params.state != RECONNECT_REBINDING) { dhcpc_timeout_flush_net(); } else { /* 收到NAK后重新开始DISCOVERY前刷新参数 */ dhcpc_params_update(); } dhcpc_params.timeout = 0; dhcpc_params.yiaddr = 0; dhcpc_params.packet = 0; dhcpc_params.state = DISCOVERY; memset(dhcpc_params.server_mac, 0, MAC_ADDR_SIZE); break; } } LOCAL S32 dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING("call back parameter error."); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { DHCPC_DEBUG("Now start dhcpc progress."); link_up_inner(); dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG("Now stop dhcpc progress."); link_down_inner(msg->code); return OK; } DHCPC_WARNING("Unknown command."); return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT LOCAL S32 dhcpc_socket_reload() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR("client socket call failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR("client socket set reuseaddr option failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &option, sizeof(option))) { DHCPC_ERROR("client socket set broadcast option failed"); goto dhcpc_error_exit; } /* 设置缓存大小 */ buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } /* 绑定网卡 */ struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); IF_CONF if_conf = {0}; LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { strncpy(ifr.ifr_name, DHCPC_4G_IPC_DEV_NAME, strlen(DHCPC_4G_IPC_DEV_NAME) + 1); DHCPC_ERROR("ifr.ifr_name:%s", ifr.ifr_name); }else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); goto dhcpc_error_exit; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); goto dhcpc_error_exit; } strncpy(ifr.ifr_name, if_conf.ifname, strlen(if_conf.ifname)); } if(ERROR == setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char*)&ifr, sizeof(ifr))) { DHCPC_ERROR("can't bind to interface :%s", ifr.ifr_name); } DHCPC_ERROR("ifr.ifr_name:%s", ifr.ifr_name); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR("server socket set broadcast option failed"); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL int dhcpc_param_reload(int flag) { IF_CONF if_conf = {0}; DHCPC dhcpc_data; dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; //dhcpc_params.call_bk_id = -1; dhcpc_params.path = DHCPC_PATH; if(flag == DHCPC_4G_INTERNET_MODE) { /* 4G_ICP使用usb0 */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", DHCPC_4G_IPC_DEV_NAME); if(0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } } else { if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return ERROR; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return ERROR; } /* IPC使用br-wan */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } } /* 智能ip,IPC断开dhcp时不释放租约 */ dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.flags = FALSE; /* 默认广播。 */ if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; dhcpc_params.last_arp_timestamp = 0; dhcpc_params.arp_failed_times = 0; if(dhcpc_params.sock) { inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; } dhcpc_params.sock = dhcpc_socket_reload(); g_sock_idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if(0 > g_sock_idx) { DHCPC_ERROR("add dhcp client socket to inetd failed"); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if(0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR("add dhcp timer to inetd failed"); inet_del_socket(g_sock_idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } return OK; } LOCAL S32 lte_dhcpc_ctrl_callback(dms_handler_t *handler, U8 *mbuf, U32 mlen, U32 sender_dms_id) { DHCPC_MSG *msg = (DHCPC_MSG *)mbuf; U8 dev_mac[6] = {0}; if (NULL == msg || sizeof(DHCPC_MSG) != mlen) { DHCPC_WARNING("call back parameter error."); return ERROR; } if (DHCPC_CTRL_START == msg->ctrl) { if(!strncmp(dhcpc_params.dev_name, DHCPC_4G_IPC_DEV_NAME, sizeof(dhcpc_params.dev_name))) { DHCPC_DEBUG("Now start dhcpc progress."); if(0 > read_interface_info(dhcpc_params.dev_name, NULL, dev_mac)) { DHCPC_ERROR("read usb0 device info error"); return ERROR; } if(memcmp(dhcpc_params.mac, dev_mac, sizeof(dhcpc_params.mac))) { DHCPC_ERROR("usb0 device mac change, reload dhcpc params."); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } link_up_inner(); }else { DHCPC_DEBUG("Change dhcpc device first"); DHCPC_DEBUG("Now start dhcpc progress."); if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } link_up_inner(); } dhcpc_params.call_bk_id = msg->call_bk_id; return OK; } if (DHCPC_CTRL_STOP == msg->ctrl) { DHCPC_DEBUG("Now stop dhcpc progress."); link_down_inner(msg->code); return OK; } DHCPC_WARNING("Unknown command."); return ERROR; } #endif LOCAL S32 dhcpc_socket_init() { S32 fd = -1; struct sockaddr_in addr; S32 option = 1; S32 buf_size = 0; if (0 > (fd = socket(AF_INET, SOCK_DGRAM, 0))) { DHCPC_ERROR("client socket call failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option))) { DHCPC_ERROR("client socket set reuseaddr option failed"); goto dhcpc_error_exit; } if (0 > setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char *) &option, sizeof(option))) { DHCPC_ERROR("client socket set broadcast option failed"); goto dhcpc_error_exit; } /* 设置缓存大小 */ buf_size = DHCPC_SOCKET_RECV_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } buf_size = DHCPC_SOCKET_SEND_BUF_SIZE; if (ERROR == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size))) { DHCPC_ERROR("Set sock rcv buf error."); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(CLIENT_PORT); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(fd, (struct sockaddr *)&addr, sizeof(addr))) { DHCPC_ERROR("server socket set broadcast option failed"); goto dhcpc_error_exit; } return fd; dhcpc_error_exit: if (-1 != fd) { close(fd); fd = -1; } return fd; } LOCAL void dhcpc_param_init() { IF_CONF if_conf = {0}; DHCPC dhcpc_data; if (0 == ds_read(IF_CONF_PATH, &if_conf, sizeof(IF_CONF))) { DHCPC_ERROR("Read wan config error"); return; } /* 无论是否为bridge ifname都存放我们需要的值 */ if (0 == if_conf.ifname[0]) { DHCPC_ERROR("Get ifname failed."); return; } memset(&dhcpc_params, 0, sizeof(DHCPC_PARAMS)); /* 智能ip,设置ip为0xFFFFFFFF 标记是开机后首次获取ip */ dhcpc_params.yiaddr = 0xFFFFFFFF; dhcpc_params.call_bk_id_new = -1; dhcpc_params.call_bk_id = -1; dhcpc_params.mac[0] = 0x00; dhcpc_params.mac[1] = 0x11; dhcpc_params.mac[2] = 0x22; dhcpc_params.mac[3] = 0x33; dhcpc_params.mac[4] = 0x44; dhcpc_params.mac[5] = 0x55; dhcpc_params.path = DHCPC_PATH; /* IPC使用br-wan */ snprintf(dhcpc_params.dev_name, sizeof(dhcpc_params.dev_name), "%s", if_conf.ifname); if (0 > read_interface_info(dhcpc_params.dev_name, &dhcpc_params.dev, dhcpc_params.mac)) { return; } /* 智能ip,IPC断开dhcp时不释放租约 */ dhcpc_params.send_release = FALSE; dhcpc_params.support_un_cast = TRUE; dhcpc_params.mtu = 1500; dhcpc_params.state = INIT; dhcpc_params.flags = FALSE; /* 默认广播。 */ if (NULL != dhcpc_params.path) { memset(&dhcpc_data, 0, sizeof(DHCPC)); ds_read(dhcpc_params.path, (U8*)&dhcpc_data, sizeof(DHCPC)); dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } dhcpc_params.client[OPT_CODE] = DHCP_CLIENT_ID; dhcpc_params.client[OPT_LEN] = 7; dhcpc_params.client[OPT_DATA] = 1; memcpy(&(dhcpc_params.client[OPT_DATA + 1]), dhcpc_params.mac, MAC_ADDR_SIZE); dhcpc_params.client[dhcpc_params.client[OPT_LEN] + 2] = '\0'; dhcpc_params.packet = 0; /* start things over */ dhcpc_params.timeout = 0xFFFFFFFF; /* Kill any timeouts because the user wants this to hurry along */ dhcpc_params.retry = 0; dhcpc_params.re_dial = FALSE; dhcpc_params.code = LINK_CODE_NORMAL; dhcpc_params.last_arp_timestamp = 0; dhcpc_params.arp_failed_times = 0; dhcpc_params.sock = dhcpc_socket_init(); } LOCAL S32 dhcpc_init() { S32 idx = -1; dhcpc_param_init(); if (0 > dhcpc_params.sock) { DHCPC_ERROR("dhcp client socket init failed"); return ERROR; } idx = inet_add_socket(dhcpc_params.sock, (void*)dhcpc_handle, NULL, NULL); if (0 > idx) { DHCPC_ERROR("add dhcp client socket to inetd failed"); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } if (0 > inet_add_timer((void*)dhcpc_check_timer, 0, 1, EXECUTE_FOREVER)) { DHCPC_ERROR("add dhcp timer to inetd failed"); inet_del_socket(idx); close(dhcpc_params.sock); dhcpc_params.sock = -1; return ERROR; } msg_attach_handler(NSD_DHCPC_CTRL, dhcpc_ctrl_callback); #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT g_sock_idx = idx; msg_attach_handler(LTE_DHCPC_CTRL, lte_dhcpc_ctrl_callback); #endif #if 0 ds_register_action("dhcpc", "renew", dhcp_renew_handle); #endif DHCPC_ERROR("DHCPC init over."); return OK; } LOCAL S32 dhcpc_reload(DS_MSG *msg) { if (NULL == msg) { return ERROR; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(!get_lte_config_data_flag) { if(0 == ds_read(LTE_INFO_DATA_PATH, (U8*)&g_lte_config_data, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("ds read path [%s] failed.", LTE_INFO_DATA_PATH); return ERROR; } get_lte_config_data_flag = 1; } #endif if (ds_path_id_exist(msg->id, msg->num, DHCPC_PATH)) { DHCPC dhcpc_data; memset(&dhcpc_data, 0, sizeof(DHCPC)); if (0 == ds_read(DHCPC_PATH, (U8 *)&dhcpc_data, sizeof(DHCPC))) { DHCPC_ERROR("Read dhcpc data ERROR"); return ERROR; } dhcpc_params.mtu = dhcpc_data.mtu; dhcpc_params.flags = !dhcpc_data.enable_broadcast; dhcpc_params.manual_dns = (dhcpc_data.dns_mode == DNS_MODE_MANUAL); /*TODO: 目前只考虑为非手动获取dns的情况 */ #if 0 dhcpc_params[iface].dns[0] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[0] : 0; dhcpc_params[iface].dns[1] = dhcpc_params[iface].manual_dns ? dhcpc_data.dns[1] : 0; #endif dhcpc_params.name[OPT_CODE] = DHCP_HOST_NAME; dhcpc_params.name[OPT_LEN] = strlen(dhcpc_data.hostname); strncpy(&(dhcpc_params.name[OPT_DATA]), dhcpc_data.hostname, MAX_HOST_NAME_LEN); dhcpc_params.name[dhcpc_params.name[OPT_LEN] + 2] = '\0'; } #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT if(ds_path_id_exist(msg->id, msg->num, INFO_INTERNET_PATH)) { INFO_INTERNET info_internet = {0}; if(0 == ds_read(INFO_INTERNET_PATH, (U8*)&info_internet, sizeof(INFO_INTERNET))) { DHCPC_ERROR("ds read path [%s] failed.", INFO_INTERNET_PATH); return ERROR; } LTE_CONFIG_INFO_DATA lte_config; memset(&lte_config, 0, sizeof(LTE_CONFIG_INFO_DATA)); if(info_internet.link_status == INTERNET_4G_DISCONNECTED) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } }else if(info_internet.link_status == INTERNET_4G_CONNECTING) { if(0 == ds_read(LTE_INFO_DATA_PATH, &lte_config, sizeof(LTE_CONFIG_INFO_DATA))) { DHCPC_ERROR("Read lte config data ERROR"); return ERROR; } if(lte_config.internet_wired_enable == 0) { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_4G_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } else { if(lte_config.internet_wired_enable != g_lte_config_data.internet_wired_enable) { g_lte_config_data.internet_wired_enable = lte_config.internet_wired_enable; if(ERROR == dhcpc_param_reload(DHCPC_WIRED_INTERNET_MODE)) { DHCPC_ERROR("reload dhcpc param failed"); return ERROR; } } } } } #endif return OK; } LOCAL void dhcpc_main() { DS_DAT_MON_DESC dhcpc_data_monitor[] = { DS_DAT_MON(DHCPC_PATH, DATA_ATTRI_NOTIFY), #ifdef CONFIG_MOBILE_ACCESS_SET_SUPPORT DS_DAT_MON(INFO_INTERNET_PATH, DATA_ATTRI_NOTIFY), #endif }; DS_MOD_DESC dhcpc_module = DS_STRUCT_MOD("dhcpc", dhcpc_init, NULL, dhcpc_reload, NULL, NULL, NULL, dhcpc_data_monitor); MODULE *module_node = ds_register_module("dhcpc", &dhcpc_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(dhcpc_main);
09-23
写出下面代码用到的AT命令,讲解每个AT命令的具体的含义: #include <base/functional/bind.h> 27 #include <base/functional/callback_forward.h> 28 #include <string.h> 29 30 #include "device/include/esco_parameters.h" 31 #include "hcidefs.h" 32 #include "hcimsgs.h" 33 #include "internal_include/bt_target.h" 34 #include "main/shim/acl_api.h" 35 #include "osi/include/allocator.h" 36 #include "stack/include/bt_dev_class.h" 37 #include "stack/include/bt_hdr.h" 38 #include "stack/include/bt_lap.h" 39 #include "stack/include/bt_octets.h" 40 #include "stack/include/bt_types.h" 41 #include "stack/include/btu_hcif.h" 42 #include "types/raw_address.h" 43 44 /* Message by message.... */ 45 46 #define HCIC_PARAM_SIZE_INQUIRY 5 47 48 #define HCIC_INQ_INQ_LAP_OFF 0 49 #define HCIC_INQ_DUR_OFF 3 50 #define HCIC_INQ_RSP_CNT_OFF 4 51 52 /* Periodic Inquiry Mode */ 53 #define HCIC_PARAM_SIZE_PER_INQ_MODE 9 54 55 #define HCI_PER_INQ_MAX_INTRVL_OFF 0 56 #define HCI_PER_INQ_MIN_INTRVL_OFF 2 57 #define HCI_PER_INQ_INQ_LAP_OFF 4 58 #define HCI_PER_INQ_DURATION_OFF 7 59 #define HCI_PER_INQ_RSP_CNT_OFF 8 60 /* Periodic Inquiry Mode */ 61 62 /* Exit Periodic Inquiry Mode */ 63 #define HCIC_PARAM_SIZE_EXIT_PER_INQ 0 64 65 /* Create Connection */ 66 #define HCIC_PARAM_SIZE_CREATE_CONN 13 67 68 #define HCIC_CR_CONN_BD_ADDR_OFF 0 69 #define HCIC_CR_CONN_PKT_TYPES_OFF 6 70 #define HCIC_CR_CONN_REP_MODE_OFF 8 71 #define HCIC_CR_CONN_PAGE_SCAN_MODE_OFF 9 72 #define HCIC_CR_CONN_CLK_OFF_OFF 10 73 #define HCIC_CR_CONN_ALLOW_SWITCH_OFF 12 74 /* Create Connection */ 75 76 /* Disconnect */ 77 #define HCIC_PARAM_SIZE_DISCONNECT 3 78 79 #define HCI_DISC_HANDLE_OFF 0 80 #define HCI_DISC_REASON_OFF 2 81 /* Disconnect */ 82 83 /* Add SCO Connection */ 84 #define HCIC_PARAM_SIZE_ADD_SCO_CONN 4 85 86 #define HCI_ADD_SCO_HANDLE_OFF 0 87 #define HCI_ADD_SCO_PACKET_TYPES_OFF 2 88 /* Add SCO Connection */ 89 90 /* Create Connection Cancel */ 91 #define HCIC_PARAM_SIZE_CREATE_CONN_CANCEL 6 92 93 #define HCIC_CR_CONN_CANCEL_BD_ADDR_OFF 0 94 /* Create Connection Cancel */ 95 96 /* Accept Connection Request */ 97 #define HCIC_PARAM_SIZE_ACCEPT_CONN 7 98 99 #define HCI_ACC_CONN_BD_ADDR_OFF 0 100 #define HCI_ACC_CONN_ROLE_OFF 6 101 /* Accept Connection Request */ 102 103 /* Reject Connection Request */ 104 #define HCIC_PARAM_SIZE_REJECT_CONN 7 105 106 #define HCI_REJ_CONN_BD_ADDR_OFF 0 107 #define HCI_REJ_CONN_REASON_OFF 6 108 /* Reject Connection Request */ 109 110 /* Link Key Request Reply */ 111 #define HCIC_PARAM_SIZE_LINK_KEY_REQ_REPLY 22 112 113 #define HCI_LINK_KEY_REPLY_BD_ADDR_OFF 0 114 #define HCI_LINK_KEY_REPLY_LINK_KEY_OFF 6 115 /* Link Key Request Reply */ 116 117 /* Link Key Request Neg Reply */ 118 #define HCIC_PARAM_SIZE_LINK_KEY_NEG_REPLY 6 119 120 #define HCI_LINK_KEY_NEG_REP_BD_ADR_OFF 0 121 /* Link Key Request Neg Reply */ 122 123 /* PIN Code Request Reply */ 124 #define HCIC_PARAM_SIZE_PIN_CODE_REQ_REPLY 23 125 126 #define HCI_PIN_CODE_REPLY_BD_ADDR_OFF 0 127 #define HCI_PIN_CODE_REPLY_PIN_LEN_OFF 6 128 #define HCI_PIN_CODE_REPLY_PIN_CODE_OFF 7 129 /* PIN Code Request Reply */ 130 131 /* Link Key Request Neg Reply */ 132 #define HCIC_PARAM_SIZE_PIN_CODE_NEG_REPLY 6 133 134 #define HCI_PIN_CODE_NEG_REP_BD_ADR_OFF 0 135 /* Link Key Request Neg Reply */ 136 137 /* Change Connection Type */ 138 #define HCIC_PARAM_SIZE_CHANGE_CONN_TYPE 4 139 140 #define HCI_CHNG_PKT_TYPE_HANDLE_OFF 0 141 #define HCI_CHNG_PKT_TYPE_PKT_TYPE_OFF 2 142 /* Change Connection Type */ 143 144 #define HCIC_PARAM_SIZE_CMD_HANDLE 2 145 146 #define HCI_CMD_HANDLE_HANDLE_OFF 0 147 148 /* Set Connection Encryption */ 149 #define HCIC_PARAM_SIZE_SET_CONN_ENCRYPT 3 150 151 #define HCI_SET_ENCRYPT_HANDLE_OFF 0 152 #define HCI_SET_ENCRYPT_ENABLE_OFF 2 153 /* Set Connection Encryption */ 154 155 /* Remote Name Request */ 156 #define HCIC_PARAM_SIZE_RMT_NAME_REQ 10 157 158 #define HCI_RMT_NAME_BD_ADDR_OFF 0 159 #define HCI_RMT_NAME_REP_MODE_OFF 6 160 #define HCI_RMT_NAME_PAGE_SCAN_MODE_OFF 7 161 #define HCI_RMT_NAME_CLK_OFF_OFF 8 162 /* Remote Name Request */ 163 164 /* Remote Name Request Cancel */ 165 #define HCIC_PARAM_SIZE_RMT_NAME_REQ_CANCEL 6 166 167 #define HCI_RMT_NAME_CANCEL_BD_ADDR_OFF 0 168 /* Remote Name Request Cancel */ 169 170 /* Remote Extended Features */ 171 #define HCIC_PARAM_SIZE_RMT_EXT_FEATURES 3 172 173 #define HCI_RMT_EXT_FEATURES_HANDLE_OFF 0 174 #define HCI_RMT_EXT_FEATURES_PAGE_NUM_OFF 2 175 /* Remote Extended Features */ 176 177 #define HCIC_PARAM_SIZE_SETUP_ESCO 17 178 179 #define HCI_SETUP_ESCO_HANDLE_OFF 0 180 #define HCI_SETUP_ESCO_TX_BW_OFF 2 181 #define HCI_SETUP_ESCO_RX_BW_OFF 6 182 #define HCI_SETUP_ESCO_MAX_LAT_OFF 10 183 #define HCI_SETUP_ESCO_VOICE_OFF 12 184 #define HCI_SETUP_ESCO_RETRAN_EFF_OFF 14 185 #define HCI_SETUP_ESCO_PKT_TYPES_OFF 15 186 187 #define HCIC_PARAM_SIZE_ACCEPT_ESCO 21 188 189 #define HCI_ACCEPT_ESCO_BDADDR_OFF 0 190 #define HCI_ACCEPT_ESCO_TX_BW_OFF 6 191 #define HCI_ACCEPT_ESCO_RX_BW_OFF 10 192 #define HCI_ACCEPT_ESCO_MAX_LAT_OFF 14 193 #define HCI_ACCEPT_ESCO_VOICE_OFF 16 194 #define HCI_ACCEPT_ESCO_RETRAN_EFF_OFF 18 195 #define HCI_ACCEPT_ESCO_PKT_TYPES_OFF 19 196 197 #define HCIC_PARAM_SIZE_REJECT_ESCO 7 198 199 #define HCI_REJECT_ESCO_BDADDR_OFF 0 200 #define HCI_REJECT_ESCO_REASON_OFF 6 201 202 /* Hold Mode */ 203 #define HCIC_PARAM_SIZE_HOLD_MODE 6 204 205 #define HCI_HOLD_MODE_HANDLE_OFF 0 206 #define HCI_HOLD_MODE_MAX_PER_OFF 2 207 #define HCI_HOLD_MODE_MIN_PER_OFF 4 208 /* Hold Mode */ 209 210 /* Sniff Mode */ 211 #define HCIC_PARAM_SIZE_SNIFF_MODE 10 212 213 #define HCI_SNIFF_MODE_HANDLE_OFF 0 214 #define HCI_SNIFF_MODE_MAX_PER_OFF 2 215 #define HCI_SNIFF_MODE_MIN_PER_OFF 4 216 #define HCI_SNIFF_MODE_ATTEMPT_OFF 6 217 #define HCI_SNIFF_MODE_TIMEOUT_OFF 8 218 /* Sniff Mode */ 219 220 /* Park Mode */ 221 #define HCIC_PARAM_SIZE_PARK_MODE 6 222 223 #define HCI_PARK_MODE_HANDLE_OFF 0 224 #define HCI_PARK_MODE_MAX_PER_OFF 2 225 #define HCI_PARK_MODE_MIN_PER_OFF 4 226 /* Park Mode */ 227 228 /* QoS Setup */ 229 #define HCIC_PARAM_SIZE_QOS_SETUP 20 230 231 #define HCI_QOS_HANDLE_OFF 0 232 #define HCI_QOS_FLAGS_OFF 2 233 #define HCI_QOS_SERVICE_TYPE_OFF 3 234 #define HCI_QOS_TOKEN_RATE_OFF 4 235 #define HCI_QOS_PEAK_BANDWIDTH_OFF 8 236 #define HCI_QOS_LATENCY_OFF 12 237 #define HCI_QOS_DELAY_VAR_OFF 16 238 /* QoS Setup */ 239 240 #define HCIC_PARAM_SIZE_SWITCH_ROLE 7 241 242 #define HCI_SWITCH_BD_ADDR_OFF 0 243 #define HCI_SWITCH_ROLE_OFF 6 244 /* Switch Role Request */ 245 246 /* Write Policy Settings */ 247 #define HCIC_PARAM_SIZE_WRITE_POLICY_SET 4 248 249 #define HCI_WRITE_POLICY_HANDLE_OFF 0 250 #define HCI_WRITE_POLICY_SETTINGS_OFF 2 251 /* Write Policy Settings */ 252 253 /* Write Default Policy Settings */ 254 #define HCIC_PARAM_SIZE_WRITE_DEF_POLICY_SET 2 255 256 #define HCI_WRITE_DEF_POLICY_SETTINGS_OFF 0 257 /* Write Default Policy Settings */ 258 259 #define HCIC_PARAM_SIZE_SNIFF_SUB_RATE 8 260 261 #define HCI_SNIFF_SUB_RATE_HANDLE_OFF 0 262 #define HCI_SNIFF_SUB_RATE_MAX_LAT_OFF 2 263 #define HCI_SNIFF_SUB_RATE_MIN_REM_LAT_OFF 4 264 #define HCI_SNIFF_SUB_RATE_MIN_LOC_LAT_OFF 6 265 /* Sniff Subrating */ 266 267 /* Extended Inquiry Response */ 268 #define HCIC_PARAM_SIZE_EXT_INQ_RESP 241 269 270 #define HCIC_EXT_INQ_RESP_FEC_OFF 0 271 #define HCIC_EXT_INQ_RESP_RESPONSE 1 272 /* IO Capabilities Response */ 273 #define HCIC_PARAM_SIZE_IO_CAP_RESP 9 274 275 #define HCI_IO_CAP_BD_ADDR_OFF 0 276 #define HCI_IO_CAPABILITY_OFF 6 277 #define HCI_IO_CAP_OOB_DATA_OFF 7 278 #define HCI_IO_CAP_AUTH_REQ_OFF 8 279 280 /* IO Capabilities Req Neg Reply */ 281 #define HCIC_PARAM_SIZE_IO_CAP_NEG_REPLY 7 282 283 #define HCI_IO_CAP_NR_BD_ADDR_OFF 0 284 #define HCI_IO_CAP_NR_ERR_CODE 6 285 286 /* Read Local OOB Data */ 287 #define HCIC_PARAM_SIZE_R_LOCAL_OOB 0 288 289 /* Read Local OOB Extended Data */ 290 #define HCIC_PARAM_SIZE_R_LOCAL_OOB_EXTENDED 0 291 292 #define HCIC_PARAM_SIZE_UCONF_REPLY 6 293 294 #define HCI_USER_CONF_BD_ADDR_OFF 0 295 296 #define HCIC_PARAM_SIZE_U_PKEY_REPLY 10 297 298 #define HCI_USER_PASSKEY_BD_ADDR_OFF 0 299 #define HCI_USER_PASSKEY_VALUE_OFF 6 300 301 #define HCIC_PARAM_SIZE_U_PKEY_NEG_REPLY 6 302 303 #define HCI_USER_PASSKEY_NEG_BD_ADDR_OFF 0 304 305 /* Remote OOB Data Request Reply */ 306 #define HCIC_PARAM_SIZE_REM_OOB_REPLY 38 307 308 #define HCI_REM_OOB_DATA_BD_ADDR_OFF 0 309 #define HCI_REM_OOB_DATA_C_OFF 6 310 #define HCI_REM_OOB_DATA_R_OFF 22 311 312 /* Remote OOB Data Request Negative Reply */ 313 #define HCIC_PARAM_SIZE_REM_OOB_NEG_REPLY 6 314 315 #define HCI_REM_OOB_DATA_NEG_BD_ADDR_OFF 0 316 317 /* Read Tx Power Level */ 318 #define HCIC_PARAM_SIZE_R_TX_POWER 0 319 320 /* Read Default Erroneous Data Reporting */ 321 #define HCIC_PARAM_SIZE_R_ERR_DATA_RPT 0 322 323 #define HCIC_PARAM_SIZE_SEND_KEYPRESS_NOTIF 7 324 325 #define HCI_SEND_KEYPRESS_NOTIF_BD_ADDR_OFF 0 326 #define HCI_SEND_KEYPRESS_NOTIF_NOTIF_OFF 6 327 328 /**** end of Simple Pairing Commands ****/ 329 330 #define HCIC_PARAM_SIZE_SET_EVT_FILTER 9 331 332 #define HCI_FILT_COND_FILT_TYPE_OFF 0 333 #define HCI_FILT_COND_COND_TYPE_OFF 1 334 #define HCI_FILT_COND_FILT_OFF 2 335 /* Set Event Filter */ 336 337 /* Delete Stored Key */ 338 #define HCIC_PARAM_SIZE_DELETE_STORED_KEY 7 339 340 #define HCI_DELETE_KEY_BD_ADDR_OFF 0 341 #define HCI_DELETE_KEY_ALL_FLAG_OFF 6 342 /* Delete Stored Key */ 343 344 /* Change Local Name */ 345 #define HCIC_PARAM_SIZE_CHANGE_NAME BD_NAME_LEN 346 347 #define HCI_CHANGE_NAME_NAME_OFF 0 348 /* Change Local Name */ 349 350 #define HCIC_PARAM_SIZE_READ_CMD 0 351 352 #define HCIC_PARAM_SIZE_WRITE_PARAM1 1 353 354 #define HCIC_WRITE_PARAM1_PARAM_OFF 0 355 356 #define HCIC_PARAM_SIZE_WRITE_PARAM2 2 357 358 #define HCIC_WRITE_PARAM2_PARAM_OFF 0 359 360 #define HCIC_PARAM_SIZE_WRITE_PARAM3 3 361 362 #define HCIC_WRITE_PARAM3_PARAM_OFF 0 363 364 #define HCIC_PARAM_SIZE_SET_AFH_CHANNELS 10 365 366 #define HCIC_PARAM_SIZE_ENH_SET_ESCO_CONN 59 367 #define HCIC_PARAM_SIZE_ENH_ACC_ESCO_CONN 63 368 369 #define HCIC_PARAM_SIZE_WRITE_PAGESCAN_CFG 4 370 371 #define HCI_SCAN_CFG_INTERVAL_OFF 0 372 #define HCI_SCAN_CFG_WINDOW_OFF 2 373 /* Write Page Scan Activity */ 374 375 /* Write Inquiry Scan Activity */ 376 #define HCIC_PARAM_SIZE_WRITE_INQSCAN_CFG 4 377 378 #define HCI_SCAN_CFG_INTERVAL_OFF 0 379 #define HCI_SCAN_CFG_WINDOW_OFF 2 380 /* Write Inquiry Scan Activity */ 381 382 /* Host Controller to Host flow control */ 383 #define HCI_HOST_FLOW_CTRL_OFF 0 384 #define HCI_HOST_FLOW_CTRL_ACL_ON 1 385 #define HCI_HOST_FLOW_CTRL_SCO_ON 2 386 #define HCI_HOST_FLOW_CTRL_BOTH_ON 3 387 388 #define HCIC_PARAM_SIZE_WRITE_AUTOMATIC_FLUSH_TIMEOUT 4 389 390 #define HCI_FLUSH_TOUT_HANDLE_OFF 0 391 #define HCI_FLUSH_TOUT_TOUT_OFF 2 392 393 #define HCIC_PARAM_SIZE_READ_TX_POWER 3 394 395 #define HCI_READ_TX_POWER_HANDLE_OFF 0 396 #define HCI_READ_TX_POWER_TYPE_OFF 2 397 398 /* Read transmit power level parameter */ 399 #define HCI_READ_CURRENT 0x00 400 #define HCI_READ_MAXIMUM 0x01 401 402 #define HCIC_PARAM_SIZE_NUM_PKTS_DONE_SIZE sizeof(btmsg_hcic_num_pkts_done_t) 403 404 #define MAX_DATA_HANDLES 10 405 406 #define HCI_PKTS_DONE_NUM_HANDLES_OFF 0 407 #define HCI_PKTS_DONE_HANDLE_OFF 1 408 #define HCI_PKTS_DONE_NUM_PKTS_OFF 3 409 410 #define HCIC_PARAM_SIZE_WRITE_LINK_SUPER_TOUT 4 411 412 #define HCI_LINK_SUPER_TOUT_HANDLE_OFF 0 413 #define HCI_LINK_SUPER_TOUT_TOUT_OFF 2 414 /* Write Link Supervision Timeout */ 415 416 #define MAX_IAC_LAPS 0x40 417 418 #define HCI_WRITE_IAC_LAP_NUM_OFF 0 419 #define HCI_WRITE_IAC_LAP_LAP_OFF 1 420 /* Write Current IAC LAP */ 421 422 #define HCIC_PARAM_SIZE_CONFIGURE_DATA_PATH 3 423 424 /******************************************************************************* 425 * BLE Commands 426 * Note: "local_controller_id" is for transport, not counted in HCI 427 * message size 428 ******************************************************************************/ 429 #define HCIC_BLE_RAND_DI_SIZE 8 430 #define HCIC_BLE_IRK_SIZE 16 431 432 #define HCIC_PARAM_SIZE_SET_USED_FEAT_CMD 8 433 #define HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD 6 434 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS 15 435 #define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_RSP 31 436 #define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE 1 437 #define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM 7 438 #define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE 2 439 #define HCIC_PARAM_SIZE_BLE_CREATE_LL_CONN 25 440 #define HCIC_PARAM_SIZE_BLE_CREATE_CONN_CANCEL 0 441 #define HCIC_PARAM_SIZE_CLEAR_ACCEPTLIST 0 442 #define HCIC_PARAM_SIZE_ADD_ACCEPTLIST 7 443 #define HCIC_PARAM_SIZE_REMOVE_ACCEPTLIST 7 444 #define HCIC_PARAM_SIZE_BLE_UPD_LL_CONN_PARAMS 14 445 #define HCIC_PARAM_SIZE_SET_HOST_CHNL_CLASS 5 446 #define HCIC_PARAM_SIZE_READ_CHNL_MAP 2 447 #define HCIC_PARAM_SIZE_BLE_READ_REMOTE_FEAT 2 448 #define HCIC_PARAM_SIZE_BLE_ENCRYPT 32 449 #define HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED 2 450 451 #define HCIC_BLE_RAND_DI_SIZE 8 452 #define HCIC_BLE_ENCRYPT_KEY_SIZE 16 453 #define HCIC_PARAM_SIZE_BLE_START_ENC \ 454 (4 + HCIC_BLE_RAND_DI_SIZE + HCIC_BLE_ENCRYPT_KEY_SIZE) 455 #define HCIC_PARAM_SIZE_LTK_REQ_REPLY (2 + HCIC_BLE_ENCRYPT_KEY_SIZE) 456 #define HCIC_PARAM_SIZE_LTK_REQ_NEG_REPLY 2 457 #define HCIC_BLE_CHNL_MAP_SIZE 5 458 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31 459 460 #define HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST (7 + HCIC_BLE_IRK_SIZE * 2) 461 #define HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST 7 462 #define HCIC_PARAM_SIZE_BLE_SET_PRIVACY_MODE 8 463 #define HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST 0 464 #define HCIC_PARAM_SIZE_BLE_READ_RESOLVING_LIST_SIZE 0 465 #define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER 7 466 #define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL 7 467 #define HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE 1 468 #define HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT 2 469 470 #define HCIC_PARAM_SIZE_BLE_READ_PHY 2 471 #define HCIC_PARAM_SIZE_BLE_SET_DEFAULT_PHY 3 472 #define HCIC_PARAM_SIZE_BLE_SET_PHY 7 473 #define HCIC_PARAM_SIZE_BLE_ENH_RX_TEST 3 474 #define HCIC_PARAM_SIZE_BLE_ENH_TX_TEST 4 475 476 #define HCIC_PARAM_SIZE_BLE_SET_DATA_LENGTH 6 477 #define HCIC_PARAM_SIZE_BLE_WRITE_EXTENDED_SCAN_PARAM 11 478 479 #define HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_REPLY 14 480 #define HCIC_PARAM_SIZE_BLE_RC_PARAM_REQ_NEG_REPLY 3 481 482 static void btsnd_hcic_disconnect(uint16_t handle, uint8_t reason) { 483 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 484 uint8_t* pp = (uint8_t*)(p + 1); 485 486 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_DISCONNECT; 487 p->offset = 0; 488 489 UINT16_TO_STREAM(pp, HCI_DISCONNECT); 490 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_DISCONNECT); 491 UINT16_TO_STREAM(pp, handle); 492 UINT8_TO_STREAM(pp, reason); 493 494 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 495 } 496 497 void btsnd_hcic_add_SCO_conn(uint16_t handle, uint16_t packet_types) { 498 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 499 uint8_t* pp = (uint8_t*)(p + 1); 500 501 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ADD_SCO_CONN; 502 p->offset = 0; 503 504 UINT16_TO_STREAM(pp, HCI_ADD_SCO_CONNECTION); 505 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ADD_SCO_CONN); 506 507 UINT16_TO_STREAM(pp, handle); 508 UINT16_TO_STREAM(pp, packet_types); 509 510 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 511 } 512 513 void btsnd_hcic_create_conn_cancel(const RawAddress& dest) { 514 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 515 uint8_t* pp = (uint8_t*)(p + 1); 516 517 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CREATE_CONN_CANCEL; 518 p->offset = 0; 519 520 UINT16_TO_STREAM(pp, HCI_CREATE_CONNECTION_CANCEL); 521 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CREATE_CONN_CANCEL); 522 523 BDADDR_TO_STREAM(pp, dest); 524 525 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 526 } 527 528 void btsnd_hcic_accept_conn(const RawAddress& dest, uint8_t role) { 529 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 530 uint8_t* pp = (uint8_t*)(p + 1); 531 532 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ACCEPT_CONN; 533 p->offset = 0; 534 535 UINT16_TO_STREAM(pp, HCI_ACCEPT_CONNECTION_REQUEST); 536 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ACCEPT_CONN); 537 BDADDR_TO_STREAM(pp, dest); 538 UINT8_TO_STREAM(pp, role); 539 540 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 541 } 542 543 void btsnd_hcic_reject_conn(const RawAddress& dest, uint8_t reason) { 544 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 545 uint8_t* pp = (uint8_t*)(p + 1); 546 547 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_REJECT_CONN; 548 p->offset = 0; 549 550 UINT16_TO_STREAM(pp, HCI_REJECT_CONNECTION_REQUEST); 551 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_REJECT_CONN); 552 553 BDADDR_TO_STREAM(pp, dest); 554 UINT8_TO_STREAM(pp, reason); 555 556 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 557 } 558 559 void btsnd_hcic_link_key_req_reply(const RawAddress& bd_addr, 560 const LinkKey& link_key) { 561 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 562 uint8_t* pp = (uint8_t*)(p + 1); 563 564 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_LINK_KEY_REQ_REPLY; 565 p->offset = 0; 566 567 UINT16_TO_STREAM(pp, HCI_LINK_KEY_REQUEST_REPLY); 568 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_LINK_KEY_REQ_REPLY); 569 570 BDADDR_TO_STREAM(pp, bd_addr); 571 ARRAY16_TO_STREAM(pp, link_key.data()); 572 573 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 574 } 575 576 void btsnd_hcic_link_key_neg_reply(const RawAddress& bd_addr) { 577 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 578 uint8_t* pp = (uint8_t*)(p + 1); 579 580 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_LINK_KEY_NEG_REPLY; 581 p->offset = 0; 582 583 UINT16_TO_STREAM(pp, HCI_LINK_KEY_REQUEST_NEG_REPLY); 584 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_LINK_KEY_NEG_REPLY); 585 586 BDADDR_TO_STREAM(pp, bd_addr); 587 588 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 589 } 590 591 void btsnd_hcic_pin_code_req_reply(const RawAddress& bd_addr, 592 uint8_t pin_code_len, PIN_CODE pin_code) { 593 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 594 uint8_t* pp = (uint8_t*)(p + 1); 595 int i; 596 597 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_PIN_CODE_REQ_REPLY; 598 p->offset = 0; 599 600 UINT16_TO_STREAM(pp, HCI_PIN_CODE_REQUEST_REPLY); 601 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_PIN_CODE_REQ_REPLY); 602 603 BDADDR_TO_STREAM(pp, bd_addr); 604 UINT8_TO_STREAM(pp, pin_code_len); 605 606 for (i = 0; i < pin_code_len; i++) *pp++ = *pin_code++; 607 608 for (; i < PIN_CODE_LEN; i++) *pp++ = 0; 609 610 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 611 } 612 613 void btsnd_hcic_pin_code_neg_reply(const RawAddress& bd_addr) { 614 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 615 uint8_t* pp = (uint8_t*)(p + 1); 616 617 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_PIN_CODE_NEG_REPLY; 618 p->offset = 0; 619 620 UINT16_TO_STREAM(pp, HCI_PIN_CODE_REQUEST_NEG_REPLY); 621 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_PIN_CODE_NEG_REPLY); 622 623 BDADDR_TO_STREAM(pp, bd_addr); 624 625 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 626 } 627 628 void btsnd_hcic_change_conn_type(uint16_t handle, uint16_t packet_types) { 629 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 630 uint8_t* pp = (uint8_t*)(p + 1); 631 632 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CHANGE_CONN_TYPE; 633 p->offset = 0; 634 635 UINT16_TO_STREAM(pp, HCI_CHANGE_CONN_PACKET_TYPE); 636 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CHANGE_CONN_TYPE); 637 638 UINT16_TO_STREAM(pp, handle); 639 UINT16_TO_STREAM(pp, packet_types); 640 641 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 642 } 643 644 void btsnd_hcic_auth_request(uint16_t handle) { 645 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 646 uint8_t* pp = (uint8_t*)(p + 1); 647 648 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CMD_HANDLE; 649 p->offset = 0; 650 651 UINT16_TO_STREAM(pp, HCI_AUTHENTICATION_REQUESTED); 652 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CMD_HANDLE); 653 654 UINT16_TO_STREAM(pp, handle); 655 656 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 657 } 658 659 void btsnd_hcic_set_conn_encrypt(uint16_t handle, bool enable) { 660 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 661 uint8_t* pp = (uint8_t*)(p + 1); 662 663 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_SET_CONN_ENCRYPT; 664 p->offset = 0; 665 666 UINT16_TO_STREAM(pp, HCI_SET_CONN_ENCRYPTION); 667 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_CONN_ENCRYPT); 668 669 UINT16_TO_STREAM(pp, handle); 670 UINT8_TO_STREAM(pp, enable); 671 672 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 673 } 674 675 void btsnd_hcic_rmt_ext_features(uint16_t handle, uint8_t page_num) { 676 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 677 uint8_t* pp = (uint8_t*)(p + 1); 678 679 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_RMT_EXT_FEATURES; 680 p->offset = 0; 681 682 UINT16_TO_STREAM(pp, HCI_READ_RMT_EXT_FEATURES); 683 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_RMT_EXT_FEATURES); 684 685 UINT16_TO_STREAM(pp, handle); 686 UINT8_TO_STREAM(pp, page_num); 687 688 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 689 } 690 691 void btsnd_hcic_rmt_ver_req(uint16_t handle) { 692 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 693 uint8_t* pp = (uint8_t*)(p + 1); 694 695 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CMD_HANDLE; 696 p->offset = 0; 697 698 UINT16_TO_STREAM(pp, HCI_READ_RMT_VERSION_INFO); 699 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CMD_HANDLE); 700 701 UINT16_TO_STREAM(pp, handle); 702 703 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 704 } 705 706 void btsnd_hcic_read_rmt_clk_offset(uint16_t handle) { 707 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 708 uint8_t* pp = (uint8_t*)(p + 1); 709 710 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CMD_HANDLE; 711 p->offset = 0; 712 713 UINT16_TO_STREAM(pp, HCI_READ_RMT_CLOCK_OFFSET); 714 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CMD_HANDLE); 715 716 UINT16_TO_STREAM(pp, handle); 717 718 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 719 } 720 721 void btsnd_hcic_setup_esco_conn(uint16_t handle, uint32_t transmit_bandwidth, 722 uint32_t receive_bandwidth, 723 uint16_t max_latency, uint16_t voice, 724 uint8_t retrans_effort, uint16_t packet_types) { 725 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 726 uint8_t* pp = (uint8_t*)(p + 1); 727 728 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_SETUP_ESCO; 729 p->offset = 0; 730 731 UINT16_TO_STREAM(pp, HCI_SETUP_ESCO_CONNECTION); 732 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SETUP_ESCO); 733 734 UINT16_TO_STREAM(pp, handle); 735 UINT32_TO_STREAM(pp, transmit_bandwidth); 736 UINT32_TO_STREAM(pp, receive_bandwidth); 737 UINT16_TO_STREAM(pp, max_latency); 738 UINT16_TO_STREAM(pp, voice); 739 UINT8_TO_STREAM(pp, retrans_effort); 740 UINT16_TO_STREAM(pp, packet_types); 741 742 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 743 } 744 745 void btsnd_hcic_accept_esco_conn(const RawAddress& bd_addr, 746 uint32_t transmit_bandwidth, 747 uint32_t receive_bandwidth, 748 uint16_t max_latency, uint16_t content_fmt, 749 uint8_t retrans_effort, 750 uint16_t packet_types) { 751 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 752 uint8_t* pp = (uint8_t*)(p + 1); 753 754 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ACCEPT_ESCO; 755 p->offset = 0; 756 757 UINT16_TO_STREAM(pp, HCI_ACCEPT_ESCO_CONNECTION); 758 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ACCEPT_ESCO); 759 760 BDADDR_TO_STREAM(pp, bd_addr); 761 UINT32_TO_STREAM(pp, transmit_bandwidth); 762 UINT32_TO_STREAM(pp, receive_bandwidth); 763 UINT16_TO_STREAM(pp, max_latency); 764 UINT16_TO_STREAM(pp, content_fmt); 765 UINT8_TO_STREAM(pp, retrans_effort); 766 UINT16_TO_STREAM(pp, packet_types); 767 768 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 769 } 770 771 void btsnd_hcic_reject_esco_conn(const RawAddress& bd_addr, uint8_t reason) { 772 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 773 uint8_t* pp = (uint8_t*)(p + 1); 774 775 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_REJECT_ESCO; 776 p->offset = 0; 777 778 UINT16_TO_STREAM(pp, HCI_REJECT_ESCO_CONNECTION); 779 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_REJECT_ESCO); 780 781 BDADDR_TO_STREAM(pp, bd_addr); 782 UINT8_TO_STREAM(pp, reason); 783 784 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 785 } 786 787 void btsnd_hcic_hold_mode(uint16_t handle, uint16_t max_hold_period, 788 uint16_t min_hold_period) { 789 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 790 uint8_t* pp = (uint8_t*)(p + 1); 791 792 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_HOLD_MODE; 793 p->offset = 0; 794 795 UINT16_TO_STREAM(pp, HCI_HOLD_MODE); 796 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_HOLD_MODE); 797 798 UINT16_TO_STREAM(pp, handle); 799 UINT16_TO_STREAM(pp, max_hold_period); 800 UINT16_TO_STREAM(pp, min_hold_period); 801 802 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 803 } 804 805 void btsnd_hcic_sniff_mode(uint16_t handle, uint16_t max_sniff_period, 806 uint16_t min_sniff_period, uint16_t sniff_attempt, 807 uint16_t sniff_timeout) { 808 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 809 uint8_t* pp = (uint8_t*)(p + 1); 810 811 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_SNIFF_MODE; 812 p->offset = 0; 813 814 UINT16_TO_STREAM(pp, HCI_SNIFF_MODE); 815 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SNIFF_MODE); 816 817 UINT16_TO_STREAM(pp, handle); 818 UINT16_TO_STREAM(pp, max_sniff_period); 819 UINT16_TO_STREAM(pp, min_sniff_period); 820 UINT16_TO_STREAM(pp, sniff_attempt); 821 UINT16_TO_STREAM(pp, sniff_timeout); 822 823 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 824 } 825 826 void btsnd_hcic_exit_sniff_mode(uint16_t handle) { 827 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 828 uint8_t* pp = (uint8_t*)(p + 1); 829 830 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CMD_HANDLE; 831 p->offset = 0; 832 833 UINT16_TO_STREAM(pp, HCI_EXIT_SNIFF_MODE); 834 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CMD_HANDLE); 835 836 UINT16_TO_STREAM(pp, handle); 837 838 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 839 } 840 841 void btsnd_hcic_park_mode(uint16_t handle, uint16_t beacon_max_interval, 842 uint16_t beacon_min_interval) { 843 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 844 uint8_t* pp = (uint8_t*)(p + 1); 845 846 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_PARK_MODE; 847 p->offset = 0; 848 849 UINT16_TO_STREAM(pp, HCI_PARK_MODE); 850 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_PARK_MODE); 851 852 UINT16_TO_STREAM(pp, handle); 853 UINT16_TO_STREAM(pp, beacon_max_interval); 854 UINT16_TO_STREAM(pp, beacon_min_interval); 855 856 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 857 } 858 859 void btsnd_hcic_exit_park_mode(uint16_t handle) { 860 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 861 uint8_t* pp = (uint8_t*)(p + 1); 862 863 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CMD_HANDLE; 864 p->offset = 0; 865 866 UINT16_TO_STREAM(pp, HCI_EXIT_PARK_MODE); 867 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CMD_HANDLE); 868 869 UINT16_TO_STREAM(pp, handle); 870 871 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 872 } 873 874 static void btsnd_hcic_switch_role(const RawAddress& bd_addr, uint8_t role) { 875 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 876 uint8_t* pp = (uint8_t*)(p + 1); 877 878 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_SWITCH_ROLE; 879 p->offset = 0; 880 881 UINT16_TO_STREAM(pp, HCI_SWITCH_ROLE); 882 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SWITCH_ROLE); 883 884 BDADDR_TO_STREAM(pp, bd_addr); 885 UINT8_TO_STREAM(pp, role); 886 887 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 888 } 889 890 void btsnd_hcic_write_policy_set(uint16_t handle, uint16_t settings) { 891 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 892 uint8_t* pp = (uint8_t*)(p + 1); 893 894 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_POLICY_SET; 895 p->offset = 0; 896 UINT16_TO_STREAM(pp, HCI_WRITE_POLICY_SETTINGS); 897 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_POLICY_SET); 898 899 UINT16_TO_STREAM(pp, handle); 900 UINT16_TO_STREAM(pp, settings); 901 902 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 903 } 904 905 void btsnd_hcic_write_def_policy_set(uint16_t settings) { 906 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 907 uint8_t* pp = (uint8_t*)(p + 1); 908 909 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_DEF_POLICY_SET; 910 p->offset = 0; 911 UINT16_TO_STREAM(pp, HCI_WRITE_DEF_POLICY_SETTINGS); 912 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_DEF_POLICY_SET); 913 914 UINT16_TO_STREAM(pp, settings); 915 916 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 917 } 918 919 void btsnd_hcic_set_event_filter(uint8_t filt_type, uint8_t filt_cond_type, 920 uint8_t* filt_cond, uint8_t filt_cond_len) { 921 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 922 uint8_t* pp = (uint8_t*)(p + 1); 923 924 p->offset = 0; 925 926 UINT16_TO_STREAM(pp, HCI_SET_EVENT_FILTER); 927 928 if (filt_type) { 929 p->len = (uint16_t)(HCIC_PREAMBLE_SIZE + 2 + filt_cond_len); 930 UINT8_TO_STREAM(pp, (uint8_t)(2 + filt_cond_len)); 931 932 UINT8_TO_STREAM(pp, filt_type); 933 UINT8_TO_STREAM(pp, filt_cond_type); 934 935 if (filt_cond_type == HCI_FILTER_COND_DEVICE_CLASS) { 936 DEVCLASS_TO_STREAM(pp, filt_cond); 937 filt_cond += kDevClassLength; 938 DEVCLASS_TO_STREAM(pp, filt_cond); 939 filt_cond += kDevClassLength; 940 941 filt_cond_len -= (2 * kDevClassLength); 942 } else if (filt_cond_type == HCI_FILTER_COND_BD_ADDR) { 943 BDADDR_TO_STREAM(pp, *((RawAddress*)filt_cond)); 944 filt_cond += BD_ADDR_LEN; 945 946 filt_cond_len -= BD_ADDR_LEN; 947 } 948 949 if (filt_cond_len) ARRAY_TO_STREAM(pp, filt_cond, filt_cond_len); 950 } else { 951 p->len = (uint16_t)(HCIC_PREAMBLE_SIZE + 1); 952 UINT8_TO_STREAM(pp, 1); 953 954 UINT8_TO_STREAM(pp, filt_type); 955 } 956 957 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 958 } 959 960 void btsnd_hcic_write_pin_type(uint8_t type) { 961 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 962 uint8_t* pp = (uint8_t*)(p + 1); 963 964 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1; 965 p->offset = 0; 966 967 UINT16_TO_STREAM(pp, HCI_WRITE_PIN_TYPE); 968 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1); 969 970 UINT8_TO_STREAM(pp, type); 971 972 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 973 } 974 975 void btsnd_hcic_delete_stored_key(const RawAddress& bd_addr, 976 bool delete_all_flag) { 977 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 978 uint8_t* pp = (uint8_t*)(p + 1); 979 980 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_DELETE_STORED_KEY; 981 p->offset = 0; 982 983 UINT16_TO_STREAM(pp, HCI_DELETE_STORED_LINK_KEY); 984 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_DELETE_STORED_KEY); 985 986 BDADDR_TO_STREAM(pp, bd_addr); 987 UINT8_TO_STREAM(pp, delete_all_flag); 988 989 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 990 } 991 992 void btsnd_hcic_change_name(BD_NAME name) { 993 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 994 uint8_t* pp = (uint8_t*)(p + 1); 995 uint16_t len = strlen((char*)name) + 1; 996 997 memset(pp, 0, HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CHANGE_NAME); 998 999 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CHANGE_NAME; 1000 p->offset = 0; 1001 1002 UINT16_TO_STREAM(pp, HCI_CHANGE_LOCAL_NAME); 1003 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CHANGE_NAME); 1004 1005 if (len > HCIC_PARAM_SIZE_CHANGE_NAME) len = HCIC_PARAM_SIZE_CHANGE_NAME; 1006 1007 ARRAY_TO_STREAM(pp, name, len); 1008 1009 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1010 } 1011 1012 void btsnd_hcic_read_name(void) { 1013 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1014 uint8_t* pp = (uint8_t*)(p + 1); 1015 1016 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD; 1017 p->offset = 0; 1018 1019 UINT16_TO_STREAM(pp, HCI_READ_LOCAL_NAME); 1020 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_CMD); 1021 1022 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1023 } 1024 1025 void btsnd_hcic_write_page_tout(uint16_t timeout) { 1026 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1027 uint8_t* pp = (uint8_t*)(p + 1); 1028 1029 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM2; 1030 p->offset = 0; 1031 1032 UINT16_TO_STREAM(pp, HCI_WRITE_PAGE_TOUT); 1033 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM2); 1034 1035 UINT16_TO_STREAM(pp, timeout); 1036 1037 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1038 } 1039 1040 void btsnd_hcic_write_scan_enable(uint8_t flag) { 1041 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1042 uint8_t* pp = (uint8_t*)(p + 1); 1043 1044 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1; 1045 p->offset = 0; 1046 1047 UINT16_TO_STREAM(pp, HCI_WRITE_SCAN_ENABLE); 1048 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1); 1049 1050 UINT8_TO_STREAM(pp, flag); 1051 1052 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1053 } 1054 1055 void btsnd_hcic_write_pagescan_cfg(uint16_t interval, uint16_t window) { 1056 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1057 uint8_t* pp = (uint8_t*)(p + 1); 1058 1059 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PAGESCAN_CFG; 1060 p->offset = 0; 1061 1062 UINT16_TO_STREAM(pp, HCI_WRITE_PAGESCAN_CFG); 1063 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PAGESCAN_CFG); 1064 1065 UINT16_TO_STREAM(pp, interval); 1066 UINT16_TO_STREAM(pp, window); 1067 1068 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1069 } 1070 1071 void btsnd_hcic_write_inqscan_cfg(uint16_t interval, uint16_t window) { 1072 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1073 uint8_t* pp = (uint8_t*)(p + 1); 1074 1075 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_INQSCAN_CFG; 1076 p->offset = 0; 1077 1078 UINT16_TO_STREAM(pp, HCI_WRITE_INQUIRYSCAN_CFG); 1079 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_INQSCAN_CFG); 1080 1081 UINT16_TO_STREAM(pp, interval); 1082 UINT16_TO_STREAM(pp, window); 1083 1084 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1085 } 1086 1087 void btsnd_hcic_write_auth_enable(uint8_t flag) { 1088 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1089 uint8_t* pp = (uint8_t*)(p + 1); 1090 1091 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1; 1092 p->offset = 0; 1093 1094 UINT16_TO_STREAM(pp, HCI_WRITE_AUTHENTICATION_ENABLE); 1095 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1); 1096 1097 UINT8_TO_STREAM(pp, flag); 1098 1099 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1100 } 1101 1102 void btsnd_hcic_write_dev_class(DEV_CLASS dev_class) { 1103 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1104 uint8_t* pp = (uint8_t*)(p + 1); 1105 1106 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM3; 1107 p->offset = 0; 1108 1109 UINT16_TO_STREAM(pp, HCI_WRITE_CLASS_OF_DEVICE); 1110 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM3); 1111 1112 DEVCLASS_TO_STREAM(pp, dev_class); 1113 1114 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1115 } 1116 1117 void btsnd_hcic_write_voice_settings(uint16_t flags) { 1118 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1119 uint8_t* pp = (uint8_t*)(p + 1); 1120 1121 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM2; 1122 p->offset = 0; 1123 1124 UINT16_TO_STREAM(pp, HCI_WRITE_VOICE_SETTINGS); 1125 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM2); 1126 1127 UINT16_TO_STREAM(pp, flags); 1128 1129 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1130 } 1131 1132 void btsnd_hcic_write_auto_flush_tout(uint16_t handle, uint16_t tout) { 1133 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1134 uint8_t* pp = (uint8_t*)(p + 1); 1135 1136 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_AUTOMATIC_FLUSH_TIMEOUT; 1137 p->offset = 0; 1138 1139 UINT16_TO_STREAM(pp, HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT); 1140 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_AUTOMATIC_FLUSH_TIMEOUT); 1141 1142 UINT16_TO_STREAM(pp, handle); 1143 UINT16_TO_STREAM(pp, tout); 1144 1145 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1146 } 1147 1148 void btsnd_hcic_read_tx_power(uint16_t handle, uint8_t type) { 1149 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1150 uint8_t* pp = (uint8_t*)(p + 1); 1151 1152 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_TX_POWER; 1153 p->offset = 0; 1154 1155 UINT16_TO_STREAM(pp, HCI_READ_TRANSMIT_POWER_LEVEL); 1156 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_TX_POWER); 1157 1158 UINT16_TO_STREAM(pp, handle); 1159 UINT8_TO_STREAM(pp, type); 1160 1161 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1162 } 1163 1164 void btsnd_hcic_write_link_super_tout(uint16_t handle, uint16_t timeout) { 1165 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1166 uint8_t* pp = (uint8_t*)(p + 1); 1167 1168 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_LINK_SUPER_TOUT; 1169 p->offset = 0; 1170 1171 UINT16_TO_STREAM(pp, HCI_WRITE_LINK_SUPER_TOUT); 1172 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_LINK_SUPER_TOUT); 1173 1174 UINT16_TO_STREAM(pp, handle); 1175 UINT16_TO_STREAM(pp, timeout); 1176 1177 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1178 } 1179 1180 void btsnd_hcic_write_cur_iac_lap(uint8_t num_cur_iac, LAP* const iac_lap) { 1181 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1182 uint8_t* pp = (uint8_t*)(p + 1); 1183 1184 p->len = HCIC_PREAMBLE_SIZE + 1 + (LAP_LEN * num_cur_iac); 1185 p->offset = 0; 1186 1187 UINT16_TO_STREAM(pp, HCI_WRITE_CURRENT_IAC_LAP); 1188 UINT8_TO_STREAM(pp, p->len - HCIC_PREAMBLE_SIZE); 1189 1190 UINT8_TO_STREAM(pp, num_cur_iac); 1191 1192 for (int i = 0; i < num_cur_iac; i++) LAP_TO_STREAM(pp, iac_lap[i]); 1193 1194 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1195 } 1196 1197 /****************************************** 1198 * Lisbon Features 1199 ******************************************/ 1200 void btsnd_hcic_sniff_sub_rate(uint16_t handle, uint16_t max_lat, 1201 uint16_t min_remote_lat, 1202 uint16_t min_local_lat) { 1203 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1204 uint8_t* pp = (uint8_t*)(p + 1); 1205 1206 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_SNIFF_SUB_RATE; 1207 p->offset = 0; 1208 1209 UINT16_TO_STREAM(pp, HCI_SNIFF_SUB_RATE); 1210 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SNIFF_SUB_RATE); 1211 1212 UINT16_TO_STREAM(pp, handle); 1213 UINT16_TO_STREAM(pp, max_lat); 1214 UINT16_TO_STREAM(pp, min_remote_lat); 1215 UINT16_TO_STREAM(pp, min_local_lat); 1216 1217 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1218 } 1219 1220 /**** Extended Inquiry Response Commands ****/ 1221 void btsnd_hcic_write_ext_inquiry_response(void* buffer, uint8_t fec_req) { 1222 BT_HDR* p = (BT_HDR*)buffer; 1223 uint8_t* pp = (uint8_t*)(p + 1); 1224 1225 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_EXT_INQ_RESP; 1226 p->offset = 0; 1227 1228 UINT16_TO_STREAM(pp, HCI_WRITE_EXT_INQ_RESPONSE); 1229 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_EXT_INQ_RESP); 1230 1231 UINT8_TO_STREAM(pp, fec_req); 1232 1233 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1234 } 1235 1236 void btsnd_hcic_io_cap_req_reply(const RawAddress& bd_addr, uint8_t capability, 1237 uint8_t oob_present, uint8_t auth_req) { 1238 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1239 uint8_t* pp = (uint8_t*)(p + 1); 1240 1241 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_IO_CAP_RESP; 1242 p->offset = 0; 1243 1244 UINT16_TO_STREAM(pp, HCI_IO_CAPABILITY_REQUEST_REPLY); 1245 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_IO_CAP_RESP); 1246 1247 BDADDR_TO_STREAM(pp, bd_addr); 1248 UINT8_TO_STREAM(pp, capability); 1249 UINT8_TO_STREAM(pp, oob_present); 1250 UINT8_TO_STREAM(pp, auth_req); 1251 1252 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1253 } 1254 1255 void btsnd_hcic_enhanced_set_up_synchronous_connection( 1256 uint16_t conn_handle, enh_esco_params_t* p_params) { 1257 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1258 uint8_t* pp = (uint8_t*)(p + 1); 1259 1260 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ENH_SET_ESCO_CONN; 1261 p->offset = 0; 1262 1263 UINT16_TO_STREAM(pp, HCI_ENH_SETUP_ESCO_CONNECTION); 1264 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ENH_SET_ESCO_CONN); 1265 1266 UINT16_TO_STREAM(pp, conn_handle); 1267 UINT32_TO_STREAM(pp, p_params->transmit_bandwidth); 1268 UINT32_TO_STREAM(pp, p_params->receive_bandwidth); 1269 UINT8_TO_STREAM(pp, p_params->transmit_coding_format.coding_format); 1270 UINT16_TO_STREAM(pp, p_params->transmit_coding_format.company_id); 1271 UINT16_TO_STREAM(pp, 1272 p_params->transmit_coding_format.vendor_specific_codec_id); 1273 UINT8_TO_STREAM(pp, p_params->receive_coding_format.coding_format); 1274 UINT16_TO_STREAM(pp, p_params->receive_coding_format.company_id); 1275 UINT16_TO_STREAM(pp, 1276 p_params->receive_coding_format.vendor_specific_codec_id); 1277 UINT16_TO_STREAM(pp, p_params->transmit_codec_frame_size); 1278 UINT16_TO_STREAM(pp, p_params->receive_codec_frame_size); 1279 UINT32_TO_STREAM(pp, p_params->input_bandwidth); 1280 UINT32_TO_STREAM(pp, p_params->output_bandwidth); 1281 UINT8_TO_STREAM(pp, p_params->input_coding_format.coding_format); 1282 UINT16_TO_STREAM(pp, p_params->input_coding_format.company_id); 1283 UINT16_TO_STREAM(pp, p_params->input_coding_format.vendor_specific_codec_id); 1284 UINT8_TO_STREAM(pp, p_params->output_coding_format.coding_format); 1285 UINT16_TO_STREAM(pp, p_params->output_coding_format.company_id); 1286 UINT16_TO_STREAM(pp, p_params->output_coding_format.vendor_specific_codec_id); 1287 UINT16_TO_STREAM(pp, p_params->input_coded_data_size); 1288 UINT16_TO_STREAM(pp, p_params->output_coded_data_size); 1289 UINT8_TO_STREAM(pp, p_params->input_pcm_data_format); 1290 UINT8_TO_STREAM(pp, p_params->output_pcm_data_format); 1291 UINT8_TO_STREAM(pp, p_params->input_pcm_payload_msb_position); 1292 UINT8_TO_STREAM(pp, p_params->output_pcm_payload_msb_position); 1293 UINT8_TO_STREAM(pp, p_params->input_data_path); 1294 UINT8_TO_STREAM(pp, p_params->output_data_path); 1295 UINT8_TO_STREAM(pp, p_params->input_transport_unit_size); 1296 UINT8_TO_STREAM(pp, p_params->output_transport_unit_size); 1297 UINT16_TO_STREAM(pp, p_params->max_latency_ms); 1298 UINT16_TO_STREAM(pp, p_params->packet_types); 1299 UINT8_TO_STREAM(pp, p_params->retransmission_effort); 1300 1301 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1302 } 1303 1304 void btsnd_hcic_enhanced_accept_synchronous_connection( 1305 const RawAddress& bd_addr, enh_esco_params_t* p_params) { 1306 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1307 uint8_t* pp = (uint8_t*)(p + 1); 1308 1309 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ENH_ACC_ESCO_CONN; 1310 p->offset = 0; 1311 1312 UINT16_TO_STREAM(pp, HCI_ENH_ACCEPT_ESCO_CONNECTION); 1313 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ENH_ACC_ESCO_CONN); 1314 1315 BDADDR_TO_STREAM(pp, bd_addr); 1316 UINT32_TO_STREAM(pp, p_params->transmit_bandwidth); 1317 UINT32_TO_STREAM(pp, p_params->receive_bandwidth); 1318 UINT8_TO_STREAM(pp, p_params->transmit_coding_format.coding_format); 1319 UINT16_TO_STREAM(pp, p_params->transmit_coding_format.company_id); 1320 UINT16_TO_STREAM(pp, 1321 p_params->transmit_coding_format.vendor_specific_codec_id); 1322 UINT8_TO_STREAM(pp, p_params->receive_coding_format.coding_format); 1323 UINT16_TO_STREAM(pp, p_params->receive_coding_format.company_id); 1324 UINT16_TO_STREAM(pp, 1325 p_params->receive_coding_format.vendor_specific_codec_id); 1326 UINT16_TO_STREAM(pp, p_params->transmit_codec_frame_size); 1327 UINT16_TO_STREAM(pp, p_params->receive_codec_frame_size); 1328 UINT32_TO_STREAM(pp, p_params->input_bandwidth); 1329 UINT32_TO_STREAM(pp, p_params->output_bandwidth); 1330 UINT8_TO_STREAM(pp, p_params->input_coding_format.coding_format); 1331 UINT16_TO_STREAM(pp, p_params->input_coding_format.company_id); 1332 UINT16_TO_STREAM(pp, p_params->input_coding_format.vendor_specific_codec_id); 1333 UINT8_TO_STREAM(pp, p_params->output_coding_format.coding_format); 1334 UINT16_TO_STREAM(pp, p_params->output_coding_format.company_id); 1335 UINT16_TO_STREAM(pp, p_params->output_coding_format.vendor_specific_codec_id); 1336 UINT16_TO_STREAM(pp, p_params->input_coded_data_size); 1337 UINT16_TO_STREAM(pp, p_params->output_coded_data_size); 1338 UINT8_TO_STREAM(pp, p_params->input_pcm_data_format); 1339 UINT8_TO_STREAM(pp, p_params->output_pcm_data_format); 1340 UINT8_TO_STREAM(pp, p_params->input_pcm_payload_msb_position); 1341 UINT8_TO_STREAM(pp, p_params->output_pcm_payload_msb_position); 1342 UINT8_TO_STREAM(pp, p_params->input_data_path); 1343 UINT8_TO_STREAM(pp, p_params->output_data_path); 1344 UINT8_TO_STREAM(pp, p_params->input_transport_unit_size); 1345 UINT8_TO_STREAM(pp, p_params->output_transport_unit_size); 1346 UINT16_TO_STREAM(pp, p_params->max_latency_ms); 1347 UINT16_TO_STREAM(pp, p_params->packet_types); 1348 UINT8_TO_STREAM(pp, p_params->retransmission_effort); 1349 1350 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1351 } 1352 1353 void btsnd_hcic_io_cap_req_neg_reply(const RawAddress& bd_addr, 1354 uint8_t err_code) { 1355 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1356 uint8_t* pp = (uint8_t*)(p + 1); 1357 1358 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_IO_CAP_NEG_REPLY; 1359 p->offset = 0; 1360 1361 UINT16_TO_STREAM(pp, HCI_IO_CAP_REQ_NEG_REPLY); 1362 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_IO_CAP_NEG_REPLY); 1363 1364 BDADDR_TO_STREAM(pp, bd_addr); 1365 UINT8_TO_STREAM(pp, err_code); 1366 1367 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1368 } 1369 1370 void btsnd_hcic_read_local_oob_data(void) { 1371 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1372 uint8_t* pp = (uint8_t*)(p + 1); 1373 1374 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_R_LOCAL_OOB; 1375 p->offset = 0; 1376 1377 UINT16_TO_STREAM(pp, HCI_READ_LOCAL_OOB_DATA); 1378 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_R_LOCAL_OOB); 1379 1380 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1381 } 1382 1383 void btsnd_hcic_read_local_oob_extended_data(void) { 1384 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1385 uint8_t* pp = (uint8_t*)(p + 1); 1386 1387 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_R_LOCAL_OOB_EXTENDED; 1388 p->offset = 0; 1389 1390 UINT16_TO_STREAM(pp, HCI_READ_LOCAL_OOB_EXTENDED_DATA); 1391 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_R_LOCAL_OOB_EXTENDED); 1392 1393 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1394 } 1395 1396 void btsnd_hcic_user_conf_reply(const RawAddress& bd_addr, bool is_yes) { 1397 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1398 uint8_t* pp = (uint8_t*)(p + 1); 1399 1400 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_UCONF_REPLY; 1401 p->offset = 0; 1402 1403 if (!is_yes) { 1404 /* Negative reply */ 1405 UINT16_TO_STREAM(pp, HCI_USER_CONF_VALUE_NEG_REPLY); 1406 } else { 1407 /* Confirmation */ 1408 UINT16_TO_STREAM(pp, HCI_USER_CONF_REQUEST_REPLY); 1409 } 1410 1411 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_UCONF_REPLY); 1412 1413 BDADDR_TO_STREAM(pp, bd_addr); 1414 1415 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1416 } 1417 1418 void btsnd_hcic_user_passkey_reply(const RawAddress& bd_addr, uint32_t value) { 1419 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1420 uint8_t* pp = (uint8_t*)(p + 1); 1421 1422 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_U_PKEY_REPLY; 1423 p->offset = 0; 1424 1425 UINT16_TO_STREAM(pp, HCI_USER_PASSKEY_REQ_REPLY); 1426 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_U_PKEY_REPLY); 1427 1428 BDADDR_TO_STREAM(pp, bd_addr); 1429 UINT32_TO_STREAM(pp, value); 1430 1431 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1432 } 1433 1434 void btsnd_hcic_user_passkey_neg_reply(const RawAddress& bd_addr) { 1435 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1436 uint8_t* pp = (uint8_t*)(p + 1); 1437 1438 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_U_PKEY_NEG_REPLY; 1439 p->offset = 0; 1440 1441 UINT16_TO_STREAM(pp, HCI_USER_PASSKEY_REQ_NEG_REPLY); 1442 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_U_PKEY_NEG_REPLY); 1443 1444 BDADDR_TO_STREAM(pp, bd_addr); 1445 1446 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1447 } 1448 1449 void btsnd_hcic_rem_oob_reply(const RawAddress& bd_addr, const Octet16& c, 1450 const Octet16& r) { 1451 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1452 uint8_t* pp = (uint8_t*)(p + 1); 1453 1454 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_REM_OOB_REPLY; 1455 p->offset = 0; 1456 1457 UINT16_TO_STREAM(pp, HCI_REM_OOB_DATA_REQ_REPLY); 1458 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_REM_OOB_REPLY); 1459 1460 BDADDR_TO_STREAM(pp, bd_addr); 1461 ARRAY16_TO_STREAM(pp, c.data()); 1462 ARRAY16_TO_STREAM(pp, r.data()); 1463 1464 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1465 } 1466 1467 void btsnd_hcic_rem_oob_neg_reply(const RawAddress& bd_addr) { 1468 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1469 uint8_t* pp = (uint8_t*)(p + 1); 1470 1471 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_REM_OOB_NEG_REPLY; 1472 p->offset = 0; 1473 1474 UINT16_TO_STREAM(pp, HCI_REM_OOB_DATA_REQ_NEG_REPLY); 1475 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_REM_OOB_NEG_REPLY); 1476 1477 BDADDR_TO_STREAM(pp, bd_addr); 1478 1479 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1480 } 1481 1482 /**** end of Simple Pairing Commands ****/ 1483 1484 /************************* 1485 * End of Lisbon Commands 1486 *************************/ 1487 1488 void btsnd_hcic_read_rssi(uint16_t handle) { 1489 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1490 uint8_t* pp = (uint8_t*)(p + 1); 1491 1492 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CMD_HANDLE; 1493 p->offset = 0; 1494 1495 UINT16_TO_STREAM(pp, HCI_READ_RSSI); 1496 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CMD_HANDLE); 1497 1498 UINT16_TO_STREAM(pp, handle); 1499 1500 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1501 } 1502 1503 static void read_encryption_key_size_complete( 1504 ReadEncKeySizeCb cb, uint8_t* return_parameters, 1505 uint16_t /* return_parameters_length */) { 1506 uint8_t status; 1507 uint16_t handle; 1508 uint8_t key_size; 1509 STREAM_TO_UINT8(status, return_parameters); 1510 STREAM_TO_UINT16(handle, return_parameters); 1511 STREAM_TO_UINT8(key_size, return_parameters); 1512 1513 std::move(cb).Run(status, handle, key_size); 1514 } 1515 1516 void btsnd_hcic_read_encryption_key_size(uint16_t handle, ReadEncKeySizeCb cb) { 1517 constexpr uint8_t len = 2; 1518 uint8_t param[len]; 1519 memset(param, 0, len); 1520 1521 uint8_t* p = param; 1522 UINT16_TO_STREAM(p, handle); 1523 1524 btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_READ_ENCR_KEY_SIZE, param, len, 1525 base::Bind(&read_encryption_key_size_complete, base::Passed(&cb))); 1526 } 1527 1528 void btsnd_hcic_read_failed_contact_counter(uint16_t handle) { 1529 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1530 uint8_t* pp = (uint8_t*)(p + 1); 1531 1532 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CMD_HANDLE; 1533 p->offset = 0; 1534 1535 UINT16_TO_STREAM(pp, HCI_READ_FAILED_CONTACT_COUNTER); 1536 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CMD_HANDLE); 1537 1538 UINT16_TO_STREAM(pp, handle); 1539 1540 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1541 } 1542 1543 void btsnd_hcic_enable_test_mode(void) { 1544 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1545 uint8_t* pp = (uint8_t*)(p + 1); 1546 1547 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD; 1548 p->offset = 0; 1549 1550 UINT16_TO_STREAM(pp, HCI_ENABLE_DEV_UNDER_TEST_MODE); 1551 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_CMD); 1552 1553 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1554 } 1555 1556 void btsnd_hcic_write_inqscan_type(uint8_t type) { 1557 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1558 uint8_t* pp = (uint8_t*)(p + 1); 1559 1560 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1; 1561 p->offset = 0; 1562 1563 UINT16_TO_STREAM(pp, HCI_WRITE_INQSCAN_TYPE); 1564 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1); 1565 1566 UINT8_TO_STREAM(pp, type); 1567 1568 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1569 } 1570 1571 void btsnd_hcic_write_inquiry_mode(uint8_t mode) { 1572 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1573 uint8_t* pp = (uint8_t*)(p + 1); 1574 1575 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1; 1576 p->offset = 0; 1577 1578 UINT16_TO_STREAM(pp, HCI_WRITE_INQUIRY_MODE); 1579 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1); 1580 1581 UINT8_TO_STREAM(pp, mode); 1582 1583 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1584 } 1585 1586 void btsnd_hcic_write_pagescan_type(uint8_t type) { 1587 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1588 uint8_t* pp = (uint8_t*)(p + 1); 1589 1590 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1; 1591 p->offset = 0; 1592 1593 UINT16_TO_STREAM(pp, HCI_WRITE_PAGESCAN_TYPE); 1594 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_WRITE_PARAM1); 1595 1596 UINT8_TO_STREAM(pp, type); 1597 1598 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1599 } 1600 1601 static void btsnd_hcic_vendor_spec_complete(tBTM_VSC_CMPL_CB* p_vsc_cplt_cback, 1602 uint16_t opcode, uint8_t* data, 1603 uint16_t len) { 1604 /* If there was a callback address for vcs complete, call it */ 1605 if (p_vsc_cplt_cback) { 1606 tBTM_VSC_CMPL vcs_cplt_params; 1607 vcs_cplt_params.opcode = opcode; 1608 vcs_cplt_params.param_len = len; 1609 vcs_cplt_params.p_param_buf = data; 1610 /* Call the VSC complete callback function */ 1611 (*p_vsc_cplt_cback)(&vcs_cplt_params); 1612 } 1613 } 1614 1615 void btsnd_hcic_vendor_spec_cmd(uint16_t opcode, uint8_t len, uint8_t* p_data, 1616 tBTM_VSC_CMPL_CB* p_cmd_cplt_cback) { 1617 uint16_t v_opcode = HCI_GRP_VENDOR_SPECIFIC | opcode; 1618 1619 btu_hcif_send_cmd_with_cb( 1620 FROM_HERE, v_opcode, p_data, len, 1621 base::BindOnce(&btsnd_hcic_vendor_spec_complete, 1622 base::Unretained(p_cmd_cplt_cback), v_opcode)); 1623 } 1624 1625 void btsnd_hcic_configure_data_path(hci_data_direction_t data_path_direction, 1626 uint8_t data_path_id, 1627 std::vector<uint8_t> vendor_config) { 1628 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1629 uint8_t* pp = (uint8_t*)(p + 1); 1630 uint8_t size = static_cast<uint8_t>(vendor_config.size()); 1631 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CONFIGURE_DATA_PATH + size; 1632 p->offset = 0; 1633 1634 UINT16_TO_STREAM(pp, HCI_CONFIGURE_DATA_PATH); 1635 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CONFIGURE_DATA_PATH + size); 1636 UINT8_TO_STREAM(pp, data_path_direction); 1637 UINT8_TO_STREAM(pp, data_path_id); 1638 UINT8_TO_STREAM(pp, vendor_config.size()); 1639 if (size != 0) { 1640 ARRAY_TO_STREAM(pp, vendor_config.data(), size); 1641 } 1642 1643 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1644 } 1645 1646 namespace bluetooth::legacy::hci { 1647 class InterfaceImpl : public Interface { 1648 void Disconnect(uint16_t handle, uint8_t reason) const override { 1649 btsnd_hcic_disconnect(handle, reason); 1650 } 1651 void ChangeConnectionPacketType(uint16_t handle, 1652 uint16_t packet_types) const override { 1653 btsnd_hcic_change_conn_type(handle, packet_types); 1654 } 1655 void StartRoleSwitch(const RawAddress& bd_addr, uint8_t role) const override { 1656 btsnd_hcic_switch_role(bd_addr, role); 1657 } 1658 void ConfigureDataPath(hci_data_direction_t data_path_direction, 1659 uint8_t data_path_id, 1660 std::vector<uint8_t> vendor_config) const override { 1661 btsnd_hcic_configure_data_path(data_path_direction, data_path_id, 1662 vendor_config); 1663 } 1664 void SendVendorSpecificCmd(unsigned short opcode, 1665 unsigned char len, unsigned char* param, void (*cb)(tBTM_VSC_CMPL*)) const override { 1666 btsnd_hcic_vendor_spec_cmd(opcode, len, param, cb); 1667 } 1668 }; 1669 1670 namespace { 1671 const InterfaceImpl interface_; 1672 } 1673 1674 const Interface& GetInterface() { return interface_; } 1675 } // namespace bluetooth::legacy::hci 1676 1677 void btsnd_hcic_flow_spec(uint16_t handle, uint8_t unused, uint8_t direction, 1678 uint8_t service_type, uint32_t token_rate, 1679 uint32_t token_size, uint32_t peak, uint32_t latency){ 1680 1681 BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE); 1682 uint8_t* pp = (uint8_t*)(p + 1); 1683 1684 p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_FLOW_SPECIFICATION; 1685 p->offset = 0; 1686 1687 UINT16_TO_STREAM(pp, HCI_FLOW_SPECIFICATION); 1688 UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_FLOW_SPECIFICATION); 1689 1690 UINT16_TO_STREAM(pp, handle); 1691 UINT8_TO_STREAM(pp, unused); 1692 UINT8_TO_STREAM(pp, direction); 1693 UINT8_TO_STREAM(pp, service_type); 1694 UINT32_TO_STREAM(pp, token_rate); 1695 UINT32_TO_STREAM(pp, token_size); 1696 UINT32_TO_STREAM(pp, peak); 1697 UINT32_TO_STREAM(pp, latency); 1698 1699 btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); 1700 }
07-18
本项目构建于RASA开源架构之上,旨在实现一个具备多模态交互能力的智能对话系统。该系统的核心模块涵盖自然语言理解、语音转文本处理以及动态对话流程控制三个主要方面。 在自然语言理解层面,研究重点集中于增强连续对话中的用户目标判定效能,并运用深度神经网络技术提升关键信息提取的精确度。目标判定旨在解析用户话语背后的真实需求,从而生成恰当的反馈;信息提取则专注于从语音输入中析出具有特定意义的要素,例如个体名称、空间位置或时间节点等具体参数。深度神经网络的应用显著优化了这些功能的实现效果,相比经典算法,其能够解析更为复杂的语言结构,展现出更优的识别精度与更强的适应性。通过分层特征学习机制,这类模型可深入捕捉语言数据中隐含的语义关联。 语音转文本处理模块承担将音频信号转化为结构化文本的关键任务。该技术的持续演进大幅提高了人机语音交互的自然度与流畅性,使语音界面日益成为高效便捷的沟通渠道。 动态对话流程控制系统负责维持交互过程的连贯性与逻辑性,包括话轮转换、上下文关联维护以及基于情境的决策生成。该系统需具备处理各类非常规输入的能力,例如用户使用非规范表达或对系统指引产生歧义的情况。 本系统适用于多种实际应用场景,如客户服务支持、个性化事务协助及智能教学辅导等。通过准确识别用户需求并提供对应信息或操作响应,系统能够创造连贯顺畅的交互体验。借助深度学习的自适应特性,系统还可持续优化语言模式理解能力,逐步完善对新兴表达方式与用户偏好的适应机制。 在技术实施方面,RASA框架为系统开发提供了基础支撑。该框架专为构建对话式人工智能应用而设计,支持多语言环境并拥有活跃的技术社区。利用其内置工具集,开发者可高效实现复杂的对话逻辑设计与部署流程。 配套资料可能包含补充学习文档、实例分析报告或实践指导手册,有助于使用者深入掌握系统原理与应用方法。技术文档则详细说明了系统的安装步骤、参数配置及操作流程,确保用户能够顺利完成系统集成工作。项目主体代码及说明文件均存放于指定目录中,构成完整的解决方案体系。 总体而言,本项目整合了自然语言理解、语音信号处理与深度学习技术,致力于打造能够进行复杂对话管理、精准需求解析与高效信息提取的智能语音交互平台。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值