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 &paraTable)123 int32_t GetScanParaValues(const std::string &deviceId, ScanOptionValue &value, ScanParaTable &paraTable)
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 &paraTable)248 bool MemSetScannerOptions(Scan_ScannerOptions* scannerOptions, int32_t &optionCount, ScanParaTable &paraTable)
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 &paraTable)284 Scan_ScannerOptions* GetScanParaValue(ScanParaTable &paraTable)
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 }