mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-10 20:36:48 +00:00
1
This commit is contained in:
parent
ab29434ac1
commit
1e94d1e7d0
81
kernel/common/hid.h
Normal file
81
kernel/common/hid.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <common/stddef.h>
|
||||||
|
|
||||||
|
#define __HID_USAGE_TABLE_SIZE 64 // usage stack的大小
|
||||||
|
#define HID_MAX_REPORT 300 // 最大允许的hid report数目(包括feature、input、output)
|
||||||
|
#define HID_MAX_PATH_SIZE 16 // maximum depth for path
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 描述hid path中的一个节点
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct hid_node_t
|
||||||
|
{
|
||||||
|
int u_page;
|
||||||
|
int usage;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 描述一条hid path
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct hid_path_t
|
||||||
|
{
|
||||||
|
int size; // 路径中的节点数目
|
||||||
|
struct hid_node_t node[HID_MAX_PATH_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Describe a HID Data with its location in report
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct hid_data_t
|
||||||
|
{
|
||||||
|
int value; // hid对象的值
|
||||||
|
struct hid_path_t path; // hid path
|
||||||
|
|
||||||
|
int report_count; // count of reports for this usage type
|
||||||
|
int offset; // offset of data in report
|
||||||
|
int size; // size of data in bits
|
||||||
|
|
||||||
|
uint8_t report_id; // report id(from incoming report)
|
||||||
|
uint8_t type; // 数据类型:FEATURE / INPUT / OUTPUT
|
||||||
|
uint8_t attribue; // report field attribute. (2 = (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position))
|
||||||
|
// (6 = (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position))
|
||||||
|
int8_t uuit_exp; // unit exponent;
|
||||||
|
|
||||||
|
uint32_t uuit; // HID unit
|
||||||
|
|
||||||
|
int logical_min; // Logical min
|
||||||
|
int logical_max; // Logical max
|
||||||
|
int phys_min; // Physical min
|
||||||
|
int phys_max; // Physical max
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief hid解析器
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct hid_parser
|
||||||
|
{
|
||||||
|
const uint8_t *report_desc; // 指向report descriptor的指针
|
||||||
|
int report_desc_size; // report descriptor的大小(字节)
|
||||||
|
int pos; // report_desc中,当前正在处理的位置
|
||||||
|
uint8_t item; // 暂存当前的item
|
||||||
|
uint32_t value; // 暂存当前的值
|
||||||
|
|
||||||
|
struct hid_data_t data; // 存储当前的环境
|
||||||
|
|
||||||
|
int offset_table[HID_MAX_REPORT][3]; // 存储 hid report的ID、type、offset
|
||||||
|
int report_count; // hid report的数量
|
||||||
|
int count; // local items的计数
|
||||||
|
|
||||||
|
uint32_t u_page;
|
||||||
|
struct hid_node_t usage_table[__HID_USAGE_TABLE_SIZE]; // Usage stack
|
||||||
|
int usage_size; // usage的数量
|
||||||
|
int usage_min;
|
||||||
|
int usage_max;
|
||||||
|
|
||||||
|
int cnt_objects; // report descriptor中的对象数目
|
||||||
|
int cnt_report // report desc中的report数目
|
||||||
|
};
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
CFLAGS += -I .
|
CFLAGS += -I .
|
||||||
|
|
||||||
kernel_driver_subdirs:=video interrupt usb pci uart acpi disk keyboard mouse multiboot2 timers tty
|
kernel_driver_subdirs:=video interrupt usb pci uart acpi disk keyboard mouse multiboot2 timers tty hid
|
||||||
|
|
||||||
ECHO:
|
ECHO:
|
||||||
@echo "$@"
|
@echo "$@"
|
||||||
|
19
kernel/driver/hid/Makefile
Normal file
19
kernel/driver/hid/Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
CFLAGS += -I .
|
||||||
|
|
||||||
|
kernel_driver_hid_subdirs:= usbhid
|
||||||
|
|
||||||
|
kernel_driver_hid_objs:= $(shell find ./*.c)
|
||||||
|
|
||||||
|
ECHO:
|
||||||
|
@echo "$@"
|
||||||
|
|
||||||
|
$(kernel_driver_hid_subdirs): ECHO
|
||||||
|
$(MAKE) -C $@ all CFLAGS="$(CFLAGS)" ASFLAGS="$(ASFLAGS)" PIC="$(PIC)"
|
||||||
|
|
||||||
|
$(kernel_driver_hid_objs): ECHO
|
||||||
|
gcc $(CFLAGS) -c $@ -o $@.o
|
||||||
|
|
||||||
|
all: $(kernel_driver_hid_objs) $(kernel_driver_hid_subdirs)
|
||||||
|
@echo $(kernel_driver_hid_objs)
|
||||||
|
|
366
kernel/driver/hid/hidparse.c
Normal file
366
kernel/driver/hid/hidparse.c
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
#include <common/compiler.h>
|
||||||
|
#include <common/glib.h>
|
||||||
|
#include <common/hid.h>
|
||||||
|
#include <common/printk.h>
|
||||||
|
#include <common/string.h>
|
||||||
|
#include <debug/bug.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
参考文档:https://www.usb.org/document-library/device-class-definition-hid-111
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool HID_PARSE_OUTPUT = true; // 是否输出解析信息
|
||||||
|
|
||||||
|
static void hid_reset_parser(struct hid_parser *parser);
|
||||||
|
|
||||||
|
static const char *hid_print_usage_page(const int u_page);
|
||||||
|
static const char *hid_print_usage_type(const int page, const int type);
|
||||||
|
static const char *hid_print_collection(const int value);
|
||||||
|
static int *__get_report_offset(struct hid_parser *hid_parser, const uint8_t report_id, const uint8_t report_type);
|
||||||
|
|
||||||
|
// hid item的低2位为size
|
||||||
|
#define HID_SIZE_MASK 0x3
|
||||||
|
// 高6bit为item内容
|
||||||
|
#define HID_ITEM_MASK 0xFC
|
||||||
|
#define HID_ITEM_UPAGE 0x04 // usage page
|
||||||
|
#define HID_ITEM_USAGE 0x08 // local item
|
||||||
|
#define HID_ITEM_LOG_MIN 0x14
|
||||||
|
#define HID_ITEM_USAGE_MIN 0x18 // local item
|
||||||
|
#define HID_ITEM_LOG_MAX 0x24
|
||||||
|
#define HID_ITEM_USAGE_MAX 0x28 // local item
|
||||||
|
#define HID_ITEM_PHY_MIN 0x34
|
||||||
|
#define HID_ITEM_PHY_MAX 0x44
|
||||||
|
#define HID_ITEM_UNIT_EXP 0x54
|
||||||
|
#define HID_ITEM_UNIT 0x64
|
||||||
|
#define HID_ITEM_REP_SIZE 0x74
|
||||||
|
#define HID_ITEM_STRING 0x78 // local item?
|
||||||
|
#define HID_ITEM_REP_ID 0x84
|
||||||
|
#define HID_ITEM_REP_COUNT 0x94
|
||||||
|
|
||||||
|
// 这部分请参考hid_1_11.pdf Section 6.2.2.4
|
||||||
|
|
||||||
|
#define HID_ITEM_COLLECTION 0xA0
|
||||||
|
#define HID_ITEM_END_COLLECTION 0xC0
|
||||||
|
#define HID_ITEM_FEATURE 0xB0
|
||||||
|
#define HID_ITEM_INPUT 0x80
|
||||||
|
#define HID_ITEM_OUTPUT 0x90
|
||||||
|
|
||||||
|
static char __spaces_buf[33];
|
||||||
|
char *__spaces(uint8_t cnt)
|
||||||
|
{
|
||||||
|
static char __space_overflow_str[] = "**";
|
||||||
|
if (cnt > 32)
|
||||||
|
{
|
||||||
|
return &__space_overflow_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(__spaces_buf, ' ', 32);
|
||||||
|
__spaces_buf[cnt] = '\0';
|
||||||
|
return __spaces_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 重置parser
|
||||||
|
*
|
||||||
|
* @param parser 解析器
|
||||||
|
* @return int 状态码
|
||||||
|
*/
|
||||||
|
static void hid_reset_parser(struct hid_parser *parser)
|
||||||
|
{
|
||||||
|
memset(parser, 0, sizeof(struct hid_parser));
|
||||||
|
parser->data.report_id = 1; // we must give it a non-zero value or the parser doesn't work
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从usage_stack中弹出第一个元素
|
||||||
|
*
|
||||||
|
* @param parser 解析器
|
||||||
|
* @return __always_inline
|
||||||
|
*/
|
||||||
|
static __always_inline void __pop_usage_stack(struct hid_parser *parser)
|
||||||
|
{
|
||||||
|
if (parser->usage_size > 0)
|
||||||
|
{
|
||||||
|
for (int js = 0; js < parser->usage_size - 1; ++js)
|
||||||
|
memmove(&parser->usage_table[js], &parser->usage_table[js + 1], sizeof(struct hid_node_t));
|
||||||
|
|
||||||
|
--parser->usage_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 解析hid report,并获取下一个数据到data字段中
|
||||||
|
*
|
||||||
|
* @param parser 解析器
|
||||||
|
* @param data 返回的数据
|
||||||
|
* @return true 解析成功
|
||||||
|
* @return false 解析失败
|
||||||
|
*/
|
||||||
|
static bool hid_parse(struct hid_parser *parser, struct hid_data_t *data)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
static uint8_t space_cnt = 0;
|
||||||
|
static bool did_collection = false;
|
||||||
|
static int item_size[4] = {0, 1, 2, 4};
|
||||||
|
|
||||||
|
// 循环解析
|
||||||
|
while (!found && (parser->pos < parser->report_desc_size))
|
||||||
|
{
|
||||||
|
// 当前parse过程还没有解析到report
|
||||||
|
if (parser->count == 0)
|
||||||
|
{
|
||||||
|
// 打印当前 report_data 的值
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
printk("\n %02X ", parser->report_desc[parser->pos]);
|
||||||
|
// 获取到report size
|
||||||
|
parser->item = parser->report_desc[parser->pos++];
|
||||||
|
parser->value = 0;
|
||||||
|
// 拷贝report的数据
|
||||||
|
memcpy(&parser->value, &parser->report_desc[parser->pos], item_size[parser->item & HID_SIZE_MASK]);
|
||||||
|
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
if (i < item_size[parser->item & HID_SIZE_MASK])
|
||||||
|
printk("%02X ", parser->report_desc[parser->pos + i]);
|
||||||
|
else
|
||||||
|
printk(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 将指针指向下一个item
|
||||||
|
parser->pos += item_size[parser->item & HID_SIZE_MASK];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (parser->item & HID_ITEM_MASK)
|
||||||
|
{
|
||||||
|
case HID_ITEM_UPAGE:
|
||||||
|
// 拷贝upage
|
||||||
|
parser->u_page = (int)parser->value;
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
printk("%sUsage Page (%s)", __spaces(space_cnt), hid_print_usage_page(parser->u_page));
|
||||||
|
// 拷贝到 usage table。由于这是一个USAGE entry,因此不增加usage_size(以便后面覆盖它)
|
||||||
|
parser->usage_table[parser->usage_size].u_page = parser->u_page;
|
||||||
|
parser->usage_table[parser->usage_size].usage = 0xff;
|
||||||
|
break;
|
||||||
|
case HID_ITEM_USAGE:
|
||||||
|
// 拷贝upage到usage table中
|
||||||
|
if (parser->item & HID_SIZE_MASK > 2) // item大小为32字节
|
||||||
|
parser->usage_table[parser->usage_size].u_page = (int)(parser->value >> 16);
|
||||||
|
else
|
||||||
|
parser->usage_table[parser->usage_size].u_page = parser->u_page;
|
||||||
|
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
printk("%sUsage (%s)", __spaces(space_cnt),
|
||||||
|
hid_print_usage_type(parser->u_page, parser->value & 0xffff));
|
||||||
|
++parser->usage_size;
|
||||||
|
break;
|
||||||
|
case HID_ITEM_USAGE_MIN:
|
||||||
|
// todo: 设置usage min
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
printk("%sUsage min (%i=%s)", __spaces(space_cnt), parser->value,
|
||||||
|
hid_print_usage_type(parser->u_page, parser->value));
|
||||||
|
break;
|
||||||
|
case HID_ITEM_USAGE_MAX:
|
||||||
|
// todo: 设置usage max
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
printk("%sUsage max (%i=%s)", __spaces(space_cnt), parser->value,
|
||||||
|
hid_print_usage_type(parser->u_page, parser->value));
|
||||||
|
break;
|
||||||
|
case HID_ITEM_COLLECTION:
|
||||||
|
// 从usage table中取出第一个u_page和usage,并且将他们存储在parser->data.path
|
||||||
|
parser->data.path.node[parser->data.path.size].u_page = parser->usage_table[0].u_page;
|
||||||
|
parser->data.path.node[parser->data.path.size].usage = parser->usage_table[0].usage;
|
||||||
|
++parser->data.path.size;
|
||||||
|
|
||||||
|
// 由于上面取出了元素,因此将队列往前移动1个位置
|
||||||
|
__pop_usage_stack(parser);
|
||||||
|
|
||||||
|
// 获取index(如果有的话)???
|
||||||
|
if (parser->value > 0x80)
|
||||||
|
{
|
||||||
|
kdebug("parser->value > 0x80");
|
||||||
|
parser->data.path.node[parser->data.path.size].u_page = 0xff;
|
||||||
|
parser->data.path.node[parser->data.path.size].usage = parser->value & 0x7f;
|
||||||
|
++parser->data.path.size;
|
||||||
|
}
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
{
|
||||||
|
printk("%sCollection (%s)", __spaces(space_cnt), hid_print_collection(parser->value));
|
||||||
|
space_cnt += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HID_ITEM_END_COLLECTION:
|
||||||
|
--parser->data.path.size; // 为什么要--?????
|
||||||
|
// 删除多余的(未识别的)node
|
||||||
|
if (parser->data.path.node[parser->data.path.size].u_page == 0xff)
|
||||||
|
--parser->data.path.size;
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
{
|
||||||
|
if (space_cnt >= 2)
|
||||||
|
space_cnt -= 2;
|
||||||
|
printk("%sEnd Collection", __spaces(space_cnt));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HID_ITEM_FEATURE:
|
||||||
|
case HID_ITEM_INPUT:
|
||||||
|
case HID_ITEM_OUTPUT:
|
||||||
|
// 找到了一个对象
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
// 增加对象计数器
|
||||||
|
++parser->cnt_objects;
|
||||||
|
|
||||||
|
// 更新local items的计数
|
||||||
|
if (parser->count == 0)
|
||||||
|
parser->count = parser->report_count;
|
||||||
|
|
||||||
|
// 从usage_table获取u_page和usage,将他们存储到parser.data.path
|
||||||
|
parser->data.path.node[parser->data.path.size].u_page = parser->usage_table[0].u_page;
|
||||||
|
parser->data.path.node[parser->data.path.size].usage = parser->usage_table[0].usage;
|
||||||
|
++parser->data.path.size;
|
||||||
|
|
||||||
|
// 从usage table中弹出刚刚那个node
|
||||||
|
__pop_usage_stack(parser);
|
||||||
|
|
||||||
|
// 拷贝数据到data
|
||||||
|
parser->data.type = (uint8_t)(parser->item & HID_ITEM_MASK);
|
||||||
|
parser->data.attribue = (uint8_t)parser->value;
|
||||||
|
int *offset_ptr =
|
||||||
|
__get_report_offset(parser, parser->data.report_id, (uint8_t)(parser->item & HID_ITEM_MASK));
|
||||||
|
|
||||||
|
if (unlikely(offset_ptr == NULL))
|
||||||
|
{
|
||||||
|
BUG_ON(1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
parser->data.offset = *offset_ptr;
|
||||||
|
|
||||||
|
// 获取pData中的对象
|
||||||
|
memcpy(data, &parser->data, sizeof(struct hid_data_t));
|
||||||
|
|
||||||
|
// 增加report offset
|
||||||
|
*offset_ptr = (*offset_ptr) + 1;
|
||||||
|
|
||||||
|
// 从path中删除最后一个节点(刚刚弹出的这个节点)
|
||||||
|
--parser->data.path.size;
|
||||||
|
|
||||||
|
// 减少local items计数
|
||||||
|
if (parser->count > 0)
|
||||||
|
--parser->count;
|
||||||
|
|
||||||
|
if (!did_collection)
|
||||||
|
{
|
||||||
|
if (HID_PARSE_OUTPUT)
|
||||||
|
{
|
||||||
|
if ((parser->item & HID_ITEM_MASK) == HID_ITEM_FEATURE)
|
||||||
|
printk("%sFeature ", __spaces(space_cnt));
|
||||||
|
else if ((parser->item & HID_ITEM_MASK) == HID_ITEM_INPUT)
|
||||||
|
printk("%sInput ", __spaces(space_cnt));
|
||||||
|
else if ((parser->item & HID_ITEM_MASK) == HID_ITEM_OUTPUT)
|
||||||
|
printk("%sOutut ", __spaces(space_cnt));
|
||||||
|
|
||||||
|
printk("(%s,%s,%s" /* ",%s,%s,%s,%s" */ ")", !(parser->value & (1 << 0)) ? "Data" : "Constant",
|
||||||
|
!(parser->value & (1 << 1)) ? "Array" : "Variable",
|
||||||
|
!(parser->value & (1 << 2)) ? "Absolute" : "Relative" /*,
|
||||||
|
!(parser->value & (1<<3)) ? "No Wrap" : "Wrap",
|
||||||
|
!(parser->value & (1<<4)) ? "Linear" : "Non Linear",
|
||||||
|
!(parser->value & (1<<5)) ? "Preferred State" : "No Preferred",
|
||||||
|
!(parser->value & (1<<6)) ? "No Null" : "Null State",
|
||||||
|
//!(parser->value & (1<<8)) ? "Bit Fueld" : "Buffered Bytes"
|
||||||
|
*/
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
did_collection = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HID_ITEM_REP_ID:
|
||||||
|
// todo:
|
||||||
|
break;
|
||||||
|
case HID_ITEM_REP_SIZE:
|
||||||
|
// todo:
|
||||||
|
break;
|
||||||
|
case HID_ITEM_REP_COUNT:
|
||||||
|
// todo:
|
||||||
|
break;
|
||||||
|
case HID_ITEM_UNIT_EXP:
|
||||||
|
// todo:
|
||||||
|
break;
|
||||||
|
case HID_ITEM_UNIT:
|
||||||
|
// todo:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 解析hid report的数据
|
||||||
|
*
|
||||||
|
* @param report_data 从usb hid设备获取到hid report
|
||||||
|
* @param len report_data的大小(字节)
|
||||||
|
* @return int错误码
|
||||||
|
*/
|
||||||
|
int hid_parse_report(const void *report_data, const int len)
|
||||||
|
{
|
||||||
|
struct hid_parser parser = {0};
|
||||||
|
struct hid_data_t data;
|
||||||
|
|
||||||
|
hid_reset_parser(&parser);
|
||||||
|
parser.report_desc = (const uint8_t *)report_data;
|
||||||
|
parser.report_desc_size = len;
|
||||||
|
|
||||||
|
while (hid_parse(&parser, &data))
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打印usage page的数据
|
||||||
|
*
|
||||||
|
* @param u_page usage page的id
|
||||||
|
* @return const char* usage page的字符串
|
||||||
|
*/
|
||||||
|
static const char *hid_print_usage_page(const int u_page)
|
||||||
|
{
|
||||||
|
// todo:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 打印usage page的类型
|
||||||
|
*
|
||||||
|
* @param page
|
||||||
|
* @param type
|
||||||
|
* @return const char*
|
||||||
|
*/
|
||||||
|
static const char *hid_print_usage_type(const int page, const int type)
|
||||||
|
{
|
||||||
|
// todo:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 输出colection字符串
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return const char*
|
||||||
|
*/
|
||||||
|
static const char *hid_print_collection(const int value)
|
||||||
|
{
|
||||||
|
// todo:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 从parser的offset table中,根据report_id和report_type,获取表中指向offset字段的指针
|
||||||
|
*
|
||||||
|
* @param hid_parser 解析器
|
||||||
|
* @param report_id report_id
|
||||||
|
* @param report_type report类型
|
||||||
|
* @return int* 指向offset字段的指针
|
||||||
|
*/
|
||||||
|
static int *__get_report_offset(struct hid_parser *hid_parser, const uint8_t report_id, const uint8_t report_type)
|
||||||
|
{
|
||||||
|
// todo:
|
||||||
|
}
|
15
kernel/driver/hid/usbhid/Makefile
Normal file
15
kernel/driver/hid/usbhid/Makefile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
CFLAGS += -I .
|
||||||
|
|
||||||
|
|
||||||
|
kernel_driver_usbhid_objs:= $(shell find ./*.c)
|
||||||
|
|
||||||
|
ECHO:
|
||||||
|
@echo "$@"
|
||||||
|
|
||||||
|
$(kernel_driver_usbhid_objs): ECHO
|
||||||
|
gcc $(CFLAGS) -c $@ -o $@.o
|
||||||
|
|
||||||
|
all: $(kernel_driver_hid_objs) $(kernel_driver_hid_subdirs)
|
||||||
|
@echo $(kernel_driver_hid_objs)
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user