提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


文章目录

  • 前言
  • 一、Android的wifi框架简介
    • 1. wifi驱动启动流程
  • 二、wifi驱动代码编译进内核
  • 三、DTS配置
  • 四、扫描SDIO CARD
    • 1. sdio device扫描
      • 1) mmc_alloc_host()
      • 2) mmc_rescan()
      • 3) mmc_rescan_try_freq()
      • 4) mmc_attach_sdio()
      • 5) mmc_sdio_init_card()
      • 6) mmc_add_card()
    • 2. sdio driver匹配
    • 3. 扫卡小结
  • 五、firmware加载
  • 六、wpa_supplicant启动
  • 七、问题排查
    • 1. sdio扫卡无法识别
      • 1) sdio硬件原理图
      • 2) sdio管脚
      • 3) sdio cmd格式
      • 4) 问题现象
      • 5) 问题解决
    • 2. 无法扫描热点
  • 总结

前言

刚入职两周不到,接到移植wifi驱动的工作,之前从来没有接触过wifi驱动,看了一周没什么成果,同事没给出太多建设性意见,厂家技术支持也不给力,一个人硬啃效率太低了。
平台:amlogic
soc:a311d
wifi模组:aw3155(sdio接口)


一、Android的wifi框架简介

参考博客:
Android sdio_wifi架构
wifi详解(一)
wifi详解(二)
wifi详解(三)
wifi详解(四)
wifi详解(五)
Wifi模块全总结

1. wifi驱动启动流程

1)wifi芯片上电:
common\drivers\amlogic\wifi\wifi_dt.c中注册的平台驱动会解析DTS中关于上电管脚、中断管脚等资源,然后将管脚拉高,完成wifi芯片上电,我的VDDIO是1.8V;
2)扫描sdio card:
common\drivers\amlogic\mmc\aml_sd_emmc.c中注册的平台驱动会解析DTS中f_min、f_max等资源,然后调用mmc_alloc_host开始扫卡,扫描sdio card成功则创建一个sdio设备,在/sys/bus/sdio/devices/下生成节点;
3)加载aml_sdio.ko:
加载sdio的驱动,这是厂家给的驱动代码,加载的sdio_driver会和扫卡生成的sdio_device匹配,规则是vid、pid能够匹配上,然后进入probe中开始一些初始化工作;
4)加载vlsicomm.ko:
加载wifi驱动,这也是厂家给的驱动代码,
5)加载firmware:
6)启动wpa_supplicant:

二、wifi驱动代码编译进内核

之前都是手动编译,手动加载驱动,现在修改Android的编译脚本,实现编译源码时自动编译wifi驱动,开发板启动后自动加载驱动模块;

wifi_driver.mk:(用于自动编译目标文件下的驱动代码,并将ko文件拷贝出来)

+define aw3155-sdio-wifi
+  @echo "make aw3155 sdio wifi driver"
+  $(MAKE) -C $(shell pwd)/$(PRODUCT_OUT)/obj/KERNEL_OBJ M=$(shell pwd)/hardware/wifi/amlogic/a311d/vmac CONFIG_DHD_USE_STATIC_BUF=n CONFIG_BCMDHD_SDIO=n \
+  ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
+  cp $(shell pwd)/hardware/wifi/amlogic/a311d/vmac/vlsicomm.ko $(TARGET_OUT)/
+endefmultiwifi:@echo "make wifi module KERNEL_ARCH is $(KERNEL_ARCH)"mkdir -p $(TARGET_OUT)/
+  $(aw3155-sdio-wifi)

wifi_modules.mk:

######################################################################################## multiwifi
ifeq ($(WIFI_MODULE),multiwifi)
DEFAULT_WIFI_KERNEL_MODULES := \
+  $(PRODUCT_OUT)/obj/lib_vendor/vlsicomm.ko \

init.amlogic.wifi_buildin.rc:(启动脚本里自动加载驱动模块)

on bootinsmod /vendor/lib/modules/vlsicomm.ko

三、DTS配置

DTS配置:

