日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux移植wifi sd8688.bin 最新固件,[ZZ]浅析firmware完整生存和使用流程

發布時間:2024/4/17 linux 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux移植wifi sd8688.bin 最新固件,[ZZ]浅析firmware完整生存和使用流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

/class/firmware

error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);//創建/class/firmware/mmc1:0001:1/目錄

if (error)

goto Error;

if (platform_notify)

platform_notify(dev);

if (dev->bus)

blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

BUS_NOTIFY_ADD_DEVICE,

dev);

error = device_create_file(dev, &uevent_attr);

if (error)

goto attrError;

if (MAJOR(dev->devt)) {

error = device_create_file(dev, &devt_attr);

if (error)

goto

ueventattrError;

}

error =

device_add_class_symlinks(dev);

if (error)

goto

SymlinkError;

error = device_add_attrs(dev);

if (error)

goto

AttrsError;

error = dpm_sysfs_add(dev);

if (error)

goto PMError;

device_pm_add(dev);

error = bus_add_device(dev);

if (error)

goto BusError;

kobject_uevent(&dev->kobj,

KOBJ_ADD);//向用戶空間發送uevent事件,如果kset和class

bus_attach_device(dev);

if (parent)

klist_add_tail(&dev->knode_parent,

&parent->klist_children);

if (dev->class) {

down(&dev->class->sem);

list_add_tail(&dev->node, &dev->class->devices);

list_for_each_entry(class_intf, &dev->class->interfaces, node)

if (class_intf->add_dev)

class_intf->add_dev(dev, class_intf);

up(&dev->class->sem);

}

Done:

put_device(dev);

return error;

BusError:

device_pm_remove(dev);

PMError:

if (dev->bus)

blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

BUS_NOTIFY_DEL_DEVICE,

dev);

device_remove_attrs(dev);

AttrsError:

device_remove_class_symlinks(dev);

SymlinkError:

if (MAJOR(dev->devt))

device_remove_file(dev, &devt_attr);

ueventattrError:

device_remove_file(dev, &uevent_attr);

attrError:

kobject_uevent(&dev->kobj,

KOBJ_REMOVE);

kobject_del(&dev->kobj);

Error:

cleanup_device_parent(dev);

if (parent)

put_device(parent);

goto Done;

}

int

kobject_uevent(struct

kobject *kobj, enum kobject_action action)

{

return

kobject_uevent_env(kobj, action, NULL);//發布uevent事件

}

int

kobject_uevent_env(struct kobject *kobj, enum kobject_action action,

char *envp_ext[])

{

struct kobj_uevent_env

*env;

const char *action_string = kobject_actions[action];

const char *devpath = NULL;

const char *subsystem;

struct kobject

*top_kobj;

struct kset *kset;

struct kset_uevent_ops

*uevent_ops;

u64 seq;

int i = 0;

int retval = 0;

pr_debug("kobject: '%s' (%p):

%s\n",

kobject_name(kobj), kobj, __FUNCTION__);

top_kobj =

kobj;

while (!top_kobj->kset && top_kobj->parent)

top_kobj =

top_kobj->parent;

if (!top_kobj->kset) {

pr_debug("kobject: '%s' (%p): %s: attempted to send

uevent "

"without

kset!\n",

kobject_name(kobj), kobj,

__FUNCTION__);

return -EINVAL;

}

//對于device_register(),

//kset =

devices_kset;

//uevent_ops =

device_uevent_ops;[luther.gliethttp]

kset =

top_kobj->kset;

uevent_ops =

kset->uevent_ops;

if (uevent_ops &&

uevent_ops->filter)

if (!uevent_ops->filter(kset, kobj)) {

//該uevent是否被過濾了,

//對于device_register(),如果dev->uevent_suppress

= 1;

//那么表示用戶希望過濾掉該uevent,所以在這里直接返回即可.

//對于上面request_firmware中fw_register_device的

//retval =

device_register(f_dev);在執行之前,調用了f_dev->uevent_suppress

= 1;

//就表示在這里將直接返回,它不希望產生uevent事件到用戶空間,它會自己選擇時機

//調用kobject_uevent()來讓uevent事件發送給用戶空間[luther.gliethttp].

pr_debug("kobject: '%s' (%p): %s: filter function

"

"caused the event to

drop!\n",

kobject_name(kobj), kobj, __FUNCTION__);

return 0;

}

if (uevent_ops &&

uevent_ops->name)

subsystem =

uevent_ops->name(kset, kobj);

else

subsystem =

kobject_name(&kset->kobj);

if (!subsystem) {

pr_debug("kobject: '%s' (%p): %s: unset subsystem

caused the "

"event to

drop!\n",

kobject_name(kobj), kobj,

__FUNCTION__);

return 0;

}

env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);

