libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
desc_str.cpp
1#include "desc_str.hpp"
2
3using namespace LibXR::USB;
4
6 const std::initializer_list<const LanguagePack*>& lang_list, const uint8_t* uid,
7 size_t uid_len)
8 : LANG_NUM(lang_list.size()),
9 header_(new uint16_t[LANG_NUM + 1]),
10 land_id_(header_ + 1),
11 string_list_(new const LanguagePack*[LANG_NUM])
12{
13 ASSERT(LANG_NUM > 0);
14 ASSERT(uid != nullptr || uid_len == 0);
15
16 auto lang = lang_list.begin();
17 size_t max_str_len = 0;
18
19 // 每个字节 -> 2个HEX字符 -> 每字符2字节UTF-16LE => 每字节4字节UTF-16LE
20 const size_t EXTRA_SERIAL_UTF16 = uid ? uid_len * 4 : 0;
21
22 for (size_t i = 0; i < LANG_NUM; i++)
23 {
24 land_id_[i] = static_cast<uint16_t>((*lang)->lang_id);
25 string_list_[i] = *lang;
26
27 size_t lang_max = (*lang)->max_string_length;
28
29 if (EXTRA_SERIAL_UTF16 != 0)
30 {
31 const size_t IDX_SERIAL = static_cast<size_t>(Index::SERIAL_NUMBER_STRING) - 1;
32 size_t serial_prefix_len = (*lang)->string_lens[IDX_SERIAL];
33 size_t serial_total_len = serial_prefix_len + EXTRA_SERIAL_UTF16;
34 if (serial_total_len > lang_max)
35 {
36 lang_max = serial_total_len;
37 }
38 }
39
40 if (max_str_len < lang_max)
41 {
42 max_str_len = lang_max;
43 }
44
45 ++lang;
46 }
47
48 *header_ = (static_cast<uint16_t>(LANG_NUM * 2 + 2)) | (0x03 << 8);
49 buffer_.addr_ = new uint8_t[max_str_len + 2];
50 buffer_.size_ = max_str_len + 2;
51
52 ASSERT(max_str_len + 2 <= 255);
53
54 serial_uid_ = uid;
55 serial_uid_len_ = uid_len;
56}
57
58ErrorCode DescriptorStrings::GenerateString(Index index, uint16_t lang)
59{
60 ASSERT(buffer_.addr_ != nullptr);
61
62 if (index == Index::LANGUAGE_ID)
63 {
64 return ErrorCode::NOT_SUPPORT;
65 }
66
67 int ans = -1;
68 for (size_t i = 0; i < LANG_NUM; ++i)
69 {
70 if (land_id_[i] == lang)
71 {
72 ans = static_cast<int>(i);
73 break;
74 }
75 }
76 if (ans == -1)
77 {
78 return ErrorCode::NOT_FOUND;
79 }
80
81 uint8_t* buffer = reinterpret_cast<uint8_t*>(buffer_.addr_);
82
83 // 有 UID 且请求的是 Serial:前缀 + UID 的十六进制字符串
84 if (index == Index::SERIAL_NUMBER_STRING && serial_uid_ != nullptr)
85 {
86 const LanguagePack* pack = string_list_[ans];
87 constexpr size_t IDX = static_cast<size_t>(Index::SERIAL_NUMBER_STRING) - 1;
88
89 const char* const SERIAL_PREFIX = pack->strings[IDX];
90 const size_t PREFIX_UTF16_LEN = pack->string_lens[IDX];
91
92 const uint8_t DATA_LEN =
93 static_cast<uint8_t>(PREFIX_UTF16_LEN + serial_uid_len_ * 4 + 2);
94
95 ASSERT(PREFIX_UTF16_LEN + serial_uid_len_ * 4 + 2 <= 255);
96
97 buffer[1] = 0x03;
98 buffer[0] = DATA_LEN;
99
100 uint8_t* out = buffer + 2;
101
102 // 先写前缀(UTF-8 -> UTF-16LE)
103 ToUTF16LE(SERIAL_PREFIX, out);
104 out += PREFIX_UTF16_LEN; // 前缀的 UTF-16LE 字节数
105
106 // 再写 UID 的十六进制(ASCII 0-9 A-F)
107 static const char HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
108 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
109
110 for (size_t i = 0; i < serial_uid_len_; ++i)
111 {
112 uint8_t b = serial_uid_[i];
113 char hi = HEX[(b >> 4) & 0x0F];
114 char lo = HEX[b & 0x0F];
115
116 // hi
117 *out++ = static_cast<uint8_t>(hi);
118 *out++ = 0x00;
119
120 // lo
121 *out++ = static_cast<uint8_t>(lo);
122 *out++ = 0x00;
123 }
124
125 return ErrorCode::OK;
126 }
127
128 // 其它字符串:走原来的逻辑
129 auto data_len = string_list_[ans]->string_lens[static_cast<size_t>(index) - 1] + 2;
130
131 buffer[1] = 0x03;
132 buffer[0] = static_cast<uint8_t>(data_len);
133 const char* str = string_list_[ans]->strings[static_cast<size_t>(index) - 1];
134 ToUTF16LE(str, buffer + 2);
135 return ErrorCode::OK;
136}
137
139{
140 ASSERT(buffer_.addr_ != nullptr);
141 uint8_t* buffer = reinterpret_cast<uint8_t*>(buffer_.addr_);
142 return RawData{buffer_.addr_, buffer[0]};
143}
144
146{
147 return RawData{header_, (LANG_NUM + 1) * sizeof(uint16_t)};
148}
149
150void DescriptorStrings::ToUTF16LE(const char* str, uint8_t* buffer)
151{
152 size_t len = 0;
153 const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
154
155 while (*s)
156 {
157 uint32_t codepoint = 0;
158
159 if (*s < 0x80)
160 {
161 codepoint = *s++;
162 }
163 else if ((*s & 0xE0) == 0xC0)
164 {
165 codepoint = (*s & 0x1F) << 6;
166 s++;
167 codepoint |= (*s & 0x3F);
168 s++;
169 }
170 else if ((*s & 0xF0) == 0xE0)
171 {
172 codepoint = (*s & 0x0F) << 12;
173 s++;
174 codepoint |= (*s & 0x3F) << 6;
175 s++;
176 codepoint |= (*s & 0x3F);
177 s++;
178 }
179 else if ((*s & 0xF8) == 0xF0)
180 {
181 // 忽略超出 BMP 的字符(如 emoji)
182 s++;
183 if (*s)
184 {
185 s++;
186 }
187 if (*s)
188 {
189 s++;
190 }
191 if (*s)
192 {
193 s++;
194 }
195 continue;
196 }
197 else
198 {
199 s++;
200 continue;
201 }
202
203 buffer[len++] = codepoint & 0xFF;
204 buffer[len++] = (codepoint >> 8) & 0xFF;
205 }
206}
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ErrorCode GenerateString(Index index, uint16_t lang)
生成指定语言和索引的字符串描述符 Generate USB string descriptor for given language and string index
Definition desc_str.cpp:58
const size_t LANG_NUM
已注册语言数量 / Registered language count
Definition desc_str.hpp:166
RawData GetData()
获取当前构建好的字符串描述符数据 Get the descriptor buffer
Definition desc_str.cpp:138
RawData buffer_
临时描述符缓冲区 / Temp descriptor buffer
Definition desc_str.hpp:170
size_t serial_uid_len_
UID 字节数 / UID byte count.
Definition desc_str.hpp:173
RawData GetLangIDData()
获取语言ID描述符内容 Get LangID descriptor data
Definition desc_str.cpp:145
DescriptorStrings(const std::initializer_list< const LanguagePack * > &lang_list, const uint8_t *uid=nullptr, size_t uid_len=0)
USB 描述符字符串管理器构造函数 USB descriptor string manager constructor.
Definition desc_str.cpp:5
const uint8_t * serial_uid_
序列号后缀 UID (原始字节) / Serial number suffix UID (original bytes)
Definition desc_str.hpp:172
Index
描述符字符串索引 / USB descriptor string index
Definition desc_str.hpp:25
@ LANGUAGE_ID
语言ID描述符 / LangID descriptor
@ SERIAL_NUMBER_STRING
序列号字符串索引 / Serial number string
const LanguagePack ** string_list_
多语言包指针表 / LanguagePack pointer table
Definition desc_str.hpp:169
uint16_t * land_id_
语言ID数组 / LangID array
Definition desc_str.hpp:168
uint16_t * header_
语言ID描述符头部 / LangID descriptor header
Definition desc_str.hpp:167
单语言描述符包(用于注册静态多语言字符串) Single language USB string descriptor pack for registration
Definition desc_str.hpp:49
StringData strings[STRING_LIST_SIZE]
Definition desc_str.hpp:51
size_t max_string_length
最大字符串长度 / Maximum string length
Definition desc_str.hpp:55