wifi{compatible = "amlogic, aml_wifi";dev_name = "aml_wifi";status = "okay";interrupt_pin = <&gpio GPIOX_7 GPIO_ACTIVE_HIGH>;irq_trigger_type = "GPIO_IRQ_LOW";power_on_pin = <&gpio GPIOX_6 GPIO_ACTIVE_HIGH>;dhd_static_buf;pinctrl-names = "default";pinctrl-0 = <&pwm_e_pins>;pwm_config = <&wifi_pwm_conf>;
};
wifi_pwm_conf:wifi_pwm_conf{pwm_channel1_conf {pwms = <&pwm_ef MESON_PWM_0 30541 0>;duty-cycle = <15270>;times = <10>;};pwm_channel2_conf {pwms = <&pwm_ef MESON_PWM_2 30500 0>;duty-cycle = <15250>;times = <12>;};
};
sd_emmc_a:sdio@ffe03000 {status = "disabled";compatible = "amlogic, meson-mmc-g12b";reg = <0xffe03000 0x800>;interrupts = <0 189 4>;pinctrl-names = "sdio_all_pins","sdio_clk_cmd_pins";pinctrl-0 = <&sdio_all_pins>;pinctrl-1 = <&sdio_clk_cmd_pins>;clocks = <&clkc CLKID_SD_EMMC_A>,<&clkc CLKID_SD_EMMC_A_P0_COMP>,<&clkc CLKID_FCLK_DIV2>,<&clkc CLKID_FCLK_DIV5>,<&xtal>;clock-names = "core", "clkin0", "clkin1", "clkin2", "xtal";bus-width = <4>;//此配置同SD卡功能。number of data lines,此配置标识需要使用SD卡的线宽。SD卡最大支持4线模式.cap-sd-highspeed;//此配置同SD卡功能,作为SDIO外设,也有区分是否为highspeed的SDIO外设cap-mmc-highspeed;max-frequency = <100000000>;//sd卡的配置,最大运行频率为100Mhzdisable-wp;sdio {pinname = "sdio";ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */max_req_size = <0x20000>; /**128KB*/card_type = <3>;/* 3:sdio device(ie:sdio-wifi),* 4:SD combo (IO+mem) card*/};
};
&sd_emmc_a {status = "okay";sdio {caps = "MMC_CAP_4_BIT_DATA","MMC_CAP_MMC_HIGHSPEED","MMC_CAP_SD_HIGHSPEED","MMC_CAP_NONREMOVABLE","MMC_CAP_UHS_SDR12","MMC_CAP_UHS_SDR25","MMC_CAP_UHS_SDR50","MMC_CAP_UHS_SDR104","MMC_PM_KEEP_POWER","MMC_CAP_SDIO_IRQ";f_min = <400000>;f_max = <200000000>;};
};

四、扫描SDIO CARD

1. sdio device扫描

wifi模组上电之后,进入扫卡阶段,主要代码在driver/mmc/下的文件;

MMC子系统识别sdio设备大致过程如下:第一步 : 创建 mmc_bus,sdio_bus 两条虚拟总线第二步 : 创建卡设备驱动,并挂载到其对应的总线上去。
mmc设备驱动:初始化注册块设备驱动,在 drivers/mmc/card/block.c 中注册一个块设备,并将他挂载到前面创建的 mmc总线上;
sdio设备驱动:初始化注册sdio设备驱动,在 drivers/mmc/card/sdio_uart.c 中注册一个sdio设备,并将他挂载到前面创建的 sdio总线上。第三步 : 初始化 struct mmc_host结构体第四步 : 初始化 host->detect = mmc_rescan,该函数用于检测扫描添加卡设备,检测到卡设备后,
根据卡类型创建初始化该卡,并添加到对应的总线上去;
本例是sdio设备,所以创建并初始化struct mmc_card 设备,并将其挂在sdio总线上。第五步 : 设置中断函数,内部是 mmc_schedule_delayed_work(&host->detect, delay),
即执行延期工作的任务调用host->detect = mmc_rescan 检测扫描添加 mmc设备。
此处中断中这是该扫描操作应该是为了识别那些在mmc_host 被添加之前插入的卡。第六步 : 添加 mmc_host,并开始执行 mmc_schedule_delayed_work(&host->detect, delay),
即执行延期工作的任务 调用host->detect = mmc_rescan 检测扫描添加 mmc设备。第七步 : 等到识别到卡插入,添加struct mmc_card 设备到其对应的总线其所在的总线开始调用match()进行匹配,
匹配与其对应的驱动,我们这个是sdio设备,匹配的就是sdio设备驱动,匹配成功后调用总线驱动的prob,prob中再调用sdio设备驱动的prob。