if (!env)

return -ENOMEM;

devpath =

kobject_get_path(kobj, GFP_KERNEL);

if (!devpath) {

retval = -ENOENT;

goto exit;

}

retval =

add_uevent_var(env, "ACTION=%s", action_string);

if (retval)

goto exit;

retval =

add_uevent_var(env, "DEVPATH=%s", devpath);

if (retval)

goto exit;

retval =

add_uevent_var(env, "SUBSYSTEM=%s", subsystem);

if (retval)

goto exit;

if (envp_ext) {

for (i = 0; envp_ext[i]; i++) {

retval =

add_uevent_var(env, envp_ext[i]);

if (retval)

goto exit;

}

}

if (uevent_ops &&

uevent_ops->uevent) {

//對于device_register()來說,就是對于f_dev這個kobj來說,

//就是調用dev_uevent添加major和minor等操作[luther.gliethttp]

retval =

uevent_ops->uevent(kset, kobj, env);

if (retval) {

pr_debug("kobject: '%s' (%p): %s: uevent() returned

"

"%d\n", kobject_name(kobj), kobj,

__FUNCTION__, retval);

goto exit;

}

}

...

}

int __init

devices_init(void)

{

devices_kset =

kset_create_and_add("devices", &device_uevent_ops,

NULL);

//在sysfs文件系統的根目錄下建立deviecs這個kset可視文件,比如/sys/devices

//該kset的uevent處理函數為device_uevent_ops

if (!devices_kset)

return -ENOMEM;

return 0;

}

static struct kset_uevent_ops

device_uevent_ops =

{

.filter = dev_uevent_filter,

.name = dev_uevent_name,

.uevent = dev_uevent,

};

static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)

{

struct kobj_type

*ktype = get_ktype(kobj);

if (ktype == &device_ktype)

{

//為默認的device_ktype管理

//在device_register=>device_initialize=>kobject_init(&dev->kobj,

&device_ktype);

struct device *dev = to_dev(kobj);

if (dev->uevent_suppress)//調用device_register()函數的驅動不希望dev的uevent發布到用戶空間

return 0;

if (dev->bus)

return 1;

if (dev->class)

return 1;

}

return 0;

}

static int dev_uevent(struct kset *kset, struct kobject *kobj,

struct kobj_uevent_env

*env)

{

struct device *dev = to_dev(kobj);

int retval = 0;

if (MAJOR(dev->devt)) {//填充major和minor設備號,以便接收uevent事件的init進程,能夠mknod來創建相應的節點文件在/dev目錄下[luther.gliethttp].

add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));

add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));

}

if (dev->type && dev->type->name)

add_uevent_var(env, "DEVTYPE=%s", dev->type->name);

if (dev->driver)

add_uevent_var(env, "DRIVER=%s", dev->driver->name);

#ifdef CONFIG_SYSFS_DEPRECATED

