android usb 分析(2)

分析Android USB通信从应用层到内核层的完整调用链路-2 本文分析了Linux内核中USB通信流程的第二部分,重点聚焦URB提交与硬件交互过程。首先介绍了USB核心层的usb_submit_urb()实现,包括设备状态检查、endpoint验证和传输类型处理等关键步骤。随后深入HCD层,解析了usb_hcd_submit_urb()如何通过引用计数、监控钩子和具体HCD驱动方法处理URB提交。最后以EHCI驱动为例,展示了不同类型传输(Control、Interrupt、Bulk、Isochronous)在硬件控制器层的具体实现方式,包括QTD构建和QH调度队列管 阅读详情

上次分析到 usb_composite_probe(&android_usb_driver, android_bind);

这里继续分析android_usb_driver 和 android_bind。

1. android_usb_driver

    static struct usb_composite_driver android_usb_driver = {
        .name = "android_usb",   //driver名
        .dev = &device_desc,     //usb_device_descriptor 内容
        .strings = dev_strings,
        .enable_function = android_enable_function,
    };
a. usb_composite_driver 数据结构原型定义在 include/linux/usb/composite.h 中

    /**
     * struct usb_composite_driver - groups configurations into a gadget
     * @name: For diagnostics, identifies the driver.
     * @iProduct: Used as iProduct override if @dev->iProduct is not set.
     * If NULL value of @name is taken.
     * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
     * not set. If NULL a default "<system> <release> with <udc>" value
     * will be used.
     * @dev: Template descriptor for the device, including default device
     * identifiers.
     * @strings: tables of strings, keyed by identifiers assigned during bind()
     * and language IDs provided in control requests
     * @needs_serial: set to 1 if the gadget needs userspace to provide
     * a serial number. If one is not provided, warning will be printed.
     * @unbind: Reverses bind; called as a side effect of unregistering
     * this driver.
     * @disconnect: optional driver disconnect method
     * @suspend: Notifies when the host stops sending USB traffic,
     * after function notifications
     * @resume: Notifies configuration when the host restarts USB traffic,
     * before function notifications
     *
     * Devices default to reporting self powered operation. Devices which rely
     * on bus powered operation should report this in their @bind() method.
     *
     * Before returning from bind, various fields in the template descriptor
     * may be overridden. These include the idVendor/idProduct/bcdDevice values
     * normally to bind the appropriate host side driver, and the three strings
     * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
     * meaningful device identifiers. (The strings will not be defined unless
     * they are defined in @dev and @strings.) The correct ep0 maxpacket size
     * is also reported, as defined by the underlying controller driver.
     */
    struct usb_composite_driver {
        const char *name;
        const char *iProduct;
        const char *iManufacturer;
        const struct usb_device_descriptor *dev;
        struct usb_gadget_strings **strings;
        unsigned needs_serial:1;
        struct class *class;
        atomic_t function_count;
        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 *);
        void (*enable_function)(struct usb_function *f, int enable);
    };
b. device_desc 设备描述声明:
    static struct usb_device_descriptor device_desc = {
        .bLength = sizeof(device_desc),
        .bDescriptorType = USB_DT_DEVICE,
        .bcdUSB = __constant_cpu_to_le16(0x0200),
        .bDeviceClass = USB_CLASS_PER_INTERFACE,
        .idVendor = __constant_cpu_to_le16(VENDOR_ID),
        .idProduct = __constant_cpu_to_le16(PRODUCT_ID),
        .bcdDevice = __constant_cpu_to_le16(0xffff),
        .bNumConfigurations = 1,
    };
c. dev_strings 设备的字符内容 声明:
    static struct usb_gadget_strings *dev_strings[] = {  //多个usb_gadget_string集合
        &stringtab_dev,    //具体一个usb_gadget_string
        NULL,
    };

    static struct usb_gadget_strings stringtab_dev = {
        .language = 0x0409, /* en-us */
        .strings = strings_dev,
    };

    /* String Table */
    static struct usb_string strings_dev[] = {
        /* These dummy values should be overridden by platform data */
        [STRING_MANUFACTURER_IDX].s = "Android",
        [STRING_PRODUCT_IDX].s = "Android",
        [STRING_SERIAL_IDX].s = "0123456789ABCDEF",
        { } /* end of list */
    };