1) mmc_alloc_host()

drivers/mmc/core/host.c

struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{int err;struct mmc_host *host;// 分配 struct mmc_host结构体空间host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
...//设置 host->detect = mmc_rescan    延期工作的任务初始化INIT_DELAYED_WORK(&host->detect, mmc_rescan);...
}

2) mmc_rescan()

drivers/mmc/core/core.c

//在4个频率下扫描设备(400kHZ,300kHZ,200kHZ,100kHZ)
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };void mmc_rescan(struct work_struct *work)
{/* 1 检测卡是否插入有效 */....../* 2 扫描该卡 */for (i = 0; i < ARRAY_SIZE(freqs); i++) {if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) {extend_wakelock = true;break;}if (freqs[i] <= host->f_min)break;}......
}

3) mmc_rescan_try_freq()

drivers/mmc/core/core.c

static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
{....../** sdio_reset sends CMD52 to reset card.  Since we do not know* if the card is being re-initialized, just send it.  CMD52* should be ignored by SD/eMMC cards.*/sdio_reset(host);//在扫描前先发个sdio_reset(CMD52)命令,只有sdio设备会有响应;mmc_go_idle(host);//发送CMD0,设置卡为IDLE状态mmc_send_if_cond(host, host->ocr_avail);//通过命令CMD8检测sd card支持的工作电压/* host在扫描卡的过程中,其识别的顺序为SDIO  SD MMC,一旦扫到立即返回;*//* Order's important: probe SDIO, then SD, then MMC */if (!mmc_attach_sdio(host))return 0;if (!mmc_attach_sd(host))return 0;if (!mmc_attach_mmc(host))return 0;mmc_power_off(host);return -EIO;
}

4) mmc_attach_sdio()

drivers/mmc/core/sdio.c

int mmc_attach_sdio(struct mmc_host *host)
{struct mmc_card *card;/*通过CMD5,获取card支持的电压域,根据host所支持的电压域,得到host和card都支持的电压域rocr,并将rocr传入mmc_sdio_init_card*/err = mmc_send_io_op_cond(host, 0, &ocr);if (err)return err;mmc_attach_bus(host, &mmc_sdio_ops);if (host->ocr_avail_sdio)host->ocr_avail = host->ocr_avail_sdio;/*确定host、card都支持的最低电压*/rocr = mmc_select_voltage(host, ocr);.../*这个函数用于检测,并初始化card,从CCCR寄存器获取card支持的speed模式,bus width;从CIS Area中获取CIS 信息,比如vendor id,device id等*/mmc_sdio_init_card();card->type = MMC_TYPE_SDIO;//设置卡的类型为 MMC_TYPE_SDIO.../*注册SDIO的各个功能模块,初始化每个function,获取每个function的CIS信息,并为每个function分配一个device,设置bus type为sdio_bus_type,去匹配sdio_driver;将所有的function device调用device_add(&func->dev),添加到device架构中*/for (i = 0;i < funcs;i++) {err = sdio_add_func(host->card->sdio_func[i]);if (err)goto remove_added;}/*添加SDIO卡。成功则打印:mmc1: new ultra high speed SDR104 SDIO card at address 0001*/err = mmc_add_card(host->card);}

5) mmc_sdio_init_card()

drivers/mmc/core/sdio.c

