nexus5 博通芯片WIFI详解 (3)
1 WLAN驱动结构介绍
1.1 SDIO驱动
1.2 Boardcom无线通讯芯片
1.2.1 概述
1.2.2 源码
这里主要内容到bcmsdio,dhd和wl三个目录下,bcm4330驱动的入口在dhd/sys/dhd_linux.c文件中的dhd_module()函数,设备的初始化和相关驱动注册都从这里开始,
1.3 详细接口及代码分析
1.3.1 WIFI驱动流程分析
以boardcom bcm4329芯片驱动为例,相应的函数流程图如下:
1.3.2 WIFI设备注册流程
Static struct Platform_driverwifi_device={
Static struct Platform_driverwifi_device_legacy={
上面的展示了wifi平台设备驱动的注册过程,那么在平台相关的代码区应该有wifi作为平台设备被初始化和注册的地方:
Path: kernel/arch/arm/mach-msm/msm_
static struct resource mahimahi_wifi_resources[] = {
.start =MSM_GPIO_TO_INT(MAHIMAHI_GPIO_WIFI_IRQ),
.end = MSM_GPIO_TO_INT(MAHIMAHI_GPIO_WIFI_IRQ),
.flags = IORESOURCE_IRQ |IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE,
static structwifi_platform_data mahimahi_wifi_control = {
.set_power = mahimahi_wifi_power,
.set_reset = mahimahi_wifi_reset,
.set_carddetect = mahimahi_wifi_set_carddetect,
.mem_prealloc = mahimahi_wifi_mem_prealloc,
static struct platform_device mahimahi_wifi_device = {
.num_resources = ARRAY_SIZE(mahimahi_wifi_resources),
.resource = mahimahi_wifi_resources,
.platform_data = &mahimahi_wifi_control,
上面是对wifi_device设备的初始化,下面是对该设备的注册:
static int __initmahimahi_wifi_init(void)
printk("%s: start\n",__func__);
mahimahi_wifi_update_nvs("sd_oobonly=1\r\n", 0);
mahimahi_wifi_update_nvs("btc_params70=0x32\r\n", 1);
ret = platform_device_register(&mahimahi_wifi_device);
late_initcall(mahimahi_wifi_init);//表明在系统启动的后期会自动调用加载该模块
static int wifi_probe(structplatform_device *pdev)
struct wifi_platform_data *wifi_ctrl =
(structwifi_platform_data *)(pdev->dev.platform_data);
DHD_ERROR(("## %s\n",__FUNCTION__));
wifi_irqres = platform_get_resource_byname(pdev,IORESOURCE_IRQ, "bcmdhd_wlan_irq");
wifi_irqres =platform_get_resource_byname(pdev,
IORESOURCE_IRQ,"bcm4329_wlan_irq");
wifi_control_data = wifi_ctrl;
wifi_set_power(1,0); /* Power On */
wifi_set_carddetect(1); /* CardDetect (0->1) */
int wifi_set_power(int on, unsignedlong msec)
DHD_ERROR(("%s = %d\n",__FUNCTION__, on));
if (wifi_control_data &&wifi_control_data->set_power) {
wifi_control_data->set_power(on);
static struct platform_device mahimahi_wifi_device = {
.num_resources = ARRAY_SIZE(mahimahi_wifi_resources),
.resource = mahimahi_wifi_resources,
.platform_data =&mahimahi_wifi_control,
static struct wifi_platform_datamahimahi_wifi_control= {
.set_power = mahimahi_wifi_power,
.set_reset = mahimahi_wifi_reset,
.set_carddetect =mahimahi_wifi_set_carddetect,
.mem_prealloc = mahimahi_wifi_mem_prealloc,
所以它实际调用的是mahimahi_wifi_power函数,该函数的定义在kernel/arch/arm /mach-msm/board-mahimahi-mmc.c之中:
int mahimahi_wifi_power(int on)
printk("%s: %d\n", __func__, on);
config_gpio_table(wifi_on_gpio_table,
ARRAY_SIZE(wifi_on_gpio_table));
config_gpio_table(wifi_off_gpio_table,
ARRAY_SIZE(wifi_off_gpio_table));
gpio_set_value(MAHIMAHI_GPIO_WIFI_SHUTDOWN_N,on); /* WIFI_SHUTDOWN */
mahimahi_wifi_power_state = on;
调用gpio_set_value操作wifi芯片,给wifi芯片上电。那么来看看wifi_set_ carddetect函数究竟干了什么:
static int wifi_set_carddetect(int on)
DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
if(wifi_control_data && wifi_control_data->set_carddetect) {
wifi_control_data->set_carddetect(on);
同样会调用wifi_device的mahimahi_wifi_set_carddetect函数:
Path:kernel/arch/arm/mach-msm/board-mahimahi-mmc.c
int mahimahi_wifi_set_carddetect(int val)
pr_info("%s: %d\n", __func__, val);
wifi_status_cb(val,wifi_status_cb_devid);
pr_warning("%s: Nobody to notify\n", __func__);
static int mahimahi_wifi_status_register(
void (*callback)(intcard_present, void *dev_id),
wifi_status_cb_devid = dev_id;
static unsigned intmahimahi_wifi_status(struct device *dev)
static structmmc_platform_data mahimahi_wifi_data = {
.status = mahimahi_wifi_status,
.register_status_notify= mahimahi_wifi_status_register,
.embedded_sdio = &mahimahi_wifi_emb_data,
int msm_add_sdcc(unsigned intcontroller, struct mmc_platform_data *plat,
unsigned int stat_irq,unsigned long stat_irq_flags);
int __initmahimahi_init_mmc(unsigned int sys_rev, unsigned debug_uart)
msm_add_sdcc(1, &mahimahi_wifi_data, 0, 0);
msm_add_sdcc(2,&mahimahi_sdslot_data, 0, 0);
mahimahi_sdslot_data.status =mahimahi_sdslot_status_rev0;
mahimahi_sdslot_data.register_status_notify = NULL;
set_irq_wake(MSM_GPIO_TO_INT(MAHIMAHI_GPIO_SDMC_CD_REV0_N), 1);
msm_add_sdcc(2, &mahimahi_sdslot_data,
可以跟踪到这里Path:kernel/arch/arm/mach-msm/devices-msm7x30.c
struct platform_device msm_device_sdc1 = {
.num_resources = ARRAY_SIZE(resources_sdc1),
.coherent_dma_mask =0xffffffff,
struct platform_device msm_device_sdc2 = {
.num_resources = ARRAY_SIZE(resources_sdc2),
.coherent_dma_mask =0xffffffff,
struct platform_devicemsm_device_sdc3 = {
.num_resources = ARRAY_SIZE(resources_sdc3),
.coherent_dma_mask = 0xffffffff,
struct platform_device msm_device_sdc4= {
.num_resources = ARRAY_SIZE(resources_sdc4),
.coherent_dma_mask = 0xffffffff,
static struct platform_device *msm_sdcc_devices[] __initdata = {
int __initmsm_add_sdcc(unsigned int controller, struct mmc_platform_data *plat,
unsigned int stat_irq,unsigned long stat_irq_flags)
pdev =msm_sdcc_devices[controller-1]; //因为传过来的controller是1,所以下面注册的是第一个平台设备
pdev->dev.platform_data= plat;//被传递给平台设备的platform_data
res =platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq");
res->start = res->end =stat_irq;
res->flags &=~IORESOURCE_DISABLED;
return platform_device_register(pdev); //如上所述
那么这个平台设备是什么呢,就是sd卡控制器,也就是前面说的host驱动所驱动的主机控制设备。
Path: drivers/mmc/host/msm_sdcc.c
static struct platform_drivermsmsdcc_driver = {
static int __initmsmsdcc_init(void)
return platform_driver_register(&msmsdcc_driver);
msmsdcc_probe(structplatform_device *pdev)
if (stat_irqres &&!(stat_irqres->flags & IORESOURCE_DISABLED)) {
} else if(plat->register_status_notify) {
plat->register_status_notify(msmsdcc_status_notify_cb,host);
msmsdcc_status_notify_cb调用msmsdcc_check_status函数:
msmsdcc_status_notify_cb(intcard_present, void *dev_id)
struct msmsdcc_host *host = dev_id;
printk(KERN_DEBUG "%s:card_present %d\n", mmc_hostname(host->mmc),
msmsdcc_check_status((unsigned long) host);
msmsdcc_check_status调用mmc_detect_change函数:
msmsdcc_check_status(unsignedlong data)
pr_info("%s: Slot statuschange detected (%d -> %d)\n",
mmc_hostname(host->mmc),host->oldstat, status);
if (status &&!host->plat->built_in)
mmc_detect_change(host->mmc, (5 * HZ) / 2);
mmc_detect_change(host->mmc, 0);
mod_timer(&host->timer,jiffies + HZ);
可以看到mmc_detect_change被调用了,这个函数触发了一个延时工作:
void mmc_detect_change(structmmc_host *host, unsigned long delay)
mmc_schedule_delayed_work(&host->detect, delay);
msmsdcc_probe(structplatform_device *pdev)
mmc = mmc_alloc_host(sizeof(struct msmsdcc_host),&pdev->dev);
struct mmc_host*mmc_alloc_host(int extra, struct device *dev)
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
mmc_rescan是core.c中一个很重要的函数,它遵照 SDIO 卡协议的 SDIO 卡启动过程,包括了非激活模式、卡识别模式和数据传输模式三种模式共九种状态的转换,你需要参照相关规范来理解。
void mmc_rescan(structwork_struct *work)
container_of(work, structmmc_host, detect.work);
mmc_send_if_cond(host, host->ocr_avail);
err = mmc_send_io_op_cond(host, 0, &ocr);
if (mmc_attach_sdio(host, ocr))
这个mmc_attach_sdio函数很重要,它是SDIO卡的初始化的起点,主要工作包括:匹配SDIO卡的工作电压,分配并初始化mmc_card结构,然后注册mmc_card到系统中:
* Starting point for SDIO card init.
int mmc_attach_sdio(structmmc_host *host, u32 ocr)
mmc_attach_bus(host,&mmc_sdio_ops); //初始化host的bus_ops
host->ocr = mmc_select_voltage(host, ocr);//匹配SDIO卡工作电压
err = mmc_sdio_init_card(host, host->ocr, NULL, 0);//检测,分配初始化mmc_card
* If needed, disconnect card detectionpull-up resistor.
*Initialize (but don't add) all present functions.
for (i = 0; i < funcs; i++, card->sdio_funcs++) {
#ifdef CONFIG_MMC_EMBEDDED_SDIO
if(host->embedded_sdio_data.funcs) {
tmp = sdio_alloc_func(host->card);
tmp->class = host->embedded_sdio_data.funcs[i].f_class;
tmp->max_blksize = host->embedded_sdio_data.funcs[i].f_maxblksize;
tmp->vendor = card->cis.vendor;
tmp->device = card->cis.device;
err =sdio_init_func(host->card, i + 1);
#ifdefCONFIG_MMC_EMBEDDED_SDIO
* First add the card to the drivermodel...
err = mmc_add_card(host->card); //添加mmc_card
err =sdio_add_func(host->card->sdio_func[i]);//将sdio_func加入系统
1.3.2.1 加载SDIO host驱动模块
static struct platform_drivermsmsdcc_driver = {
static int __initmsmsdcc_init(void)
returnplatform_driver_register(&msmsdcc_driver);
Probe函数会调用mmc_alloc_host函数(代码前面已经贴出)来创建mmc_host结构变量,进行必要的初始化之后,调用mmc_add_host函数将它添加到驱动里面:
int mmc_add_host(structmmc_host *host)
err =device_add(&host->class_dev);
if (!(host->pm_flags &MMC_PM_IGNORE_PM_NOTIFY))
register_pm_notifier(&host->pm_notify);
void mmc_start_host(structmmc_host *host)
mmc_power_off中对ios进行了设置,然后调用 mmc_set_ios(host);
host->ios.power_mode = MMC_POWER_OFF;
host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing =MMC_TIMING_LEGACY;
mmc_set_ios(host) 中的关键语句 host->ops->set_ios(host, ios),实际上在host驱动的probe函数中就已经对host->ops进行了初始化:
static const structmmc_host_ops msmsdcc_ops = {
.enable_sdio_irq =msmsdcc_enable_sdio_irq,
所以实际上调用的是msmsdcc_set_ios,关于这个函数就不介绍了,可以参考源码,再看 mmc_detect_change(host, 0),最后一句是:
mmc_schedule_delayed_work(&host->detect,delay);
实际上就是调用我们前面说的延时函数 mmc_rescan,后面的流程是一样的。
1.3.2.2 SDIO设备中断
msmsdcc_probe(structplatform_device *pdev)
cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
pio_irqres =platform_get_resource_byname(pdev, IORESOURCE_IRQ,
stat_irqres =platform_get_resource_byname(pdev, IORESOURCE_IRQ,
if (stat_irqres && !(stat_irqres->flags &IORESOURCE_DISABLED)) {
unsigned long irqflags =IRQF_SHARED |
(stat_irqres->flags& IRQF_TRIGGER_MASK);
host->stat_irq = stat_irqres->start;
ret = request_irq(host->stat_irq,
pr_err("%s: Unableto get slot IRQ %d (%d)\n",
mmc_hostname(mmc), host->stat_irq, ret);
当产生相应的中断时调用msmsdcc_platform_status_irq中断处理函数,这个函数的处理流程:
中断引发的调用mmc_rescan动作的意义:实现了SDIO设备的热插拔功能。
1.3.3 WIFI驱动流程(二)
dhd_mudule_init—> //path:dhd/sys/dhd_linux.c
Dhd_bus_registerà // dhd/sys/dhd_sdio.c
Bcmsdh_registerà // bcmsdio/sys/bcmsdh_linux.c
Sdio_function_inità // bcmsdio/sys/bcmsdh_sdmmc_linux.c
Sdio_register_driverà // bcmsdio/sys/bcmsdh_sdmmc_linux.c
Bcmsdh_sdmmc_probeà//bcmsdio/sys/bcmsdh_sdmmc_linux.c
Bcmsdh_probeà//bcmsdio/sys/bcmsdh_linux.c
Bcmsdio_probeà //dhd/sys/dhd_sdio.c
bcmsdh_register(bcmsdh_driver_t*driver)
drvinfo = *driver; //注意这里,后面会介绍到它的用处
SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
SDLX_MSG(("Intel PXA270 SDIO Driver\n"));
error =driver_register(&bcmsdh_driver);
#endif /* defined(BCMLXSDMMC) */
#endif /*defined(BCMPLATFORM_BUS) */
#if !defined(BCMPLATFORM_BUS)&& !defined(BCMLXSDMMC)
#if (LINUX_VERSION_CODE <KERNEL_VERSION(2, 6, 0))
if (!(error =pci_module_init(&bcmsdh_pci_driver)))
if (!(error =pci_register_driver(&bcmsdh_pci_driver)))
SDLX_MSG(("%s: pci_module_initfailed 0x%x\n", __FUNCTION__, error));
再看看dhdsdio_probe函数调用的玄机,从上面的bcmsdh_register函数可以看出它的参数被传递给了drvinfo,看看bcmsdh_register的调用地方:
static bcmsdh_driver_t dhd_sdio = {
DHD_TRACE(("%s: Enter\n",__FUNCTION__));
return bcmsdh_register(&dhd_sdio);
上面传递的参数是dhd_sdio结构变量,被用两个函数初始化了,那么哪一个是attach呢?需要找到定义bcmsdh_driver_t结构定义的地方:
void *(*attach)(uint16 vend_id, uint16 dev_id, uint16 bus,uint16 slot,
uint16 func, uint bustype, void * regsva, osl_t * osh,
没错,就是第一个dhdsdio_probe函数,再来看看什么地方调用了这个attach函数:
Path:bcmsdio/sys/bcmsdh_linux.c
int bcmsdh_probe(struct device*dev)
if (!(sdhc->ch =drvinfo.attach((vendevid>> 16),
(vendevid & 0xFFFF), 0, 0, 0, 0,
SDLX_MSG(("%s: device attachfailed\n", __FUNCTION__));
1.3.4 网络设备注册流程
dhd_attach(osl_t *osh, structdhd_bus *bus, uint bus_hdrlen)
struct net_device *net = NULL;
/* Allocate etherdev, including spacefor private structure */
if (!(net = alloc_etherdev(sizeof(dhd)))) {//网络设备的创建
DHD_ERROR(("%s: OOM -alloc_etherdev\n", __FUNCTION__));
dhd_state |=DHD_ATTACH_STATE_NET_ALLOC;
/* Allocate primary dhd_info */
if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { //dhd的创建
DHD_ERROR(("%s: OOM -alloc dhd_info\n", __FUNCTION__));
/* Set network interface name if it was provided as moduleparameter */
strncpy(net->name,iface_name, IFNAMSIZ);
if ((ch > '9' || ch <'0') && (len < IFNAMSIZ - 2))
if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0)== DHD_BAD_IF)//将前面创建的net添加到iflist列表中
dhd_state |= DHD_ATTACH_STATE_ADD_IF;
Memcpy(netdev_priv(net), &dhd, sizeof(dhd));//关联dhd和net
dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
uint8 *mac_addr,uint32 flags, uint8 bssidx)
DHD_TRACE(("%s: idx %d,handle->%p\n", __FUNCTION__, ifidx, handle));
ASSERT(dhd && (ifidx <DHD_MAX_IFS));
free_netdev(ifp->net); //如果已经存在,释放net成员
if ((ifp = MALLOC(dhd->pub.osh,sizeof(dhd_if_t))) == NULL) {
DHD_ERROR(("%s: OOM - dhd_if_t\n", __FUNCTION__)); //否则,创建一个dhd_if_t结构变量
memset(ifp, 0, sizeof(dhd_if_t));
ifp->info = dhd;//进行系列初始化,添加工作
strncpy(ifp->name, name, IFNAMSIZ);
memcpy(&ifp->mac_addr, mac_addr,ETHER_ADDR_LEN);
ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0);
up(&dhd->thr_sysioc_ctl.sema);
ifp->net = (struct net_device *)handle;//handle即一个net_device变量
这样,一个net_device网路设备就被添加到了接口管理列表中了,但是这是网路设备还没有完成初始化和注册工作,bcmsdio_probe函数随后对dhd_net_attach的调用完成了这个操作:
dhd_net_attach(dhd_pub_t*dhdp, int ifidx)
dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
struct net_device *net = NULL;
uint8 temp_addr[ETHER_ADDR_LEN] = {0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 };
DHD_TRACE(("%s: ifidx %d\n",__FUNCTION__, ifidx));
ASSERT(dhd &&dhd->iflist[ifidx]);
net = dhd->iflist[ifidx]->net;//首先从刚才添加的接口列表中取出net,然后进行下面的系列初始化工作
//根据内核版本信息,选择对net成员函数的初始化方式,假设是2.6.30的版本
#if (LINUX_VERSION_CODE <KERNEL_VERSION(2, 6, 31))
net->get_stats = dhd_get_stats;
net->do_ioctl =dhd_ioctl_entry;
net->hard_start_xmit = dhd_start_xmit;
net->set_mac_address = dhd_set_mac_address;
net->set_multicast_list = dhd_set_multicast_list;
net->netdev_ops = &dhd_ops_virt;
/* Ok, link into the network layer...*/
* device functions for theprimary interface only
#if (LINUX_VERSION_CODE <KERNEL_VERSION(2, 6, 31))
net->netdev_ops = &dhd_ops_pri;
* We have to use the primaryMAC for virtual interfaces
memcpy(temp_addr,dhd->iflist[ifidx]->mac_addr, ETHER_ADDR_LEN);
* Android sets the locallyadministered bit to indicate that this is a
* portable hotspot. This will not work in simultaneous AP/STAmode,
* nor with P2P. Need to set the Donlge's MAC address, andthen use that.
if(!memcmp(temp_addr, dhd->iflist[0]->mac_addr,
DHD_ERROR(("%sinterface [%s]: set locally administered bit in MAC\n",
net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
#if LINUX_VERSION_CODE >=KERNEL_VERSION(2, 6, 24)
net->ethtool_ops = &dhd_ethtool_ops;
#endif /* LINUX_VERSION_CODE>= KERNEL_VERSION(2, 6, 24) */
#ifdefined(CONFIG_WIRELESS_EXT)
net->get_wireless_stats = dhd_get_wireless_stats;
#endif /*defined(CONFIG_WIRELESS_EXT) */
dhd->pub.rxsz =DBUS_RX_BUFFER_SIZE_DHD(net);
memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
if ((err =register_netdev(net)) != 0) { //注册net
DHD_ERROR(("couldn'tregister the net device, err %d\n", err));
到这里net网络设备就被注册到系统中了,设备准备好了就好对设备进行访问了
nexus5 博通芯片WIFI详解 (3)相关推荐
- nexus5 博通芯片WIFI详解 (1)
1 WLAN技术 WLAN是英文WirelessLAN的缩写,就是无线局域网的意思.无线以太网技术是一种基于无线传输的局域网技术,与有线网络技术相比,具有灵活.建网迅速.个人化等特点.将 ...
- nexus5 博通芯片WIFI详解 (4)
1 IOCTL的调用逻辑 之所以要分析这个,是因为上层wpa_supplicant和WIFI驱动打交道的方式,多半是通过ioctl的方式进行的,所以看看它的调用逻辑(这里只列出其主要的调 ...
- nexus5 博通芯片WIFI详解 (2)
1 Wifi模块解析和启动流程 1.1 框架分析 WIFI整体框架如图所示: 首先,用户程序使用WifiManager类来管理Wifi模块,它能够获得Wifi模块的状态,配置和 ...
- 国产GPU的发展历程及芯片性能详解
一.国产GPU的发展历程 二.国产GPU进口代替的紧迫性 三.景嘉微:具有完全自主知识产权,打破国外GPU长期垄断 四.景嘉微国产GPU芯片概述 五.景嘉微国产GPU芯片性能详解 六.景嘉微国产GPU ...
- 利用和讯博客赚钱步骤详解
利用和讯博客赚钱步骤详解 来自朋友邻居大唐 玩博客的时间也不短了,原来一直在博客天下做,现在搬来和讯了.感觉这里很好,准备坚持做下去.踏进和讯的大门,发现这里的朋友都在玩Google AdSense, ...
- android wifi驱动_OTT盒子WiFi方案首选:博通2T2R WiFi模块
IT6356 WiFi模组简介 WiFi/BT/FM 3合1模块: 此模块为 2.4G + 5G 双频道,支持802.11a/b/g/n/AC,支持蓝牙 4.0:2T2R 双天线. 具有以下优势: 1 ...
- 通过源码详解 Servlet
Servlet 结构 1.Servlet Servlet 该接口定义了5个方法. init(),初始化 servlet 对象,完成一些初始化工作.它是由 servlet 容器控制的,该方法只能被调用一 ...
- linux中关于wifi函数,wifi详解(五)
user interface Android WiFiService WPA_Supplicant DHD Driver Dongle Binary BCM43xxHardware 蓝色:需要修改 黑 ...
- [转载]Android Wi-Fi 设置country code的调用流程(博通芯片为base)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/xiaoxiangyuhai/artic ...
最新文章
- 更快的 Maven 来了!!!性能提升 300%
- 南昌航空航天c语言试卷,2016年南昌航空大学软件学院程序设计复试笔试仿真模拟题...
- leetcode算法题--LRU缓存机制
- IETF访谈: HTTP/3全球份额持续增长,QUIC前景一片光明
- logcat不显示信息
- 机器学习、深度学习资料推荐
- 【比原链】比原启动后去哪里连接别的节点
- 把CS文件编译成dll文件
- Chart 控件 for vs2008的安装
- 小飞机安卓android手机设置教程,全民飞机大战叉叉助手安卓版设置步骤教程详解...
- 双系统格式化Ubuntu分区后Windows 开机出现grub rescue问题
- SlickEdit配置保存路径
- 卡方检验检验水准矫正_医学统计学 第七章 卡方检验
- 抓取微信小程序数据加密内容
- mentohust找不到服务器 重启认证,mentohust官方使用说明(全+转)
- java导出帆软pdf,java后台把fineRepo图表导出pdf格式时发生错误!
- linux两个邮件服务,Linux系列-Red Hat5平台下的Postfix邮件服务搭建(二)
- C++画图 => 蓝桥杯青少组C++ => 信奥 学习路线图
- 201421410039鹿永润实验二第一部分
- 华硕fl8000u是什么型号_华硕fl8000u怎么样 华硕笔记本fl8000u配置是什么
热门文章
- FlowJO X 流式补偿调整
- vue-router路由防卫
- html设计的概念,HTML标签, 元素与列表,前端UI设计-2019.08.30
- java淡蓝色怎么表示_最淡的蓝是什么颜色(淡蓝色配什么颜色好看)
- 2022-2-13 转换函数(conversion function) non-explicit-one argument ctor explicit-one argument ctor
- snap 无法卸载_你手机里有哪些不想卸载的良心 App?
- 电脑显示找不到msvcp140.dll怎么修复?
- 红亚太学链微信公众号正式发布
- python控制苹果手机触摸屏失灵怎么办_苹果手机触摸屏失灵的各种解决方法
- 转:网页游戏都有哪些安全问题