2. android_enable_function() :
    void android_enable_function(struct usb_function *f, int enable)
    {
        struct android_dev *dev = _android_dev;   //获得全局变量 _android_dev
        int disable = !enable;
        int product_id;
        if (!!f->disabled != disable) {
            usb_function_set_enabled(f, !disable);    //使能usb function.
    #ifdef CONFIG_USB_ANDROID_RNDIS
            if (!strcmp(f->name, "rndis")) {
                struct usb_function *func;
                /* Windows does not support other interfaces when RNDIS is enabled,
                 * so we disable UMS and MTP when RNDIS is on.
                 */
                list_for_each_entry(func, &android_config_driver.functions, list) {
                    if (!strcmp(func->name, "usb_mass_storage")
                        || !strcmp(func->name, "mtp")) {
                        usb_function_set_enabled(func, !enable);
                    }
                }
            }
    #endif
            update_dev_desc(dev);  //更新设备描述
            product_id = get_product_id(dev);
            device_desc.idProduct = __constant_cpu_to_le16(product_id);
            if (dev->cdev)
                dev->cdev->desc.idProduct = device_desc.idProduct;
            usb_composite_force_reset(dev->cdev);    //reset
        }
    }
a. usb_function_set_enabled():
    void usb_function_set_enabled(struct usb_function *f, int enabled)
    {
        f->disabled = !enabled;
        kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);
    }
b. update_dev_desc() : 更新设备描述符
    void update_dev_desc(struct android_dev *dev)
    {
        struct usb_function *f;
        struct usb_function *last_enabled_f = NULL;
        int num_enabled = 0;
        int has_iad = 0;
            
        dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
        dev->cdev->desc.bDeviceSubClass = 0x00;
        dev->cdev->desc.bDeviceProtocol = 0x00;
        list_for_each_entry(f, &android_config_driver.functions, list) {
            if (!f->disabled) {
                num_enabled++;
                last_enabled_f = f;
                if (f->descriptors[0]->bDescriptorType ==
                        USB_DT_INTERFACE_ASSOCIATION)
                    has_iad = 1;
            }
            if (num_enabled > 1 && has_iad) {
                dev->cdev->desc.bDeviceClass = USB_CLASS_MISC;
                dev->cdev->desc.bDeviceSubClass = 0x02;
                dev->cdev->desc.bDeviceProtocol = 0x01;
                break;
            }
        }
        if (num_enabled == 1) {
    #ifdef CONFIG_USB_ANDROID_RNDIS
            if (!strcmp(last_enabled_f->name, "rndis")) {
    #ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS
                dev->cdev->desc.bDeviceClass =
                        USB_CLASS_WIRELESS_CONTROLLER;
    #else
                dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
    #endif
            }
    #endif
        }
    }
c. usb_composite_force_reset():  重置usb gadget.
    void usb_composite_force_reset(struct usb_composite_dev *cdev)
    {
        unsigned long flags;
        spin_lock_irqsave(&cdev->lock, flags);
        /* force reenumeration */
        if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) {
            spin_unlock_irqrestore(&cdev->lock, flags);
            usb_gadget_disconnect(cdev->gadget);
            msleep(10);
            usb_gadget_connect(cdev->gadget);
        } else {
            spin_unlock_irqrestore(&cdev->lock, flags);
        }
    }
