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
16 #include <fcntl.h>
17 #include <unistd.h>
18 #include <iostream>
19 #include <fstream>
20 #include <streambuf>
21 #include "scan_log.h"
22 #include "scan_usb_manager.h"
23 #include "scan_util.h"
24 #include "scan_system_data.h"
25 #include "scan_service_ability.h"
26
27 namespace {
28 const std::string SCANNER_LIST_FILE = "/data/service/el2/public/print_service/sane/tmp/scanner_list.json";
29 const std::string SCANNER_LIST_VERSION = "v1";
30 } // namespace
31
32 namespace OHOS {
33 namespace Scan {
34 std::map<std::string, std::string> ScanSystemData::usbSnToPortMap_;
CheckJsonObjectValue(const nlohmann::json & object)35 bool ScanSystemData::CheckJsonObjectValue(const nlohmann::json& object)
36 {
37 const std::vector<std::string> keyList = {"deviceId", "manufacturer", "model", "deviceType",
38 "discoverMode", "serialNumber", "deviceName", "uniqueId"};
39 for (auto key : keyList) {
40 if (!object.contains(key) || !object[key].is_string()) {
41 SCAN_HILOGW("can not find %{public}s", key.c_str());
42 return false;
43 }
44 }
45 return true;
46 }
47
ParseScannerListJsonV1(nlohmann::json & jsonObject)48 bool ScanSystemData::ParseScannerListJsonV1(nlohmann::json& jsonObject)
49 {
50 if (!jsonObject.contains("scaner_list") || !jsonObject["scaner_list"].is_array()) {
51 SCAN_HILOGW("can not find scaner_list");
52 return false;
53 }
54 for (auto &element : jsonObject["scaner_list"].items()) {
55 nlohmann::json object = element.value();
56 if (!CheckJsonObjectValue(object)) {
57 continue;
58 }
59 ScanDeviceInfo scanDeviceInfo;
60 scanDeviceInfo.deviceId = object["deviceId"];
61 scanDeviceInfo.manufacturer = object["manufacturer"];
62 scanDeviceInfo.model = object["model"];
63 scanDeviceInfo.deviceType = object["deviceType"];
64 scanDeviceInfo.discoverMode = object["discoverMode"];
65 scanDeviceInfo.serialNumber = object["serialNumber"];
66 scanDeviceInfo.deviceName = object["deviceName"];
67 scanDeviceInfo.uniqueId = object["uniqueId"];
68 scanDeviceInfo.uuid = object["uuid"];
69 std::string uniqueId = scanDeviceInfo.discoverMode + scanDeviceInfo.uniqueId;
70 InsertScannerInfo(uniqueId, scanDeviceInfo);
71 }
72 RefreshUsbDeviceId();
73 return true;
74 }
75
Init()76 bool ScanSystemData::Init()
77 {
78 addedScannerMap_.clear();
79 std::ifstream ifs(SCANNER_LIST_FILE.c_str(), std::ios::in | std::ios::binary);
80 if (!ifs.is_open()) {
81 SCAN_HILOGW("open scanner list file fail");
82 return false;
83 }
84 std::string fileData((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
85 ifs.close();
86 if (!nlohmann::json::accept(fileData)) {
87 SCAN_HILOGW("json accept fail");
88 return false;
89 }
90 nlohmann::json jsonObject = nlohmann::json::parse(fileData);
91 if (!jsonObject.contains("version") || !jsonObject["version"].is_string()) {
92 SCAN_HILOGW("can not find version");
93 return false;
94 }
95 std::string version = jsonObject["version"].get<std::string>();
96 SCAN_HILOGI("json version: %{public}s", version.c_str());
97 if (version == SCANNER_LIST_VERSION) {
98 return ParseScannerListJsonV1(jsonObject);
99 }
100 return false;
101 }
102
RefreshUsbDeviceId()103 void ScanSystemData::RefreshUsbDeviceId()
104 {
105 ScanUsbManager::GetInstance()->RefreshUsbDevicePort();
106 if (usbSnToPortMap_.empty()) {
107 SCAN_HILOGW("Failed to refresh the USB device.");
108 return;
109 }
110 for (auto &scanDevIt : addedScannerMap_) {
111 std::string discoverMode = scanDevIt.second->discoverMode;
112 if (discoverMode == "TCP") {
113 continue;
114 }
115 std::string serialNumber = scanDevIt.second->serialNumber;
116 auto it = usbSnToPortMap_.find(serialNumber);
117 if (it == usbSnToPortMap_.end()) {
118 continue;
119 }
120 std::string oldDeviceId = scanDevIt.second->deviceId;
121 std::string usbPort = it->second;
122 std::string newDeviceId = ReplaceDeviceIdUsbPort(oldDeviceId, usbPort);
123 if (newDeviceId == "" || newDeviceId == oldDeviceId) {
124 SCAN_HILOGD("cannot update usb deviceId.");
125 continue;
126 }
127 scanDevIt.second->deviceId = newDeviceId;
128 ScanDeviceInfoSync syncInfo;
129 syncInfo.deviceId = newDeviceId;
130 syncInfo.serialNumber = serialNumber;
131 syncInfo.oldDeviceId = oldDeviceId;
132 syncInfo.discoverMode = "USB";
133 auto saPtr = ScanServiceAbility::GetInstance();
134 if (saPtr == nullptr) {
135 SCAN_HILOGE("saPtr is a nullptr");
136 return;
137 }
138 saPtr->UpdateScannerId(syncInfo);
139 }
140 if (!SaveScannerMap()) {
141 SCAN_HILOGW("Failed to save the JSON file.");
142 }
143 }
144
ReplaceDeviceIdUsbPort(const std::string & deviceId,const std::string & usbPort)145 std::string ScanSystemData::ReplaceDeviceIdUsbPort(const std::string& deviceId, const std::string& usbPort)
146 {
147 constexpr int32_t invalidPort = -1;
148 int32_t start = invalidPort;
149 int32_t end = invalidPort;
150 char dash;
151 std::istringstream(usbPort) >> start >> dash >> end;
152 if (start < 0 || end < 0 || dash != '-') {
153 SCAN_HILOGE("usbPort format is error");
154 return "";
155 }
156 std::ostringstream oss;
157 char zero = '0';
158 constexpr int32_t portWidth = 3;
159 oss << std::setw(portWidth) << std::setfill(zero) << start;
160 std::string formattedStart = oss.str();
161 oss.str("");
162 oss << std::setw(portWidth) << std::setfill(zero) << end;
163 std::string formattedEnd = oss.str();
164 size_t pos1 = deviceId.rfind(':');
165 if (pos1 == std::string::npos) {
166 SCAN_HILOGE("deviceId format is error");
167 return "";
168 }
169 size_t pos2 = deviceId.rfind(':', pos1 - 1);
170 if (pos2 == std::string::npos) {
171 SCAN_HILOGE("deviceId format is error");
172 return "";
173 }
174 std::string newDeviceId = deviceId.substr(0, pos2 + 1).append(formattedStart).append(":").append(formattedEnd);
175 SCAN_HILOGD("new deviceId = %{private}s", newDeviceId.c_str());
176 return newDeviceId;
177 }
178
GetNewDeviceId(std::string oldDeviceId,std::string usbDevicePort)179 std::string ScanSystemData::GetNewDeviceId(std::string oldDeviceId, std::string usbDevicePort)
180 {
181 if (oldDeviceId.find_last_of(":") == std::string::npos ||
182 oldDeviceId.find_last_of(":") < USB_DEVICEID_FIRSTID_LEN_3 ||
183 oldDeviceId.find_last_of("-") == std::string::npos ||
184 oldDeviceId.find_last_of("-") < 1) {
185 return nullptr;
186 }
187 std::string deviceIdHead = oldDeviceId.substr(0, oldDeviceId.find_last_of(":") - USB_DEVICEID_FIRSTID_LEN_3);
188 std::string firstPort = usbDevicePort.substr(0, usbDevicePort.find("-"));
189 std::string secondPort = usbDevicePort.substr(usbDevicePort.find("-") + 1, usbDevicePort.size() - 1);
190 SCAN_HILOGI("firstPort = %{public}s, secondPort = %{public}s.",
191 firstPort.c_str(), secondPort.c_str());
192 FormatUsbPort(firstPort);
193 FormatUsbPort(secondPort);
194 return deviceIdHead + firstPort + ":" + secondPort;
195 }
196
FormatUsbPort(std::string & port)197 void ScanSystemData::FormatUsbPort(std::string &port)
198 {
199 port.insert(0, USB_DEVICEID_FIRSTID_LEN_3 - port.size(), '0');
200 }
201
UpdateScannerIdByUsbDevicePort(const std::string & uniqueId,const std::string & usbDevicePort)202 bool ScanSystemData::UpdateScannerIdByUsbDevicePort(const std::string &uniqueId, const std::string &usbDevicePort)
203 {
204 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
205 auto iter = addedScannerMap_.find(uniqueId);
206 if (iter != addedScannerMap_.end() && iter->second != nullptr) {
207 std::string oldDeviceId = iter->second->deviceId;
208 std::string newDeviceId = ReplaceDeviceIdUsbPort(oldDeviceId, usbDevicePort);
209 SCAN_HILOGD("newDeviceId : %{private}s", newDeviceId.c_str());
210 if (newDeviceId == "" || newDeviceId == oldDeviceId) {
211 SCAN_HILOGD("cannot update usb deviceId.");
212 return false;
213 }
214 iter->second->deviceId = newDeviceId;
215 } else {
216 SCAN_HILOGE("ScanSystemData UpdateScannerIdByUsbDevicePort fail");
217 return false;
218 }
219 return true;
220 }
221
InsertScannerInfo(const std::string & uniqueId,const ScanDeviceInfo & scannerInfo)222 void ScanSystemData::InsertScannerInfo(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)
223 {
224 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
225 auto iter = addedScannerMap_.find(uniqueId);
226 if (iter == addedScannerMap_.end() || iter->second == nullptr) {
227 SCAN_HILOGI("insert new scanner");
228 addedScannerMap_[uniqueId] = std::make_shared<ScanDeviceInfo>(scannerInfo);
229 } else {
230 SCAN_HILOGI("update exist scanner");
231 iter->second->deviceId = scannerInfo.deviceId;
232 iter->second->manufacturer = scannerInfo.manufacturer;
233 iter->second->model = scannerInfo.model;
234 iter->second->deviceType = scannerInfo.deviceType;
235 iter->second->serialNumber = scannerInfo.serialNumber;
236 iter->second->deviceName = scannerInfo.deviceName;
237 iter->second->uniqueId = scannerInfo.uniqueId;
238 iter->second->uuid = scannerInfo.uuid;
239 }
240 }
241
DeleteScannerInfo(const std::string & uniqueId)242 bool ScanSystemData::DeleteScannerInfo(const std::string &uniqueId)
243 {
244 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
245 auto iter = addedScannerMap_.find(uniqueId);
246 if (iter != addedScannerMap_.end()) {
247 addedScannerMap_.erase(uniqueId);
248 } else {
249 SCAN_HILOGE("ScanSystemData delete connected scanner fail");
250 return false;
251 }
252 return true;
253 }
254
UpdateScannerNameByUniqueId(const std::string & uniqueId,const std::string & deviceName)255 bool ScanSystemData::UpdateScannerNameByUniqueId(const std::string &uniqueId, const std::string &deviceName)
256 {
257 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
258 auto iter = addedScannerMap_.find(uniqueId);
259 if (iter != addedScannerMap_.end() && iter->second != nullptr) {
260 iter->second->deviceName = deviceName;
261 } else {
262 SCAN_HILOGE("ScanSystemData UpdateScannerNameByUniqueId fail");
263 return false;
264 }
265 return true;
266 }
267
UpdateScannerInfoByUniqueId(const std::string & uniqueId,const ScanDeviceInfo & scannerInfo)268 bool ScanSystemData::UpdateScannerInfoByUniqueId(const std::string &uniqueId, const ScanDeviceInfo &scannerInfo)
269 {
270 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
271 auto iter = addedScannerMap_.find(uniqueId);
272 if (iter != addedScannerMap_.end()) {
273 iter->second->deviceId = scannerInfo.deviceId;
274 iter->second->model = scannerInfo.model;
275 iter->second->deviceType = scannerInfo.deviceType;
276 iter->second->serialNumber = scannerInfo.serialNumber;
277 iter->second->deviceName = scannerInfo.deviceName;
278 iter->second->uniqueId = scannerInfo.uniqueId;
279 return true;
280 }
281 SCAN_HILOGE("ScanSystemData UpdateScannerInfoByUniqueId not found scannerInfo");
282 return false;
283 }
284
QueryScannerNameByUniqueId(const std::string & uniqueId,std::string & deviceName)285 bool ScanSystemData::QueryScannerNameByUniqueId(const std::string &uniqueId, std::string &deviceName)
286 {
287 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
288 auto iter = addedScannerMap_.find(uniqueId);
289 if (iter != addedScannerMap_.end()) {
290 deviceName = iter->second->deviceName;
291 return true;
292 }
293 SCAN_HILOGW("QueryScannerNameByUniqueId fail");
294 return false;
295 }
296
QueryScannerInfoByUniqueId(const std::string & uniqueId,ScanDeviceInfo & scannerInfo)297 bool ScanSystemData::QueryScannerInfoByUniqueId(const std::string &uniqueId, ScanDeviceInfo &scannerInfo)
298 {
299 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
300 for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
301 auto info = iter->second;
302 if (info == nullptr) {
303 continue;
304 }
305 std::string iterSn = info->discoverMode + info->serialNumber;
306 std::string iterUniqueId = info->discoverMode + info->uniqueId;
307 if (uniqueId == iterSn || uniqueId == iterUniqueId) {
308 scannerInfo.deviceId = info->deviceId;
309 scannerInfo.manufacturer = info->manufacturer;
310 scannerInfo.model = info->model;
311 scannerInfo.deviceType = info->deviceType;
312 scannerInfo.discoverMode = info->discoverMode;
313 scannerInfo.serialNumber = info->serialNumber;
314 scannerInfo.deviceName = info->deviceName;
315 scannerInfo.uniqueId = info->uniqueId;
316 return true;
317 }
318 }
319 return false;
320 }
321
GetAddedScannerInfoList(std::vector<ScanDeviceInfo> & infoList)322 void ScanSystemData::GetAddedScannerInfoList(std::vector<ScanDeviceInfo> &infoList)
323 {
324 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
325 for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
326 if (iter->second != nullptr) {
327 infoList.push_back(*(iter->second));
328 }
329 }
330 }
331
SaveScannerMap()332 bool ScanSystemData::SaveScannerMap()
333 {
334 int32_t fd = open(SCANNER_LIST_FILE.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0640);
335 SCAN_HILOGD("SaveScannerMap fd: %{public}d", fd);
336 if (fd < 0) {
337 SCAN_HILOGW("Failed to open file errno: %{public}s", std::to_string(errno).c_str());
338 return false;
339 }
340 nlohmann::json scannerMapJson = nlohmann::json::array();
341 {
342 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
343 for (auto iter = addedScannerMap_.begin(); iter != addedScannerMap_.end(); ++iter) {
344 auto info = iter->second;
345 if (info == nullptr) {
346 continue;
347 }
348 nlohmann::json scannerJson = nlohmann::json::object();
349 scannerJson["deviceId"] = info->deviceId;
350 scannerJson["manufacturer"] = info->manufacturer;
351 scannerJson["model"] = info->model;
352 scannerJson["deviceType"] = info->deviceType;
353 scannerJson["discoverMode"] = info->discoverMode;
354 scannerJson["serialNumber"] = info->serialNumber;
355 scannerJson["deviceName"] = info->deviceName;
356 scannerJson["uniqueId"] = info->uniqueId;
357 scannerJson["uuid"] = info->uuid;
358 scannerMapJson.push_back(scannerJson);
359 }
360 }
361 nlohmann::json jsonObject;
362 jsonObject["version"] = SCANNER_LIST_VERSION;
363 jsonObject["scaner_list"] = scannerMapJson;
364 std::string jsonString = jsonObject.dump();
365 size_t jsonLength = jsonString.length();
366 auto writeLength = write(fd, jsonString.c_str(), jsonLength);
367 close(fd);
368 fd = -1;
369 SCAN_HILOGI("SaveScannerMap finished");
370 if (writeLength < 0) {
371 return false;
372 }
373 return (size_t)writeLength == jsonLength;
374 }
375
IsContainScanner(const std::string & uniqueId)376 bool ScanSystemData::IsContainScanner(const std::string &uniqueId)
377 {
378 if (addedScannerMap_.find(uniqueId) != addedScannerMap_.end()) {
379 SCAN_HILOGI("The map contains the scanner.");
380 return true;
381 } else {
382 SCAN_HILOGW("The scanner is not included in the map.");
383 return false;
384 }
385 }
386
UpdateNetScannerByUuid(const std::string & uuid,const std::string & ip)387 std::pair<std::string, std::string> ScanSystemData::UpdateNetScannerByUuid(const std::string &uuid,
388 const std::string& ip)
389 {
390 std::string oldKey;
391 std::shared_ptr<ScanDeviceInfo> scannerInfo;
392 std::lock_guard<std::mutex> autoLock(addedScannerMapLock_);
393 for (const auto& [key, info] : addedScannerMap_) {
394 if (info != nullptr && info->uuid == uuid) {
395 oldKey = key;
396 scannerInfo = info;
397 break;
398 }
399 }
400 if (oldKey == "" || scannerInfo == nullptr) {
401 SCAN_HILOGE("Cannot find scanner by uuid");
402 return std::make_pair("", "");
403 }
404 std::string oldDeviceId = scannerInfo->deviceId;
405 std::string newDeviceId = ScanUtil::ReplaceIpAddress(oldDeviceId, ip);
406 if (newDeviceId == scannerInfo->deviceId) {
407 SCAN_HILOGE("Get new device Id fail.");
408 return std::make_pair("", "");
409 }
410 SCAN_HILOGD("newdeviceId = %{private}s", newDeviceId.c_str());
411 addedScannerMap_.erase(oldKey);
412 std::string newKey = "TCP" + ip;
413 scannerInfo->deviceId = newDeviceId;
414 scannerInfo->uniqueId = ip;
415 auto it = addedScannerMap_.find(newKey);
416 if (it == addedScannerMap_.end()) {
417 addedScannerMap_.insert(std::make_pair(newKey, scannerInfo));
418 } else {
419 it->second = scannerInfo;
420 }
421 return std::make_pair(oldDeviceId, newDeviceId);
422 }
423
424 } // namespace Scan
425 } // namespace OHOS