精华内容
下载资源
问答
  • gadget之usb_gadget

    2021-03-17 22:27:13
    gadget之usb_gadget 简介 略。 struct usb_gadget /** * struct usb_gadget - represents a usb slave device * @work: (internal use) Workqueue to be used for sysfs_notify() * @udc: struct usb_udc pointer...

    gadget之usb_gadget

    简介

    略。

    struct usb_gadget

    /**
     * struct usb_gadget - represents a usb slave device
     * @work: (internal use) Workqueue to be used for sysfs_notify()
     * @udc: struct usb_udc pointer for this gadget
     * @ops: Function pointers used to access hardware-specific operations.
     * @ep0: Endpoint zero, used when reading or writing responses to
     *	driver setup() requests
     * @ep_list: List of other endpoints supported by the device.
     * @speed: Speed of current connection to USB host.
     * @max_speed: Maximal speed the UDC can handle.  UDC must support this
     *      and all slower speeds.
     * @state: the state we are now (attached, suspended, configured, etc)
     * @name: Identifies the controller hardware type.  Used in diagnostics
     *	and sometimes configuration.
     * @dev: Driver model state for this abstract device.
     * @isoch_delay: value from Set Isoch Delay request. Only valid on SS/SSP
     * @out_epnum: last used out ep number
     * @in_epnum: last used in ep number
     * @mA: last set mA value
     * @otg_caps: OTG capabilities of this gadget.
     * @sg_supported: true if we can handle scatter-gather
     * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
     *	gadget driver must provide a USB OTG descriptor.
     * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
     *	is in the Mini-AB jack, and HNP has been used to switch roles
     *	so that the "A" device currently acts as A-Peripheral, not A-Host.
     * @a_hnp_support: OTG device feature flag, indicating that the A-Host
     *	supports HNP at this port.
     * @a_alt_hnp_support: OTG device feature flag, indicating that the A-Host
     *	only supports HNP on a different root port.
     * @b_hnp_enable: OTG device feature flag, indicating that the A-Host
     *	enabled HNP support.
     * @hnp_polling_support: OTG device feature flag, indicating if the OTG device
     *	in peripheral mode can support HNP polling.
     * @host_request_flag: OTG device feature flag, indicating if A-Peripheral
     *	or B-Peripheral wants to take host role.
     * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
     *	MaxPacketSize.
     * @quirk_altset_not_supp: UDC controller doesn't support alt settings.
     * @quirk_stall_not_supp: UDC controller doesn't support stalling.
     * @quirk_zlp_not_supp: UDC controller doesn't support ZLP.
     * @quirk_avoids_skb_reserve: udc/platform wants to avoid skb_reserve() in
     *	u_ether.c to improve performance.
     * @is_selfpowered: if the gadget is self-powered.
     * @deactivated: True if gadget is deactivated - in deactivated state it cannot
     *	be connected.
     * @connected: True if gadget is connected.
     * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag
     *	indicates that it supports LPM as per the LPM ECN & errata.
     *
     * Gadgets have a mostly-portable "gadget driver" implementing device
     * functions, handling all usb configurations and interfaces.  Gadget
     * drivers talk to hardware-specific code indirectly, through ops vectors.
     * That insulates the gadget driver from hardware details, and packages
     * the hardware endpoints through generic i/o queues.  The "usb_gadget"
     * and "usb_ep" interfaces provide that insulation from the hardware.
     *
     * Except for the driver data, all fields in this structure are
     * read-only to the gadget driver.  That driver data is part of the
     * "driver model" infrastructure in 2.6 (and later) kernels, and for
     * earlier systems is grouped in a similar structure that's not known
     * to the rest of the kernel.
     *
     * Values of the three OTG device feature flags are updated before the
     * setup() call corresponding to USB_REQ_SET_CONFIGURATION, and before
     * driver suspend() calls.  They are valid only when is_otg, and when the
     * device is acting as a B-Peripheral (so is_a_peripheral is false).
     */
    struct usb_gadget {
    	struct work_struct		work;
    	struct usb_udc			*udc;
    	/* readonly to gadget driver */
    	const struct usb_gadget_ops	*ops;
    	struct usb_ep			*ep0;
    	struct list_head		ep_list;	/* of usb_ep */
    	enum usb_device_speed		speed;
    	enum usb_device_speed		max_speed;
    	enum usb_device_state		state;
    	const char			*name;
    	struct device			dev;
    	unsigned			isoch_delay;
    	unsigned			out_epnum;
    	unsigned			in_epnum;
    	unsigned			mA;
    	struct usb_otg_caps		*otg_caps;
    
    	unsigned			sg_supported:1;
    	unsigned			is_otg:1;
    	unsigned			is_a_peripheral:1;
    	unsigned			b_hnp_enable:1;
    	unsigned			a_hnp_support:1;
    	unsigned			a_alt_hnp_support:1;
    	unsigned			hnp_polling_support:1;
    	unsigned			host_request_flag:1;
    	unsigned			quirk_ep_out_aligned_size:1;
    	unsigned			quirk_altset_not_supp:1;
    	unsigned			quirk_stall_not_supp:1;
    	unsigned			quirk_zlp_not_supp:1;
    	unsigned			quirk_avoids_skb_reserve:1;
    	unsigned			is_selfpowered:1;
    	unsigned			deactivated:1;
    	unsigned			connected:1;
    	unsigned			lpm_capable:1;
    };
    

    struct usb_gadget_ops

    该ops主要是usb device conctrl相关控制的实例。

    /* 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 *);
    	void	(*udc_set_speed)(struct usb_gadget *, enum usb_device_speed);
    	struct usb_ep *(*match_ep)(struct usb_gadget *,
    			struct usb_endpoint_descriptor *,
    			struct usb_ss_ep_comp_descriptor *);
    };
    

    usb_gadget创建:

    该成员需由实现udc控制器驱动者创建及初始化,示例如下:

    	udc->gadget.ops             = &arobot_gadget_ops; //初始化usb_gadget_ops
    	udc->gadget.speed           = USB_SPEED_FULL;
    	udc->gadget.max_speed       = USB_SPEED_FULL;       // usb 1.1
    	udc->gadget.dev.parent      = &pdev->dev;
    	udc->gadget.dev.init_name   = "gadget";
    	udc->gadget.name            = arobot_udc_name;
    	udc->gadget.ep0             = &udc->ep[0]->uep;
    	INIT_LIST_HEAD(&udc->gadget.ep_list);//初始化ep链表
    	INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
    	
    	//初始化endpoint
    	buff_use_base = AROBOT_EP0_BUFF_BASE;
    	for (i = USBD_EPT0; i < USBD_MAXEPT; i++) {
    		_ep = udc->ep[i];
    		_ep->udc = udc;
    		_ep->uep.desc = NULL;
    		_ep->uep.name = udc_ep_name[i];
    		_ep->uep.ops  = &arobot_udc_ep_ops;
    
    		INIT_LIST_HEAD(&_ep->queue);
    		spin_lock_init(&_ep->lock);
    
    		if (i == USBD_EPT0) {           // endpoint 0
    			_ep->buff_addr = buff_use_base;
    			buff_use_base += AROBOT_EP_04567_BUFF_MAX_SIZE;
    
    			_ep->uep.caps.type_control = true;
    			_ep->uep.caps.type_iso     = false;
    			_ep->uep.caps.type_bulk    = false;
    			_ep->uep.caps.type_int     = false;
    		} else if (i <= USBD_EPT3) {    // endpoint 1~3
    			_ep->buff_addr = buff_use_base;
    			buff_use_base += (AROBOT_EP_123_BUFF_MAX_SIZE);
    
    			_ep->uep.caps.type_control = false;
    			_ep->uep.caps.type_iso     = false;
    			_ep->uep.caps.type_bulk    = true;
    			_ep->uep.caps.type_int     = true;
    		} else {                        // endpoint 4~7
    			_ep->buff_addr = buff_use_base;
    			buff_use_base += AROBOT_EP_04567_BUFF_MAX_SIZE;
    			_ep->uep.caps.type_control = false;
    			_ep->uep.caps.type_iso     = true;
    			_ep->uep.caps.type_bulk    = true;
    			_ep->uep.caps.type_int     = true;
    		}
    
    		_ep->uep.caps.dir_in  = true;
    		_ep->uep.caps.dir_out = true;
    
            //将endpoint添加到gadget.ep_list链表中
    		if (USBD_EPT0 != i) {
    			list_add_tail(&_ep->uep.ep_list, &udc->gadget.ep_list);
    		}
    
    		usb_ep_set_maxpacket_limit(&_ep->uep, AROBOT_EP_BUFF_MAX_SIZE);
    
    		udc_dbg("%s:0x%x \r\n", _ep->uep.name, _ep->buff_addr);
    	}
    

    usb_gadget_ops的创建:

    该成员需由实现udc控制器驱动者创建及初始化,示例如下:

    static const struct usb_gadget_ops arobot_gadget_ops = {
    	.get_frame       = arobot_udc_get_frame,
    	.wakeup          = arobot_udc_wakeup,
    	.set_selfpowered = arobot_udc_selfpowered,
    	.vbus_session	 = arobot_udc_vbus_session,
    	.vbus_draw	     = arobot_udc_vbus_draw,
    	.pullup          = arobot_udc_pullup,
    	.udc_start       = arobot_udc_start,
    	.udc_stop        = arobot_udc_stop,
    };
    

    usb_gadget的注册:
    该函数将创建一个usb_udc设备,并添加到udc_list链表中,具体过程详见:gadget之udc。

    /**
     * usb_add_gadget_udc - 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
     *
     * Returns zero on success, negative errno otherwise.
     */
    int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
    {
    	return usb_add_gadget_udc_release(parent, gadget, NULL);
    }
    EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
    

    struct usb_gadget_driver

    /**
     * struct usb_gadget_driver - driver for usb 'slave' devices
     * @function: String describing the gadget's function
     * @max_speed: Highest speed the driver handles.
     * @setup: Invoked for ep0 control requests that aren't handled by
     *	the hardware level driver. Most calls must be handled by
     *	the gadget driver, including descriptor and configuration
     *	management.  The 16 bit members of the setup data are in
     *	USB byte order. Called in_interrupt; this may not sleep.  Driver
     *	queues a response to ep0, or returns negative to stall.
     * @disconnect: Invoked after all transfers have been stopped,
     *	when the host is disconnected.  May be called in_interrupt; this
     *	may not sleep.  Some devices can't detect disconnect, so this might
     *	not be called except as part of controller shutdown.
     * @bind: the driver's bind callback
     * @unbind: Invoked when the driver is unbound from a gadget,
     *	usually from rmmod (after a disconnect is reported).
     *	Called in a context that permits sleeping.
     * @suspend: Invoked on USB suspend.  May be called in_interrupt.
     * @resume: Invoked on USB resume.  May be called in_interrupt.
     * @reset: Invoked on USB bus reset. It is mandatory for all gadget drivers
     *	and should be called in_interrupt.
     * @driver: Driver model state for this driver.
     * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL,
     *	this driver will be bound to any available UDC.
     * @pending: UDC core private data used for deferred probe of this driver.
     * @match_existing_only: If udc is not found, return an error and don't add this
     *      gadget driver to list of pending driver
     *
     * Devices are disabled till a gadget driver successfully bind()s, which
     * means the driver will handle setup() requests needed to enumerate (and
     * meet "chapter 9" requirements) then do some useful work.
     *
     * If gadget->is_otg is true, the gadget driver must provide an OTG
     * descriptor during enumeration, or else fail the bind() call.  In such
     * cases, no USB traffic may flow until both bind() returns without
     * having called usb_gadget_disconnect(), and the USB host stack has
     * initialized.
     *
     * Drivers use hardware-specific knowledge to configure the usb hardware.
     * endpoint addressing is only one of several hardware characteristics that
     * are in descriptors the ep0 implementation returns from setup() calls.
     *
     * Except for ep0 implementation, most driver code shouldn't need change to
     * run on top of different usb controllers.  It'll use endpoints set up by
     * that ep0 implementation.
     *
     * The usb controller driver handles a few standard usb requests.  Those
     * include set_address, and feature flags for devices, interfaces, and
     * endpoints (the get_status, set_feature, and clear_feature requests).
     *
     * Accordingly, the driver's setup() callback must always implement all
     * get_descriptor requests, returning at least a device descriptor and
     * a configuration descriptor.  Drivers must make sure the endpoint
     * descriptors match any hardware constraints. Some hardware also constrains
     * other descriptors. (The pxa250 allows only configurations 1, 2, or 3).
     *
     * The driver's setup() callback must also implement set_configuration,
     * and should also implement set_interface, get_configuration, and
     * get_interface.  Setting a configuration (or interface) is where
     * endpoints should be activated or (config 0) shut down.
     *
     * (Note that only the default control endpoint is supported.  Neither
     * hosts nor devices generally support control traffic except to ep0.)
     *
     * Most devices will ignore USB suspend/resume operations, and so will
     * not provide those callbacks.  However, some may need to change modes
     * when the host is not longer directing those activities.  For example,
     * local controls (buttons, dials, etc) may need to be re-enabled since
     * the (remote) host can't do that any longer; or an error state might
     * be cleared, to make the device behave identically whether or not
     * power is maintained.
     */
     //该驱动是usbcore和composite之间交互必不可少的一环,
     //两者之间的联系主要靠他来维持,
     //内核已经提供好了,不需要我们去实现。
    struct usb_gadget_driver {
    	char			*function;
    	enum usb_device_speed	max_speed;
    	int			(*bind)(struct usb_gadget *gadget,
    					struct usb_gadget_driver *driver);
    	void			(*unbind)(struct usb_gadget *);
    	int			(*setup)(struct usb_gadget *,
    					const struct usb_ctrlrequest *); 枚举过程中必不可少的函数。不需要驱动去实现。
    	void			(*disconnect)(struct usb_gadget *);
    	void			(*suspend)(struct usb_gadget *);
    	void			(*resume)(struct usb_gadget *);
    	void			(*reset)(struct usb_gadget *);
    
    	/* FIXME support safe rmmod */
    	struct device_driver	driver;
    
    	char			*udc_name;
    	struct list_head	pending;
    	unsigned                match_existing_only:1;
    };
    

    usb_gadget_driver的创建:

    源码:drivers/usb/gadget/composite.c

    static const struct usb_gadget_driver composite_driver_template = {
    	.bind		= composite_bind,
    	.unbind		= composite_unbind,
    
    	.setup		= composite_setup,
    	.reset		= composite_disconnect,
    	.disconnect	= composite_disconnect,
    
    	.suspend	= composite_suspend,
    	.resume		= composite_resume,
    
    	.driver	= {
    		.owner		= THIS_MODULE,
    	},
    };
    

    usb_gadget_driver的注册:

    以serial为例:源码为drivers/usb/gadget/legacy/serial.c

    static int __init init(void)
    {
    	/* We *could* export two configs; that'd be much cleaner...
    	 * but neither of these product IDs was defined that way.
    	 */
    	if (use_acm) {
    		serial_config_driver.label = "CDC ACM config";
    		serial_config_driver.bConfigurationValue = 2;
    		device_desc.bDeviceClass = USB_CLASS_COMM;
    		device_desc.idProduct =
    				cpu_to_le16(GS_CDC_PRODUCT_ID);
    	} else if (use_obex) {
    		serial_config_driver.label = "CDC OBEX config";
    		serial_config_driver.bConfigurationValue = 3;
    		device_desc.bDeviceClass = USB_CLASS_COMM;
    		device_desc.idProduct =
    			cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
    	} else {
    		serial_config_driver.label = "Generic Serial config";
    		serial_config_driver.bConfigurationValue = 1;
    		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
    		device_desc.idProduct =
    				cpu_to_le16(GS_PRODUCT_ID);
    	}
    	strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
    
    	return usb_composite_probe(&gserial_driver);
    }
    module_init(init);
    
    static void __exit cleanup(void)
    {
    	usb_composite_unregister(&gserial_driver);
    }
    module_exit(cleanup);
    

    源码:drivers/usb/gadget/composite.c

    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";
    
        //usb_gadget_driver注册到usb_composite_driver
    	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 = -ENODEV;
    
    	if (!driver || !driver->bind || !driver->setup)
    		return -EINVAL;
    
    	mutex_lock(&udc_lock);
    	//遍历udc_list链表,查找udc设备
    	if (driver->udc_name) {
    		list_for_each_entry(udc, &udc_list, list) {
    			ret = strcmp(driver->udc_name, dev_name(&udc->dev));
    			if (!ret)
    				break;
    		}
    		if (ret)
    			ret = -ENODEV;
    		else if (udc->driver)
    			ret = -EBUSY;
    		else
    			goto found;
    	} else {
    		list_for_each_entry(udc, &udc_list, list) {
    			/* For now we take the first one */
    			if (!udc->driver)
    				goto found;
    		}
    	}
    
        //无udc设备,则将usb_gadget_driver添加到gadget_driver_pending_list链表
    	if (!driver->match_existing_only) {
    		list_add_tail(&driver->pending, &gadget_driver_pending_list);
    		pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
    			driver->function);
    		ret = 0;
    	}
    
    	mutex_unlock(&udc_lock);
    	return ret;
    found:
        //udc设备与usb_gadget_driver绑定,详见gadget之udc
    	ret = udc_bind_to_driver(udc, driver);
    	mutex_unlock(&udc_lock);
    	return ret;
    }
    EXPORT_SYMBOL_GPL(usb_gadget_probe_driver);
    
    展开全文
  • Gadget properties

    2020-12-08 23:43:41
    For illustration purposes, I have converted one gadget (GrappaGadget) to the new system. Please do don't merge just yet. At this point, I would just like some comments. , , , <p>The way it works...
  • When playing ctf pwn challenges we usually need the one-gadget RCE (remote code execution), which leads to call execve('/bin/sh', NULL, NULL). This gem provides such gadgets finder, no need to use ...
  • exchanging gadget

    2020-12-08 23:21:29
    <div><p>i have found something wrong with the exchanging gadget i sometimes get the block.buildinggadget.effect_block.name it picks the temporary block and makes it a solid block and you have to break...
  • SelectorGadget工具

    2018-06-29 11:57:41
    SelectorGadget可以与谷歌浏览器结合使用,能够为复杂网站的元素生成CSS选择器,这款神器有助于我们快速找到html的节点信息。
  • Linux usb gadget

    2014-09-14 18:14:12
    Linux usb gadget
  • Gadget Serial Control

    2015-09-15 12:13:04
    Gadget Serial Control,三星驱动
  • usb gadget

    2016-09-12 14:37:32
    1. 前言 2. 源码架构 3. 枚举过程 ...Gadget,小饰品。USB Gadget,就是指所开发的电子设备以...本文以Mavell为例,以Gadget插入主机的全过程为主线,分析USB Gadget的架构。   2. 源码架构 USB的源码位

    1. 前言

    2. 源码架构

    3. 枚举过程


    1. 前言

    Gadget,小饰品。USB Gadget,就是指所开发的电子设备以USB从设备的模式通过USB连接到主机。比如手机用USB线插入PC后,手机就是USB Gadget。本文以Mavell为例,以Gadget插入主机的全过程为主线,分析USB Gadget的架构。

     

    2. 源码架构

    USB的源码位于/drivers/usb文件夹内,其中包括核心层core,主控制器host,U盘storage,以及USB Gadget等。

    gadget文件夹里存放了各芯片厂商支援的USB Gadget控制器驱动,比如支持Mavell的PXA9XX系列的USB Gadget驱动为mv_gadget.c,其架构如下图所示,

     2.1 Gadget控制器驱动

     设备要有gadget功能,硬件上要集成gadget控制器,软件上要具备gadget控制器驱动。

    首先是该驱动的数据结构 struct mv_usb_dev,

    -> struct usb_gadget, 由linux定义的gadget所需要的数据成员,其中包含了sturct usb_ep。

    -> struct mv_usb_ep, 其中的struct usb_ep是由linux定义的endpoint所需要的成员,关于endpoint参看USB协议。

    -> struct usb_gadget_driver, 对应该gadget设备功能的驱动,下节将作具体描述。

    -> void *mv_usb_handle, 指针指向芯片控制器的数据结构。

     

    概括地讲,gadget控制器驱动完成了五个任务,

    • 通过platform_data和resource的到gadget芯片物理地址,中断号等 (橙色)
    • 初始化gadget芯片和相关数据 (浅灰色)
    • 初始化数据struct usb_gadget (蓝色)
    • 初始化数据struct usb_ep (粉色)
    • 注册gadget服务

    gadget服务,即该设备所具备的gadget能力,比如reset, suspend, resume, speed,以及需要重点关注的枚举功能mv_usb_ep0_complete_service。注意到,注册服务的函数usb_device_register_service()的第一个参数mv_usb_handle用于得到底层芯片的数据,第三个参数回调函数实现具体功能。

     2.2 Gadget设备驱动

      需要区别gadget设备驱动与上节提到的gadget控制器驱动。gadget设备驱动,是指设备插入主机后具备的功能,该驱动被挂在到struct usb_gadget_driver下。比如手机插入PC作为U盘,那么U盘的驱动程序就是所谓的gadget设备驱动。

    (*bind)绑定设备的功能,比如U盘。

    (*setup)实现USB设备的枚举。

     2.3 Composite

    如果一个设备插入主机后拥有多个功能,比如同时有U盘和Android调试功能,那么该设备称为composite复用设备。其数据结构如下,

    通过(*bind)绑定设备的各个功能。

     

     

    3. 枚举过程

    系统初始化USB设备的过程就是枚举过程。

    根据USB协议,USB设备初始化的过程为attached->powered->default->address->configured。

    当设备插入主机,将等待来自主机的中断信号,通过request_irq()进入中断处理函数。

    设备通过读取控制器状态寄存器的值,得到来自主机的反馈,进而执行相应的任务,枚举就是其中的一项任务,通过调用gadget控制器驱动已经注册好的枚举服务,开始枚举过程。

    该枚举服务归纳为两步,

    第一步,通过读取gadget控制器,得到来自主机的请求,存放至mv_ctrl_req。

    第二步,通过switch(mv_ctrl_req),对具体请求作具体处理,处理类别又可分为两类。

    1) 标准请求,即所有USB设备可通用的请求,具体有得到状态请求,设置/清除feature请求,设置地址请求。

    2) USB设备请求,即根据具体设备,处理具体请求,通过回调函数mv_dev->driver->setup()来实现。

    PS: 关于请求,参看USB协议ch9。

    重点关注mv_dev->driver->setup()的枚举过程,其实质就是主机从USB设备得到描述符。

    这里的mv_dev->driver就是上文2.2所提到的gadget设备驱动,通过driver->bind绑定具体的驱动功能,如果是composite复用设备,则绑定usb_composite_driver结构,通过driver->setup实现设备的枚举过程,代码如下,其中的GET_DESCRIPTOR, SET_CONFIGURATION, 以及f->setup是必要的枚举过程。

    展开全文
  • <div><p><a href="https://github.com/aquasecurity/tracee">Tracee</a> is a Linux tracer based on <a href="https://github.com/iovisor/bcc">bcc</a>. It can trace the ...kinvolk/inspektor-gadget</p></div>
  • USB Gadget implementation

    2020-12-09 04:16:13
    <div><p>Would be great to wrap the <a href="https://www.kernel.org/doc/html/latest/driver-api/usb/gadget.html">USB Gadget API for Linux</a> for testing purposes. Maybe more a request for the eventual ...
  • CPU.Gadget

    2013-12-10 14:58:59
    CPU.Gadget
  • Single recon gadget

    2021-01-03 12:15:58
    <div><p>A single recon gadget for grappa is added. <p>An example is given for T2W data, Generic_Cartesian_Grappa_T2W.xml, which works with integration test data meas_MID00057_T2w.dat <p>The changes on...
  • usb-gadget.zip

    2020-11-25 11:28:21
    对应主题是高通sxr2130平台,android10,创建一个新的usb gadget的附件,对应主题是高通sxr2130平台,android10,创建一个新的usb gadget的附件
  • usb gadget g_webcam uvc gadget调试

    千次阅读 2017-07-20 15:30:30
    调试 usb gadget webcam时的记录: 1. 加载webcam驱动 2. 从http://git.ideasonboard.org/uvc-gadget.git下载 uvc应用层的代码,编译 3. 执行uvc_gadget时发现一直提示 iotrl 错误,原来使用的交叉编译器中的内核...

    开发板连接了一个USB camera,想通过UVC gadget将摄像头输出到PC上。


    内核关于gadget的测试说明 gadget-testing.txt 中提到:

    # uvc-gadget -u /dev/video<uvc video node #> -v /dev/video<vivid video node #>

    where uvc-gadget is this program: http://git.ideasonboard.org/uvc-gadget.git

    with these patches: http://www.spinics.net/lists/linux-usb/msg99220.html

     

    这里有一份整理好的测试代码,可以将开发板上的camera通过USB OTG连接到PC,在PC端显示摄像头图像:

     

    https://github.com/wlhe/uvc-gadget.git

     

    需要注意的是,代码中默认只支持360p和720p的分辨率大小,如果摄像头的分辨率不一样,需要修改代码中中支持的分辨率,另外,还需要在修改驱动webcam.c中添加新的分辨率,如我的摄像头分辨率是640x480,这里说明内核中分辨率的添加方法:

     

    1.添加新的描述符:

     

    static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_640x480 = {
        .bLength        = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
        .bDescriptorType    = USB_DT_CS_INTERFACE,
        .bDescriptorSubType    = UVC_VS_FRAME_UNCOMPRESSED,
        .bFrameIndex        = 2,
        .bmCapabilities        = 0,
        .wWidth            = cpu_to_le16(640),
        .wHeight        = cpu_to_le16(480),
        .dwMinBitRate        = cpu_to_le32(147456000),
        .dwMaxBitRate        = cpu_to_le32(147456000),
        .dwMaxVideoFrameBufferSize    = cpu_to_le32(614400),
        .dwDefaultFrameInterval    = cpu_to_le32(333333),
        .bFrameIntervalType    = 1,
        .dwFrameInterval[0]    = cpu_to_le32(333333),

    };

    其中dwMaxBitRate=dwMinBitRate= wWidth*wHeight*2*FrameRate,dwDefaultFrameInterval=333333,表示间隔为33.3333ms,即FrameRate=30。另外注意bFrameIndex的设定,一定要按顺序来设定。同时uvc_format_yuv的bNumFrameDescriptors也要相应更改

     

    2. 在uvc_fs_streaming_cls ,uvc_hs_streaming_cls,uvc_ss_streaming_cls中添加新的描述

    3.安装 g_webcam.ko 驱动,先运行./uvc-gadget -u /dev/video1 -v /dev/video0 -f 0 -r 0 ,再连接usb到pc, 打开camera应用即可看到图像。

     

    补充:

          内核驱动里面默认支持360p帧率为30f,720p帧率为2f,720p的帧率过低导致win10的camera应用一直不显示720p的分辨率选项,将帧率调整为15就可以了

    展开全文
  • gadget之composite

    2021-03-17 22:28:10
    gadget之composite composite简介 composite英文意思为复合/综合。其为整个gadget驱动的中间层,往下注册usb_gadget_driver并与usb_udc(usb_gadget设备)绑定,往上通过usb_composite_dev与usb_composite_driver...

    gadget之composite

    composite简介

    composite英文意思为复合/综合。其为整个gadget驱动的中间层,往下注册usb_gadget_driver并与usb_udc(usb_gadget设备)绑定,往上通过usb_composite_dev与usb_composite_driver实现usb_function的绑定。usb_function、composite、udc三者相互联系共同实现usb device的功能。

    struct usb_composite_dev

    //作为composite复合设备,所有composite设备都必须实现该结构体。
    struct usb_composite_dev {
    	struct usb_gadget		*gadget; //设备和gadget交互,gadget与udc交互
    	struct usb_request		*req; //used for control responses; buffer is pre-allocated
    	struct usb_request		*os_desc_req; //used for OS descriptors responses; buffer is pre-allocated
    
    	struct usb_configuration	*config; //当前激活的配置
    
    	/* OS String is a custom (yet popular) extension to the USB standard. */
    	u8				qw_sign[OS_STRING_QW_SIGN_LEN]; //qwSignature part of the OS string
    	u8				b_vendor_code; //bMS_VendorCode part of the OS string
    	struct usb_configuration	*os_desc_config; //the configuration to be used with OS descriptors
    	unsigned int			use_os_string:1; //false by default, interested gadgets set it
    
    	/* private: */
    	/* internals */
    	unsigned int			suspended:1;
    	struct usb_device_descriptor	desc; //设备描述符,唯一
    	struct list_head		configs; //配置链表
    	struct list_head		gstrings; //字符描述链表
    	struct usb_composite_driver	*driver; //设备绑定的composite驱动
    	u8				next_string_id;
    	char				*def_manufacturer; //默认制造商
    
    	/* the gadget driver won't enable the data pullup
    	 * while the deactivation count is nonzero.
    	 */
    	unsigned			deactivations;
    
    	/* the composite driver won't complete the control transfer's
    	 * data/status stages till delayed_status is zero.
    	 */
    	int				delayed_status;
    
    	/* protects deactivations and delayed_status counts*/
    	spinlock_t			lock;
    
    	/* public: */
    	unsigned int			setup_pending:1;
    	unsigned int			os_desc_pending:1;
    };
    

    USB_COMPOSITE_DEV的创建

    源码:/drivers/usb/gadget/composite.c

    
    static int composite_bind(struct usb_gadget *gadget,
    		struct usb_gadget_driver *gdriver)
    {
    	struct usb_composite_dev	*cdev;
    	struct usb_composite_driver	*composite = to_cdriver(gdriver);
    	int				status = -ENOMEM;
    
    	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);//创建usb_composite_dev
    	if (!cdev)
    		return status;
    
    	spin_lock_init(&cdev->lock);
    	cdev->gadget = gadget;
    	set_gadget_data(gadget, cdev);
    	INIT_LIST_HEAD(&cdev->configs);
    	INIT_LIST_HEAD(&cdev->gstrings);
    
        //初始化conctrl req
    	status = composite_dev_prepare(composite, cdev);
    	if (status)
    		goto fail;
    
    	/* composite gadget needs to assign strings for whole device (like
    	 * serial number), register function drivers, potentially update
    	 * power state and consumption, etc
    	 */
    	 //初始化设备描述符、字符描述付等
    	status = composite->bind(cdev);
    	if (status < 0)
    		goto fail;
    
    	if (cdev->use_os_string) {
    		status = composite_os_desc_req_prepare(cdev, gadget->ep0);
    		if (status)
    			goto fail;
    	}
    
    	update_unchanged_dev_desc(&cdev->desc, composite->dev);
    
    	/* has userspace failed to provide a serial number? */
    	if (composite->needs_serial && !cdev->desc.iSerialNumber)
    		WARNING(cdev, "userspace failed to provide iSerialNumber\n");
    
    	INFO(cdev, "%s ready\n", composite->name);
    	return 0;
    
    fail:
    	__composite_unbind(gadget, false);
    	return status;
    }
    
    
    
    int composite_dev_prepare(struct usb_composite_driver *composite,
    		struct usb_composite_dev *cdev)
    {
    	struct usb_gadget *gadget = cdev->gadget;
    	int ret = -ENOMEM;
    
    	/* preallocate control response and buffer */
    	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
    	if (!cdev->req)
    		return -ENOMEM;
    
        //USB_COMP_EP0_BUFSIZ=4096
    	cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
    	if (!cdev->req->buf)
    		goto fail;
    
        //创建设备文件
    	ret = device_create_file(&gadget->dev, &dev_attr_suspended);
    	if (ret)
    		goto fail_dev;
    
    	cdev->req->complete = composite_setup_complete;
    	cdev->req->context = cdev;
    	gadget->ep0->driver_data = cdev;
    
    	cdev->driver = composite;
    
    	/*
    	 * As per USB compliance update, a device that is actively drawing
    	 * more than 100mA from USB must report itself as bus-powered in
    	 * the GetStatus(DEVICE) call.
    	 */
    	if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
    		usb_gadget_set_selfpowered(gadget);
    
    	/* interface and string IDs start at zero via kzalloc.
    	 * we force endpoints to start unassigned; few controller
    	 * drivers will zero ep->driver_data.
    	 */
    	usb_ep_autoconfig_reset(gadget);
    	return 0;
    fail_dev:
    	kfree(cdev->req->buf);
    fail:
    	usb_ep_free_request(gadget->ep0, cdev->req);
    	cdev->req = NULL;
    	return ret;
    }
    
    

    struct usb_composite_driver

    struct usb_composite_driver {//所有compesite驱动必须填充该结构体
    	const char				*name;
    	const struct usb_device_descriptor	*dev; //必须实现
    	struct usb_gadget_strings		**strings;
    	enum usb_device_speed			max_speed;
    	unsigned		needs_serial:1;
    
    	int			(*bind)(struct usb_composite_dev *cdev);//必须实现
    	int			(*unbind)(struct usb_composite_dev *); //必须实现
    
    	void			(*disconnect)(struct usb_composite_dev *);
    
    	/* global suspend hooks */
    	void			(*suspend)(struct usb_composite_dev *);
    	void			(*resume)(struct usb_composite_dev *);
    	struct usb_gadget_driver		gadget_driver;这个地方的驱动由composite提供,所有和composite相关的驱动都会默认分配该驱动。
    };
    

    usb_composite_driver的创建,以serial.c为例:

    源码:/drivers/usb/gadget/legacy/serial.c

    static struct usb_composite_driver gserial_driver = {
    	.name		= "g_serial",
    	.dev		= &device_desc,
    	.strings	= dev_strings,
    	.max_speed	= USB_SPEED_SUPER,
    	.bind		= gs_bind,
    	.unbind		= gs_unbind,
    };
    
    展开全文
  • 通用gadget详解

    千次阅读 2019-12-26 10:52:55
    gadget 利用gadget是做pwn题时控制程序流程一种重要且常用的方法。 rop是什么? 参考链接 https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop-zh/ 我今天主要写我对通用gadget的原理的理解 ...
  • selectorgadget插件.zip

    2020-04-13 16:35:49
    selectorgadget插件,R语言爬取网页
  • Gadget0 fix

    2020-11-30 20:16:27
    <div><p>I was having trouble getting the gadget0 tests to pass reliably on stm32f0-discovery. These patches address that. <p>See commit messages for details.</p><p>该提问来源于开源项目:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,554
精华内容 1,421
关键字:

gadget