int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,struct mmc_card *oldcard, int powered_resume)
{/*如果host支持uhs模式,则switch信号电压为1.8v*/if (mmc_host_uhs(host))ocr |= R4_18V_PRESENT;/*设置card支持的电压为ocr,这个电压是mmc_sdio_init_card传入的rocr*/if (!powered_resume) {err = mmc_send_io_op_cond(host, ocr, &rocr);/*分配一个mmc_card结构体*/card = mmc_alloc_card(host, NULL);if (IS_ERR(card)) {err = PTR_ERR(card);goto err;}/*如果card存在memory部分,那么获取card的cid,并设置card类型是SD_COMBO card。*/if ((rocr & R4_MEMORY_PRESENT) &&mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) {card->type = MMC_TYPE_SD_COMBO;if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) {mmc_remove_card(card);return -ENOENT;}} else {/*如果没有memory部分,那么card类型为MMC_TYPE_SDIO card*/card->type = MMC_TYPE_SDIO;if (oldcard && oldcard->type != MMC_TYPE_SDIO) {mmc_remove_card(card);return -ENOENT;}}/*如果card支持UHS-I(rocr 中S18A=1),并且和host也支持UHS-I,那么进行信号电压电平切换为1.8vif (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {/*发送CMD11,然后进行电压切换操作*/err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,ocr_card);if (err == -EAGAIN) {sdio_reset(host);mmc_go_idle(host);mmc_send_if_cond(host, host->ocr_avail);mmc_remove_card(card);retries--;goto try_again;} else if (err) {ocr &= ~R4_18V_PRESENT;}err = 0;} else {ocr &= ~R4_18V_PRESENT;}/** For native busses:  set card RCA and quit open drain mode.*/if (!powered_resume && !mmc_host_is_spi(host)) {/*发送CMD3,获取RCA*/err = mmc_send_relative_addr(host, &card->rca);if (err)goto remove;}/** Read CSD, before selecting the card*/if (!oldcard && card->type == MMC_TYPE_SD_COMBO) {/*如果包含memory部分,则获取CSD*/err = mmc_sd_get_csd(host, card);if (err)return err;mmc_decode_cid(card);                         }/** Select card, as all following commands rely on that.*/if (!powered_resume && !mmc_host_is_spi(host)) {/*发送CMD7 select carderr = mmc_select_card(card);                       if (err)goto remove;}  /*获取CCCR信息*/err = sdio_read_cccr(card,  ocr);if (err)goto remove;/*获取Common CIS信息*/err = sdio_read_common_cis(card);if (err)goto remove;card->ocr = ocr_card;        mmc_fixup_device(card, NULL);/** If needed, disconnect card detection pull-up resistor.*/err = sdio_disable_cd(card);if (err)goto remove;/* Initialization sequence for UHS-I cards *//* Only if card supports 1.8v and UHS signaling *//*设置card speed,wide*/if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) err = mmc_sdio_init_uhs_card(card);}

6) mmc_add_card()

drivers/mmc/core/bus.c

int mmc_add_card(struct mmc_card *card)
{int ret;//将card注册进linux设备模型  注册结果就是可以在/sys/bus/mmc/devices目录下见到card 的名字ret = device_add(&card->dev);//struct device dev;/* the device */return 0;
}

扫卡成功会在/sys/bus/mmc/devices/和/sys/bus/sdio/devices/下生成sdio设备节点。
参考博客:MMC子系统识别SD设备过程简述

2. sdio driver匹配

加载的sdio_driver和sdio_device会进行匹配,规则为:
通过driver id和func比较vendor和device来确定是否匹配device和driver

static struct bus_type sdio_bus_type = {.name       = "sdio",                .dev_groups = sdio_dev_groups,       .match      = sdio_bus_match,        .uevent     = sdio_bus_uevent,       .probe      = sdio_bus_probe,        .remove     = sdio_bus_remove,       .pm     = &sdio_bus_pm_ops,
};static int sdio_bus_match(struct device *dev, struct device_driver *drv)
{                                                                       struct sdio_func *func = dev_to_sdio_func(dev);                     struct sdio_driver *sdrv = to_sdio_driver(drv);                     if (sdio_match_device(func, sdrv))                                  return 1;                                                       return 0;
}static const struct sdio_device_id *sdio_match_device(struct sdio_func *func,struct sdio_driver *sdrv)
{                                                                            const struct sdio_device_id *ids;                                        ids = sdrv->id_table;                                                    if (ids) {                                                               while (ids->class || ids->vendor || ids->device) {                   if (sdio_match_one(func, ids))                                   return ids;                                                  ids++;                                                           }                                                                    }                                                                        return NULL;
}
static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,const struct sdio_device_id *id)
{                                                                         if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)       return NULL;                                                      if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)   return NULL;                                                      if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)   return NULL;                                                      return id;
}

