Android Qcom USB Driver学习(十)

本文介绍了在Android系统中,基于QcomUSBDriver实现hidraw驱动的过程,探讨了两种识别USB设备的方法:usb_device_id和hid_device_id。文章详细解析了hid_probe、usb_device_id匹配以及hid_device_id匹配的流程,并展示了hidraw驱动注册、探测及hidraw_demo的示例代码,包括hidraw_raw_event函数的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

该系列文章总目录链接与各部分简介: Android Qcom USB Driver学习(零)

Android Qcom USB Driver学习(四)
Android Qcom USB Driver学习(七)

本章主要是基于之前的学习,实现一个hidraw的驱动,发现有两种用于识别usb设备的方式,放别是usb_device_id和hid_device_id

hid_probe

(2)usb_device_id

kernel/msm-4.19/drivers/hid/usbhid/usbmouse.c  
static const struct usb_device_id usb_mouse_id_table[] = {
    USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
                USB_INTERFACE_PROTOCOL_MOUSE)

(1)hid_device_id

kernel/msm-4.19/drivers/hid/usbhid/hid-core.c
bus = usb usb_register  注册驱动        -> sys/bus/usb/driver

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

kernel/msm-4.19/drivers/hid/hid-core.c
bus = hid  hid_register_driver 注册驱动  -> sys/bus/hid/driver

hid bus本身没有探测的能力,都是需要其他模块来进行hid_add_device,

usb探测的过程如下

usb_new_device -> usb_enumerate_device + announce_device + device_add -> bus_probe_device -> device_initial_probe 

	-> driver_match_device -> usb_device_match (driver.c)-> usb_match_id  (usb_device_id usbmouse.c)				   
	-> driver_probe_device ->  really_probe -> usb_mouse_probe -> input_register_device(usbmouse.c)
											-> usbhid_probe (usbhid/hid-core.c)-> hid_add_device -> device_add
											
		-> driver_match_device ->  hid_bus_match (hid/hid-core.c) -> hid_match_id   (hid_device_id hid-generic.c)	
		-> driver_probe_device ->   hid_device_probe(hid/hid-core.c) -> hid_generic_probe (hid/hid-generic.c)

issues

E hidraw 0003: 0C2E:1007.0001: device has no listeners, quitting
.raw_event =     hidraw_raw_event, //hidwar必须要实现这个函数

CONFIG_HIDRAW=y //需要打开这个函数,不然会调用hidraw.h中的空函数

hidraw_demo

在android的源码中没有只有hidraw的驱动,只有一些定义在hidraw.c中的api, 通过这些参数实现了hidraw接口的功能并测试通过

