broadcom 6356s模组驱动

匿名 (未验证) 提交于 2019-12-03 00:37:01

模组broadcom 6356s 蓝牙wifi双模

wifi驱动的通用的软件架构

  1. 分为两部分,上面为主机端驱动,下面是我们之前所说的firmware

  2. 其中固件部分的主要工作是:因为天线接受和发送回来的都是802.11帧的帧,而主机接受和传送出来的数据都必须是802.3的帧,所以必须由firmware来负责802.3的帧和802.11帧之间的转换

  3. 当天线收到数据,并被firmware处理好后会放在一个buffer里,并产生一个中断,主机在收到中断后就去读这个buffer



WiFi芯片内部有一个小系统,用来运行802.11协议,此部分代码就叫Firmware。有些芯片(例如 broadcom)的Firmware是以文件的形式存放的,有些芯片(例如 realteck)的Firmware是做到驱动代码中的。



WiFi芯片工作前,需要host先下载Firmware文件到WiFi芯片中,此部分工作在WiFi驱动中完成。

Broadcom WLAN模块同样存在着一个至关重要的文件:bcmdhd.cal,该文件定义了针对WLAN模块的NV值


Firmware与Nvram文件存放于external/wlan_loader/firmware/目录中,最终被编译到系统的/system/etc/firmware

WLAN Module工作的3种模式



(3)P2P

Broadcom WLAN Module所使用的2种Firmware


(2)fw_bcmdhd_apsta.bin

WLAN Module工作模式与固件的对应关系



扫描,ftrace信息





调用数据处理函数:dhd_sched_dpc-》dhd_dpc_thread-》dhd_dpc_thread-》dhdsdio_readframes-》dhd_rx_frame-》

        /* Process special event packets and then discard them */         memset(&event, 0, sizeof(event));//非数据处理即事件如扫描完成,断开,加密出错等事件         if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) {             dhd_wl_host_event(dhd, &ifidx,
  • 1
  • 2
  • 3
  • 4













PROC_START(wl_event_handler, cfg, &cfg->event_tsk, 0, “wl_event_handler”);

static s32 wl_event_handler(void *data) {     struct bcm_cfg80211 *cfg = NULL;     struct wl_event_q *e;     tsk_ctl_t *tsk = (tsk_ctl_t *)data;     struct wireless_dev *wdev = NULL;      cfg = (struct bcm_cfg80211 *)tsk->parent;      printf("tsk Enter, tsk = 0x%p\n", tsk);      while (down_interruptible (&tsk->sema) == 0) {//由于来传来的参数是&cfg->event_tsk,此处&tsk->sema刚好是 &cfg->event_tsk.sema     /*     static void wl_wakeup_event(struct bcm_cfg80211 *cfg) {     dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);      if (dhd->up && (cfg->event_tsk.thr_pid >= 0)) {         up(&cfg->event_tsk.sema);唤醒进程     } }      * /         SMP_RD_BARRIER_DEPENDS();         if (tsk->terminated) {             break;         }         while ((e = wl_deq_event(cfg))) {//出队,将刚接收到的事件取出             WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",                 e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));              if (e->emsg.ifidx > WL_MAX_IFS) {                 WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));                 goto fail;             }              if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {                 /* For WLC_E_IF would be handled by wl_host_event */                 if (e->etype != WLC_E_IF)                     WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"                         " Ignoring event.\n", e->emsg.bsscfgidx));             } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {                 dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);                 if (dhd->busstate == DHD_BUS_DOWN) {                     WL_ERR((": BUS is DOWN.\n"));                 } else { #ifdef DHD_IFDEBUG                     if (cfg->iface_cnt == 0) {                         wl_dump_ifinfo(cfg);                     } #endif                     cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),                         &e->emsg, e->edata);//调用处理事件的函数,这是一个钩子函数                 }             } else {                 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));             } fail:             wl_put_event(e);             DHD_EVENT_WAKE_UNLOCK(cfg->pub);         }     }     printf("%s: was terminated\n", __FUNCTION__);     complete_and_exit(&tsk->completed, 0);     return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
                cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),                     &e->emsg, e->edata); 
  • 1
  • 2
  • 3

