1 /*
2 * Copyright (c) 2025 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 <thread>
17 #include <cups/ipp.h>
18 #include <cups/cups-private.h>
19 #include <securec.h>
20 #include <fstream>
21 #include <algorithm>
22 #include <sstream>
23 #include "usb_manager.h"
24 #include "usb_errors.h"
25 #include "usb_ipp_manager.h"
26
27 namespace OHOS::CUPS {
28 constexpr int32_t errorReasonCount = 19;
29 static constexpr std::array<const char*, errorReasonCount> ippPrinterErrorReason = {
30 "other",
31 "cover-open",
32 "input-tray-missing",
33 "marker-supply-empty",
34 "marker-supply-low",
35 "marker-waste-almost-full",
36 "marker-waste-full",
37 "media-empty",
38 "media-jam",
39 "media-low",
40 "media-needed",
41 "moving-to-paused",
42 "paused",
43 "spool-area-full",
44 "toner-empty",
45 "toner-low",
46 "offline",
47 "marker-ink-almost-empty",
48 "door-open"
49 };
50 static auto &usbSrvClient = UsbSrvClient::GetInstance();
IppUsbManager()51 IppUsbManager::IppUsbManager()
52 {
53 isTerminated_.store(false);
54 }
55
~IppUsbManager()56 IppUsbManager::~IppUsbManager()
57 {
58 std::lock_guard<std::mutex> autoLock(lock_);
59 for (auto [uri, ippPrinter] : ippPrinterMap_) {
60 if (ippPrinter.isOpened) {
61 usbSrvClient.Close(ippPrinter.ippPipe);
62 }
63 }
64 ippPrinterMap_.clear();
65 }
66
GetInstance()67 IppUsbManager& IppUsbManager::GetInstance()
68 {
69 static IppUsbManager instance;
70 return instance;
71 }
72
FindUsbPrinter(UsbDevice & device,const std::string & uri)73 bool IppUsbManager::FindUsbPrinter(UsbDevice& device, const std::string& uri)
74 {
75 std::vector<UsbDevice> devlist;
76 auto getDevRet = usbSrvClient.GetDevices(devlist);
77 if (getDevRet != OHOS::ERR_OK) {
78 fprintf(stderr, "DEBUG: USB_MONITOR GetDevices fail, ret = %d\n", getDevRet);
79 return false;
80 }
81 if (devlist.empty()) {
82 fprintf(stderr, "DEBUG: USB_MONITOR No usb devices\n");
83 return false;
84 }
85 for (size_t i = 0; i < devlist.size(); i++) {
86 ohusb_pipe pipe;
87 pipe.busNum = devlist[i].GetBusNum();
88 pipe.devAddr = devlist[i].GetDevAddr();
89 constexpr int32_t MAX_SN_LENGTH = 256;
90 char tempsern[MAX_SN_LENGTH] = {};
91 int32_t length = OH_GetStringDescriptor(&pipe, devlist[i].GetiSerialNumber(),
92 reinterpret_cast<unsigned char *>(tempsern), sizeof(tempsern) - 1);
93 std::string sn;
94 if (length <= 0) {
95 fprintf(stderr, "DEBUG: USB_MONITOR Not find sn\n");
96 continue;
97 }
98 sn = std::string(tempsern);
99 if (uri.find(sn) == std::string::npos) {
100 continue;
101 }
102 device = devlist[i];
103 fprintf(stderr, "DEBUG: USB_MONITOR find printer\n");
104 return true;
105 }
106 fprintf(stderr, "DEBUG: USB_MONITOR not find sn\n");
107 return false;
108 }
109
IsSupportIppOverUsb(const std::string & uri)110 bool IppUsbManager::IsSupportIppOverUsb(const std::string& uri)
111 {
112 {
113 std::lock_guard<std::mutex> autoLock(lock_);
114 auto it = ippPrinterMap_.find(uri);
115 if (it != ippPrinterMap_.end() && it->second.isSupportIpp) {
116 fprintf(stderr, "DEBUG: USB_MONITOR Support has been checked\n");
117 return true;
118 }
119 }
120 UsbDevice usbDevice;
121 if (!FindUsbPrinter(usbDevice, uri)) {
122 fprintf(stderr, "DEBUG: USB_MONITOR FindUsbPrinter fail\n");
123 return false;
124 }
125 int32_t configCount = usbDevice.GetConfigCount();
126 std::vector<PrinterTranIndex> indexVec;
127 for (int32_t configIndex = 0; configIndex < configCount; configIndex++) {
128 int32_t interfaceCount = static_cast<int32_t>(usbDevice.GetConfigs()[configIndex].GetInterfaceCount());
129 for (int32_t interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) {
130 UsbInterface usbInterface = usbDevice.GetConfigs()[configIndex].GetInterfaces()[interfaceIndex];
131 bool isSupportIpp = (usbInterface.GetClass() == USB_DEVICE_CLASS_PRINT &&
132 usbInterface.GetSubClass() == USB_DEVICE_SUBCLASS_PRINT &&
133 usbInterface.GetProtocol() == USB_DEVICE_PROTOCOL_PRINT);
134 if (isSupportIpp) {
135 PrinterTranIndex indexPair;
136 indexPair.configIndex = configIndex;
137 indexPair.interfaceIndex = interfaceIndex;
138 indexVec.push_back(indexPair);
139 }
140 }
141 }
142 constexpr int32_t USB_INTERFACE_MIN_COUNT = 1;
143 if (indexVec.size() >= USB_INTERFACE_MIN_COUNT) {
144 std::lock_guard<std::mutex> autoLock(lock_);
145 auto& printer = ippPrinterMap_[uri];
146 printer.device = usbDevice;
147 printer.isSupportIpp = true;
148 printer.indexVec = std::move(indexVec);
149 fprintf(stderr, "DEBUG: USB_MONITOR printer support ipp-over-usb\n");
150 return true;
151 }
152 fprintf(stderr, "DEBUG: USB_MONITOR printer is not support ipp-over-usb\n");
153 return false;
154 }
155
ConnectUsbPinter(const std::string & uri)156 bool IppUsbManager::ConnectUsbPinter(const std::string &uri)
157 {
158 if (uri.empty()) {
159 fprintf(stderr, "DEBUG: USB_MONITOR uri is empty\n");
160 return false;
161 }
162 UsbDevice usbdevice;
163 {
164 std::lock_guard<std::mutex> autoLock(lock_);
165 auto it = ippPrinterMap_.find(uri);
166 if (it == ippPrinterMap_.end()) {
167 fprintf(stderr, "DEBUG: USB_MONITOR not find uri in ippPrinterMap_\n");
168 return false;
169 }
170 if (it->second.isOpened) {
171 fprintf(stderr, "DEBUG: USB_MONITOR printer is opened\n");
172 return true;
173 } else {
174 usbdevice = it->second.device;
175 }
176 }
177 USBDevicePipe usbDevicePipe;
178 int32_t openDeviceRet = usbSrvClient.OpenDevice(usbdevice, usbDevicePipe);
179 if (openDeviceRet == UEC_OK) {
180 return AllocateInterface(uri, usbdevice, usbDevicePipe);
181 }
182 fprintf(stderr, "DEBUG: USB_MONITOR OpenDevice fail, ret = %d\n", openDeviceRet);
183 return false;
184 }
185
DisConnectUsbPinter(const std::string & uri)186 bool IppUsbManager::DisConnectUsbPinter(const std::string& uri)
187 {
188 if (uri.empty()) {
189 fprintf(stderr, "DEBUG: USB_MONITOR uri is empty\n");
190 return false;
191 }
192 std::lock_guard<std::mutex> autoLock(lock_);
193 auto it = ippPrinterMap_.find(uri);
194 if (it == ippPrinterMap_.end()) {
195 fprintf(stderr, "DEBUG: USB_MONITOR uri is not in ippPrinterMap_\n");
196 return false;
197 }
198 usbSrvClient.Close(it->second.ippPipe);
199 ippPrinterMap_.erase(uri);
200 return true;
201 }
202
SetPrinterStateReasons(PrinterStatus & printerStatus)203 void IppUsbManager::SetPrinterStateReasons(PrinterStatus& printerStatus)
204 {
205 std::vector<int> errorReasonIndex;
206 for (size_t i = 0; i < ippPrinterErrorReason.size(); i++) {
207 if (strstr(printerStatus.printerStateReasons, ippPrinterErrorReason[i]) != nullptr) {
208 errorReasonIndex.push_back(i);
209 }
210 }
211
212 std::ostringstream errorReasonStream;
213 bool first = true;
214 for (const auto index : errorReasonIndex) {
215 if (!first) {
216 errorReasonStream << ",";
217 }
218 errorReasonStream << ippPrinterErrorReason[index] << "-error";
219 first = false;
220 }
221
222 const std::string errorReason = errorReasonStream.str();
223 if (!errorReason.empty()) {
224 int ret = snprintf_s(
225 printerStatus.printerStateReasons,
226 sizeof(printerStatus.printerStateReasons),
227 sizeof(printerStatus.printerStateReasons) - 1,
228 "%s",
229 errorReason.c_str());
230 if (ret < 0) {
231 fprintf(stderr, "DEBUG: USB_MONITOR snprintf_s printerStateReasons error\n");
232 }
233 }
234 }
235
ReportPrinterState(bool & isPrinterStarted,PrinterStatus & printerStatus,MonitorPrinterCallback callback)236 void IppUsbManager::ReportPrinterState(bool& isPrinterStarted, PrinterStatus& printerStatus,
237 MonitorPrinterCallback callback)
238 {
239 if (callback == nullptr) {
240 fprintf(stderr, "DEBUG: USB_MONITOR callback is nullptr\n");
241 return;
242 }
243 SetPrinterStateReasons(printerStatus);
244 ipp_pstate_t printerState = printerStatus.printerState;
245 if (!isPrinterStarted && printerState == IPP_PSTATE_IDLE &&
246 strcmp(printerStatus.printerStateReasons, "none") != 0) {
247 callback(&printerStatus); // report faults before the printer is started
248 return;
249 }
250 if (!isPrinterStarted && printerState != IPP_PSTATE_IDLE) {
251 isPrinterStarted = true;
252 }
253 constexpr int32_t bufferSize = PRINTER_STATE_REASONS_SIZE;
254 if (isPrinterStarted && printerState == IPP_PSTATE_IDLE &&
255 strcmp(printerStatus.printerStateReasons, "none") != 0 &&
256 memset_s(printerStatus.printerStateReasons, bufferSize, 0, bufferSize) == 0 &&
257 sprintf_s(printerStatus.printerStateReasons, bufferSize, "none") < 0) {
258 fprintf(stderr, "DEBUG: USB_MONITOR memset_s printerStateReasons fail\n");
259 }
260 if (isPrinterStarted) {
261 callback(&printerStatus); // report processing or stopped state
262 }
263 }
264
ProcessMonitorPrinter(const std::string & uri,MonitorPrinterCallback callback)265 bool IppUsbManager::ProcessMonitorPrinter(const std::string& uri, MonitorPrinterCallback callback)
266 {
267 int32_t ret = 0;
268 constexpr uint32_t MAX_LOOP_TIME = 60 * 60 * 24 * 30; // 30 days
269 bool isPrinterStarted = false;
270 for (uint32_t loopCount = 0; loopCount < MAX_LOOP_TIME && !isTerminated_.load(); loopCount++) {
271 std::this_thread::sleep_for(std::chrono::seconds(INDEX_1));
272 int32_t writeDataRetryCount = 0;
273 do {
274 auto ippdata = BuildIppRequest();
275 ret = BulkTransferWrite(uri, ippdata);
276 if (ret == EORROR_HDF_DEV_ERR_TIME_OUT) {
277 std::this_thread::sleep_for(std::chrono::milliseconds(USB_WRITE_INTERVAL));
278 writeDataRetryCount++;
279 fprintf(stderr, "DEBUG: USB_MONITOR retrwriteDataRetryCounty = %d fail\n", writeDataRetryCount);
280 }
281 } while (ret == EORROR_HDF_DEV_ERR_TIME_OUT && writeDataRetryCount < WRITE_RETRY_MAX_TIMES);
282 if (ret != UEC_OK) {
283 fprintf(stderr, "DEBUG: USB_MONITOR BulkTransferWrite fail, ret = %d\n", ret);
284 break;
285 }
286 PrinterStatus printerStatus;
287 if (!ProcessDataFromDevice(uri, printerStatus)) {
288 fprintf(stderr, "DEBUG: USB_MONITOR ProcessDataFromDevice false\n");
289 break;
290 }
291 ReportPrinterState(isPrinterStarted, printerStatus, callback);
292 if (isPrinterStarted && printerStatus.printerState == IPP_PSTATE_IDLE) {
293 fprintf(stderr, "DEBUG: USB_MONITOR ProcessMonitorPrinter job is completed\n");
294 return true;
295 }
296 }
297 fprintf(stderr, "DEBUG: USB_MONITOR endtWriteDataToPrinterLooper\n");
298 return false;
299 }
300
SetTerminalSingal()301 void IppUsbManager::SetTerminalSingal()
302 {
303 isTerminated_.store(true);
304 }
305
RemoveHttpHeader(std::vector<uint8_t> & readTempBuffer)306 void IppUsbManager::RemoveHttpHeader(std::vector<uint8_t>& readTempBuffer)
307 {
308 auto it = std::search(
309 readTempBuffer.begin(), readTempBuffer.end(),
310 reinterpret_cast<const uint8_t*>("\r\n\r\n"),
311 reinterpret_cast<const uint8_t*>("\r\n\r\n") + 4
312 );
313 if (it != readTempBuffer.end()) {
314 readTempBuffer.erase(readTempBuffer.begin(), it + INDEX_4);
315 }
316 }
317
ProcessDataFromDevice(const std::string & uri,PrinterStatus & printerStatus)318 bool IppUsbManager::ProcessDataFromDevice(const std::string& uri, PrinterStatus& printerStatus)
319 {
320 constexpr int32_t MAX_TIME = 50;
321 for (int32_t readCount = 0; readCount < MAX_TIME; readCount++) {
322 std::this_thread::sleep_for(std::chrono::milliseconds(USB_WRITE_INTERVAL));
323 std::vector<uint8_t> readTempBuffer;
324 int32_t readFromUsbRes = BulkTransferRead(uri, readTempBuffer);
325 if (readFromUsbRes != UEC_OK && readFromUsbRes != EORROR_HDF_DEV_ERR_TIME_OUT) {
326 fprintf(stderr, "DEBUG: USB_MONITOR BulkTransferRead fail, ret = %d\n", readFromUsbRes);
327 break;
328 }
329 RemoveHttpHeader(readTempBuffer);
330 if (readTempBuffer.empty()) {
331 continue;
332 }
333 if (ParseIppResponse(readTempBuffer, printerStatus)) {
334 fprintf(stderr, "DEBUG: USB_MONITOR ProcessDataFromDevice success\n");
335 return true;
336 }
337 }
338 fprintf(stderr, "DEBUG: USB_MONITOR ProcessDataFromDevice fail\n");
339 return false;
340 }
341
BulkTransferRead(const std::string & uri,std::vector<uint8_t> & readTempBuffer)342 int32_t IppUsbManager::BulkTransferRead(const std::string& uri, std::vector<uint8_t>& readTempBuffer)
343 {
344 std::lock_guard<std::mutex> autoLock(lock_);
345 auto it = ippPrinterMap_.find(uri);
346 if (it == ippPrinterMap_.end()) {
347 fprintf(stderr, "DEBUG: USB_MONITOR not found uri in ippPrinterMap_\n");
348 return INVAILD_VALUE;
349 }
350 UsbDevice usbdevice = it->second.device;
351 PrinterTranIndex tranIndex = it->second.tranIndex;
352 int32_t currentConfigIndex = tranIndex.configIndex;
353 int32_t currentInterfaceIndex = tranIndex.interfaceIndex;
354 UsbInterface useInterface = usbdevice.GetConfigs()[currentConfigIndex].GetInterfaces()[currentInterfaceIndex];
355 USBEndpoint pointRead;
356 std::vector<USBEndpoint>& endPoints = useInterface.GetEndpoints();
357 for (auto& point : endPoints) {
358 if (point.GetDirection() != 0) {
359 pointRead = point;
360 break;
361 }
362 }
363 USBDevicePipe usbDevicePipe = it->second.ippPipe;
364 int32_t readFromUsbRes = 0;
365 int32_t claimRetryCount = 0;
366 do {
367 readFromUsbRes = usbSrvClient.BulkTransfer(usbDevicePipe, pointRead, readTempBuffer,
368 USB_BULKTRANSFER_READ_TIMEOUT);
369 if (readFromUsbRes == EORROR_HDF_DEV_ERR_IO_FAILURE) {
370 int claimRes = usbSrvClient.ClaimInterface(usbDevicePipe, useInterface, true);
371 if (claimRes < 0 || ++claimRetryCount >= CLAIM_INTERFACE_RETRY_MAX_TIMES) {
372 break;
373 }
374 }
375 } while (readFromUsbRes == EORROR_HDF_DEV_ERR_IO_FAILURE);
376 return readFromUsbRes;
377 }
378
BulkTransferWrite(const std::string & uri,std::vector<uint8_t> & vectorRequestBuffer)379 int32_t IppUsbManager::BulkTransferWrite(const std::string& uri, std::vector<uint8_t>& vectorRequestBuffer)
380 {
381 std::lock_guard<std::mutex> autoLock(lock_);
382 auto it = ippPrinterMap_.find(uri);
383 if (it == ippPrinterMap_.end()) {
384 fprintf(stderr, "DEBUG: USB_MONITOR not found uri in ippPrinterMap_\n");
385 return INVAILD_VALUE;
386 }
387 UsbDevice& usbdevice = it->second.device;
388 PrinterTranIndex& tranIndex = it->second.tranIndex;
389 int32_t currentConfigIndex = tranIndex.configIndex;
390 int32_t currentInterfaceIndex = tranIndex.interfaceIndex;
391 UsbInterface useInterface = usbdevice.GetConfigs()[currentConfigIndex].GetInterfaces()[currentInterfaceIndex];
392 USBEndpoint pointWrite;
393 std::vector<USBEndpoint>& endPoints = useInterface.GetEndpoints();
394 for (auto& point : endPoints) {
395 if (point.GetDirection() == 0) {
396 pointWrite = point;
397 break;
398 }
399 }
400 USBDevicePipe usbDevicePipe = it->second.ippPipe;
401 int32_t writeRet = 0;
402 int32_t claimRetryCount = 0;
403 do {
404 writeRet = usbSrvClient.BulkTransfer(usbDevicePipe, pointWrite, vectorRequestBuffer,
405 USB_BULKTRANSFER_WRITE_TIMEOUT);
406 if (writeRet == EORROR_HDF_DEV_ERR_IO_FAILURE) {
407 int claimRes = usbSrvClient.ClaimInterface(usbDevicePipe, useInterface, true);
408 if (claimRes < 0 || ++claimRetryCount >= CLAIM_INTERFACE_RETRY_MAX_TIMES) {
409 break;
410 }
411 }
412 } while (writeRet == EORROR_HDF_DEV_ERR_IO_FAILURE);
413 return writeRet;
414 }
415
AllocateInterface(const std::string & uri,UsbDevice & usbdevice,USBDevicePipe & usbDevicePipe)416 bool IppUsbManager::AllocateInterface(const std::string &uri, UsbDevice& usbdevice,
417 USBDevicePipe &usbDevicePipe)
418 {
419 PrinterTranIndex tranIndex;
420 std::lock_guard<std::mutex> autoLock(lock_);
421 auto it = ippPrinterMap_.find(uri);
422 if (it == ippPrinterMap_.end()) {
423 fprintf(stderr, "DEBUG: USB_MONITOR AllocateInterface, cannot find uri in ippPrinterMap_\n");
424 usbSrvClient.Close(usbDevicePipe);
425 return false;
426 }
427 std::vector<PrinterTranIndex>& indexVec = it->second.indexVec;
428 for (auto indexVecIt = indexVec.rbegin(); indexVecIt != indexVec.rend(); it++) {
429 int32_t configIndex = indexVecIt->configIndex;
430 int32_t interfaceIndex = indexVecIt->interfaceIndex;
431 UsbInterface ippInterface =
432 usbdevice.GetConfigs()[configIndex].GetInterfaces()[interfaceIndex];
433 int32_t ret = usbSrvClient.ClaimInterface(usbDevicePipe, ippInterface, true);
434 if (ret != UEC_OK) {
435 fprintf(stderr, "DEBUG: USB_MONITOR ClaimInterface fail, ret = %d\n", ret);
436 continue;
437 }
438 if (ippInterface.GetAlternateSetting() != 0) {
439 ret = usbSrvClient.SetInterface(usbDevicePipe, ippInterface);
440 if (ret != UEC_OK) {
441 fprintf(stderr, "DEBUG: USB_MONITOR SetInterface fail, ret = %d\n", ret);
442 continue;
443 }
444 }
445 tranIndex.configIndex = configIndex;
446 tranIndex.interfaceIndex = interfaceIndex;
447 break;
448 }
449 if (tranIndex.configIndex == INVAILD_VALUE) {
450 fprintf(stderr, "DEBUG: USB_MONITOR connect usb fail");
451 usbSrvClient.Close(usbDevicePipe);
452 return false;
453 }
454 auto& printer = it->second;
455 printer.isOpened = true;
456 printer.ippPipe = usbDevicePipe;
457 printer.tranIndex = tranIndex;
458 return true;
459 }
460
BuildIppRequest()461 std::vector<uint8_t> IppUsbManager::BuildIppRequest()
462 {
463 ipp_t* request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
464 if (request == nullptr) {
465 fprintf(stderr, "DEBUG: USB_MONITOR request is a nullptr.\n");
466 return {};
467 }
468 static const char * const jattrs[] = {
469 "printer-state",
470 "printer-state-reasons"
471 };
472 static const std::string DEFAULT_USER = "default";
473 static const std::string LOCAL_URI = "ipp://127.0.0.1:60000/ipp/print";
474 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", nullptr, LOCAL_URI.c_str());
475 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", nullptr, DEFAULT_USER.c_str());
476 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes",
477 sizeof(jattrs) / sizeof(jattrs[0]), nullptr, jattrs);
478
479 std::vector<uint8_t> ippdata;
480 ippWriteIO(&ippdata, (ipp_iocb_t)IppUsbManager::WriteToBuffer, true, nullptr, request);
481 ippDelete(request);
482 if (ippdata.empty()) {
483 fprintf(stderr, "DEBUG: USB_MONITOR ippWriteIO fail.\n");
484 return {};
485 }
486 std::string httpHeader = "POST /ipp/print HTTP/1.1\r\n"
487 "Host: localhost:60000\r\n"
488 "Content-Type: application/ipp\r\n"
489 "Content-Length: " + std::to_string(ippdata.size()) + "\r\n\r\n";
490
491 std::vector<uint8_t> fullData(ippdata.size() + httpHeader.size());
492 if (memcpy_s(fullData.data(), fullData.size(), httpHeader.data(), httpHeader.size()) != 0) {
493 fprintf(stderr, "DEBUG: USB_MONITOR memcpy_s httpHeader fail.\n");
494 return {};
495 }
496 if (memcpy_s(fullData.data() + httpHeader.size(), fullData.size(), ippdata.data(), ippdata.size()) != 0) {
497 fprintf(stderr, "DEBUG: USB_MONITOR memcpy_s ippdata fail.\n");
498 return {};
499 }
500 return fullData;
501 }
502
WriteToBuffer(void * ctx,const void * data,size_t len)503 ssize_t IppUsbManager::WriteToBuffer(void* ctx, const void* data, size_t len)
504 {
505 auto *buffer = static_cast<std::vector<uint8_t> *>(ctx);
506 if (buffer == nullptr) {
507 fprintf(stderr, "DEBUG: USB_MONITOR buffer is a nullptr.\n");
508 return IPP_STATE_ERROR;
509 }
510 size_t oldSize = buffer->size();
511 buffer->resize(oldSize + len);
512 if (memcpy_s(buffer->data() + oldSize, buffer->size(), data, len) != 0) {
513 fprintf(stderr, "DEBUG: USB_MONITOR WriteToBuffer memcpy_s fail.\n");
514 return IPP_STATE_ERROR;
515 }
516 return static_cast<ssize_t>(len);
517 }
518
ReadFromBuffer(void * ctx,void * data,size_t len)519 ssize_t IppUsbManager::ReadFromBuffer(void *ctx, void *data, size_t len)
520 {
521 if (ctx == nullptr || data == nullptr) {
522 fprintf(stderr, "DEBUG: USB_MONITOR ctx or data is a nullptr.\n");
523 return IPP_STATE_ERROR;
524 }
525 auto* context = static_cast<BufferContext*>(ctx);
526 size_t remainSize = context->size - context->pos;
527 if (remainSize == INDEX_0) {
528 fprintf(stderr, "DEBUG: USB_MONITOR Read completed.\n");
529 return INDEX_0;
530 }
531 size_t toRead = std::min(len, remainSize);
532 if (memcpy_s(data, len, context->data + context->pos, toRead) != 0) {
533 fprintf(stderr, "DEBUG: USB_MONITOR ReadFromBuffer memcpy_s fail.\n");
534 return IPP_STATE_ERROR;
535 }
536 context->pos += toRead;
537 return static_cast<ssize_t>(toRead);
538 }
539
ParseIppResponse(std::vector<uint8_t> & responseData,PrinterStatus & printerStatus)540 bool IppUsbManager::ParseIppResponse(std::vector<uint8_t>& responseData, PrinterStatus& printerStatus)
541 {
542 ipp_t *response = ippNew();
543 if (response == nullptr) {
544 fprintf(stderr, "DEBUG: USB_MONITOR response is nullptr.\n");
545 return false;
546 }
547 BufferContext context { responseData.data(), responseData.size(), 0};
548 ipp_state_t state = ippReadIO(&context, (ipp_iocb_t)IppUsbManager::ReadFromBuffer, true, nullptr, response);
549 if (state != IPP_STATE_DATA) {
550 fprintf(stderr, "DEBUG: USB_MONITOR Failed to parse IPP response.\n");
551 ippDelete(response);
552 return false;
553 }
554 ipp_attribute_t *attr = nullptr;
555 constexpr int32_t bufferSize = PRINTER_STATE_REASONS_SIZE;
556 printerStatus.printerState = IPP_PSTATE_IDLE;
557 if (memset_s(printerStatus.printerStateReasons, bufferSize, 0, bufferSize) != 0) {
558 fprintf(stderr, "DEBUG: USB_MONITOR memset_s printerStateReasons fail\n");
559 ippDelete(response);
560 return false;
561 }
562 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != nullptr) {
563 printerStatus.printerState = (ipp_pstate_e)ippGetInteger(attr, 0);
564 }
565 if ((attr = ippFindAttribute(response, "printer-state-reasons", IPP_TAG_KEYWORD)) != nullptr) {
566 ippAttributeString(attr, printerStatus.printerStateReasons, sizeof(printerStatus.printerStateReasons));
567 }
568 fprintf(stderr, "DEBUG: USB_MONITOR printerStateReasons = %s, printerState = %d\n",
569 printerStatus.printerStateReasons, static_cast<int32_t>(printerStatus.printerState));
570 ippDelete(response);
571 return true;
572 }
573 } // namespace OHOS::CUPS