从上面可以看出sdio_driver通过driver id匹配的device实际上是function的device

3. 扫卡小结

1)scan card设置的频率是在400k到host支持的最低频率,逐个频率之间进行扫描,直到扫描到card为止
2)获取card支持的电压ocr域,是否支持UHS,以及card支持的function num
3)card支持uhs,则对电压电平进行切换
4)读取card的CCCR和CIS寄存器信息,其中CCCR信息包括了sdio version,bus wide以及card支持的速率,CIS信息包括vendor,device id等
5)调用sdio_alloc_func 为每一func分配一个sdio_func结构体,并通过device_initialize初始化func->dev
6)调用sdio_add_func 通过device_add添加每个fun的dev,用于匹配sdio_driver

五、firmware加载

之前使用的博通的AP6256wifi模组,需要脚本里修改firmware的路径才能让驱动完成加载;这次使用的AW3155,厂家说不需要加载.biin文件,省不少事。

六、wpa_supplicant启动

参考博客:wpa_supplicant连接wifi

博通wpa_supplicant启动参数:

service wpa_supplicant /system/bin/wpa_supplicant \-iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \-I/system/etc/wifi/wpa_supplicant_overlay.conf \-e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0class mainsocket wpa_wlan0 dgram 660 wifi wifidisabledoneshot

参数解释:

-iwlan0:指定网络接口wlan0
-D 指定wifi驱动的的接口 这里是nl80211
-C 指定 wpa_supplicant 初始化的时候需要读取配置文件
这里是/data/misc/wifi/wpa_supplicant.conf
-I 备用读取配置文件
-g 指定 ctrl_interface =  @android:wpa_ 和 -i 指定waln0组合
-B:表示将守护进程wpa_supplicant 挂到后台运行

wpa_supplicant.conf:

update_config=1
eapol_version=1
ap_scan=1
fast_reauth=1
pmf=1
wowlan_triggers=any

七、问题排查

1. sdio扫卡无法识别

1) sdio硬件原理图

2) sdio管脚

SDIO_DATA_0~3:数据线,平时为高,电压取决于 VDDIO的电压;
SDIO_DATA_CMD:命令线,平时为高,电压取决于 VDDIO的电压;
SDIO_DATA_CLK:时钟,平时为低,电压取决于 VDDIO的电压;
VBAT_WL:WIFI 模组供电电源,一直都为高,为3.3v;
VDDIO:给 DATA/CMD/CLK 的 IO 供电电源,可以为 3.3 或者 1.8v,但 SDIO3.0必须为 1.8v;
WL_REG_ON: 正常工作时为 1.8v,WiFi 关闭时为 0v;

3) sdio cmd格式

#CMD Line上传输的是MSB优先
command:由host发送到device的命令
response:在device收到这个cmd之后会在CMD信号线上返回一个response令牌(token)用来回复之前接收到的命令。
但是不是所有的cmd,sdio device都会回复,如果sdio device没有包含memory portion,则不会响应给SD card的cmd命令。

a. Command格式:

[47]bit:起始位start bit始终为0
[46]bit:代表传输的方向,bit = 1代表由host端发送给device端,bit = 0代表由device端回复给host
[45:40]bit:代表命令索引command index,例如CMD0 这项值为0 ,CMD5则这项值为5,它的范围是0-63
[39:8]bit:是该CMD所附带的一些参数,不同的CMD,这32bit每一位所代表的含义是不一样的
[7:1]bit:这7位是CRC校验码,它是对[47-8]bit进行循环冗余校验所得到的值,line的校验方式与command有所不同,它使用的是CRC16,而Command使用的是CRC7,command和response使用的多项式生成公式都是G(x) = x^7+x^3+1 data
[0]bit:始终为1,代表cmd命令结束

