(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及其相关操作
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 *);
};
* 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,
};
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;
}
pr_err("%s: called with no device\n", __func__);
return -ENODEV;
}
if (!driver) {
dev_err(hsotg->dev, "%s: no driver\n", __func__);
return -EINVAL;
}
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__);
dev_err(hsotg->dev, "%s: bad speed\n", __func__);
if (!driver->setup) {
dev_err(hsotg->dev, "%s: missing entry points\n", __func__);
return -EINVAL;
}
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;
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;
}
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);
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);
}
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;
}
goto err;
}
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget);
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);
}
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);
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;
}
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;
* 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);
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;
}
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;
}
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;
}
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;
{
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);
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 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;
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);
}
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;
}
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;
}
/**
* 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);
list_add_tail(&udc->list, &udc_list);
ret = device_add(&udc->dev);
if (ret)
goto err4;
if (ret)
goto err4;
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
udc->vbus = true;
udc->vbus = true;
mutex_unlock(&udc_lock);
// 最终添加到链表里面去了
static struct class *udc_class;
static LIST_HEAD(udc_list);
// 最终添加到链表里面去了
static struct class *udc_class;
static LIST_HEAD(udc_list);
// 每一层 换一个马甲 指针赋值
// 上层哪里被调用 中间层
找到 udc驱动
方式一:
gadget/legacy
例子:ether.c
// 上层哪里被调用 中间层
找到 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,
};
.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)
* 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;
return -EINVAL;
if (!driver->name)
driver->name = "composite";
driver->name = "composite";
driver->gadget_driver = composite_driver_template;
gadget_driver = &driver->gadget_driver;
gadget_driver = &driver->gadget_driver;
gadget_driver->function = (char *) driver->name;
gadget_driver->driver.name = driver->name;
gadget_driver->max_speed = driver->max_speed;
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);
}
EXPORT_SYMBOL_GPL(usb_composite_probe);
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
{
struct usb_udc *udc = NULL;
int ret;
{
struct usb_udc *udc = NULL;
int ret;
if (!driver || !driver->bind || !driver->setup)
return -EINVAL;
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;
}
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);
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;
使用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';
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;
}
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;
{
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);
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);
}
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);
}
* 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);
}