3. android_bind():
    static int android_bind(struct usb_composite_dev *cdev)
    {
        struct android_dev *dev = _android_dev;
        struct usb_gadget *gadget = cdev->gadget;
        int gcnum, id, product_id, ret;
        printk(KERN_INFO "android_bind\n");
        /* Allocate string descriptor numbers ... note that string
         * contents can be overridden by the composite_dev glue.
         */
        id = usb_string_id(cdev); //allocate an unused string ID
        if (id < 0)
            return id;
        strings_dev[STRING_MANUFACTURER_IDX].id = id;
        device_desc.iManufacturer = id;
        id = usb_string_id(cdev);
        if (id < 0)
            return id;
        strings_dev[STRING_PRODUCT_IDX].id = id;
        device_desc.iProduct = id;
        id = usb_string_id(cdev);
        if (id < 0)
            return id;
        strings_dev[STRING_SERIAL_IDX].id = id;
        device_desc.iSerialNumber = id;
        /* register our configuration */
        ret = usb_add_config(cdev, &android_config_driver, android_bind_config); //add a configuration to a device.
        if (ret) {
            printk(KERN_ERR "usb_add_config failed\n");
            return ret;
        }
        gcnum = usb_gadget_controller_number(gadget); //support bcdDevice id convention.
        if (gcnum >= 0)
            device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
        else {
            /* gadget zero is so simple (for now, no altsettings) that
             * it SHOULD NOT have problems with bulk-capable hardware.
             * so just warn about unrcognized controllers -- don't panic.
             *
             * things like configuration and altsetting numbering
             * can need hardware-specific attention though.
             */
            pr_warning("%s: controller '%s' not recognized\n",
                longname, gadget->name);
            device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
        }
        usb_gadget_set_selfpowered(gadget); 
        dev->cdev = cdev;
        product_id = get_product_id(dev);
        device_desc.idProduct = __constant_cpu_to_le16(product_id);
        cdev->desc.idProduct = device_desc.idProduct;
        return 0;
    }
a. usb_string_id() :
    /**
     * usb_string_id() - allocate an unused string ID
     * @cdev: the device whose string descriptor IDs are being allocated
     * Context: single threaded during gadget setup
     *
     * @usb_string_id() is called from bind() callbacks to allocate
     * string IDs. Drivers for functions, configurations, or gadgets will
     * then store that ID in the appropriate descriptors and string table.
     *
     * All string identifier should be allocated using this,
     * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure
     * that for example different functions don't wrongly assign different
     * meanings to the same identifier.
     */
    int usb_string_id(struct usb_composite_dev *cdev)
    {
        if (cdev->next_string_id < 254) {
            /* string id 0 is reserved by USB spec for list of
             * supported languages */
            /* 255 reserved as well? -- mina86 */
            cdev->next_string_id++;
            return cdev->next_string_id;
        }
        return -ENODEV;
    }
b. usb_add_config()
    /**
     * usb_add_config() - add a configuration to a device.
     * @cdev: wraps the USB gadget
     * @config: the configuration, with bConfigurationValue assigned
     * @bind: the configuration's bind function
     * Context: single threaded during gadget setup
     *
     * One of the main tasks of a composite @bind() routine is to
     * add each of the configurations it supports, using this routine.
     *
     * This function returns the value of the configuration's @bind(), which
     * is zero for success else a negative errno value. Binding configurations
     * assigns global resources including string IDs, and per-configuration
     * resources such as interface IDs and endpoints.
     */
    int usb_add_config(struct usb_composite_dev *cdev,
            struct usb_configuration *config,
            int (*bind)(struct usb_configuration *))
    {
        int status = -EINVAL;
        struct usb_configuration *c;
        DBG(cdev, "adding config #%u '%s'/%p\n",
                config->bConfigurationValue,
                config->label, config);
        
        if (!config->bConfigurationValue || !bind)
            goto done;
        
        /* Prevent duplicate configuration identifiers */
        list_for_each_entry(c, &cdev->configs, list) {
            if (c->bConfigurationValue == config->bConfigurationValue) {
                status = -EBUSY;
                goto done;
            }
        }
        
        config->cdev = cdev;
        list_add_tail(&config->list, &cdev->configs);
        INIT_LIST_HEAD(&config->functions);
        config->next_interface_id = 0;
        status = bind(config);
        if (status < 0) {
            list_del(&config->list);
            config->cdev = NULL;
        } else {
            unsigned i;
            DBG(cdev, "cfg %d/%p speeds:%s%s\n",
                config->bConfigurationValue, config,
                config->highspeed ? " high" : "",
                config->fullspeed
                    ? (gadget_is_dualspeed(cdev->gadget)
                        ? " full"
                        : " full/low")
                    : "");
            for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
                struct usb_function *f = config->interface[i];
                if (!f)
                    continue;
                DBG(cdev, " interface %d = %s/%p\n",
                    i, f->name, f);
            }
        }
        /* set_alt(), or next bind(), sets up
         * ep->driver_data as needed.
         */
        usb_ep_autoconfig_reset(cdev->gadget);
    done:
        if (status)
            DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
                    config->bConfigurationValue, status);
        return status;
    }
