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 30using namespace OHOS::Scan; 31 32struct ValueMap { 33 uint32_t valueType; 34 int32_t optionIndex; 35 std::set<std::string> numList; 36 std::set<std::string> strList; 37}; 38 39struct 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 46static constexpr int32_t SCAN_INT_TYPE = 1; 47static constexpr int32_t SCAN_STRING_TYPE = 3; 48static constexpr int32_t SCAN_NUM_LIST = 2; 49static constexpr int32_t SCAN_STRING_LIST = 3; 50static std::map<std::string, std::map<int, ValueMap>> g_valueMap; 51static std::map<std::string, Scan_ScannerOptions* > g_scanParaTables; 52static bool g_isListening = false; 53static const char* GET_SCANNER_DEVICE_LIST = "GET_SCANNER_DEVICE_LIST"; 54static Scan_ScannerDiscoveryCallback g_discoverCallback = nullptr; 55 56 57static 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 65auto 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 108namespace { 109int32_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 123int32_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 173void 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 197Scan_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 230bool 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 248bool 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 284Scan_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 305int32_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 320int32_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 346int32_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 363int32_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 380Scan_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 418int32_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 468int32_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 485int32_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 502int32_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 523int32_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}