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
59{
60 ASSERT(buffer_.addr_ != nullptr);
61
62 if (index == Index::LANGUAGE_ID)
63 {
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 {
79 }
80
81 uint8_t* buffer = reinterpret_cast<uint8_t*>(buffer_.addr_);
82
83 const auto INDEX_NUM = static_cast<uint8_t>(index);
84 if (INDEX_NUM < static_cast<uint8_t>(Index::MANUFACTURER_STRING) ||
85 INDEX_NUM > static_cast<uint8_t>(Index::SERIAL_NUMBER_STRING))
86 {
88 }
89
90 if (index == Index::SERIAL_NUMBER_STRING && serial_uid_ != nullptr)
91 {
92 // 序列号字符串 = 配置前缀 + UID 的 UTF-16LE 十六进制表示。
93 // Serial string = configured prefix + UID rendered as UTF-16LE hex pairs.
94 const LanguagePack* pack = string_list_[ans];
95 constexpr size_t IDX = static_cast<size_t>(Index::SERIAL_NUMBER_STRING) - 1;
96
97 const char* const SERIAL_PREFIX = pack->strings[IDX];
98 const size_t PREFIX_UTF16_LEN = pack->string_lens[IDX];
99
100 const uint8_t DATA_LEN =
101 static_cast<uint8_t>(PREFIX_UTF16_LEN + serial_uid_len_ * 4 + 2);
102
103 ASSERT(PREFIX_UTF16_LEN + serial_uid_len_ * 4 + 2 <= 255);
104
105 buffer[1] = 0x03;
106 buffer[0] = DATA_LEN;
107
108 uint8_t* out = buffer + 2;
109
110 ToUTF16LE(SERIAL_PREFIX, out);
111 out += PREFIX_UTF16_LEN;
112
113 static const char HEX[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
114 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
115
116 for (size_t i = 0; i < serial_uid_len_; ++i)
117 {
118 uint8_t b = serial_uid_[i];
119 char hi = HEX[(b >> 4) & 0x0F];
120 char lo = HEX[b & 0x0F];
121
122 *out++ = static_cast<uint8_t>(hi);
123 *out++ = 0x00;
124 *out++ = static_cast<uint8_t>(lo);
125 *out++ = 0x00;
126 }
127
129 }
130
131 auto data_len = string_list_[ans]->string_lens[INDEX_NUM - 1] + 2;
132 buffer[1] = 0x03;
133 buffer[0] = static_cast<uint8_t>(data_len);
134 const char* str = string_list_[ans]->strings[INDEX_NUM - 1];
135 ToUTF16LE(str, buffer + 2);
137}
138
140{
141 ASSERT(buffer_.addr_ != nullptr);
142 uint8_t* buffer = reinterpret_cast<uint8_t*>(buffer_.addr_);
143 return RawData{buffer_.addr_, buffer[0]};
144}
145
147{
148 return RawData{header_, (LANG_NUM + 1) * sizeof(uint16_t)};
149}
150
151bool DescriptorStrings::HasLanguage(uint16_t lang) const
152{
153 // 接口字符串与内建字符串表共用同一套语言门控。
154 // Interface strings follow the same language gating as the built-in string table.
155 for (size_t i = 0; i < LANG_NUM; ++i)
156 {
157 if (land_id_[i] == lang)
158 {
159 return true;
160 }
161 }
162 return false;
163}
164
165void DescriptorStrings::ToUTF16LE(const char* str, uint8_t* buffer)
166{
167 size_t len = 0;
168 const unsigned char* s = reinterpret_cast<const unsigned char*>(str);
169
170 while (*s)
171 {
172 uint32_t codepoint = 0;
173
174 if (*s < 0x80)
175 {
176 codepoint = *s++;
177 }
178 else if ((*s & 0xE0) == 0xC0)
179 {
180 codepoint = (*s & 0x1F) << 6;
181 s++;
182 codepoint |= (*s & 0x3F);
183 s++;
184 }
185 else if ((*s & 0xF0) == 0xE0)
186 {
187 codepoint = (*s & 0x0F) << 12;
188 s++;
189 codepoint |= (*s & 0x3F) << 6;
190 s++;
191 codepoint |= (*s & 0x3F);
192 s++;
193 }
194 else if ((*s & 0xF8) == 0xF0)
195 {
196 // 忽略 BMP 之外的字符,保持描述符生成逻辑简单且有界。
197 // Ignore code points outside BMP to keep descriptor generation simple and bounded.
198 s++;
199 if (*s)
200 {
201 s++;
202 }
203 if (*s)
204 {
205 s++;
206 }
207 if (*s)
208 {
209 s++;
210 }
211 continue;
212 }
213 else
214 {
215 s++;
216 continue;
217 }
218
219 buffer[len++] = codepoint & 0xFF;
220 buffer[len++] = (codepoint >> 8) & 0xFF;
221 }
222}
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
const size_t LANG_NUM
已注册语言数量 / Registered language count
Definition desc_str.hpp:163
bool HasLanguage(uint16_t lang) const
检查是否注册了指定语言 / Check whether the given language is registered
Definition desc_str.cpp:151
RawData GetData()
获取当前构建好的字符串描述符数据 Get the descriptor buffer
Definition desc_str.cpp:139
RawData buffer_
临时描述符缓冲区 / Temp descriptor buffer
Definition desc_str.hpp:167
size_t serial_uid_len_
UID 字节数 / UID byte count.
Definition desc_str.hpp:171
RawData GetLangIDData()
获取语言ID描述符内容 Get LangID descriptor data
Definition desc_str.cpp:146
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
Index
描述符字符串索引 / USB descriptor string index
Definition desc_str.hpp:21
@ MANUFACTURER_STRING
厂商字符串索引 / Manufacturer string
@ LANGUAGE_ID
语言ID描述符 / LangID descriptor
@ SERIAL_NUMBER_STRING
序列号字符串索引 / Serial number string
const LanguagePack ** string_list_
多语言包指针表 / LanguagePack pointer table
Definition desc_str.hpp:166
ErrorCode GenerateString(Index index, uint16_t lang)
生成指定语言和索引的字符串描述符 Generate USB string descriptor for given language and string index
Definition desc_str.cpp:58
uint16_t * land_id_
语言ID数组 / LangID array
Definition desc_str.hpp:165
uint16_t * header_
语言ID描述符头部 / LangID descriptor header
Definition desc_str.hpp:164
ErrorCode
定义错误码枚举
@ NOT_FOUND
未找到 | Not found
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
单语言描述符包(用于注册静态多语言字符串) Single language USB string descriptor pack for registration
Definition desc_str.hpp:45
size_t string_lens[STRING_LIST_SIZE]
每个字符串的字节数 / String byte lengths
Definition desc_str.hpp:48
StringData strings[STRING_LIST_SIZE]
指向 UTF-16LE 静态数组 / UTF-16LE strings
Definition desc_str.hpp:47
size_t max_string_length
最大字符串长度 / Maximum string length
Definition desc_str.hpp:49