在wl_init_event_handler中注册回调函数

static void wl_init_event_handler(struct bcm_cfg80211 *cfg) {     memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));      cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;     cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;     cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;     cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;     cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;     cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;     cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;     cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;     cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;     cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;     cfg->evt_handler[WLC_E_START] = wl_notify_connect_status; #ifdef PNO_SUPPORT     cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; #endif /* PNO_SUPPORT */ #ifdef GSCAN_SUPPORT     cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;     cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;     cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;     cfg->evt_handler[WLC_E_PFN_SWC] = wl_notify_gscan_event;     cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;     cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event; #endif /* GSCAN_SUPPORT */ #ifdef WLTDLS     cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler; #endif /* WLTDLS */     cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status; #ifdef  WL_RELMCAST     cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status; #endif #ifdef BT_WIFI_HANDOVER     cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req; #endif #ifdef WL_NAN     cfg->evt_handler[WLC_E_NAN] = wl_cfgnan_notify_nan_status;     cfg->evt_handler[WLC_E_PROXD] = wl_cfgnan_notify_proxd_status; #endif /* WL_NAN */     cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind; #ifdef DHD_LOSSLESS_ROAMING     cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status; #endif     cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind; #ifdef CUSTOM_EVENT_PM_WAKE     cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus; #endif /* CUSTOM_EVENT_PM_WAKE */     cfg->evt_handler[WLC_E_PSK_SUP] = wl_notify_idsup_status; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59


wl_notify_scan_status

