当前位置:首页>Linux>Linux内核HDA JACK检测流程深度分析

Linux内核HDA JACK检测流程深度分析

  • 2026-08-18 23:11:11
Linux内核HDA JACK检测流程深度分析

一、概述:什么是JACK SENSE

JACK SENSE(插孔检测)是HDA(High Definition Audio)音频子系统中的核心机制,用于实时检测音频插孔上设备的插拔状态。当用户插入或拔出耳机、麦克风等设备时,系统需要:

  • 检测到插拔事件
  • 自动切换音频输出路径(如插入耳机时自动静音扬声器)
  • 自动切换音频输入路径(如插入外接麦克风时自动切换输入源)
  • 向用户空间报告插孔状态变化

整个流程从硬件中断开始,经过内核多层级处理,最终到达用户空间,涉及HDA Controller、HDA Codec、ALSA Core三个主要层次。

二、HDA架构与JACK检测的硬件基础

2.1 HDA总线架构

HDA(High Definition Audio)采用Controller-Codec架构:

  • HDA Controller
    :PCI设备,负责与CPU交互,管理CORB(Command Output Ring Buffer)和RIRB(Response Input Ring Buffer)通信
  • HDA Codec
    :挂载在HDA总线上的编解码芯片,包含多个Widget(Pin Complex、DAC、ADC、Mixer等)

2.2 JACK SENSE的硬件实现

在HDA规范中,每个Pin Complex Widget可以支持Presence Detection(存在检测)。当插孔状态变化时:

  1. Codec芯片的JSENSE管脚检测到阻抗变化
  2. Codec通过HDA总线向Controller发送Unsolicited Response(主动上报响应)
  3. Controller将响应写入RIRB缓冲区
  4. Controller触发硬件中断

关键前提:Pin Widget必须通过AC_VERB_SET_UNSOLICITED_ENABLEVerb启用Unsolicited Response上报功能,并分配一个tag值用于标识事件来源。

三、JACK检测全流程总览

硬件层

插拔设备 → JSENSE管脚电平变化 → Codec发送Unsolicited ResponseController中断

azx_interrupt→ snd_hdac_bus_update_rirb事件入队

snd_hdac_bus_queue_event → 写入unsol_queue → schedule_work工作队列

snd_hdac_bus_process_unsol_events → 查找codec → drv->unsol_eventCodec驱动层

hda_codec_unsol_event → ops->unsol_event即 snd_hda_jack_unsol_eventJACK核心层

提取tag → 查找jack_tbl → 标记dirty → call_jack_callback回调执行

hp_automute / line_automute / mic_autoswitch状态上报

snd_hda_jack_report_sync() → snd_jack_report() → input子系统 + ALSA kcontrol

四、阶段一:硬件中断触发

4.1 中断处理函数 azx_interrupt()

当HDA Controller接收到Codec的响应后,触发硬件中断。中断处理函数读取中断状态寄存器和RIRB状态寄存器:

