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