static s32 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,     const wl_event_msg_t *e, void *data) {     struct channel_info channel_inform;     struct wl_scan_results *bss_list;     struct net_device *ndev = NULL;     u32 len = WL_SCAN_BUF_MAX;     s32 err = 0;     unsigned long flags;  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))     struct cfg80211_scan_info info; #endif     WL_DBG(("Enter \n"));     if (!wl_get_drv_status(cfg, SCANNING, ndev)) {         WL_ERR(("scan is not ready \n"));         return err;     }     ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);      mutex_lock(&cfg->usr_sync);     wl_clr_drv_status(cfg, SCANNING, ndev);     err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,         sizeof(channel_inform), false);//获取信道信息     if (unlikely(err)) {         WL_ERR(("scan busy (%d)\n", err));         goto scan_done_out;     }     channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);     if (unlikely(channel_inform.scan_channel)) {          WL_DBG(("channel_inform.scan_channel (%d)\n",             channel_inform.scan_channel));     }     cfg->bss_list = cfg->scan_results;     bss_list = cfg->bss_list;     memset(bss_list, 0, len);     bss_list->buflen = htod32(len);     err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);//获取扫描结果     if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {         WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));         err = -EINVAL;         goto scan_done_out;     }     bss_list->buflen = dtoh32(bss_list->buflen);     bss_list->version = dtoh32(bss_list->version);     bss_list->count = dtoh32(bss_list->count);      err = wl_inform_bss(cfg);//更新bss信息,最后调用到cfg80211_inform_bss_frame更新内核无线子系统的bss信息  scan_done_out:     del_timer_sync(&cfg->scan_timeout);     spin_lock_irqsave(&cfg->cfgdrv_lock, flags);     if (cfg->scan_request) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))         info.aborted = false;         cfg80211_scan_done(cfg->scan_request, &info); #else         cfg80211_scan_done(cfg->scan_request, false);//通知内核无线子系统扫描完成,让上层去获取扫描结果等操作 #endif         cfg->scan_request = NULL;     }     spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);     WL_DBG(("cfg80211_scan_done\n"));     mutex_unlock(&cfg->usr_sync);     return err; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
wpa_supplicant-4774  [002] ...1  5463.125488: wl_cfg80211_scan <-nl80211_trigger_scan   wpa_supplicant-4774  [002] ...1  5463.125495: wl_cfg_multip2p_operational <-wl_cfg80211_scan   wpa_supplicant-4774  [002] ...1  5463.125498: wl_cfg80211_get_remain_on_channel_ndev <-wl_cfg80211_scan   wpa_supplicant-4774  [002] ...1  5463.125504: wl_cfgp2p_discover_enable_search <-wl_cfg80211_scan   wpa_supplicant-4774  [002] ...1  5463.125506: wl_cfg80211_set_mgmt_vndr_ies <-wl_cfg80211_scan   wpa_supplicant-4774  [002] ...1  5463.125509: wl_cfg80211_parse_vndr_ies <-wl_cfg80211_set_mgmt_vndr_ies   wpa_supplicant-4774  [002] ...1  5463.125511: bcm_next_tlv <-wl_cfg80211_parse_vndr_ies   wpa_supplicant-4774  [002] ...1  5463.125513: bcm_next_tlv <-wl_cfg80211_parse_vndr_ies   wpa_supplicant-4774  [002] ...1  5463.125514: bcm_next_tlv <-wl_cfg80211_parse_vndr_ies   wpa_supplicant-4774  [002] ...1  5463.125515: bcm_next_tlv <-wl_cfg80211_parse_vndr_ies   wpa_supplicant-4774  [002] ...1  5463.125519: $x <-wl_cfg80211_scan   wpa_supplicant-4774  [002] ...1  5463.125521: dhd_ioctl_entry_local <-$x   wpa_supplicant-4774  [002] ...1  5463.125522: dhd_net2idx <-dhd_ioctl_entry_local   wpa_supplicant-4774  [002] ...1  5463.125524: dhd_os_wake_lock <-dhd_ioctl_entry_local   wpa_supplicant-4774  [002] ...1  5463.125526: dhd_wl_ioctl <-dhd_ioctl_entry_local   wpa_supplicant-4774  [002] ...1  5463.125528: dhd_os_proto_block <-dhd_wl_ioctl   wpa_supplicant-4774  [002] ...1  5463.125530: dhd_os_general_spin_lock <-dhd_wl_ioctl   wpa_supplicant-4774  [002] d..2  5463.125532: dhd_os_general_spin_unlock <-dhd_wl_ioctl   wpa_supplicant-4774  [002] ...1  5463.125534: dhd_prot_ioctl <-dhd_wl_ioctl   wpa_supplicant-4774  [002] ...1  5463.125536: $x <-dhd_prot_ioctl   wpa_supplicant-4774  [002] ...1  5463.125537: dhd_os_wake_lock <-$x   wpa_supplicant-4774  [002] ...1  5463.125539: dhd_bus_txctl <-$x   wpa_supplicant-4774  [002] ...1  5463.125541: dhd_os_sdlock <-dhd_bus_txctl   wpa_supplicant-4774  [002] ...1  5463.125544: dhdsdio_bussleep <-dhd_bus_txctl   wpa_supplicant-4774  [002] ...1  5463.125545: dhdsdio_clk_devsleep_iovar <-dhdsdio_bussleep   wpa_supplicant-4774  [002] ...1  5463.125547: dhdsdio_clk_kso_enab.isra.7 <-dhdsdio_clk_devsleep_iovar   wpa_supplicant-4774  [002] ...1  5463.125549: dhdsdio_sleepcsr_get.isra.1 <-dhdsdio_clk_devsleep_iovar   wpa_supplicant-4774  [002] ...1  5463.125550: bcmsdh_cfg_read <-dhdsdio_sleepcsr_get.isra.1   wpa_supplicant-4774  [002] ...1  5463.125552: sdioh_cfg_read <-bcmsdh_cfg_read   wpa_supplicant-4774  [002] ...1  5463.125554: sdioh_request_byte <-sdioh_cfg_read   wpa_supplicant-4774  [002] ...1  5463.126236: bcmsdh_cfg_read <-dhdsdio_clk_devsleep_iovar   wpa_supplicant-4774  [002] ...1  5463.126241: sdioh_cfg_read <-bcmsdh_cfg_read   wpa_supplicant-4774  [002] ...1  5463.126242: sdioh_request_byte <-sdioh_cfg_read   wpa_supplicant-4774  [002] ...1  5463.126484: dhdsdio_clkctl.isra.10 <-dhd_bus_txctl   wpa_supplicant-4774  [002] ...1  5463.126487: dhd_os_wd_timer <-dhdsdio_clkctl.isra.10   wpa_supplicant-4774  [002] ...1  5463.126489: dhd_os_wd_wake_lock <-dhd_os_wd_timer   wpa_supplicant-4774  [002] d..2  5463.126494: dhd_os_wd_wake_lock <-dhd_os_wd_timer   wpa_supplicant-4774  [002] ...1  5463.126498: dhd_os_wd_wake_unlock <-dhd_os_wd_timer   wpa_supplicant-4774  [002] ...1  5463.126502: bcmsdh_cur_sbwad <-dhd_bus_txctl   wpa_supplicant-4774  [002] ...1  5463.126503: dhd_bcmsdh_send_buf.constprop.27 <-dhd_bus_txctl   wpa_supplicant-4774  [002] ...1  5463.126505: bcmsdh_send_buf <-dhd_bcmsdh_send_buf.constprop.27   wpa_supplicant-4774  [002] ...1  5463.126506: bcmsdhsdio_set_sbaddr_window <-bcmsdh_send_buf   wpa_supplicant-4774  [002] ...1  5463.126508: sdioh_request_buffer <-bcmsdh_send_buf   wpa_supplicant-4774  [002] ...1  5463.126510: sdioh_buffer_tofrom_bus <-sdioh_request_buffer
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