b. Response格式:
  它的格式与commad不同的地方是response格式取决于response的类型,类型不一样,长度也不一样;但是所有的response类型它的格式起始位都是0,接着一位代表传输方向固定为0。除去R3以外,其他的response都附带CRC。
  SD 内存卡支持五种response type:R1,R1b,R2,R3,R6
  SDIO卡额外支持2种response type:R4,R5

  • response R1 (normal response command):

      start bit和transmission bit都固定为0,command index代表命令的索引,表示回复的是哪个Command,card status用于表示传输过程中card的状态信息,它有32bit,除去reserved bit以外,其他的bit都代表一个状态标志,用于表示card处理上一个command时的某些状态。
  • resposne R2

      它的长度是136个bit,如果[127:1]位中包含的是CID寄存器中的信息,那么该response回复的是CMD2和CMD10,如果[127:1]位中包含的是CSD寄存器中的信息,则回复的是CMD9
  • response R3

      回复code的长度是48bit,其中包含了OCR寄存器中的信息,SD memory card用来回复ACMD41
  • response R6

      用来回复CMD3
  • response R7
      回复code的长度是48bit,用来表示该card支持的电压信息,[19:16]代表card中支持的电压信息,用来回复CMD8
  • response R4
      用来回复CMD5,该CMD是给SDIO card专用的,用来查询card中支持的电压域,response则回复支持的电压域
  • response R5
     用来回复CMD52,该CMD是给SDIO card专用的

参考博客:
sdio总线简介之CMD
SDIO设备对象管理
SD/MMC + SDIO + HAL

4) 问题现象

host发送CMD52给device,初始化

主控发出的波形: 当最开始的两个电平有一低一高时,是主控发出去的命令;
SD 卡响应的波形: 当最开始的两个电平有连续的两个低电平时,表示卡端有响应;
其次主控和响应一般包含 48 个 bit 的数据,所以 48 个 clk 为一个完整的包。要确认的就是:主控发出去命令包后,SD 卡端是否有响应。
但是捕获到的sdio cmd波形只有host给device的command,没有device给host的response,检查上电正常,sdio时钟频率正常。
总之,我的主芯片无法和sdio接口完成通讯,所以判断是硬件有问题。

补充:sdio_reset()中发送CMD52时,有资料也说从机不会发出回应给主机,不过在err = mmc_send_io_op_cond(host, 0, &ocr);中会发送CMD5获取OCR寄存器,也就是要获取card支持的电压域,这必须要从机返回R4,所以扫卡失败也可能是这句话没有执行成功,反正确定是sdio无法与主机通讯的问题。

5) 问题解决

后来把板子寄给厂家,解决办法:
1、拆掉外部晶振,因为模组自带内部晶振;
2、发现32.768khz的引脚波形不正常,将电阻从100k更换为100(可能是电阻太大了),最后就能够捕捉到正常的32.768khz波形了,sdio扫卡也能完成了。


32.768khz时钟和wifi上电时序有关系:

2. 无法扫描热点

在ui界面打开wifi按钮,没有显示热点;使用wpa_cli -iwlan0运行wpa客户端,scan命令还是扫描不到热点。折腾来折腾去,重新焊一块wifi模组后,居然成功了。


总结

刚拿到这个任务时,一脸懵逼,连脚本在哪、驱动该放到哪都不知道,一个人啃啊啃,一个月后,终于是完成了,遇到的两次大问题,居然都是硬件问题,期间还因为进度慢被老板吊了,哎,新手伤不起啊。