/* Copyright (c) 2014-2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/hid.h>
#include <linux/hid-debug.h>
#include "hid-ids.h"
#include "usbhid/usbhid.h"
#include <linux/usb.h>
#include <linux/vmalloc.h>
#include <linux/completion.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/hid.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/hidraw.h>

#define hidtype 0//1:use clamied , 0: use connect_mask

struct hidraw_data {
	struct hid_device *hdev;
};

static int hidraw_raw_event(struct hid_device *hdev,
		struct hid_report *report, u8 *raw_data, int size)
{
	struct hidraw_data *data = hid_get_drvdata(hdev);
	int ret = 0;
	if (!data)
		return 1;

	hidraw_report_event(hdev, raw_data, size);
	return ret;
}
#ifdef CONFIG_PM
static int hidraw_suspend(struct hid_device *hdev, pm_message_t message)
{

	return 0;
}
static int hidraw_resume(struct hid_device *hdev)
{
	return 0;
}
static int hidraw_reset_resume(struct hid_device *hdev)
{
	return 0;
}
#endif

static int hidraw_probe(struct hid_device *hdev,
		     const struct hid_device_id *id)
{
	struct hidraw_data *data;
	int error = -ENOMEM;
	struct usbhid_device *usbhid = hdev->driver_data;

	if(usbhid->ifnum != 0) {
		hid_err(hdev, "usbhid ifnum = %d\n", usbhid->ifnum);
		return error;
	}

	//hidraw_init();

	data = kzalloc(sizeof(struct hidraw_data), GFP_KERNEL);
	if (data == NULL) {
		hid_err(hdev, "failed to kzallocc \n");
		error = -ENOMEM;
		goto err_kzalloc;
	}

	data->hdev = hdev;

	hid_set_drvdata(hdev, data);
	error = hid_parse(hdev);
	if (error) {
		hid_err(hdev, "failed to parse \n");
		goto err_kzalloc;
	}

	hdev->quirks = HID_QUIRK_NO_INIT_REPORTS;
#if hidtype
	hdev->claimed = HID_CLAIMED_HIDRAW;
	error = hid_hw_start(hdev, 0);
#else
	error = hid_hw_start(hdev, HID_CONNECT_HIDRAW );
#endif
	if (error) {
		hid_err(hdev, "failed to hw start\n");
		goto err_drvdata_null;
	}
#if hidtype
	hidraw_connect(hdev);
#endif
	return 0;

err_kzalloc:
	kfree(data);
err_drvdata_null:
	hid_set_drvdata(hdev, NULL);
	return error;

}

static void hidraw_remove(struct hid_device *hdev)
{
	struct hidraw_data *data = hid_get_drvdata(hdev);

	hid_hw_stop(hdev);
#if hidtype
	hidraw_disconnect(hdev);
#endif
	hid_set_drvdata(hdev, NULL);

	//hidraw_exit();
	kfree(data);
}

static const struct hid_device_id hidraw_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_xxx, USB_DEVICE_ID_xxx) },
	{ }
};
MODULE_DEVICE_TABLE(hid, hidraw_devices);

static struct hid_driver hidraw_driver = {
	.name =          "hid-own",
	.id_table =      hidraw_devices,
	.probe =         hidraw_probe,
	.remove =        hidraw_remove,
	.raw_event =     hidraw_raw_event,
#ifdef CONFIG_PM
	.suspend =       hidraw_suspend,
	.resume =        hidraw_resume,
	.reset_resume =  hidraw_reset_resume,
#endif
};


//module_hid_driver(hidraw_driver);

static int __init hidown_init(void)
{
	int result;
	hidraw_init();

	result = hid_register_driver(&hidraw_driver);	
	return result;

}

static void __exit hidown_exit(void)
{
	hid_unregister_driver(&hidraw_driver);
	hidraw_exit();
}

module_init(hidown_init);
module_exit(hidown_exit);

MODULE_DESCRIPTION("Hid Raw Demo");
MODULE_LICENSE("GPL v2");

03-20
<think>好的,用户想查找与HAL HCD相关的技术资料或驱动程序,特别是在嵌入式系统或USB框架中的相关内容。首先,我需要确认HAL HCD具体指的是什么。HAL通常代表硬件抽象层(Hardware Abstraction Layer),而HCD可能指的是主机控制器驱动程序(Host Controller Driver)。在USB框架中,HCD负责管理主机控制器的操作,比如数据传输和设备通信。 接下来,我需要结合用户提供的引用内容。引用1提到STM32L0xx_HAL_Driver库,其中使用了中断方式进行UART通信,这可能与USB的HCD有关联。引用3提到vendors目录存放供应商特定的库,比如高通的专有库,这可能包括USB主机控制器的驱动。引用4中的libcore目录涉及Android的底层库,可能与USB框架相关。 用户可能需要具体的驱动程序代码或文档。在STM32的HAL库中,HCD通常涉及USB主机模式的驱动。例如,STM32的HAL库中可能有名为stm32l0xx_hal_hcd.c的文件,实现USB主机控制器的功能。此外,Linux内核中的USB HCD部分,比如drivers/usb/host目录下的代码,也是重要的参考资料。 还需要考虑不同厂商的实现,比如高通在AOSP中的专有驱动可能存放在vendors/qcom目录下。用户可能需要查找特定芯片的HCD文档,或者参考开源项目中的实现。 最后,用户可能需要知道如何访问这些资源,比如STMicroelectronics的官网、Linux内核文档或Android开源项目库。确保提供的参考资料链接正确,并指导用户如何查找具体的驱动文件和API使用示例。</think>### 关于HAL HCD驱动或组件的技术资料与驱动实现 HAL HCD(Hardware Abstraction Layer Host Controller Driver)在嵌入式系统和USB框架中主要负责管理主机控制器的底层硬件交互,例如USB主机模式下的数据传输和设备控制。以下是相关技术资料和驱动程序的查找方向: #### 1. **STM32 HAL库中的HCD实现** - 在STMicroelectronics的HAL库中,USB主机控制器驱动通常位于`Drivers/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_hcd.c`文件中,对应的头文件为`stm32l0xx_hal_hcd.h`[^1]。 - 功能包括: - 初始化主机控制器(例如USB OTG)。 - 管理USB设备枚举和传输请求。 - 中断处理和数据缓冲区管理。 - 示例代码片段: ```c HCD_HandleTypeDef hhcd; hhcd.Instance = USB_OTG_FS; HAL_HCD_Init(&hhcd); ``` 此代码初始化USB FS(全速)模式的主机控制器[^1]。 #### 2. **Linux内核中的USB HCD框架** - Linux内核通过`drivers/usb/host`目录实现通用USB主机控制器驱动,例如`ehci-hcd.c`(对应USB 2.0)和`xhci-hcd.c`(对应USB 3.0)[^3]。 - 关键结构体: - `struct hc_driver`: 定义主机控制器的操作函数(如启动/停止传输)。 - `struct usb_hcd`: 包含主机控制器的状态和资源。 - 典型调用流程: ```c usb_add_hcd(hcd, irqnum, IRQF_SHARED); // 注册HCD到内核 ``` #### 3. **Android HAL层中的USB组件** - 在AOSP(Android开源项目)中,USB主机功能涉及`hardware/libhardware`模块,具体实现可能位于`vendor/qcom/proprietary`目录下的专有库。 - 例如,高通芯片的USB驱动可能包含: - HCD初始化配置(时钟、GPIO)。 - 与Linux内核HCD的交互接口。 #### 4. **文档与调试工具** - **STMicroelectronics文档**:[STM32L0xx HAL用户手册](https://www.st.com/resource/en/user_manual/dm00105259-stm32l0xx-hal-drivers-um-stmicroelectronics.pdf)详细说明HCD API[^1]。 - **Linux内核文档**:`Documentation/usb/usb-device-drivers.txt`描述HCD开发规范。 - **调试工具**:使用`lsusb`和`dmesg`命令可查看USB主机控制器状态和设备连接信息。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值