1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <set>
16 #include <map>
17 #include <cstring>
18 #include <string>
19 #include <thread>
20 #include "securec.h"
21 #include "refbase.h"
22 #include "scan_callback.h"
23 #include "scan_manager_client.h"
24 #include "scan_constant.h"
25 #include "scan_log.h"
26 #include "scanner_info.h"
27 #include "scan_option_value.h"
28 #include "ohscan.h"
29
30 using namespace OHOS::Scan;
31
32 struct ValueMap {
33 uint32_t valueType;
34 int32_t optionIndex;
35 std::set<std::string> numList;
36 std::set<std::string> strList;
37 };
38
39 struct ScanParaTable {
40 std::vector<std::string> titBuff;
41 std::vector<std::string> desBuff;
42 std::vector<std::string> rangesBuff;
43 int32_t lengthBuff;
44 };
45
46 static constexpr int32_t SCAN_INT_TYPE = 1;
47 static constexpr int32_t SCAN_STRING_TYPE = 3;
48 static constexpr int32_t SCAN_NUM_LIST = 2;
49 static constexpr int32_t SCAN_STRING_LIST = 3;
50 static std::map<std::string, std::map<int, ValueMap>> g_valueMap;
51 static std::map<std::string, Scan_ScannerOptions* > g_scanParaTables;
52 static bool g_isListening = false;
53 static const char* GET_SCANNER_DEVICE_LIST = "GET_SCANNER_DEVICE_LIST";
54 static Scan_ScannerDiscoveryCallback g_discoverCallback = nullptr;
55
56
FreeDeviceListMemory(Scan_ScannerDevice** devices, int32_t deviceCount)57 static inline void FreeDeviceListMemory(Scan_ScannerDevice** devices, int32_t deviceCount)
58 {
59 for (int32_t i = 0; i < deviceCount; i++) {
60 DELETE_AND_NULLIFY(devices[i])
61 }
62 DELETE_ARRAY_AND_NULLIFY(devices)
63 }
64
65 auto callbackFunction = [](std::vector<ScanDeviceInfo> &infos) {
66 int32_t deviceCount = infos.size();
67 SCAN_HILOGI("deviceCount : [%{public}d]", deviceCount);
68 if (deviceCount == 0) {
69 SCAN_HILOGE("not found");
70 g_discoverCallback(nullptr, 0);
71 return;
72 }
73 Scan_ScannerDevice** devices = new (std::nothrow) Scan_ScannerDevice* [deviceCount];
74 if (devices == nullptr) {
75 SCAN_HILOGE("devices is a nullptr");
76 g_discoverCallback(nullptr, 0);
77 }
78 int32_t devicesMemSize = deviceCount * sizeof(Scan_ScannerDevice*);
79 if (memset_s(devices, devicesMemSize, 0, devicesMemSize) != 0) {
80 SCAN_HILOGW("memset_s fail");
81 FreeDeviceListMemory(devices, 0);
82 g_discoverCallback(nullptr, 0);
83 return;
84 }
85 for (int i = 0; i < deviceCount; i++) {
86 Scan_ScannerDevice* device = new (std::nothrow) Scan_ScannerDevice();
87 if (device == nullptr) {
88 SCAN_HILOGE("devices is a nullptr");
89 deviceCount = i;
90 break;
91 }
92 if (memset_s(device, sizeof(Scan_ScannerDevice), 0, sizeof(Scan_ScannerDevice)) != 0) {
93 SCAN_HILOGW("memset_s fail");
94 deviceCount = i;
95 break;
96 }
97 device->scannerId = infos[i].GetDeviceId().c_str();
98 device->manufacturer = infos[i].GetManufacturer().c_str();
99 device->model = infos[i].GetModel().c_str();
100 device->serialNumber = infos[i].GetSerialNumber().c_str();
101 device->discoverMode = infos[i].GetDiscoverMode().c_str();
102 devices[i] = device;
103 }
104 g_discoverCallback(devices, deviceCount);
105 FreeDeviceListMemory(devices, deviceCount);
106 };
107
108 namespace {
GetScanParaDesc(const std::string &deviceId, ScanOptionValue &value)109 int32_t GetScanParaDesc(const std::string &deviceId, ScanOptionValue &value)
110 {
111 auto client = ScanManagerClient::GetInstance();
112 ScanOptionDescriptor desc;
113 int32_t ret = client->GetScanOptionDesc(deviceId, 0, desc);
114 uint32_t optionType = desc.GetOptionType();
115 int32_t optionSize = desc.GetOptionSize();
116 value.SetScanOptionValueType(static_cast<ScanOptionValueType>(optionType));
117 value.SetValueSize(optionSize);
118 int32_t info = 0;
119 ret = client->OpScanOptionValue(deviceId, 0, SCAN_ACTION_GET_VALUE, value, info);
120 return ret;
121 }
122
GetScanParaValues(const std::string &deviceId, ScanOptionValue &value, ScanParaTable ¶Table)123 int32_t GetScanParaValues(const std::string &deviceId, ScanOptionValue &value, ScanParaTable ¶Table)
124 {
125 std::set<uint32_t> dataType = {SCAN_INT_TYPE, SCAN_STRING_TYPE};
126 int32_t lengthBuff = 0;
127 for (int i = 1 ; i < value.GetNumValue(); i++) {
128 ScanOptionDescriptor desc;
129 auto client = ScanManagerClient::GetInstance();
130 int32_t ret = client->GetScanOptionDesc(deviceId, i, desc);
131 if (ret != SCAN_ERROR_NONE) {
132 SCAN_HILOGE("Failed to get scanner parameters.");
133 return ret;
134 }
135 if (!dataType.count(desc.GetOptionType())) {
136 continue;
137 }
138 if (desc.GetOptionConstraintType() == SCAN_NUM_LIST) {
139 std::string tmp;
140 std::vector<std::int32_t> optionConstraintNumber;
141 desc.GetOptionConstraintNumber(optionConstraintNumber);
142 for (auto t : optionConstraintNumber) {
143 std::string numStr = std::to_string(t);
144 tmp.append(numStr).append(",");
145 g_valueMap[deviceId][lengthBuff].numList.insert(numStr);
146 g_valueMap[deviceId][lengthBuff].valueType = SCAN_INT_TYPE;
147 }
148 tmp.pop_back();
149 paraTable.rangesBuff.emplace_back(tmp);
150 } else if (desc.GetOptionConstraintType() == SCAN_STRING_LIST) {
151 std::string tmp;
152 std::vector<std::string> optionConstraintString;
153 desc.GetOptionConstraintString(optionConstraintString);
154 for (auto t : optionConstraintString) {
155 tmp.append(t).append(",");
156 g_valueMap[deviceId][lengthBuff].strList.insert(t);
157 g_valueMap[deviceId][lengthBuff].valueType = SCAN_STRING_TYPE;
158 }
159 tmp.pop_back();
160 paraTable.rangesBuff.emplace_back(tmp);
161 } else {
162 continue;
163 }
164 paraTable.titBuff.emplace_back(desc.GetOptionTitle());
165 paraTable.desBuff.emplace_back(desc.GetOptionDesc());
166 g_valueMap[deviceId][lengthBuff].optionIndex = i;
167 lengthBuff++;
168 }
169 paraTable.lengthBuff = lengthBuff;
170 return SCAN_ERROR_NONE;
171 }
172
FreeScannerOptionsMemory(Scan_ScannerOptions* scannerOptions)173 void FreeScannerOptionsMemory(Scan_ScannerOptions* scannerOptions)
174 {
175 if (scannerOptions == nullptr) {
176 SCAN_HILOGW("scannerOptions is a nullptr.");
177 return;
178 }
179
180 for (int i = 0; i < scannerOptions->optionCount; i++) {
181 DELETE_AND_NULLIFY(scannerOptions->titles[i])
182 }
183 DELETE_ARRAY_AND_NULLIFY(scannerOptions->titles)
184
185 for (int i = 0; i < scannerOptions->optionCount; i++) {
186 DELETE_AND_NULLIFY(scannerOptions->descriptions[i])
187 }
188 DELETE_ARRAY_AND_NULLIFY(scannerOptions->descriptions)
189
190 for (int i = 0; i < scannerOptions->optionCount; i++) {
191 DELETE_AND_NULLIFY(scannerOptions->ranges[i])
192 }
193 DELETE_ARRAY_AND_NULLIFY(scannerOptions->ranges)
194 DELETE_AND_NULLIFY(scannerOptions)
195 }
196
CreateScannerOptions(int32_t &optionCount)197 Scan_ScannerOptions* CreateScannerOptions(int32_t &optionCount)
198 {
199 Scan_ScannerOptions* scannerOptions = new (std::nothrow) Scan_ScannerOptions();
200 if (scannerOptions == nullptr) {
201 SCAN_HILOGE("scannerOptions is a nullptr");
202 return nullptr;
203 }
204 int32_t scannerOptionsMemSize = sizeof(Scan_ScannerOptions);
205 if (memset_s(scannerOptions, scannerOptionsMemSize, 0, scannerOptionsMemSize) != 0) {
206 SCAN_HILOGW("memset_s fail");
207 FreeScannerOptionsMemory(scannerOptions);
208 return nullptr;
209 }
210 scannerOptions->titles = new (std::nothrow) char* [optionCount];
211 scannerOptions->descriptions = new (std::nothrow) char* [optionCount];
212 scannerOptions->ranges = new (std::nothrow) char* [optionCount];
213 scannerOptions->optionCount = optionCount;
214 if (scannerOptions->titles == nullptr || scannerOptions->descriptions == nullptr ||
215 scannerOptions->ranges == nullptr) {
216 FreeScannerOptionsMemory(scannerOptions);
217 return nullptr;
218 }
219 int32_t stringMemSize = optionCount * sizeof(char**);
220 if (memset_s(scannerOptions->titles, stringMemSize, 0, stringMemSize) != 0 ||
221 memset_s(scannerOptions->descriptions, stringMemSize, 0, stringMemSize) != 0 ||
222 memset_s(scannerOptions->ranges, stringMemSize, 0, stringMemSize) != 0) {
223 SCAN_HILOGW("memset_s fail");
224 FreeScannerOptionsMemory(scannerOptions);
225 return nullptr;
226 }
227 return scannerOptions;
228 }
229
CopySingleBuf(char* destBuf, const char* srcBuf, size_t bufferSize)230 bool CopySingleBuf(char* destBuf, const char* srcBuf, size_t bufferSize)
231 {
232 if (destBuf == nullptr || srcBuf == nullptr) {
233 SCAN_HILOGW("CopySingleBuf new fail");
234 return false;
235 }
236 if (memset_s(destBuf, bufferSize, 0, bufferSize) != 0) {
237 SCAN_HILOGE("CopySingleBuf memset_s fail");
238 return false;
239 }
240 if (strncpy_s(destBuf, bufferSize, srcBuf, bufferSize) != 0) {
241 SCAN_HILOGE("CopySingleBuf strncpy_s fail");
242 return false;
243 }
244
245 return true;
246 }
247
MemSetScannerOptions(Scan_ScannerOptions* scannerOptions, int32_t &optionCount, ScanParaTable ¶Table)248 bool MemSetScannerOptions(Scan_ScannerOptions* scannerOptions, int32_t &optionCount, ScanParaTable ¶Table)
249 {
250 for (int i = 0; i < optionCount; i++) {
251 auto bufferSize = paraTable.titBuff[i].length() + 1;
252 char* titBuff = new(std::nothrow) char[bufferSize];
253 if (!CopySingleBuf(titBuff, paraTable.titBuff[i].c_str(), bufferSize)) {
254 if (titBuff != nullptr) {
255 delete[] titBuff;
256 }
257 return false;
258 }
259 scannerOptions->titles[i] = titBuff;
260
261 bufferSize = paraTable.desBuff[i].length() + 1;
262 char* desBuff = new (std::nothrow) char[bufferSize];
263 if (!CopySingleBuf(desBuff, paraTable.desBuff[i].c_str(), bufferSize)) {
264 if (desBuff != nullptr) {
265 delete[] desBuff;
266 }
267 return false;
268 }
269 scannerOptions->descriptions[i] = desBuff;
270
271 bufferSize = paraTable.rangesBuff[i].length() + 1;
272 char* rangesBuff = new (std::nothrow) char[bufferSize];
273 if (!CopySingleBuf(rangesBuff, paraTable.rangesBuff[i].c_str(), bufferSize)) {
274 if (rangesBuff != nullptr) {
275 delete[] rangesBuff;
276 }
277 return false;
278 }
279 scannerOptions->ranges[i] = rangesBuff;
280 }
281 return true;
282 }
283
GetScanParaValue(ScanParaTable ¶Table)284 Scan_ScannerOptions* GetScanParaValue(ScanParaTable ¶Table)
285 {
286 int32_t optionCount = paraTable.lengthBuff;
287 if (optionCount <= 0) {
288 SCAN_HILOGE("optionCount <= 0");
289 return nullptr;
290 }
291 Scan_ScannerOptions* scannerOptions = CreateScannerOptions(optionCount);
292 if (scannerOptions == nullptr) {
293 SCAN_HILOGE("scannerOptions is a nullptr");
294 return nullptr;
295 }
296 if (!MemSetScannerOptions(scannerOptions, optionCount, paraTable)) {
297 SCAN_HILOGE("MemSetScannerOptions error");
298 FreeScannerOptionsMemory(scannerOptions);
299 return nullptr;
300 }
301 return scannerOptions;
302 }
303 }
304
OH_Scan_Init()305 int32_t OH_Scan_Init()
306 {
307 SCAN_HILOGI("Enter OH_Scan_Init");
308 auto client = ScanManagerClient::GetInstance();
309 int32_t scanVersion = 0;
310 int32_t ret = client->InitScan(scanVersion);
311 if (ret != SCAN_ERROR_NONE) {
312 SCAN_HILOGE("InitScan failed, ErrorCode: [%{public}d]", ret);
313 return ret;
314 } else {
315 SCAN_HILOGI("InitScan successfully");
316 return SCAN_ERROR_NONE;
317 }
318 }
319
OH_Scan_StartScannerDiscovery(Scan_ScannerDiscoveryCallback callback)320 int32_t OH_Scan_StartScannerDiscovery(Scan_ScannerDiscoveryCallback callback)
321 {
322 g_discoverCallback = callback;
323 auto client = ScanManagerClient::GetInstance();
324 int32_t ret = SCAN_ERROR_NONE;
325 if (!g_isListening) {
326 OHOS::sptr<IScanCallback> call = new (std::nothrow) ScanCallback(callbackFunction);
327 if (call == nullptr) {
328 SCAN_HILOGE("call is null");
329 return SCAN_ERROR_GENERIC_FAILURE;
330 }
331 ret = client->On("", std::string(GET_SCANNER_DEVICE_LIST), call);
332 if (ret != SCAN_ERROR_NONE) {
333 SCAN_HILOGE("Failed to register event");
334 return ret;
335 }
336 g_isListening = true;
337 }
338 ret = client->GetScannerList();
339 if (ret != SCAN_ERROR_NONE) {
340 SCAN_HILOGE("Failed to GetScannerList");
341 return ret;
342 }
343 return SCAN_ERROR_NONE;
344 }
345
OH_Scan_OpenScanner(const char* scannerId)346 int32_t OH_Scan_OpenScanner(const char* scannerId)
347 {
348 if (scannerId == nullptr) {
349 SCAN_HILOGE("Invalid parameter.");
350 return SCAN_ERROR_INVALID_PARAMETER;
351 }
352 auto client = ScanManagerClient::GetInstance();
353 int32_t ret = client->OpenScanner(std::string(scannerId));
354 if (ret != SCAN_ERROR_NONE) {
355 SCAN_HILOGE("OpenScanner failed, ErrorCode: [%{public}d]", ret);
356 return ret;
357 } else {
358 SCAN_HILOGI("OpenScanner successfully");
359 return SCAN_ERROR_NONE;
360 }
361 }
362
OH_Scan_CloseScanner(const char* scannerId)363 int32_t OH_Scan_CloseScanner(const char* scannerId)
364 {
365 if (scannerId == nullptr) {
366 SCAN_HILOGE("Invalid parameter.");
367 return SCAN_ERROR_INVALID_PARAMETER;
368 }
369 auto client = ScanManagerClient::GetInstance();
370 int32_t ret = client->CloseScanner(std::string(scannerId));
371 if (ret != SCAN_ERROR_NONE) {
372 SCAN_HILOGE("CloseScanner failed, ErrorCode: [%{public}d]", ret);
373 return ret;
374 } else {
375 SCAN_HILOGI("CloseScanner successfully");
376 return SCAN_ERROR_NONE;
377 }
378 }
379
OH_Scan_GetScannerParameter(const char* scannerId, int32_t* errorCode)380 Scan_ScannerOptions* OH_Scan_GetScannerParameter(const char* scannerId, int32_t* errorCode)
381 {
382 if (scannerId == nullptr || errorCode == nullptr) {
383 SCAN_HILOGE("Invalid parameter.");
384 return nullptr;
385 }
386 std::string deviceId = std::string(scannerId);
387 if (g_scanParaTables.find(deviceId) != g_scanParaTables.end()) {
388 SCAN_HILOGW("Device parameters have been obtained.");
389 *errorCode = SCAN_ERROR_NONE;
390 return g_scanParaTables[deviceId];
391 }
392 int32_t status = SCAN_ERROR_NONE;
393 ScanOptionValue value;
394 status = GetScanParaDesc(deviceId, value);
395 if (status != SCAN_ERROR_NONE) {
396 SCAN_HILOGE("Failed to get scanner ScanOptionValue value.");
397 *errorCode = status;
398 return nullptr;
399 }
400 ScanParaTable paraTable;
401 status = GetScanParaValues(deviceId, value, paraTable);
402 if (status != SCAN_ERROR_NONE) {
403 SCAN_HILOGE("Failed to get scanner ScanParaTable paraTable.");
404 *errorCode = status;
405 return nullptr;
406 }
407
408 Scan_ScannerOptions* scaParaOptions = GetScanParaValue(paraTable);
409 if (scaParaOptions == nullptr) {
410 *errorCode = SCAN_ERROR_GENERIC_FAILURE;
411 return nullptr;
412 }
413 g_scanParaTables[scannerId] = scaParaOptions;
414 *errorCode = SCAN_ERROR_NONE;
415 return scaParaOptions;
416 }
417
OH_Scan_SetScannerParameter(const char* scannerId, const int32_t option, const char* value)418 int32_t OH_Scan_SetScannerParameter(const char* scannerId, const int32_t option, const char* value)
419 {
420 if (scannerId == nullptr || value == nullptr) {
421 SCAN_HILOGE("Invalid parameter.");
422 return SCAN_ERROR_INVALID_PARAMETER;
423 }
424 auto client = ScanManagerClient::GetInstance();
425 if (g_valueMap.find(scannerId) == g_valueMap.end() ||
426 g_valueMap[scannerId].find(option) == g_valueMap[scannerId].end()) {
427 SCAN_HILOGE("not exit this option: [%{public}d]", option);
428 return SCAN_ERROR_INVALID_PARAMETER;
429 }
430 auto t = g_valueMap[scannerId].find(option);
431 uint32_t valueType = g_valueMap[scannerId][option].valueType;
432 std::string strvalue = std::string(value);
433 ScanOptionValue optionValue;
434
435 if (valueType == SCAN_INT_TYPE) {
436 if (!t->second.numList.count(strvalue)) {
437 SCAN_HILOGE("not exit this value: [%{public}s]", strvalue.c_str());
438 return SCAN_ERROR_INVALID_PARAMETER;
439 }
440 optionValue.SetNumValue(std::stoi(strvalue));
441 optionValue.SetScanOptionValueType(SCAN_VALUE_NUM);
442 } else if (valueType == SCAN_STRING_TYPE) {
443 if (!t->second.strList.count(strvalue)) {
444 SCAN_HILOGE("not exit this value: [%{public}s]", strvalue.c_str());
445 return SCAN_ERROR_INVALID_PARAMETER;
446 }
447 optionValue.SetStrValue(strvalue);
448 optionValue.SetScanOptionValueType(SCAN_VALUE_STR);
449 } else {
450 SCAN_HILOGI("not exist this type ");
451 return SCAN_ERROR_GENERIC_FAILURE;
452 }
453
454 int32_t optionIndex = t->second.optionIndex;
455 int32_t info;
456 int32_t ret = client->OpScanOptionValue(std::string(scannerId),
457 optionIndex, SCAN_ACTION_SET_VALUE, optionValue, info);
458 if (ret != SCAN_ERROR_NONE) {
459 SCAN_HILOGE("SetScannerParameter failed, ErxrorCode: [%{public}d]", ret);
460 return ret;
461 } else {
462 SCAN_HILOGI("SetScannerParameter successfully");
463 return SCAN_ERROR_NONE;
464 }
465 return SCAN_ERROR_NONE;
466 }
467
OH_Scan_StartScan(const char* scannerId, bool batchMode)468 int32_t OH_Scan_StartScan(const char* scannerId, bool batchMode)
469 {
470 if (scannerId == nullptr) {
471 SCAN_HILOGE("Invalid parameter.");
472 return SCAN_ERROR_INVALID_PARAMETER;
473 }
474 auto client = ScanManagerClient::GetInstance();
475 int32_t ret = client->StartScan(std::string(scannerId), batchMode);
476 if (ret != SCAN_ERROR_NONE) {
477 SCAN_HILOGE("StartScan failed, ErxrorCode: [%{public}d]", ret);
478 return ret;
479 } else {
480 SCAN_HILOGI("StartScan successfully");
481 return SCAN_ERROR_NONE;
482 }
483 }
484
OH_Scan_CancelScan(const char* scannerId)485 int32_t OH_Scan_CancelScan(const char* scannerId)
486 {
487 if (scannerId == nullptr) {
488 SCAN_HILOGE("Invalid parameter.");
489 return SCAN_ERROR_INVALID_PARAMETER;
490 }
491 auto client = ScanManagerClient::GetInstance();
492 int32_t ret = client->CancelScan(std::string(scannerId));
493 if (ret != SCAN_ERROR_NONE) {
494 SCAN_HILOGE("CancelScan failed, ErxrorCode: [%{public}d]", ret);
495 return ret;
496 } else {
497 SCAN_HILOGI("CancelScan successfully");
498 return SCAN_ERROR_NONE;
499 }
500 }
501
OH_Scan_GetPictureScanProgress(const char* scannerId, Scan_PictureScanProgress* prog)502 int32_t OH_Scan_GetPictureScanProgress(const char* scannerId, Scan_PictureScanProgress* prog)
503 {
504 if (prog == nullptr) {
505 SCAN_HILOGE("Invalid parameter.");
506 return SCAN_ERROR_INVALID_PARAMETER;
507 }
508 ScanProgress scanProg;
509 auto client = ScanManagerClient::GetInstance();
510 int32_t ret = client->GetScanProgress(std::string(scannerId), scanProg);
511 if (ret != SCAN_ERROR_NONE) {
512 SCAN_HILOGE("GetScanProgress failed, ErrorCode: [%{public}d]", ret);
513 return ret;
514 } else {
515 prog->progress = scanProg.GetScanProgress();
516 prog->fd = scanProg.GetScanPictureFd();
517 prog->isFinal = scanProg.GetIsFinal();
518 SCAN_HILOGI("GetScanProgress successfully");
519 return SCAN_ERROR_NONE;
520 }
521 }
522
OH_Scan_Exit()523 int32_t OH_Scan_Exit()
524 {
525 auto client = ScanManagerClient::GetInstance();
526 int32_t ret = client->ExitScan();
527 if (ret != SCAN_ERROR_NONE) {
528 SCAN_HILOGE("ExitScan failed, ErrorCode: [%{public}d]", ret);
529 return ret;
530 }
531 for (auto table : g_scanParaTables) {
532 FreeScannerOptionsMemory(table.second);
533 }
534 g_scanParaTables.clear();
535 if (g_isListening) {
536 client->Off("", std::string(GET_SCANNER_DEVICE_LIST));
537 }
538 SCAN_HILOGI("ExitScan successfully");
539 return SCAN_ERROR_NONE;
540 }