irqreturn_t azx_interrupt(int irq, void *dev_id){    ...do {        status = azx_readl(chip, INTSTS);    // 读取中断状态if (status == 0 || status == 0xffffffff)break;if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update))            active = true;        status = azx_readb(chip, RIRBSTS);   // 读取RIRB状态if (status & RIRB_INT_MASK) {            azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); // 清除中断if (status & RIRB_INT_RESPONSE) {snd_hdac_bus_update_rirb(bus);  // 处理RIRB响应            }        }    } while (active && ++repeat < 10);return IRQ_RETVAL(handled);}

要点:中断处理函数在中断上下文中执行,只做最基础的寄存器读取和RIRB处理,将耗时的回调处理延迟到工作队列中异步执行。

五、阶段二:RIRB响应处理与事件入队

5.1 从RIRB读取响应 snd_hdac_bus_update_rirb()

RIRB(Response Input Ring Buffer)是HDA Controller维护的环形缓冲区,存储Codec的响应。每个RIRB条目为8字节:低32位为响应数据res,高32位为扩展信息res_ex

#define AZX_RIRB_EX_UNSOL_EV  (1<<4)voidsnd_hdac_bus_update_rirb(struct hdac_bus *bus){    ...while (bus->rirb.rp != wp) {        ...        res_ex = le32_to_cpu(bus->rirb.buf[rp + 1]);        res = le32_to_cpu(bus->rirb.buf[rp]);        addr = res_ex & 0xf;     // 低4位为Codec地址if (res_ex & AZX_RIRB_EX_UNSOL_EV)   // bit4: 主动事件标志snd_hdac_bus_queue_event(bus, res, res_ex);else if (bus->rirb.cmds[addr]) {            bus->rirb.res[addr] = res;      // 普通命令响应            bus->rirb.cmds[addr]--;        }    }}

res_ex & AZX_RIRB_EX_UNSOL_EV用于区分Unsolicited Response(主动上报事件)和普通命令响应。JACK检测事件走的是Unsolicited Response路径

5.2 事件入队 snd_hdac_bus_queue_event()

voidsnd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex){    ...    wp = (bus->unsol_wp + 1) % HDA_UNSOL_QUEUE_SIZE;    bus->unsol_wp = wp;    wp <<= 1;    bus->unsol_queue[wp] = res;       // 写入响应数据    bus->unsol_queue[wp + 1] = res_ex; // 写入扩展信息    schedule_work(&bus->unsol_work);  // 调度工作队列}

事件被写入unsol_queue环形缓冲区后,通过schedule_work()调度工作队列异步处理。这个工作队列在snd_hdac_bus_init()中初始化:

INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events);

六、阶段三:工作队列异步处理

snd_hdac_bus_process_unsol_events()

工作队列在进程上下文中执行,从环形缓冲区逐个取出Unsolicited Event,根据Codec地址找到对应的Codec驱动,调用其unsol_event回调:

static voidsnd_hdac_bus_process_unsol_events(struct work_struct *work){    struct hdac_bus *bus = container_of(work, struct hdac_bus, unsol_work);    ...    spin_lock_irq(&bus->reg_lock);while (bus->unsol_rp != bus->unsol_wp) {        ...        res = bus->unsol_queue[rp];        caddr = bus->unsol_queue[rp + 1];if (!(caddr & (1 << 4)))   // 非unsol事件,跳过continue;        codec = bus->caddr_tbl[caddr & 0x0f]; // 通过Codec地址查找        ...        spin_unlock_irq(&bus->reg_lock);if (drv->unsol_event)            drv->unsol_event(codec, res);  // 调用Codec驱动回调        spin_lock_irq(&bus->reg_lock);    }    spin_unlock_irq(&bus->reg_lock);}

设计要点:中断上下文只做最小工作(读取RIRB、入队),耗时的回调处理在workqueue的进程上下文中完成。这遵循了Linux内核中断处理的"顶半部/底半部"设计原则。

七、阶段四:Codec驱动层事件分发

7.1 hdac_driver层回调 hda_codec_unsol_event()

hdac_driver.unsol_event的实现在Codec驱动注册时被设置:

int__hda_codec_driver_register(struct hda_codec_driver *drv, ...){    ...    drv->core.unsol_event = hda_codec_unsol_event;  // 注册回调return driver_register(&drv->core.driver);}

该回调将事件从hdac_device层转换到hda_codec_ops层:

static voidhda_codec_unsol_event(struct hdac_device *dev, unsigned int ev){    struct hda_codec *codec = container_of(dev, struct hda_codec, core);    ...if (codec->card->shutdown || codec->bus->shutdown)return;if (codec->core.dev.power.power_state.event != PM_EVENT_ON)return;if (driver->ops->unsol_event)        driver->ops->unsol_event(codec, ev);  // 调用具体Codec的ops}

7.2 具体Codec驱动注册unsol_event

各Codec驱动(Realtek、Conexant、Generic等)都在其hda_codec_ops中注册.unsol_event = snd_hda_jack_unsol_event

static const struct hda_codec_ops generic_codec_ops = {    ...    .unsol_event = snd_hda_jack_unsol_event,  // 统一入口    ...};

统一入口:几乎所有HDA Codec驱动都将snd_hda_jack_unsol_event 作为unsol_event的处理入口,这体现了HDA JACK检测框架的通用性设计。

八、阶段五:JACK核心层处理

8.1 snd_hda_jack_unsol_event() - JACK事件核心处理

这是JACK检测的核心处理函数,负责从Unsolicited Response中提取tag,查找对应的jack表项,标记脏数据,执行回调链,最后同步上报状态:

voidsnd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res){    struct hda_jack_tbl *event;int tag = (res & AC_UNSOL_RES_TAG) >> AC_UNSOL_RES_TAG_SHIFT;    event = snd_hda_jack_tbl_get_from_tag(codec, tag, 0);if (!event)return;    event->jack_dirty = 1;              // 标记需要更新call_jack_callback(codec, res, event); // 执行回调链snd_hda_jack_report_sync(codec);       // 同步上报状态}

8.2 call_jack_callback() - 遍历执行回调链

每个jack表项维护一个回调链表,当事件发生时依次执行所有注册的回调:

static voidcall_jack_callback(struct hda_codec *codec, unsigned int res,                   struct hda_jack_tbl *jack){    struct hda_jack_callback *cb;for (cb = jack->callback; cb; cb = cb->next) {        cb->jack = jack;        cb->unsol_res = res;        cb->func(codec, cb);           // 执行回调函数    }if (jack->gated_jack) {            // 处理gated jack        ...    }}

8.3 jack_detect_update() - 读取Pin Sense状态

在状态上报前,需要通过jack_detect_update()读取Pin Widget的实际检测状态:

#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)static voidjack_detect_update(struct hda_codec *codec,                   struct hda_jack_tbl *jack){if (!jack->jack_dirty)return;if (jack->phantom_jack)        jack->pin_sense = AC_PINSENSE_PRESENCE;  // 虚拟jack始终在位else        jack->pin_sense = read_pin_sense(codec, jack->nid, jack->dev_id);// gating jack: 如果gating jack未插入,则gated jack无效if (jack->gating_jack &&        !snd_hda_jack_detect_mst(codec, jack->gating_jack, jack->dev_id))        jack->pin_sense &= ~AC_PINSENSE_PRESENCE;    jack->jack_dirty = 0;    ...}

8.4 read_pin_sense() - 执行Pin Sense Verb

该函数通过发送HDA Verb读取Pin Widget的检测状态:

static u32read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id){    u32 pincap, val;if (!codec->no_trigger_sense) {        pincap = snd_hda_query_pin_caps(codec, nid);if (pincap & AC_PINCAP_TRIG_REQ)  // 需要触发?            snd_hda_codec_read(codec, nid, 0,                    AC_VERB_SET_PIN_SENSE, 0); // 先触发    }    val = snd_hda_codec_read(codec, nid, 0,                  AC_VERB_GET_PIN_SENSE, dev_id); // 读取状态if (codec->inv_jack_detect)        val ^= AC_PINSENSE_PRESENCE;     // 反转检测逻辑    ...return val;}

九、阶段六:回调函数执行(自动静音/自动切换)

JACK检测的回调函数主要实现三大自动切换功能:

9.1 耳机自动静音 snd_hda_gen_hp_automute()

当检测到耳机插入时,自动静音扬声器;拔出时恢复扬声器输出:

voidsnd_hda_gen_hp_automute(struct hda_codec *codec,                 struct hda_jack_callback *jack){    ...    spec->hp_jack_present = detect_jacks(codec, num_pins, pins);if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))return;call_update_outputs(codec);  // 更新输出路径}

9.2 Line-out自动静音 snd_hda_gen_line_automute()

voidsnd_hda_gen_line_automute(struct hda_codec *codec,                   struct hda_jack_callback *jack){    ...    spec->line_jack_present = detect_jacks(...);if (!spec->automute_speaker || !spec->detect_lo)return;    call_update_outputs(codec);}

9.3 Mic自动切换 snd_hda_gen_mic_autoswitch()

当检测到外接麦克风插入时,自动将输入源切换到外接麦克风;拔出时切回内置麦克风:

voidsnd_hda_gen_mic_autoswitch(struct hda_codec *codec,                struct hda_jack_callback *jack){    ...// 优先级从高到低检查,找到第一个在位的micfor (i = spec->am_num_entries - 1; i > 0; i--) {if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {mux_select(codec, 0, spec->am_entry[i].idx);return;        }    }    mux_select(codec, 0, spec->am_entry[0].idx); // 默认选择内置mic}

十、阶段七:JACK状态上报

10.1 snd_hda_jack_report_sync() - 同步上报所有JACK状态

voidsnd_hda_jack_report_sync(struct hda_codec *codec){    ...// 第一步:更新所有jack的检测状态for (i = 0; i < codec->jacktbl.used; i++, jack++)if (jack->nid)            jack_detect_update(codec, jack);// 第二步:上报状态变化for (i = 0; i < codec->jacktbl.used; i++, jack++)if (jack->nid) {            ...snd_jack_report(jack->jack, state);  // 上报        }}

10.2 snd_jack_report() - 向用户空间报告

该函数通过两条路径向用户空间报告JACK状态:

voidsnd_jack_report(struct snd_jack *jack, int status){    ...// 路径1:更新ALSA kcontrol状态    list_for_each_entry(jack_kctl, &jack->kctl_list, list)        snd_kctl_jack_report(jack->card, jack_kctl->kctl,                     status & jack_kctl->mask_bits);// 路径2:通过input子系统上报for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {if (jack->type & testbit)            input_report_switch(idev, jack_switch_types[i], status & testbit);    }    input_sync(idev);    // 同步input事件}

双路径上报:JACK状态通过两条路径到达用户空间:1.ALSA kcontrol:用户空间可通过/dev/snd/controlc0的ioctl读取jack状态2.Linux input子系统:用户空间PulseAudio通过/dev/input/eventX监听SW_HEADPHONE_INSERT等switch事件

十一、回调注册机制详解

11.1 snd_hda_jack_detect_enable_callback_mst() - 启用JACK检测并注册回调

该函数是JACK检测的注册入口,完成两件事:创建jack表项并注册回调,通过Verb启用Pin的Unsolicited Response上报:

struct hda_jack_callback *snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,int dev_id, hda_jack_callback_fn func){    ...    jack = snd_hda_jack_tbl_new(codec, nid, dev_id); // 创建/获取jack表项if (func && !callback) {        callback->func = func;        callback->next = jack->callback;  // 头插法加入回调链        jack->callback = callback;    }if (jack->jack_detect)return callback;   // 已注册过    jack->jack_detect = 1;if (codec->jackpoll_interval > 0)return callback;   // 轮询模式不需要unsol// 发送Verb启用Unsolicited Response    snd_hda_codec_write_cache(codec, nid, 0,                     AC_VERB_SET_UNSOLICITED_ENABLE,                     AC_USRSP_EN | jack->tag);return callback;}

11.2 check_auto_mute_availability() - 注册HP/Line-out自动静音回调

Codec初始化snd_hda_gen_init()会调用check_auto_mute_availability(),为每个可检测的HP Pin和Line-out Pin注册自动静音回调:

static intcheck_auto_mute_availability(struct hda_codec *codec){    ...// 为每个HP pin注册 call_hp_automute 回调for (i = 0; i < cfg->hp_outs; i++) {if (!is_jack_detectable(codec, nid))continue;        snd_hda_jack_detect_enable_callback(codec, nid, call_hp_automute);        spec->detect_hp = 1;    }// 为每个Line-out pin注册 call_line_automute 回调for (i = 0; i < cfg->line_outs; i++) {if (!is_jack_detectable(codec, nid))continue;        snd_hda_jack_detect_enable_callback(codec, nid, call_line_automute);        spec->detect_lo = 1;    }    ...}

11.3 check_auto_mic_availability() - 注册Mic自动切换回调

static boolauto_mic_check_imux(struct hda_codec *codec){    ...// 第一个pin不需要jack检测(默认输入源)// 从第二个pin开始注册 call_mic_autoswitch 回调for (i = 1; i < spec->am_num_entries; i++)        snd_hda_jack_detect_enable_callback(codec,                            spec->am_entry[i].pin,call_mic_autoswitch);return true;}

11.4 is_jack_detectable() - 判断Pin是否支持JACK检测

并非所有Pin都支持JACK检测,需要满足以下条件:

boolis_jack_detectable(struct hda_codec *codec, hda_nid_t nid){if (codec->no_jack_detect)           // 全局禁用return false;if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))return false;                      // 不支持Presence Detectif (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &         AC_DEFCFG_MISC_NO_PRESENCE)return false;                      // Pin配置标记为无检测if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) &&        !codec->jackpoll_interval)return false;                      // 不支持Unsolicited且无轮询return true;}

十二、轮询模式:Jack Polling

当Codec不支持Unsolicited Response,或jackpoll_interval被设置为非零值时,系统使用轮询模式检测JACK状态:

static voidhda_jackpoll_work(struct work_struct *work){    ...if (!codec->jackpoll_interval)return;    snd_hda_jack_set_dirty_all(codec);       // 标记所有jack为dirty    snd_hda_jack_poll_all(codec);            // 轮询所有jack    schedule_delayed_work(&codec->jackpoll_work,                  codec->jackpoll_interval); // 重新调度}

snd_hda_jack_poll_all()的实现:

voidsnd_hda_jack_poll_all(struct hda_codec *codec){    ...for (i = 0; i < codec->jacktbl.used; i++, jack++) {        old_sense = get_jack_plug_state(jack->pin_sense);        jack_detect_update(codec, jack);if (old_sense == get_jack_plug_state(jack->pin_sense))continue;              // 状态未变,跳过        changes = 1;        call_jack_callback(codec, 0, jack);    }if (changes)        snd_hda_jack_report_sync(codec);}

注意:参考文档指出,在实际运行中jackpoll_interval通常为0,因此轮询模式不会实际执行。JACK检测主要依赖Unsolicited Response中断方式。轮询模式主要用于不支持Unsolicited Response的Codec或调试场景。

十三、Unsolicited Response解析

13.1 ftrace跟踪Unsolicited Event

插拔耳机时,可通过ftrace观察到Unsolicited Event:

root@E490-2:/sys/kernel/debug/tracing# cat trace<idle>-0  [007] d.h. 60822.084078: hda_unsol_event: [0000:00:1f.3:0] res=0x04000000, res_ex=0x00000010<idle>-0  [007] d.h. 60822.624109: hda_unsol_event: [0000:00:1f.3:0] res=0x08000000, res_ex=0x00000010

13.2 res字段解析

根据HDA规范(7.3.3.14 Unsolicited Response),res字段的格式为:

位域
含义
示例值
[31:26]
Tag(事件标签)
0x04000000的tag=1, 0x08000000的tag=2
[25:0]
事件相关数据
通常为0

Tag值与Pin NID的对应关系可通过/proc/asound/card0/codec#0查看:

Node 0x16 [Pin Complex] wcaps 0x400581: Stereo  Pincap 0x0001001c: OUT HP EAPD Detect  Pin Default 0x03211040: [Jack] HP Out at Ext Left  Unsolicited: tag=01, enabled=1    // tag=1 对应 0x16 (耳机)Node 0x19 [Pin Complex] wcaps 0x40048b: Stereo Amp-In  Pincap 0x00001324: IN Detect  Pin Default 0x03a11030: [Jack] Mic at Ext Left  Unsolicited: tag=02, enabled=1    // tag=2 对应 0x19 (麦克风)

结论:插拔耳机孔时,JSENSE管脚产生中断,Codec向Controller发送Node 0x16(耳机)和0x19(麦克风)的Unsolicited Response事件。tag=1对应耳机,tag=2对应麦克风。

13.3 tag分配机制

tag在snd_hda_jack_tbl_new()中分配,值为jack表项在数组中的索引:

static struct hda_jack_tbl *snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid, int dev_id){    ...    jack = snd_array_new(&codec->jacktbl);    jack->nid = nid;    jack->jack_dirty = 1;if (existing_nid_jack) {        jack->tag = existing_nid_jack->tag;    } else {        jack->tag = codec->jacktbl.used;  // tag = 数组索引    }return jack;}

十四、关键数据结构

14.1 hda_jack_tbl - JACK表项

struct hda_jack_tbl {    hda_nid_t nid;              // Pin Widget的NIDint dev_id;                  // 设备ID(DP MST用)    unsigned char tag;          // Unsolicited Response的tag    struct hda_jack_callback *callback;  // 回调链表头    unsigned int pin_sense;     // 缓存的Pin Sense值    unsigned int jack_detect:1; // 是否已启用JACK检测    unsigned int jack_dirty:1;  // 是否需要更新    unsigned int phantom_jack:1;// 虚拟jack(固定在位)    unsigned int block_report:1;// 是否阻止上报    hda_nid_t gating_jack;     // gating jack的NID    hda_nid_t gated_jack;      // gated jack的NID    hda_nid_t key_report_jack; // 按键事件上报的jack NIDint type;                    // JACK类型(HEADPHONE/MICROPHONE等)int button_state;            // 按键状态    struct snd_jack *jack;      // ALSA jack对象};

14.2 hda_jack_callback - 回调函数

struct hda_jack_callback {    hda_nid_t nid;              // 关联的Pin NIDint dev_id;                  // 设备ID    hda_jack_callback_fn func;  // 回调函数指针    unsigned int private_data;  // 私有数据    unsigned int unsol_res;     // Unsolicited Response数据    struct hda_jack_tbl *jack;  // 关联的jack表项    struct hda_jack_callback *next; // 链表下一个节点};

14.3 snd_jack - ALSA JACK对象

struct snd_jack {    struct list_head kctl_list; // kcontrol链表    struct snd_card *card;      // 所属声卡    const char *id;             // jack标识    struct input_dev *input_dev;// input设备(向用户空间报告)int type;                    // jack类型位掩码int hw_status_cache;        // 硬件状态缓存void *private_data;         // 私有数据(指向hda_jack_tbl)void (*private_free)(struct snd_jack *); // 释放回调};

14.4 hdac_bus中Unsolicited Event相关字段

struct hdac_bus {    ...    u32 unsol_queue[HDA_UNSOL_QUEUE_SIZE * 2]; // 环形缓冲区    unsigned int unsol_rp, unsol_wp;            // 读写指针    struct work_struct unsol_work;              // 工作队列项    ...};

十五、案例分析

1. CX11880重启后耳机类型识别失败

飞腾FT2000平台搭配Conexant CX11880/SN6140 Codec的机器,系统reboot后插入4段耳机,系统无法正确识别CTIA/OMTP类型,导致耳机麦克风不工作。冷启动不受影响,仅重启后出现。

受影响硬件:飞腾FT2000 + CX11880/SN6140 Codec,涉及BXC T350、NZ269等机型

根因

CX11880/SN6140的CTIA/OMTP检测依赖两个vendor寄存器:0x4f0(耳机检测使能)和0x3b0(DFET OFF电压和micbias电阻)。reboot过程中Codec不断电但vendor寄存器恢复默认值,DFET OFF电压从-0.8V回到-1.2V,micbias电阻从2.0K回到2.2K,导致CTIA/OMTP检测阈值偏移。

修复

static voidcx_fixup_headset_recog(struct hda_codec *codec){    unsigned int mic_persent;    snd_hda_codec_write(codec, 0x1c, 0, 0x4f0, 0x087);  // 使能耳机检测    snd_hda_codec_write(codec, 0x1c, 0, 0x3b0, 0xe10);  // DFET=-0.8V, micbias=2.0K    mic_persent = snd_hda_codec_read(codec, 0x19, 0, AC_VERB_GET_PIN_SENSE, 0x0);if (mic_persent & AC_PINSENSE_PRESENCE)        snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24);else        snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20);}

T350机型因硬件时序问题需延迟1500ms执行:

if (codec->core.subsystem_id == SUBSYS_ID_T350)    schedule_delayed_work(&spec->fixup_hp_recog_work, msecs_to_jiffies(1500));else    cx_fixup_headset_recog(codec);

修复原理:通过vendor verb重新配置DFET电压和micbias电阻,使CTIA/OMTP检测阈值回到正确范围。VREF根据mic在位状态动态设置。

2. CX11880耳机麦克风VREF切换导致录音静音

Bug现象

飞腾平台+CX11880/SN6140,插入4段耳机后开启录音,耳机麦克风无声音。拔出耳机后内置麦克风正常。涉及BXC NZ307C、NZ291B、NZ300、MF292B等多款机型。

根因

两个相互关联的问题:

  1. VREF与录音状态耦合
    cx_update_headset_mic_vref()在unsol回调中根据capture_pcm_state决定VREF值——录音未启动时VREF=0x20(无偏置),mic无供电而静音。
  2. ADC增益被清零
    VREF切换过程中ADC增益/boost被意外清零,需要延迟恢复。

修复

修复一:CTIA/OMTP检测完成后,根据录音状态动态切换VREF:

if (val & 0x800) {       // CTIAif (spec->capture_pcm_state == PCM_ACT_PREPARED)        snd_hda_codec_write(codec, 0x19, 0, 0x707, 0x24); // VREF+INelse        snd_hda_codec_write(codec, 0x19, 0, 0x707, 0x20); // IN only}

修复二:录音PCM prepare时先静音ADC,延迟500ms后恢复增益:

static intcxt_capture_pcm_prepare(...){// 先静音ADC(设置bit7)    snd_hda_codec_write(codec, nid, 0, (0x370 | idx), (value | 0x80));// 延迟500ms后恢复    queue_work(spec->unmute_queue, &spec->unmute_work);}static voiddo_unmute(struct work_struct *work){    msleep(500);if ((value & ~0x80) == 0x0)        snd_hda_codec_write(codec, nid, 0, (0x370 | idx), spec->init_cap_val);}

修复三:mic pin (0x19)不支持unsol event,通过gating_jack与HP pin (0x16)绑定:

if (action == HDA_FIXUP_ACT_PROBE)    snd_hda_jack_set_gating_jack(codec, 0x19, 0x16);

3. CX11880 S3恢复后播放爆音

Bug现象

飞腾平台+CX11880/SN6140,S3恢复后首次播放音频时扬声器/耳机出现"pop"爆音,之后播放正常。

根因

S3恢复时cx_resume()调用cx_auto_init()重新初始化Codec,DAC输出路径在初始化过程中被使能,但此时DAC输出电压尚未稳定,导致pop音。

修复

Resume时先静音输出,首次播放时延迟取消静音:

static intcx_resume(struct hda_codec *codec){if (is_s3_resume(codec) || is_s4_resume(codec))        cx_auto_init(codec);if (spec->is_cx11880_sn6140) {        spec->resume_work = true;        mute_output_buff(codec, 0x16, true);  // 静音HP        mute_output_buff(codec, 0x17, true);  // 静音Speaker    }}voidcxt_playback_hook(...){case HDA_GEN_PCM_ACT_PREPARE:if (spec->resume_work) {            schedule_delayed_work(&spec->resume_unmute_work, msecs_to_jiffies(100));            spec->resume_work = false;        }}static voidresume_unmute_worker(struct work_struct *work){    mute_output_buff(codec, 0x16, false);    mute_output_buff(codec, 0x17, false);}

4. ALC269飞腾平台S3恢复后Pin配置丢失

Bug现象

飞腾FT2000平台+Realtek ALC269系列Codec,S3恢复后音频功能完全异常:耳机插入无反应、扬声器/耳机切换不正常、麦克风不工作。此Bug是飞腾HDA控制器特有的,Intel平台不受影响。

根因

Intel HDA控制器S3期间不复位Codec,寄存器保持不变。但飞腾FT2000控制器在S3过程中执行azx_enter_link_reset(),导致Codec被硬件复位,Pin Config Default和Processing Coefficient寄存器全部丢失。Pin Config丢失后is_jack_detectable()判断错误,jack检测被错误禁用。

修复

Suspend时保存所有Pin Config和Coef,Resume时检测并恢复:

static intalc269_verbs_save(struct hda_codec *codec){for (i = 0; i < nodes; i++, nid++) {if (wid_type == AC_WID_PIN) {// 保存Pin Config Default为4条SET_CONFIG_DEFAULT_BYTES verb            snd_hdac_read(&codec->core, nid, AC_VERB_GET_CONFIG_DEFAULT, 0, &val);            *verb0 = snd_hdac_make_cmd(&codec->core, nid,                    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, (val >> 0) & 0xff);            ...        }if (wid_caps & AC_WCAP_PROC_WID) {// 保存所有Coef寄存器for (j = 0; j < ncoeff; j++) { ... }        }    }}static intalc269_resume(struct hda_codec *codec){if (is_ft2000_pc()) {if (alc269_restore_verbs)           // 模块参数强制恢复            alc269_verbs_restore(codec);else if (alc269_if_restore(codec))   // 检测pin config是否为出厂默认值            alc269_verbs_restore(codec);else// 配置未丢失,释放保存数据            snd_array_free(&codec->saved_verbs);    }}

智能恢复alc269_if_restore()比较当前pin config与ALC269VC/VB出厂默认值,若全部匹配则说明S3恢复后配置丢失,需要恢复。模块参数alc269_restore_verbs可强制恢复

5. ALC662/861 no_jack_detect完全禁用JACK检测

Bug现象

某些主板上ALC662/ALC861的JACK检测完全不可靠——插拔耳机时系统时而检测到时而检测不到,或始终报告"已插入"。导致扬声器/耳机反复切换或始终静音。

受影响硬件:ALC662, 1043:8469、ALC861, 1462:7254。这些主板的音频插孔物理上未连接JACK SENSE信号线,或信号被错误拉高/拉低。

根因

硬件层面JACK SENSE信号不可靠,Pin Sense寄存器的PRESENCE位始终为1或随机跳变。软件无法修复硬件信号,只能完全禁用JACK检测。

修复

static voidalc_fixup_no_jack_detect(struct hda_codec *codec,const struct hda_fixup *fix, int action){if (action == HDA_FIXUP_ACT_PRE_PROBE)        codec->no_jack_detect = 1;}// PCI Quirk匹配SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT);SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT);

no_jack_detect=1使is_jack_detectable()直接返回false,所有pin都不注册jack检测回调。耳机自动静音、mic自动切换等功能全部失效,用户需通过alsamixer手动控制。这是"宁可不检测也不能误检测"的保守策略。

6. ALC255/256 CTIA/OMTP检测与VREF控制

Bug现象

Realtek ALC255/ALC256等Codec的4段耳机combo jack,插入CTIA耳机后麦克风不工作,插入OMTP耳机后声音失真或有底噪,拔出后内置麦克风不恢复。

根因

jack由状态机alc_update_headset_mode()驱动,有4种模式:UNPLUGGED、HEADSET、MIC、HEADPHONE。CTIA/OMTP检测需800ms等待硬件完成,VREF需随模式切换动态配置。若检测未完成就切换模式,或VREF时序不对,就会导致上述问题。

修复

CTIA/OMTP检测:通过coef寄存器配置检测参数,等待800ms后读取结果:

static voidalc_determine_headset_type(struct hda_codec *codec){case 0x10ec0255:        alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10);        alc_update_coef_idx(codec, 0x49, 3<<8, 2<<8);        msleep(800);        val = alc_read_coef_idx(codec, 0x46);        is_ctia = (val & 0x00f0) == 0x00f0;break;}

模式切换:根据HP jack状态和输入源确定模式,通过coef统一管理VREF和信号路径:

static voidalc_update_headset_mode(struct hda_codec *codec){if (!snd_hda_jack_detect(codec, hp_pin))        new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;else if (mux_pin == spec->headset_mic_pin)        new_headset_mode = ALC_HEADSET_MODE_HEADSET;else if (mux_pin == spec->headphone_mic_pin)        new_headset_mode = ALC_HEADSET_MODE_MIC;else        new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;switch (new_headset_mode) {case ALC_HEADSET_MODE_HEADSET:if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)            alc_determine_headset_type(codec);if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)            alc_headset_mode_ctia(codec);else            alc_headset_mode_omtp(codec);break;case ALC_HEADSET_MODE_MIC:        alc_headset_mode_mic_in(codec, hp_pin, mic_pin);break;    }}

设计对比:Realtek通过coef寄存器统一管理CTIA/OMTP检测和VREF控制,状态机确保模式切换原子性;Conexant CX11880则在unsol回调中直接操作pin control,更容易出现竞争条件。但两者都面临msleep()在回调中阻塞的问题

十六、总结

HDA JACK检测是一个从硬件到软件、从内核到用户空间的完整链路,核心设计思想可以归纳为以下几点:

1. 中断驱动的异步架构:JACK检测采用"中断顶半部 + 工作队列底半部"的经典模式。硬件中断只做RIRB读取和事件入队,耗时的回调处理延迟到进程上下文执行,保证了中断处理的实时性和系统的响应能力。

2. tag机制解耦硬件与软件:Unsolicited Response中的tag字段将Codec物理Pin与内核jack表项一一映射,使得事件分发无需关心底层硬件细节,各Codec驱动通过统一的snd_hda_jack_unsol_events入口处理,实现框架通用性。

3. 回调链支持灵活扩展:每个jack表项维护一个回调链表,支持注册多个回调函数。gating/gated jack机制解决了某些Pin不支持独立检测的问题(如mic pin依赖hp pin的事件触发),体现了软件对硬件局限的优雅补偿。

4. 双路径上报确保兼容性:JACK状态同时通过ALSA kcontrol和Linux input子系统两条路径上报,前者供alsa-lib等传统音频库使用,后者供PulseAudio/PipeWire等现代音频服务使用,确保了用户空间不同层次的需求都能被满足。

5. 案例中的共性规律:从6个实际Bug案例可以看出,JACK检测问题主要集中在三个领域:一是S3/S4恢复后寄存器状态丢失(飞腾平台尤为突出),二是4段耳机CTIA/OMTP类型检测的时序和VREF控制,三是硬件信号不可靠时的降级策略。这些问题的修复往往需要在Codec驱动的unsol回调、PCM hook、resume回调等多个位置协同处理,并大量使用schedule_delayed_work()来规避时序竞争


最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-08-21 19:41:58 HTTP/2.0 GET : https://f.mffb.com.cn/a/506289.html
  2. 运行时间 : 0.203073s [ 吞吐率:4.92req/s ] 内存消耗:4,815.19kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=b4015c0dc119ff08d632497eb001ad35
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000967s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001546s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000734s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000709s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001372s ]
  6. SELECT * FROM `set` [ RunTime:0.000596s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001527s ]
  8. SELECT * FROM `article` WHERE `id` = 506289 LIMIT 1 [ RunTime:0.003797s ]
  9. UPDATE `article` SET `lasttime` = 1787312518 WHERE `id` = 506289 [ RunTime:0.002620s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000693s ]
  11. SELECT * FROM `article` WHERE `id` < 506289 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001077s ]
  12. SELECT * FROM `article` WHERE `id` > 506289 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001581s ]
  13. SELECT * FROM `article` WHERE `id` < 506289 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001638s ]
  14. SELECT * FROM `article` WHERE `id` < 506289 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001662s ]
  15. SELECT * FROM `article` WHERE `id` < 506289 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.021478s ]
0.206774s