Android驱动——WiFi驱动移植相关推荐

  1. android的wifi网卡移植详细过程已经通用驱动的问题

    这里有一篇详细的教程,看完还有一个问题 就是android的wifi驱动移植,如果有wifi网卡的驱动代码,是一定需要对android系统本身的代码修改重写编译吗?就是说,有无可能不改变android ...

  2. android usb wifi驱动下载,android 平台USB wifi驱动移植及使用

    一.   Android平台Wifi的基本代码路径 1.       Wpa_supplicant源码部分 external/wpa_supplicant_6/ 生成库libwpa_client.so ...

  3. android移植wifi驱动流程porting

    android载入wifi驱动流程 wifi_load_driver check_wifi_chip_type_string get_wifi_device_id save_wifi_chip_typ ...

  4. 4.0 RTL8723DU驱动(wifi+蓝牙)

    文章目录 写在前面 wifi驱动涉及代码 wifi驱动设备树修改 wifi驱动修改px30_linux_defconfig wifi驱动修改Kconfig wifi驱动修改Makefile wifi驱 ...

  5. Android wifi驱动的移植 realtek 8188

    Android wifi驱动的移植 一般我们拿到的android源代码中wifi应用层部分是好的, 主要是wifi芯片的驱动要移植并添加进去. wifi驱动的移植, 以realtek的8188etv为 ...

  6. android+wifi驱动移植,全志R16 android4平台移植wifi资料下载

    2. 模块概述 目前R16 android4.4 平台上已支持wifi 模组有5款,本文档将以R16 y3方案为例 说明如何配置每款wifi 模组.Rtl8723au暂不支持 wifi 模组可分USB ...

  7. android+wifi驱动移植,全志平台ap6476 wifi模组调试(2)驱动移植 配置文件修改

    1. 前言 基于上篇的环境,继续修改: 这里主要是修改驱动模块和配置文件 2. driver修改 当前broadcom系统的ap6xxx模组,wifi是共用同一份驱动,增加同系列的一款wifi的支持, ...

  8. GEC6818 移植 rtl8723bu wifi驱动

    文章目录 1. 配置内核 2.RTL8723BU 模块驱动编译 2.1 下载解压 2.2 配置编译 3. openssl 移植 3.1 下载解压 3.2 配置 3.3 编译安装 4. libnl 移植 ...

  9. I.MX6 AW-NB177NF WIFI 驱动移植问题

    /********************************************************************************* I.MX6 AW-NB177NF ...

最新文章

  1. 利用Python进行数据分析(第2版)
  2. morlet包络检波matlab,布里渊光纤传感系统中的信号处理的研究
  3. 算法题 身高差_10个大数据处理常见算法题
  4. np.nonzero()函数的解析
  5. 漫画算法:找出缺失的整数
  6. LeetCode 15. 三数之和 思考分析(双指针解)
  7. LeetCode MySQL 1084. 销售分析III
  8. IP计算机取证,计算机取证1资料.doc
  9. freemarker 模板填充乱码
  10. 【Java】MapReduce编程的编程思想以及基于Hadoop的Wordcount的程序的实现
  11. 一张速查表看懂Git命令,搞定版本控制照做就ok丨新手福利
  12. 基于MATLAB的指纹识别系统
  13. C#调用excel报错 (异常来自 HRESULT:0x80010105 (RPC_E_SERVERFAULT))问题的解决方案
  14. canvas制作圆角矩形(包括填充矩形的功能)
  15. SVN服务端安装与配置
  16. 微信公众平台自定义菜单
  17. 【计算机网络】DNS域名系统
  18. 直播泡沫?3.5万亿红人经济的未来在这几个字里
  19. 前端分享之tinymce编辑器设置默认字体
  20. yjk的波库在哪里_专题文档

热门文章

  1. windows下vscode + code runner + cmake + msbuild.exe搭建C++快速编译环境
  2. 如何缩小图片大小(手机照片怎么缩小尺寸)
  3. 计算机学业水平考试的选择题,信息技术学业水平考试选择题带答案.doc
  4. 低成本撬动TK亿万流量 TK带货视频有多简单?
  5. linux配置samba用户时失败,Ubuntu下Samba的设置,及用户登录失败的解决
  6. 我们为什么选择NEXTCHIP?为什么要选择ISP?为什么要选择AHD?为什么选择北京冠宇铭通?
  7. ubuntu介绍以及使用
  8. 【论文阅读】Heterogeneous Graph Attention Network
  9. STM32的频率和占空比计算
  10. 如何测试硬盘软件,如何进行硬盘测试?磁盘健康检测方法介绍