if (dev->class) {

struct device *parent = dev->parent;

while (parent && !parent->bus)

parent =

parent->parent;

if (parent && parent->bus) {

const char *path;

path =

kobject_get_path(&parent->kobj, GFP_KERNEL);

if (path) {

add_uevent_var(env, "PHYSDEVPATH=%s", path);

kfree(path);

}

add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);

if (parent->driver)

add_uevent_var(env, "PHYSDEVDRIVER=%s",

parent->driver->name);

}

} else if (dev->bus) {

add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);

if (dev->driver)

add_uevent_var(env, "PHYSDEVDRIVER=%s",

dev->driver->name);

}

#endif

if (dev->bus && dev->bus->uevent) {

retval = dev->bus->uevent(dev, env);

if (retval)

pr_debug("device: '%s': %s: bus uevent() returned

%d\n",

dev->bus_id, __FUNCTION__, retval);

}

if (dev->class && dev->class->dev_uevent) {

retval = dev->class->dev_uevent(dev, env);

if (retval)

pr_debug("device: '%s': %s: class uevent()

"

"returned

%d\n",

dev->bus_id,

__FUNCTION__, retval);

}

if (dev->type && dev->type->uevent) {

retval = dev->type->uevent(dev, env);

if (retval)

pr_debug("device: '%s': %s: dev_type uevent()

"

"returned

%d\n",

dev->bus_id,

__FUNCTION__, retval);

}

return retval;

}

static int fw_setup_device(struct firmware *fw, struct device **dev_p,

const char *fw_name, struct device *device,

int uevent)

{

struct device *f_dev;

struct firmware_priv

*fw_priv;

int retval;

*dev_p = NULL;

retval =

fw_register_device(&f_dev, fw_name, device);

if (retval)

goto out;

__module_get(THIS_MODULE);

fw_priv =

dev_get_drvdata(f_dev);

fw_priv->fw = fw;

retval =

sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);

//在sysfs中創建bin類型文件,即:firmware_attr_data_tmpl

//sysfs_create_bin_file

//直接向sysfs的'內存磁盤'創建'磁盤文件'-firmware_attr_data_tmpl

if (retval) {

printk(KERN_ERR

"%s: sysfs_create_bin_file

failed\n",

__FUNCTION__);

goto

error_unreg;

}

//device_create_file=>sysfs_create_file

//直接向sysfs的'內存磁盤'創建'磁盤文件'-dev_attr_loading

retval =

device_create_file(f_dev, &dev_attr_loading);//firmware處理狀態提示文件

if (retval) {

printk(KERN_ERR

"%s: device_create_file

failed\n",

__FUNCTION__);

goto

error_unreg;

}

if (uevent)

//如果希望該request_firmware發送uevent到用戶空間,那么f_dev->uevent_suppress清0[luther.gliethttp]

f_dev->uevent_suppress

= 0;

*dev_p = f_dev;

goto out;

error_unreg:

device_unregister(f_dev);

out:

return retval;

}

static int

_request_firmware(const struct firmware **firmware_p, const char *name,

struct device *device, int uevent)

{

struct device *f_dev;

struct firmware_priv

*fw_priv;

struct firmware

*firmware;

int retval;

if (!firmware_p)

return -EINVAL;

*firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);

if (!firmware) {

printk(KERN_ERR

"%s: kmalloc(struct firmware)

failed\n",

__FUNCTION__);

retval = -ENOMEM;

goto out;

}

retval =

fw_setup_device(firmware, &f_dev, name, device, uevent);

if (retval)

goto

error_kfree_fw;

fw_priv =

dev_get_drvdata(f_dev);

if (uevent) {

if (loading_timeout > 0) {

fw_priv->timeout.expires = jiffies + loading_timeout * HZ;

add_timer(&fw_priv->timeout);

}

//因為上面device_register時,dev->uevent_suppress

= 1;

//所以device_register將uevent過濾掉了,沒有將uevent發送到用戶空間,

//后來dev->uevent_suppress =

0;所以所以經過上面亂七八糟的設置之后,現在它認為可以安全

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的linux移植wifi sd8688.bin 最新固件,[ZZ]浅析firmware完整生存和使用流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。