• 我对回调函数理解和驱动加载为什么要有顺序


                     (1)有什么事件来了,就调用相关的函数处理,非常方便用在库函数编写者提供一个callback作为接口,然后库调用者的做相关的事件处理和状态获取,库的编写者要屏蔽相关的信息,库的使用者需要更多的灵活权限,涉及两个人的使用.

    static  xxxxxxxxxxxxx(,,callback)

    {

         if(xxx) {

                   callback

        }

       if(xxx)  {

                 callback

       } 

    }

    static callback()

    {

           // 有什么状态信息  或者自己的事件处理   自己业务逻辑处理

    }

                    (2)所有层次代码编写  都是使用  注册   也就是填充 xxx结构体    在其他地方调用     这就是为什么要各种底层代码xxx驱动的注册

                        一般在core.c文件里面  .  一个复杂的带有函数指针的结构体变量    然后添加进链表里面    其他层会从这个链表里面取相关操作

                           linux驱动   linux 各种层次    常见    给其他层次代码使用      

       

     

      

          

    /* readonly to gadget driver */
     const struct usb_gadget_ops *ops;    // 代码uc硬件操作 udc控制基本操作 不涉及端点的操作
     struct usb_ep   *ep0;    // 端点0及其相关操作
    /* the rest of the api to the controller hardware: device operations,
     * which don't involve endpoints (or i/o).
     */
    struct usb_gadget_ops {
     int (*get_frame)(struct usb_gadget *);
     int (*wakeup)(struct usb_gadget *);
     int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
     int (*vbus_session) (struct usb_gadget *, int is_active);
     int (*vbus_draw) (struct usb_gadget *, unsigned mA);
     int (*pullup) (struct usb_gadget *, int is_on);
     int (*ioctl)(struct usb_gadget *,
        unsigned code, unsigned long param);
     void (*get_config_params)(struct usb_dcd_config_params *);
     int (*udc_start)(struct usb_gadget *,
       struct usb_gadget_driver *);
     int (*udc_stop)(struct usb_gadget *);
     struct usb_ep *(*match_ep)(struct usb_gadget *,
       struct usb_endpoint_descriptor *,
       struct usb_ss_ep_comp_descriptor *);
    };
    // 硬件底层  gadget.c    定义变量
    static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = {
     .get_frame = dwc2_hsotg_gadget_getframe,
     .udc_start  = dwc2_hsotg_udc_start,
     .udc_stop  = dwc2_hsotg_udc_stop,
     .pullup                 = dwc2_hsotg_pullup,
     .vbus_session  = dwc2_hsotg_vbus_session,
     .vbus_draw  = dwc2_hsotg_vbus_draw,
    };

    /**
     * dwc2_hsotg_udc_start - prepare the udc for work
     * @gadget: The usb gadget state
     * @driver: The usb gadget driver
     *
     * Perform initialization to prepare udc device and driver
     * to work.
     */
    static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
          struct usb_gadget_driver *driver)
    {
     struct dwc2_hsotg *hsotg = to_hsotg(gadget);
     unsigned long flags;
     int ret;
     if (!hsotg) {
      pr_err("%s: called with no device\n", __func__);
      return -ENODEV;
     }
     if (!driver) {
      dev_err(hsotg->dev, "%s: no driver\n", __func__);
      return -EINVAL;
     }
     if (driver->max_speed < USB_SPEED_FULL)
      dev_err(hsotg->dev, "%s: bad speed\n", __func__);
     if (!driver->setup) {
      dev_err(hsotg->dev, "%s: missing entry points\n", __func__);
      return -EINVAL;
     }
     WARN_ON(hsotg->driver);
     driver->driver.bus = NULL;
     hsotg->driver = driver;
     hsotg->gadget.dev.of_node = hsotg->dev->of_node;
     hsotg->gadget.speed = USB_SPEED_UNKNOWN;
     if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
      ret = dwc2_lowlevel_hw_enable(hsotg);
      if (ret)
       goto err;
     }
     if (hsotg->dr_mode == USB_DR_MODE_OTG) {
      struct platform_device *pdev = to_platform_device(hsotg->dev);
      if (hsotg->uphy) {
       ret = usb_phy_init(hsotg->uphy);
      } else if (hsotg->plat && hsotg->plat->phy_init) {
       ret = hsotg->plat->phy_init(pdev,
              hsotg->plat->phy_type);
      } else {
       ret = phy_power_on(hsotg->phy);
       if (ret == 0)
        ret = phy_init(hsotg->phy);
      }
      if (ret)
       goto err;
     }
     if (!IS_ERR_OR_NULL(hsotg->uphy))
      otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget);
     spin_lock_irqsave(&hsotg->lock, flags);
     if (dwc2_hw_is_device(hsotg)) {
      dwc2_hsotg_init(hsotg);
      dwc2_hsotg_core_init_disconnected(hsotg, false);
     }
     hsotg->enabled = 0;
     spin_unlock_irqrestore(&hsotg->lock, flags);
     dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
     return 0;
    err:
     hsotg->driver = NULL;
     return ret;
    }
    /**
     * dwc2_hsotg_pullup - connect/disconnect the USB PHY
     * @gadget: The usb gadget state
     * @is_on: Current state of the USB PHY
     *
     * Connect/Disconnect the USB PHY pullup
     */
    static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on)
    {
     struct dwc2_hsotg *hsotg = to_hsotg(gadget);
     unsigned long flags = 0;
     dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on,
       hsotg->op_state);
     /* Don't modify pullup state while in host mode */
     if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
      hsotg->enabled = is_on;
      return 0;
     }
     spin_lock_irqsave(&hsotg->lock, flags);
     if (is_on) {
      hsotg->enabled = 1;
      dwc2_hsotg_core_init_disconnected(hsotg, false);
      dwc2_hsotg_core_connect(hsotg);
     } else {
      dwc2_hsotg_core_disconnect(hsotg);
      dwc2_hsotg_disconnect(hsotg);
      hsotg->enabled = 0;
     }
     hsotg->gadget.speed = USB_SPEED_UNKNOWN;
     spin_unlock_irqrestore(&hsotg->lock, flags);
     return 0;
    }
    static int dwc2_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
    {
     struct dwc2_hsotg *hsotg = to_hsotg(gadget);
     unsigned long flags;
     dev_dbg(hsotg->dev, "%s: is_active: %d\n", __func__, is_active);
     spin_lock_irqsave(&hsotg->lock, flags);
     /*
      * If controller is hibernated, it must exit from hibernation
      * before being initialized / de-initialized
      */
     if (hsotg->lx_state == DWC2_L2)
      dwc2_exit_hibernation(hsotg, false);
     if (is_active) {
      hsotg->op_state = OTG_STATE_B_PERIPHERAL;
      dwc2_hsotg_core_init_disconnected(hsotg, false);
      if (hsotg->enabled)
       dwc2_hsotg_core_connect(hsotg);
     } else {
      dwc2_hsotg_core_disconnect(hsotg);
      dwc2_hsotg_disconnect(hsotg);
     }
     spin_unlock_irqrestore(&hsotg->lock, flags);
     return 0;
    }
     
    添加到另一个变量里面
    /**
     * dwc2_gadget_init - init function for gadget
     * @dwc2: The data structure for the DWC2 driver.
     * @irq: The IRQ number for the controller.
     */
    int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
    //
     hsotg->gadget.max_speed = USB_SPEED_HIGH;
     hsotg->gadget.ops = &dwc2_hsotg_gadget_ops;
     hsotg->gadget.name = dev_name(dev);
     if (hsotg->dr_mode == USB_DR_MODE_OTG)
      hsotg->gadget.is_otg = 1;
     else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
      hsotg->op_state = OTG_STATE_B_PERIPHERAL;
     
      //这里就会跑到上层代码里面
    ret = usb_add_gadget_udc(dev, &hsotg->gadget);
    if (ret) {
     dwc2_hsotg_ep_free_request(&hsotg->eps_out[0]->ep,
           hsotg->ctrl_req);
     return ret;
    }

    /**
     * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
     * @parent: the parent device to this udc. Usually the controller driver's
     * device.
     * @gadget: the gadget to be added to the list.
     * @release: a gadget release function.
     *
     * Returns zero on success, negative errno otherwise.
     */
    int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
              void (*release)(struct device *dev))
        udc->gadget = gadget;
     gadget->udc = udc;
     mutex_lock(&udc_lock);
     list_add_tail(&udc->list, &udc_list);
     ret = device_add(&udc->dev);
     if (ret)
      goto err4;
     usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
     udc->vbus = true;
     mutex_unlock(&udc_lock);
     
     // 最终添加到链表里面去了
    static struct class *udc_class;
    static LIST_HEAD(udc_list);
      // 每一层 换一个马甲  指针赋值 
     // 上层哪里被调用     中间层
     找到 udc驱动
     方式一:
       gadget/legacy
      
    例子:ether.c
    static struct usb_composite_driver eth_driver = {
     .name  = "g_ether",
     .dev  = &device_desc,
     .strings = dev_strings,
     .max_speed = USB_SPEED_SUPER,
     .bind  = eth_bind,
     .unbind  = eth_unbind,
    };
    module_usb_composite_driver(eth_driver);
    /**
     * module_usb_composite_driver() - Helper macro for registering a USB gadget
     * composite driver
     * @__usb_composite_driver: usb_composite_driver struct
     *
     * Helper macro for USB gadget composite drivers which do not do anything
     * special in module init/exit. This eliminates a lot of boilerplate. Each
     * module may only use this macro once, and calling it replaces module_init()
     * and module_exit()
     */
    #define module_usb_composite_driver(__usb_composite_driver) \
     module_driver(__usb_composite_driver, usb_composite_probe, \
             usb_composite_unregister)
     
    int usb_composite_probe(struct usb_composite_driver *driver)
    {
     struct usb_gadget_driver *gadget_driver;
     if (!driver || !driver->dev || !driver->bind)
      return -EINVAL;
     if (!driver->name)
      driver->name = "composite";
     driver->gadget_driver = composite_driver_template;
     gadget_driver = &driver->gadget_driver;
     gadget_driver->function =  (char *) driver->name;
     gadget_driver->driver.name = driver->name;
     gadget_driver->max_speed = driver->max_speed;
     return usb_gadget_probe_driver(gadget_driver);
    }
    EXPORT_SYMBOL_GPL(usb_composite_probe);
    int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
    {
     struct usb_udc  *udc = NULL;
     int   ret;
     if (!driver || !driver->bind || !driver->setup)
      return -EINVAL;
     mutex_lock(&udc_lock);
     list_for_each_entry(udc, &udc_list, list) {
      /* For now we take the first one */
      if (!udc->driver)
       goto found;
     }
     pr_debug("couldn't find an available UDC\n");
     mutex_unlock(&udc_lock);
     return -ENODEV;
    found:
     ret = udc_bind_to_driver(udc, driver);
     mutex_unlock(&udc_lock);
     return ret;
    }
    EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
    方式二:
    使用configfs.c
    static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
      const char *page, size_t len)
    {
     struct gadget_info *gi = to_gadget_info(item);
     char *name;
     int ret;
     name = kstrdup(page, GFP_KERNEL);
     if (!name)
      return -ENOMEM;
     if (name[len - 1] == '\n')
      name[len - 1] = '\0';
     mutex_lock(&gi->lock);
     if (!strlen(name) || strcmp(name, "none") == 0) {
      ret = unregister_gadget(gi);
      if (ret)
       goto err;
      kfree(name);
     } else {
      if (gi->udc_name) {
       ret = -EBUSY;
       goto err;
      }
      ret = usb_udc_attach_driver(name, &gi->composite.gadget_driver);
      if (ret)
       goto err;
      gi->udc_name = name;
     }
     mutex_unlock(&gi->lock);
     return len;
    err:
     kfree(name);
     mutex_unlock(&gi->lock);
     return ret;
    }
     int usb_udc_attach_driver(const char *name, struct usb_gadget_driver *driver)
    {
     struct usb_udc *udc = NULL;
     int ret = -ENODEV;
     mutex_lock(&udc_lock);
     list_for_each_entry(udc, &udc_list, list) {
      ret = strcmp(name, dev_name(&udc->dev));
      if (!ret)
       break;
     }
     if (ret) {
      ret = -ENODEV;
      goto out;
     }
     if (udc->driver) {
      ret = -EBUSY;
      goto out;
     }
     ret = udc_bind_to_driver(udc, driver);
    out:
     mutex_unlock(&udc_lock);
     return ret;
    }
    EXPORT_SYMBOL_GPL(usb_udc_attach_driver);

    操作UDC:回调函数的调用
     ret = driver->bind(udc->gadget, driver);
     if (ret)
      goto err1;
     ret = usb_gadget_udc_start(udc);
     if (ret) {
      driver->unbind(udc->gadget);
      goto err1;
     }
     usb_udc_connect_control(udc);
     kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
     return 0;
     
     // 这个udc变量从驱动里面找到了 
    /**
     * usb_gadget_udc_start - tells usb device controller to start up
     * @udc: The UDC to be started
     *
     * This call is issued by the UDC Class driver when it's about
     * to register a gadget driver to the device controller, before
     * calling gadget driver's bind() method.
     *
     * It allows the controller to be powered off until strictly
     * necessary to have it powered on.
     *
     * Returns zero on success, else negative errno.
     */
    static inline int usb_gadget_udc_start(struct usb_udc *udc)
    {
     return udc->gadget->ops->udc_start(udc->gadget, udc->driver);
    }
    /**
     * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
     * @gadget: The device we want to stop activity
     * @driver: The driver to unbind from @gadget
     *
     * This call is issued by the UDC Class driver after calling
     * gadget driver's unbind() method.
     *
     * The details are implementation specific, but it can go as
     * far as powering off UDC completely and disable its data
     * line pullups.
     */
    static inline void usb_gadget_udc_stop(struct usb_udc *udc)
    {
     udc->gadget->ops->udc_stop(udc->gadget);
    }
     
     
     
     
    一勤天下无难事。
  • 相关阅读:
    c#实现串口操作 SerialPort
    ASP.NET Core 上传大文件无法接收的问题
    如何将qlv格式的腾讯视频转换为mp4格式
    C#中HttpWebRequest的GetRequestStream执行的效率太低,甚至偶尔死掉
    LGPL 与GPL的区别
    ffmpeg
    HTTP协议/RTSP协议/RTMP协议的区别
    C#写的CRC16检验算法
    VS里属性窗口中的生成操作释义
    iOS:APNS推送主要代码
  • 原文地址:https://www.cnblogs.com/nowroot/p/12155178.html
Copyright © 2020-2023  润新知