c. usb_gadget_controller_number() : support bcdDevice id convention.
    /**
     * usb_gadget_controller_number - support bcdDevice id convention
     * @gadget: the controller being driven
     *
     * Return a 2-digit BCD value associated with the peripheral controller,
     * suitable for use as part of a bcdDevice value, or a negative error code.
     *
     * NOTE: this convention is purely optional, and has no meaning in terms of
     * any USB specification. If you want to use a different convention in your
     * gadget driver firmware -- maybe a more formal revision ID -- feel free.
     *
     * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
     * to change their behavior accordingly. For example it might help avoiding
     * some chip bug.
     */
    static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
    {
        if (gadget_is_net2280(gadget))
            return 0x01;
        else if (gadget_is_dummy(gadget))
            return 0x02;
        else if (gadget_is_pxa(gadget))
            return 0x03;
        else if (gadget_is_goku(gadget))
            return 0x06;
        else if (gadget_is_omap(gadget))
            return 0x08;
        else if (gadget_is_lh7a40x(gadget))
            return 0x09;
        else if (gadget_is_pxa27x(gadget))
            return 0x11;
        else if (gadget_is_s3c2410(gadget))
            return 0x12;
        else if (gadget_is_at91(gadget))
            return 0x13;
        else if (gadget_is_imx(gadget))
            return 0x14;
        else if (gadget_is_musbhdrc(gadget))
            return 0x16;
        else if (gadget_is_atmel_usba(gadget))
            return 0x18;
        else if (gadget_is_fsl_usb2(gadget))
            return 0x19;
        else if (gadget_is_amd5536udc(gadget))
            return 0x20;
        else if (gadget_is_m66592(gadget))
            return 0x21;
        else if (gadget_is_fsl_qe(gadget))
            return 0x22;
        else if (gadget_is_ci13xxx(gadget))
            return 0x23;
        else if (gadget_is_langwell(gadget))
            return 0x24;
        else if (gadget_is_r8a66597(gadget))
            return 0x25;
        else if (gadget_is_s3c_hsotg(gadget))
            return 0x26;
        return -ENOENT;
    }
d. usb_gadget_set_selfpowered()
    /**
     * usb_gadget_set_selfpowered - sets the device selfpowered feature.
     * @gadget:the device being declared as self-powered
     *
     * this affects the device status reported by the hardware driver
     * to reflect that it now has a local power supply.
     *
     * returns zero on success, else negative errno.
     */
    static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)
    {
        if (!gadget->ops->set_selfpowered)
            return -EOPNOTSUPP;
        return gadget->ops->set_selfpowered(gadget, 1);
    }
4. android_config_driver
    static struct usb_configuration android_config_driver = {
        .label = "android",
        .setup = android_setup_config,
        .bConfigurationValue = 1,
        .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
        .bMaxPower = 0xFA, /* 500ma */
    };
android_setup_config()
    static int android_setup_config(struct usb_configuration *c,
            const struct usb_ctrlrequest *ctrl)
    {
        int i;
        int ret = -EOPNOTSUPP;
        for (i = 0; i < android_config_driver.next_interface_id; i++) {
            if (android_config_driver.interface[i]->setup) {
                ret = android_config_driver.interface[i]->setup(
                    android_config_driver.interface[i], ctrl);
                if (ret >= 0)
                    return ret;
            }
        }
        return ret;
    }
5. android_bind_config()
    static int android_bind_config(struct usb_configuration *c)
    {
        struct android_dev *dev = _android_dev;
        printk(KERN_DEBUG "android_bind_config\n");
        dev->config = c;
        if (should_bind_functions(dev))
            bind_functions(dev);
        return 0;
    }
