1 /*
2  * Copyright (c) 2023 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 #ifdef IPPOVERUSB_ENABLE
17 #include "print_usb_manager.h"
18 #include "print_log.h"
19 #include "usb_errors.h"
20 #include "print_ipp_over_usb_util.h"
21 #include "cJSON.h"
22 
23 namespace OHOS::Print {
24 using namespace OHOS;
25 using namespace OHOS::USB;
26 
PrintUsbManager()27 PrintUsbManager::PrintUsbManager()
28 {}
29 
~PrintUsbManager()30 PrintUsbManager::~PrintUsbManager()
31 {}
32 
Init()33 void PrintUsbManager::Init()
34 {
35     if (isInit) {
36         PRINT_HILOGD("has init");
37     }
38     isInit = true;
39     RefreshUsbPrinterDevice();
40 }
41 
isExistIppOverUsbPrinter(std::string printerName)42 bool PrintUsbManager::isExistIppOverUsbPrinter(std::string printerName)
43 {
44     PRINT_HILOGD("isExistIppOverUsbPrinter printerName = %{public}s", printerName.c_str());
45     if (!printerName.empty() && printDeviceMap.find(printerName) != printDeviceMap.end()) {
46         return true;
47     }
48     return false;
49 }
50 
51 
isPrintDevice(USB::UsbDevice &usbdevice, std::string &printerName)52 bool PrintUsbManager::isPrintDevice(USB::UsbDevice &usbdevice, std::string &printerName)
53 {
54     int32_t configCount = usbdevice.GetConfigCount();
55     std::vector<std::pair<int32_t, int32_t>> indexVec;
56     int32_t ippusbInterfaceCount = 0;
57     PRINT_HILOGD("name = %{public}s.", usbdevice.GetName().c_str());
58     for (int32_t configIndex = 0; configIndex < configCount; configIndex++) {
59         int32_t interfaceCount = static_cast<int32_t>(usbdevice.GetConfigs()[configIndex].GetInterfaceCount());
60         PRINT_HILOGD("configIndex = %{public}d.", configIndex);
61         for (int32_t interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) {
62             PRINT_HILOGD("interfaceIndex = %{public}d.", interfaceIndex);
63             UsbInterface usbInterface = usbdevice.GetConfigs()[configIndex].GetInterfaces()[interfaceIndex];
64             PRINT_HILOGD("isPrintDevice class = %{public}d, subclass = %{public}d, protocol = %{public}d",
65                 usbInterface.GetClass(), usbInterface.GetSubClass(), usbInterface.GetProtocol());
66             bool isSupportIpp = (usbInterface.GetClass() == USB_DEVICE_CLASS_PRINT &&
67                 usbInterface.GetSubClass() == USB_DEVICE_SUBCLASS_PRINT &&
68                 usbInterface.GetProtocol() == USB_DEVICE_PROTOCOL_PRINT);
69             if (isSupportIpp) {
70                 auto indexPair = std::make_pair(configIndex, interfaceIndex);
71                 indexVec.push_back(indexPair);
72                 ippusbInterfaceCount++;
73             }
74         }
75     }
76     // Two or more interfaces are required
77     if (ippusbInterfaceCount >= USB_INTERFACE_MIN_COUNT) {
78         printerName = GetProductName(usbdevice);
79         PRINT_HILOGI("support IppPrint printerName = %{public}s.", printerName.c_str());
80         if (printerName.empty()) {
81             return false;
82         }
83         printerIndexMap[printerName] = indexVec;
84         return true;
85     }
86     return false;
87 }
88 
RefreshUsbPrinterDevice()89 void PrintUsbManager::RefreshUsbPrinterDevice()
90 {
91     std::vector<UsbDevice> devlist;
92     int32_t ret = ERR_OK;
93     if (isUsbEnable) {
94         ret = UsbSrvClient::GetInstance().GetDevices(devlist);
95     }
96     if (ERR_OK != ret) {
97         PRINT_HILOGE("RefreshDeviceList GetDevices failed with ret = %{public}d.", ret);
98         return;
99     } else if (devlist.empty()) {
100         PRINT_HILOGE("RefreshDeviceList GetDevices empty with ret = %{public}d.", ret);
101         return;
102     }
103     for (auto dev : devlist) {
104         std::string printerName;
105         if (isPrintDevice(dev, printerName)) {
106             printDeviceMap[printerName] = dev;
107         }
108     }
109 }
110 
GetProductName(UsbDevice &usbDevice)111 std::string PrintUsbManager::GetProductName(UsbDevice &usbDevice)
112 {
113     PRINT_HILOGI("getProductName dev.GetName() = %{public}s.", usbDevice.GetName().c_str());
114     USBDevicePipe usbDevicePipe;
115     int32_t openDeviceRet = UEC_OK;
116     if (isUsbEnable) {
117         openDeviceRet = UsbSrvClient::GetInstance().OpenDevice(usbDevice, usbDevicePipe);
118     }
119     PRINT_HILOGI("openDevice ret = %{public}d", openDeviceRet);
120     if (openDeviceRet != UEC_OK) {
121         PRINT_HILOGE("openDevice fail with ret = %{public}d", openDeviceRet);
122         return "";
123     }
124     std::string productName =
125         QueryPrinterInfoFromStringDescriptor(usbDevicePipe, USB_VALUE_DESCRIPTOR_INDEX_PRODUCT_NAME);
126     std::string serialNumber =
127         QueryPrinterInfoFromStringDescriptor(usbDevicePipe, USB_VALUE_DESCRIPTOR_INDEX_SERIAL_NUMBER);
128     size_t len = serialNumber.length();
129     if (len > HTTP_COMMON_CONST_VALUE_4) {
130         serialNumber = serialNumber.substr(len - HTTP_COMMON_CONST_VALUE_4);
131     }
132     std::string printerName = productName + "-" + serialNumber;
133     PRINT_HILOGI("getProductName printerName = %{public}s.", printerName.c_str());
134     return printerName;
135 }
136 
QueryPrinterInfoFromStringDescriptor( USBDevicePipe &usbDevicePipe, uint16_t indexInStringDescriptor)137 std::string PrintUsbManager::QueryPrinterInfoFromStringDescriptor(
138     USBDevicePipe &usbDevicePipe, uint16_t indexInStringDescriptor)
139 {
140     PRINT_HILOGI("enter QueryPrinterInfoFromStringDescriptor");
141     uint8_t requestType = USB_REQUESTTYPE_DEVICE_TO_HOST;
142     uint8_t request = USB_REQUEST_GET_DESCRIPTOR;
143     uint16_t value = (USB_VALUE_DESCRIPTOR_TYPE_STRING << HTTP_COMMON_CONST_VALUE_8) | indexInStringDescriptor;
144     uint16_t index = USB_INDEX_LANGUAGE_ID_ENGLISH;
145     int32_t timeOut = HTTP_COMMON_CONST_VALUE_500;
146     const HDI::Usb::V1_0::UsbCtrlTransfer tctrl = {requestType, request, value, index, timeOut};
147     std::vector<uint8_t> bufferData(HTTP_COMMON_CONST_VALUE_100, 0);
148     int32_t ret = 0;
149     if (isUsbEnable) {
150         ret = UsbSrvClient::GetInstance().ControlTransfer(usbDevicePipe, tctrl, bufferData);
151     }
152     if (ret != 0 || bufferData[INDEX_0] == 0 ||
153         ((bufferData[INDEX_0] - HTTP_COMMON_CONST_VALUE_2) / HTTP_COMMON_CONST_VALUE_2) < 0) {
154         PRINT_HILOGE("ControlTransfer failed ret = %{public}d, buffer length = %{public}d", ret, bufferData[0]);
155         return "";
156     }
157 
158     std::vector<uint8_t> arr((bufferData[INDEX_0] - HTTP_COMMON_CONST_VALUE_2) / HTTP_COMMON_CONST_VALUE_2);
159     int arrIndex = 0;
160     for (int i = INDEX_2; i < bufferData[INDEX_0];) {
161         arr[arrIndex++] = bufferData[i];
162         i += HTTP_COMMON_CONST_VALUE_2;
163     }
164     std::string printerInfo(arr.begin(), arr.end());
165     PRINT_HILOGI("bufferData printerInfo: %{public}s\n", printerInfo.c_str());
166     return printerInfo;
167 }
168 
AllocateInterface(const std::string &printerName, UsbDevice &usbdevice, USBDevicePipe &usbDevicePipe)169 bool PrintUsbManager::AllocateInterface(const std::string &printerName, UsbDevice &usbdevice,
170     USBDevicePipe &usbDevicePipe)
171 {
172     PrinterTranIndex tranIndex;
173     for (auto index : printerIndexMap[printerName]) {
174         int32_t configIndex = index.first;
175         int32_t interfaceIndex = index.second;
176         UsbInterface ippInterface =
177             usbdevice.GetConfigs()[configIndex].GetInterfaces()[interfaceIndex];
178         int32_t ret = UEC_OK;
179         if (isUsbEnable) {
180             ret = UsbSrvClient::GetInstance().ClaimInterface(usbDevicePipe, ippInterface, true);
181         }
182         if (ret != UEC_OK) {
183             PRINT_HILOGE("ClaimInterface fail, ret = %{public}d", ret);
184             continue;
185         }
186         if (tranIndex.commonConfigIndex == INVAILD_VALUE) {
187             tranIndex.commonConfigIndex = configIndex;
188             tranIndex.commonInterfaceIndex = interfaceIndex;
189         } else if (tranIndex.sendDocConfigIndex == INVAILD_VALUE) {
190             tranIndex.sendDocConfigIndex = configIndex;
191             tranIndex.sendDocInterfaceIndex = interfaceIndex;
192             break;
193         }
194     }
195     if (tranIndex.commonConfigIndex == INVAILD_VALUE || tranIndex.sendDocConfigIndex == INVAILD_VALUE) {
196         PRINT_HILOGE("connect usb printerName = %{public}s fail!", printerName.c_str());
197         if (tranIndex.commonConfigIndex != INVAILD_VALUE) {
198             int32_t configIndex = tranIndex.commonConfigIndex;
199             UsbInterface commonInterface =
200                 usbdevice.GetConfigs()[configIndex].GetInterfaces()[tranIndex.commonInterfaceIndex];
201             if (isUsbEnable) {
202                 UsbSrvClient::GetInstance().ReleaseInterface(usbDevicePipe, commonInterface);
203             }
204         }
205         if (isUsbEnable) {
206             UsbSrvClient::GetInstance().Close(usbDevicePipe);
207         }
208         return false;
209     }
210 
211     printPipeMap[printerName] = usbDevicePipe;
212     printTranIndexMap[printerName] = tranIndex;
213     return true;
214 }
215 
ConnectUsbPinter(const std::string &printerName)216 bool PrintUsbManager::ConnectUsbPinter(const std::string &printerName)
217 {
218     PRINT_HILOGD("connect usb printerName = %{public}s", printerName.c_str());
219     if (!printerName.empty() && printPipeMap.find(printerName) != printPipeMap.end()) {
220         PRINT_HILOGD("printerName = %{public}s is opened", printerName.c_str());
221         return true;
222     }
223     if (!printerName.empty() && printDeviceMap.find(printerName) != printDeviceMap.end()) {
224         UsbDevice usbdevice = printDeviceMap[printerName];
225         USBDevicePipe usbDevicePipe;
226         int32_t openDeviceRet = UEC_OK;
227         if (isUsbEnable) {
228             openDeviceRet = UsbSrvClient::GetInstance().OpenDevice(usbdevice, usbDevicePipe);
229         }
230         PRINT_HILOGD("openDevice ret = %{public}d", openDeviceRet);
231         if (openDeviceRet == UEC_OK) {
232             return AllocateInterface(printerName, usbdevice, usbDevicePipe);
233         } else {
234             PRINT_HILOGE("ipp usb openDevice fail with ret = %{public}d", openDeviceRet);
235             return false;
236         }
237     }
238     return false;
239 }
240 
DisConnectUsbPinter(const std::string &printerName)241 void PrintUsbManager::DisConnectUsbPinter(const std::string &printerName)
242 {
243     if (!printerName.empty() && printDeviceMap.find(printerName) != printDeviceMap.end() &&
244         printPipeMap.find(printerName) != printPipeMap.end() &&
245         printTranIndexMap.find(printerName) != printTranIndexMap.end()) {
246         UsbDevice usbdevice = printDeviceMap[printerName];
247         USBDevicePipe usbDevicePipe = printPipeMap[printerName];
248         PrinterTranIndex tranIndex = printTranIndexMap[printerName];
249         UsbInterface commonInterface =
250             usbdevice.GetConfigs()[tranIndex.commonConfigIndex].GetInterfaces()[tranIndex.commonInterfaceIndex];
251         UsbInterface sendDocIterface =
252             usbdevice.GetConfigs()[tranIndex.sendDocConfigIndex].GetInterfaces()[tranIndex.sendDocInterfaceIndex];
253         if (isUsbEnable) {
254             UsbSrvClient::GetInstance().ReleaseInterface(usbDevicePipe, commonInterface);
255             UsbSrvClient::GetInstance().ReleaseInterface(usbDevicePipe, sendDocIterface);
256             UsbSrvClient::GetInstance().Close(usbDevicePipe);
257         }
258         printPipeMap.erase(printerName);
259         printTranIndexMap.erase(printerName);
260     }
261 }
262 
BulkTransferWrite(std::string printerName, const Operation operation, std::vector<uint8_t> &vectorRequestBuffer)263 int32_t PrintUsbManager::BulkTransferWrite(std::string printerName, const Operation operation,
264     std::vector<uint8_t> &vectorRequestBuffer)
265 {
266     if (printDeviceMap.find(printerName) == printDeviceMap.end()) {
267         return INVAILD_VALUE;
268     }
269     UsbDevice usbdevice = printDeviceMap[printerName];
270     int32_t currentConfigIndex = INVAILD_VALUE;
271     int32_t currentInterfaceIndex = INVAILD_VALUE;
272     PrinterTranIndex tranIndex = printTranIndexMap[printerName];
273     if (operation == Operation::Send_Document) {
274         currentConfigIndex = tranIndex.sendDocConfigIndex;
275         currentInterfaceIndex = tranIndex.sendDocInterfaceIndex;
276     } else {
277         currentConfigIndex = tranIndex.commonConfigIndex;
278         currentInterfaceIndex = tranIndex.commonInterfaceIndex;
279     }
280     UsbInterface useInterface = usbdevice.GetConfigs()[currentConfigIndex].GetInterfaces()[currentInterfaceIndex];
281     USBEndpoint point1 = useInterface.GetEndpoints().at(INDEX_0);
282     USBEndpoint point2 = useInterface.GetEndpoints().at(INDEX_1);
283     USBEndpoint pointWrite;
284     if (point1.GetDirection() == 0) {
285         pointWrite = point1;
286     } else {
287         pointWrite = point2;
288     }
289     USBDevicePipe usbDevicePipe = printPipeMap[printerName];
290     int32_t writeRet = 0;
291     if (isUsbEnable) {
292         writeRet = UsbSrvClient::GetInstance().BulkTransfer(usbDevicePipe, pointWrite, vectorRequestBuffer,
293             USB_BULKTRANSFER_WRITE_TIMEOUT);
294     }
295     return writeRet;
296 }
297 
BulkTransferRead(std::string printerName, const Operation operation, std::vector<uint8_t> &readTempBUffer)298 int32_t PrintUsbManager::BulkTransferRead(std::string printerName, const Operation operation,
299     std::vector<uint8_t> &readTempBUffer)
300 {
301     if (printDeviceMap.find(printerName) == printDeviceMap.end()) {
302         return INVAILD_VALUE;
303     }
304     UsbDevice usbdevice = printDeviceMap[printerName];
305     int32_t currentConfigIndex = INVAILD_VALUE;
306     int32_t currentInterfaceIndex = INVAILD_VALUE;
307     PrinterTranIndex tranIndex = printTranIndexMap[printerName];
308     if (operation == Operation::Send_Document) {
309         currentConfigIndex = tranIndex.sendDocConfigIndex;
310         currentInterfaceIndex = tranIndex.sendDocInterfaceIndex;
311     } else {
312         currentConfigIndex = tranIndex.commonConfigIndex;
313         currentInterfaceIndex = tranIndex.commonInterfaceIndex;
314     }
315     UsbInterface useInterface = usbdevice.GetConfigs()[currentConfigIndex].GetInterfaces()[currentInterfaceIndex];
316     USBEndpoint point1 = useInterface.GetEndpoints().at(INDEX_0);
317     USBEndpoint point2 = useInterface.GetEndpoints().at(INDEX_1);
318     USBEndpoint pointRead;
319     if (point1.GetDirection() == 0) {
320         pointRead = point2;
321     } else {
322         pointRead = point1;
323     }
324     USBDevicePipe usbDevicePipe = printPipeMap[printerName];
325     int32_t readFromUsbRes = 0;
326     if (isUsbEnable) {
327         readFromUsbRes = UsbSrvClient::GetInstance().BulkTransfer(usbDevicePipe, pointRead, readTempBUffer,
328             USB_BULKTRANSFER_READ_TIMEOUT);
329     }
330     return readFromUsbRes;
331 }
332 
DealUsbDevStatusChange(const std::string &devStr, bool isAttach)333 void PrintUsbManager::DealUsbDevStatusChange(const std::string &devStr, bool isAttach)
334 {
335     PRINT_HILOGD("DealUsbDevStatusChange isAttach = %{public}d, devStr = %{public}s.",
336         isAttach, devStr.c_str());
337     cJSON *devJson = cJSON_Parse(devStr.c_str());
338     if (devJson == nullptr) {
339         PRINT_HILOGE("Create devJson error");
340         return;
341     }
342     UsbDevice *dev = new (std::nothrow) UsbDevice(devJson);
343     if (dev == nullptr) {
344         PRINT_HILOGE("Create dev error");
345         cJSON_Delete(devJson);
346         return;
347     }
348     if (!isAttach) {
349         std::string printerName = GetPrinterName(dev->GetName());
350         PRINT_HILOGI("DealUsbDevStatusChange detached dev->GetName() = %{public}s, printerName = %{public}s.",
351             dev->GetName().c_str(), printerName.c_str());
352         if (!printerName.empty()) {
353             DisConnectUsbPinter(printerName);
354             printDeviceMap.erase(printerName);
355             printerIndexMap.erase(printerName);
356         }
357     } else {
358         std::string printerName;
359         if (isPrintDevice(*dev, printerName)) {
360             printDeviceMap[printerName] = *dev;
361             PRINT_HILOGI("DealUsbDevStatusChange attached dev->GetName() = %{public}s , printerName = %{public}s.",
362                 dev->GetName().c_str(), printerName.c_str());
363         }
364     }
365     cJSON_Delete(devJson);
366     delete dev;
367     dev = nullptr;
368 }
369 
GetPrinterName(const std::string &name)370 std::string PrintUsbManager::GetPrinterName(const std::string &name)
371 {
372     for (const auto& pair : printDeviceMap) {
373         if (pair.second.GetName() == name) {
374             return pair.first;
375         }
376     }
377     return "";
378 }
379 }
380 
381 #endif // IPPOVERUSB_ENABLE