内核netlink接收来自应用层的消息并处理

genl_rcv()接收到数据会直接调用genl_rcv_msg()  genl_family_rcv_msg  static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) {     //nlmsghdr中的type应该和family的id一致,     //但是内核中genl注册family时,id是自动非配的,那用户空间发送的消息怎么确认id,     family = genl_family_find_byid(nlh->nlmsg_type);      //根据nlh中定义的cmd类型决定     genl_family_rcv_msg(family, skb, nlh);     {         //在传入的nlh的载荷中包含着geml的头genlmsghdr,         struct genlmsghdr *hdr = nlmsg_data(nlh);          //genl 信息,里面有netlnik head,genl head,user head等信息,最终会由用户(nl80211)定义的ops处理         struct genl_info info;                //如果有family有体检需要处理的,可以放在该处         err = family->pre_doit(ops, skb, &info);          //通过cmd找到ops,对传入的数据进行处理         ops = genl_get_cmd(hdr->cmd, family);         //ops处理数据         err = ops->doit(skb, &info);          //family的后续处理         family->post_doit(ops, skb, &info);     } }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

wifi beacon强度获取:本例子驱动不走这个,直接驱动代码调用cfg80211_inform_bss_frame这类接口更新数据

  ieee80211_tasklet_handler ieee80211_rx  __ieee80211_rx_handle_packet {  ieee80211_scan_rx //probe_rsp beacon帧 { cfg80211_inform_bss_frame--> cfg80211_bss_update--> (list_add_tail(&res->list, &dev->bss_list);)-->   cfg80211_scan_done->-nl80211_send_scan_done(NL80211_CMD_NEW_SCAN_RESULTS)    1) + 12.542 us   |  cfg80211_scan_done [cfg80211]();  ------------------------------------------  1)  wl_even-4966  =>  kworker-7064   ------------------------------------------   1)               |  __cfg80211_scan_done [cfg80211]() {  1)               |    ___cfg80211_scan_done [cfg80211]() {  1)   0.834 us    |      cfg80211_sme_scan_done [cfg80211]();  1)               |      nl80211_build_scan_msg [cfg80211]() {  1)   7.541 us    |        nl80211_send_scan_msg.constprop.68 [cfg80211]();  1) + 14.750 us   |      }  1) + 22.000 us   |      nl80211_send_scan_result [cfg80211]();  1) + 48.875 us   |    }  1) + 53.667 us   |  } }  ieee80211_prepare_and_rx_handle//数据帧,已连接上了后 {     ieee80211_invoke_rx_handlers     ieee80211_rx_handlers     ieee80211_rx_h_sta_process中     sta->last_signal = status->signal;  }  }     获取给上层: const struct cfg80211_ops mac80211_config_ops = {      .get_station = ieee80211_get_station,  中:sta_set_sinfo             sinfo->signal = (s8)sta->last_signal;获取  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53






wl btc mode 0


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!