安卓设备的USB-HID通讯例程的开发(2) 安卓设备的USB-HID通讯例程的开发(2) 本博文系JGB联合商务组的原创作品,引用请标明出处 分析和理解前面的 **USB-HID通讯例程的开发(1)**博文中的主活动源码的核心方法: monitorRead() 是我接下来要探讨的话题. HID设备在与安卓主机的通讯中同样遵循的原则是: 有求必应,不求不应. 即USB通讯中的HID设备是一种完全受控于安卓主机的角色:  主机发出请求,设备一定要作出响应;主机未发出请求,设备就不能擅自发送任何数据.这一点与串口通讯是完全不同的. 本HID设备(即 阅读详情

相关推荐

Rockchip RK3588 Android13 USB 2.0调试实战:从原理图到DTS配置完整流程

本文详细介绍了Rockchip RK3588在Android13系统下USB 2.0接口的完整调试流程,从硬件原理图分析到DTS配置。内容涵盖USB 2.0接口电路设计要点、RK3588 USB子系统架构、DTS配置详解以及常见问题解决方案,为开发者提供了一套系统化的调试方法,特别适合嵌入式开发工程师参考。

weixin_29190573的博客 388

Android USB Camera(2) : UVC协议分析

1. 前言 本文对USB的功能类协议USB Video Class(UVC)的具体设计进行介绍,但不会介绍USB基础协议,所以需要对USB基础协议有一定的了解,包括USB四大描述符以及四种传输方式。分析usb协议的重点在于描述符,这里将以实际设备的描述符为线索,贯穿、分析uvc协议。 2. UVC功能概述 UVC设备都是多Interface设备,这点同普通的u盘不同。UVC设备最起码有两个I

eternity9255的博客 2万+

告别Camera2 API的复杂流程:用UVCAndroid库5分钟搞定安卓外接USB摄像头开发

本文介绍了UVCAndroid库如何简化安卓USB摄像头开发流程,相比复杂的Camera2 API,UVCAndroid仅需5分钟即可实现基础预览功能,代码量减少83%,调试时间缩短90%。文章详细展示了快速集成、多摄像头控制、参数调节及高效媒体捕获等实战技巧,帮助开发者大幅提升开发效率。

weixin_28285943的博客 217

android usb电源管理,Android usb子系统的电源管理流程分析

由于近来做的一个项目是基于android 2.3的版本,所以就对该版本的电源管理大致分析了下,跟大家分享,有错误之处,敬请指正,谢谢!针对的处理器是高通MSM8260,主要是针对一些挂起唤醒流程进行分析,以便对整个usb框架流程更好的理解。废话少说,开始分析。由于linux中的电源管理比较复杂,我就找了一个统一的接口,也就是要想操纵usb的电源管理必定要调的函数。顺便说下,跟踪代码最好的方法是用W...

weixin_42581846的博客 488

【QNX+Android虚拟化方案】120 - Android 侧 USB2.0 插拔过程

【QNX+Android虚拟化方案】120 - Android 侧 USB2.0 插拔过程

|~~~热爱生活、努力学习的小伙汁~~~| 939

Camera2和Camera1实现打开USB相机-实现Dialer 调用USB实现预览等视频通话

这里以MTK平台 Android13版本为例说明实现需求需要两步骤:平台MTK底层支持才行或者底层自己调通。Dialer 应用也需要适配才行,注意学会分析日志,对比日志,针对性 找源码业务逻辑。一定要学会针对性分析问题、分析日志。代码量太大了,短时间内不可能搞明白业务逻辑的。

十年饮冰,难凉热血 863

我的NPI项目之Android USB 系列(一) - 遥望和USB的相识

USB

xl01newstart的博客 899

SniffUSB x86:USB协议分析利器

本文还有配套的精品资源,点击获取 简介:SniffUSB x86是一款专为x86架构系统设计的USB嗅探器,能够捕获并分析USB总线上的数据包。它适用于USB协议的理解、排查设备通信问题、调试Android设备的外挂3G模块等场景。通过分析USB 1.1、2.0、3.x等不同协议版本的数据包,我们可以洞察传输速率、电源管理等方面的差异。此外,SniffUSB x86还可以用...

weixin_36364707的博客 1295

关于Android系统ADB和VNC连接问题(systemNative2)

关于Android系统ADB和VNC连接问题(systemNative2) 问题:想用VNC连接android控制触屏,VNC client在WIN7机器上,需要VNC server在安卓机器上运行。二者通过USB连接。安卓A能连上,安卓B,C连接不上。 安卓A版本:8.0 安卓B版本:9.0 安卓C版本:8.1 分析过程: ① 用ADB看log发现安卓B,C连接VNC端口5900失败,log如下...

weixin_45865306的博客 956

全新升级!USB调试助手1.2版发布

在本章中,我们将探讨Android设备中一个至关重要的功能——USB调试。对于开发者和IT专家而言,USB调试是连接和调试Android设备上应用的桥梁。我们将从USB调试的定义出发,逐步深入理解其工作原理以及如何启用和使用这一功能,为后面章节中介绍的USB调试助手软件的高级功能打下基础。USB调试(USB Debugging)是Android设备的一种开发模式,允许开发者通过USB连接将设备与电脑进行通信,以此来调试应用或执行某些特定的系统级操作。

weixin_35671843的博客 837

Windows下高效部署llama.cpp:从环境配置到模型量化的完整指南

本文提供了一份详尽的Windows系统下部署llama.cpp的完整指南。内容涵盖从Python环境配置、使用CMake与MinGW编译工具链的搭建,到编译llama.cpp项目、获取并转换模型为GGUF格式,以及执行模型量化和基础推理测试的全过程。指南旨在帮助开发者在普通Windows电脑上,无需高端显卡,仅凭CPU即可高效运行大语言模型,并重点解决了部署过程中常见的环境与编译错误。

weixin_28841265的博客 882

android usb摄像头无法缩放问题

摘要:Android相机API对USB摄像头支持存在历史演进问题。Camera1 API(Android 1.0+)通用性强,对USB摄像头支持较好;而Camera2(5.0+)和CameraX(9.0+)主要针对内置摄像头优化,对USB摄像头支持有限。系统相机能正常工作是因为使用了Camera1 API。这不是系统bug,而是Google优先优化主流设备的设计选择。对于USB摄像头缩放问题,Camera1是唯一完整支持的解决方案,建议替代CameraX/Camera2实现文档扫描功能。

Mark Wu 的博客 1248

上海交大计算机保研面试 2026:3类专项计划与10个联培方向深度解析

本文深度解析2026年上海交通大学计算机保研面试的3类专项计划与10个联培方向,包括区块链技术、智能计算系统和网络安全专项,以及蚂蚁科技、苏州智研院等联培基地。文章详细介绍了各专项的核心课程、硬件资源和就业去向,为计算机专业学生提供全面的申请策略和职业发展建议。

weixin_31528001的博客 397

android usb 检测工具,【未解决】android程序运行时可以检测到ACTION_USB_DEVICE_DETACHED,但是检测不到ACTION_USB_DEVICE_ATTACHED...

【背景】折腾:期间,需要实现:android程序在运行期间,可以检测到usb设备的插入。但是却出现:android程序运行时可以检测到ACTION_USB_DEVICE_DETACHED:但是检测不到ACTION_USB_DEVICE_ATTACHED【折腾过程】1.去参考:去试试:AndroidManifest.xml中添加:...看看效果。2.不过,参考之前就看到的:有点明白了:app,正在运...

weixin_35381903的博客 2185

第一章 Cheat Enginee(CE)使用指南

Cheat Engine核心功能详细说明(以植物大战僵尸为例) 教你修改单机游戏。

m0_74545731的博客 1万+

基础的pdf病毒木马

基础的pdf病毒木马 环境: 攻击机:Kali 目标操作系统:Windows 10或Windows 7 (关闭防火墙和安全软件) 目标软件:Adobe Reader 8.1.2 msf框架搜索:adobe-pdf 1.打开msfconsole 2.搜索 adobe_pdf模块 3.加载攻击模块并设置payload 4.运行生成pdf 5.将pdf拖入到win10 6.打开msf,加...

小小猪的博客 4624

2023最新版:用夜神模拟器安卓7抓微信小程序数据包(含开发者模式开启教程)

本文提供2023年最新教程,详细讲解如何在夜神模拟器的安卓7环境中,通过配置网络代理、安装系统根证书及启用开发者模式,成功抓取微信小程序的网络数据包。文章涵盖环境搭建、HTTPS解密及常见问题排查,是移动应用安全分析与数据交互研究的实用指南。

vscode5coder的博客 564

YOLOv8 ultralytics使用笔记----labelme标记数据,训练模型、追踪目标。

Ultralytics是一个Python库,它是为执行高级计算机视觉任务而创建的,如对象检测、实例分割、图像分类等。Ultralytics为YOLO模型发布了一个全新的存储库,它被构建为用于机器视觉统一框架。这里先利用,并激活。

qq_48050838的博客 1万+

Rockchip Android13 x3588 USB 2.0硬件调试与DTS配置实战

本文以Rockchip RK3588平台在Android13环境下USB 2.0接口失效为例,详细阐述了硬件调试与DTS配置的完整实战流程。通过分析供电原理、对照原理图与DTS配置、使用万用表定位电压异常,并最终通过修改DTS节点与定制内核驱动代码,解决了因USB HUB供电使能缺失导致的设备无法识别问题,为嵌入式开发者提供了清晰的排查思路和解决方案。

orange的博客 495

LLM评测框架Ragas:测试RAG的性能出现TimeoutError()的解决办法(Ragas+langchain+ollama)

无奈之下,自己找到了一个解决办法,在ragas支持的llm类库中加了一个如下的类,支持ollama、langchian_ollama使用ragas测试报错的问题。可以将如上的库放到你的ragas的系统库的llms目录下,然后修改__init__.py如下。最近用ragas测试rag的性能,发现老出现TimeoutError()的错误。这是一个临时的解决办法,具体等待官方给出最终的解决方案。后来发现官方也没有尽快支持的计划。然后就可以用如下代码进行一些验证。

Criss@陈磊 666

TC3XX - MCAL知识点(九):PWM EB-tresos配置说明及代码浅析

脉冲宽度调制(PWM)驱动器负责提供与AUTOSAR指定的PWM信号生成相关的标准服务。PWM通道的底层定时器驱动是GTM (TOM或ATOM片)或CCU6 (T12或T13片)定时器通道。软硬件匹配关系如下:PWM直接引用的是GTM与CCU6模块,然后GTM与CCU6再关联到Port的,根据软硬件匹配关系,也能调用中断来使用,本例子没使用中断。CCU6是一个高分辨率的16位捕获和比较单元,具有特定的应用模式,主要用于交流驱动控制。特殊的工作模式支持控制无刷直流电机使用霍尔传感器或反电动势检测。

梦想技术家 2887

Omap4470 USB驱动分析之注册过程

平台:OMAP4470,linix3.4,Android4.2平台。 问题: 1. usb host/otg模式切换的时候容易导致系统卡顿,甚至死机。 2. omap4470的usb接了一个usb-Ethernet,正常情况下,omap4470的usb模式应该是host,但是有时候会工作模式不对,重新设置host mode也可让usb-Ethernet工作正

linchuanzhi_886的专栏 1976

C# Modbus协议全解析 万字长文|RTU/TCP/UDP完整实战(寄存器映射+多从站组网+NModbus4工业级代码)

你做C#工业上位机开发,Modbus协议是绕不开的终极核心,没有之一!Modbus是由施耐德在1979年发布的工业级串行通信协议,经过40余年的发展,已经成为工业自动化领域的通用标准协议—— 小到温湿度传感器、智能电表、小型PLC,大到变频器、伺服驱动器、DCS集散控制系统,99%的工业设备都原生支持Modbus协议(RTU/TCP二选一,多数全支持)。很多开发者觉得Modbus「知识点杂、协议分支多、组网难」,本质是只掌握了零散的读写代码,没吃透。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1063
上一篇: eMMC接口
下一篇: android usb 分析1
lamdoc
博客等级 码龄18年 155粉丝 655原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值